From fb527b57609088287550e9529f1657f537bdb24a Mon Sep 17 00:00:00 2001 From: Jan Kaluza Date: Thu, 14 Jun 2012 08:06:46 +0200 Subject: [PATCH 1/4] Added NetworkPlugin::handleBuddyRemoved method to let backend remove buddy from XMPP user's roster --- include/transport/networkplugin.h | 5 +++ include/transport/networkpluginserver.h | 1 + include/transport/rostermanager.h | 8 ++++ plugin/cpp/networkplugin.cpp | 13 ++++++ src/networkpluginserver.cpp | 20 ++++++++- src/rostermanager.cpp | 54 +++++++++++++++++++++++++ 6 files changed, 99 insertions(+), 2 deletions(-) diff --git a/include/transport/networkplugin.h b/include/transport/networkplugin.h index 9f440152..f54269a0 100644 --- a/include/transport/networkplugin.h +++ b/include/transport/networkplugin.h @@ -75,6 +75,11 @@ class NetworkPlugin { bool blocked = false ); + /// Call this method when buddy is removed from legacy network contact list. + /// \param user XMPP JID of user for which this event occurs. You can get it from NetworkPlugin::handleLoginRequest(). (eg. "user%gmail.com@xmpp.domain.tld") + /// \param buddyName Name of legacy network buddy. (eg. "user2@gmail.com") + void handleBuddyRemoved(const std::string &user, const std::string &buddyName); + /// Call this function when participant in room changed. /// \param user XMPP JID of user for which this event occurs. You can get it from NetworkPlugin::handleLoginRequest(). (eg. "user%gmail.com@xmpp.domain.tld") /// \param nickname Nickname of participant. If participant renamed, this is old name of participant. (eg. "HanzZ") diff --git a/include/transport/networkpluginserver.h b/include/transport/networkpluginserver.h index 5572780a..7e43ce33 100644 --- a/include/transport/networkpluginserver.h +++ b/include/transport/networkpluginserver.h @@ -89,6 +89,7 @@ class NetworkPluginServer { void handleConnectedPayload(const std::string &payload); void handleDisconnectedPayload(const std::string &payload); void handleBuddyChangedPayload(const std::string &payload); + void handleBuddyRemovedPayload(const std::string &payload); void handleConvMessagePayload(const std::string &payload, bool subject = false); void handleParticipantChangedPayload(const std::string &payload); void handleRoomChangedPayload(const std::string &payload); diff --git a/include/transport/rostermanager.h b/include/transport/rostermanager.h index 64f05fa7..fd649b57 100644 --- a/include/transport/rostermanager.h +++ b/include/transport/rostermanager.h @@ -69,6 +69,10 @@ class RosterManager { /// \param buddy Buddy. void unsetBuddy(Buddy *buddy); + /// Removes buddy from this roster, sends proper XML to XMPP side and deletes it. + /// \param name Buddy name. + void removeBuddy(const std::string &name); + Buddy *getBuddy(const std::string &name); void setStorageBackend(StorageBackend *storageBackend); @@ -107,7 +111,11 @@ class RosterManager { void sendBuddyRosterPush(Buddy *buddy); + void sendBuddyRosterRemove(Buddy *buddy); + void sendBuddySubscribePresence(Buddy *buddy); + + void sendBuddyUnsubscribePresence(Buddy *buddy); void sendCurrentPresences(const Swift::JID &to); diff --git a/plugin/cpp/networkplugin.cpp b/plugin/cpp/networkplugin.cpp index 43d82653..4455c37e 100644 --- a/plugin/cpp/networkplugin.cpp +++ b/plugin/cpp/networkplugin.cpp @@ -165,6 +165,19 @@ void NetworkPlugin::handleBuddyChanged(const std::string &user, const std::strin send(message); } +void NetworkPlugin::handleBuddyRemoved(const std::string &user, const std::string &buddyName) { + pbnetwork::Buddy buddy; + buddy.set_username(user); + buddy.set_buddyname(buddyName); + + std::string message; + buddy.SerializeToString(&message); + + WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_BUDDY_REMOVED); + + send(message); +} + void NetworkPlugin::handleBuddyTyping(const std::string &user, const std::string &buddyName) { pbnetwork::Buddy buddy; buddy.set_username(user); diff --git a/src/networkpluginserver.cpp b/src/networkpluginserver.cpp index fdd68e68..c9b6f23c 100644 --- a/src/networkpluginserver.cpp +++ b/src/networkpluginserver.cpp @@ -264,6 +264,7 @@ NetworkPluginServer::NetworkPluginServer(Component *component, Config *config, U LOG4CXX_INFO(logger, "Listening on host " << CONFIG_STRING(m_config, "service.backend_host") << " port " << CONFIG_STRING(m_config, "service.backend_port")); unsigned long pid = exec_(CONFIG_STRING(m_config, "service.backend"), CONFIG_STRING(m_config, "service.backend_host").c_str(), CONFIG_STRING(m_config, "service.backend_port").c_str(), m_config->getConfigFile().c_str()); + LOG4CXX_INFO(logger, "Tried to spawn first backend with pid " << pid); LOG4CXX_INFO(logger, "Backend should now connect to Spectrum2 instance. Spectrum2 won't accept any connection before backend connects"); #ifndef _WIN32 @@ -509,8 +510,6 @@ void NetworkPluginServer::handleBuddyChangedPayload(const std::string &data) { if (!user) return; - LOG4CXX_INFO(logger, "HANDLE BUDDY CHANGED " << payload.buddyname() << "-" << payload.alias()); - LocalBuddy *buddy = (LocalBuddy *) user->getRosterManager()->getBuddy(payload.buddyname()); if (buddy) { handleBuddyPayload(buddy, payload); @@ -524,6 +523,20 @@ void NetworkPluginServer::handleBuddyChangedPayload(const std::string &data) { } } +void NetworkPluginServer::handleBuddyRemovedPayload(const std::string &data) { + pbnetwork::Buddy payload; + if (payload.ParseFromString(data) == false) { + // TODO: ERROR + return; + } + + User *user = m_userManager->getUser(payload.username()); + if (!user) + return; + + user->getRosterManager()->removeBuddy(payload.buddyname()); +} + void NetworkPluginServer::handleParticipantChangedPayload(const std::string &data) { pbnetwork::Participant payload; if (payload.ParseFromString(data) == false) { @@ -828,6 +841,9 @@ void NetworkPluginServer::handleDataRead(Backend *c, boost::shared_ptrgetJID().toString() << ": Tried to remove unknown buddy " << name); + return; + } + + if (m_component->inServerMode() || m_remoteRosterRequest) { + sendBuddyRosterRemove(buddy); + } + else { + sendBuddyUnsubscribePresence(buddy); + } + + unsetBuddy(buddy); + delete buddy; +} + +void RosterManager::sendBuddyRosterRemove(Buddy *buddy) { + Swift::RosterPayload::ref p = Swift::RosterPayload::ref(new Swift::RosterPayload()); + Swift::RosterItemPayload item; + item.setJID(buddy->getJID().toBare()); + item.setSubscription(Swift::RosterItemPayload::Remove); + + p->addItem(item); + + // In server mode we have to send pushes to all resources, but in gateway-mode we send it only to bare JID + if (m_component->inServerMode()) { + std::vector presences = m_component->getPresenceOracle()->getAllPresence(m_user->getJID().toBare()); + BOOST_FOREACH(Swift::Presence::ref presence, presences) { + Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(p, presence->getFrom(), m_component->getIQRouter()); + request->send(); + } + } + else { + Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(p, m_user->getJID().toBare(), m_component->getIQRouter()); + request->send(); + } +} + void RosterManager::sendBuddyRosterPush(Buddy *buddy) { // user can't receive anything in server mode if he's not logged in. // He will ask for roster later (handled in rosterreponsder.cpp) @@ -142,6 +182,20 @@ void RosterManager::sendBuddyRosterPush(Buddy *buddy) { } } +void RosterManager::sendBuddyUnsubscribePresence(Buddy *buddy) { + Swift::Presence::ref response = Swift::Presence::create(); + response->setTo(m_user->getJID()); + response->setFrom(buddy->getJID()); + response->setType(Swift::Presence::Unsubscribe); + m_component->getStanzaChannel()->sendPresence(response); + + response = Swift::Presence::create(); + response->setTo(m_user->getJID()); + response->setFrom(buddy->getJID()); + response->setType(Swift::Presence::Unsubscribed); + m_component->getStanzaChannel()->sendPresence(response); +} + void RosterManager::sendBuddySubscribePresence(Buddy *buddy) { Swift::Presence::ref response = Swift::Presence::create(); response->setTo(m_user->getJID()); From f4a3ad1cadf8d612d54e861a8a50ab21695ce86a Mon Sep 17 00:00:00 2001 From: Jan Kaluza Date: Thu, 14 Jun 2012 08:37:32 +0200 Subject: [PATCH 2/4] Changelog --- ChangeLog | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/ChangeLog b/ChangeLog index 9ef83b48..94cc0f64 100644 --- a/ChangeLog +++ b/ChangeLog @@ -13,13 +13,25 @@ Version 2.0.0-beta3 (2012-XX-XX): * Added Munin plugin (Thanks to Askovpen). * Added support for more admin_jid JIDs (Thanks to Askovpen). * Fixed allowed_servers option. + * Show error in server-mode when server port is already used. + * Fixed bug when backend could freeze on exit. + * Options from config file can now be set also using command line like + --service.jid=domain.tld . + * Do not send password in IQ-get registration response. Libpurple: * prpl-gg: Fetch the contact list properly (#252). + * Added support for prpl-novell as it was in spectrum1. Skype: * Log more errors. + Libyahoo2: + * Added new Yahoo backend based on libyahoo2. + + Swiften: + * Added new XMPP backend based on Swiften library. + Backend API: * Added Python NetworkPlugin class, so it is now easier to write backends in Python (Thanks to Sarang). From 8a66baabcb99e70931098c0c7c1eecc0a985937a Mon Sep 17 00:00:00 2001 From: Jan Kaluza Date: Wed, 20 Jun 2012 11:49:00 +0200 Subject: [PATCH 3/4] DiscoItemsResponder can add adhoc commands --- .../transport}/discoitemsresponder.h | 10 +++++++- src/discoitemsresponder.cpp | 25 ++++++++++++++----- src/transport.cpp | 4 +-- 3 files changed, 30 insertions(+), 9 deletions(-) rename {src => include/transport}/discoitemsresponder.h (82%) diff --git a/src/discoitemsresponder.h b/include/transport/discoitemsresponder.h similarity index 82% rename from src/discoitemsresponder.h rename to include/transport/discoitemsresponder.h index 4361ebe1..44bdc364 100644 --- a/src/discoitemsresponder.h +++ b/include/transport/discoitemsresponder.h @@ -27,14 +27,22 @@ namespace Transport { +class Component; + class DiscoItemsResponder : public Swift::GetResponder { public: - DiscoItemsResponder(Swift::IQRouter *router); + DiscoItemsResponder(Component *component); ~DiscoItemsResponder(); + void addAdHocCommand(const std::string &node, const std::string &name); +// void removeAdHocCommand(const std::string &node); + private: virtual bool handleGetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr payload); + + Component *m_component; + boost::shared_ptr m_commands; }; } \ No newline at end of file diff --git a/src/discoitemsresponder.cpp b/src/discoitemsresponder.cpp index 58940a20..2365b27e 100644 --- a/src/discoitemsresponder.cpp +++ b/src/discoitemsresponder.cpp @@ -18,32 +18,45 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ -#include "discoitemsresponder.h" +#include "transport/discoitemsresponder.h" #include #include #include "Swiften/Queries/IQRouter.h" -#include "Swiften/Elements/DiscoItems.h" #include "Swiften/Swiften.h" +#include "transport/transport.h" +#include "transport/logging.h" using namespace Swift; using namespace boost; namespace Transport { -DiscoItemsResponder::DiscoItemsResponder(Swift::IQRouter *router) : Swift::GetResponder(router) { +DEFINE_LOGGER(logger, "DiscoItemsResponder"); + +DiscoItemsResponder::DiscoItemsResponder(Component *component) : Swift::GetResponder(component->getIQRouter()) { + m_component = component; + m_commands = boost::shared_ptr(new DiscoItems()); + m_commands->setNode("http://jabber.org/protocol/commands"); } DiscoItemsResponder::~DiscoItemsResponder() { } +void DiscoItemsResponder::addAdHocCommand(const std::string &node, const std::string &name) { + m_commands->addItem(DiscoItems::Item(name, m_component->getJID(), node)); +} + + bool DiscoItemsResponder::handleGetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr info) { - // presence for transport - if (to.getNode().empty()) { + LOG4CXX_INFO(logger, "get request received with node " << info->getNode()); + if (info->getNode() == "http://jabber.org/protocol/commands") { + sendResponse(from, id, m_commands); + } + else if (to.getNode().empty()) { sendResponse(from, id, boost::shared_ptr(new DiscoItems())); } - // presence for buddy else { sendResponse(from, id, boost::shared_ptr(new DiscoItems())); } diff --git a/src/transport.cpp b/src/transport.cpp index 80e086a4..24f05ddf 100644 --- a/src/transport.cpp +++ b/src/transport.cpp @@ -26,7 +26,7 @@ #include "transport/userregistry.h" #include "transport/logging.h" #include "discoinforesponder.h" -#include "discoitemsresponder.h" +#include "transport/discoitemsresponder.h" #include "storageparser.h" #include "Swiften/TLS/OpenSSL/OpenSSLServerContext.h" #include "Swiften/TLS/PKCS12Certificate.h" @@ -149,7 +149,7 @@ Component::Component(Swift::EventLoop *loop, Swift::NetworkFactories *factories, m_discoInfoResponder = new DiscoInfoResponder(m_iqRouter, m_config); m_discoInfoResponder->start(); - m_discoItemsResponder = new DiscoItemsResponder(m_iqRouter); + m_discoItemsResponder = new DiscoItemsResponder(this); m_discoItemsResponder->start(); // From cfa85cd21caf8ad9923151f87a898c1349b01aa3 Mon Sep 17 00:00:00 2001 From: Jan Kaluza Date: Wed, 20 Jun 2012 12:03:53 +0200 Subject: [PATCH 4/4] Moved DiscoItemsResponder out of Component class --- include/transport/transport.h | 2 -- spectrum/src/main.cpp | 4 ++++ src/transport.cpp | 5 ----- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/include/transport/transport.h b/include/transport/transport.h index 3d81307f..e6f0610d 100644 --- a/include/transport/transport.h +++ b/include/transport/transport.h @@ -48,7 +48,6 @@ namespace Transport { // class StorageBackend; class DiscoInfoResponder; - class DiscoItemsResponder; class Factory; class UserRegistry; @@ -188,7 +187,6 @@ namespace Transport { Transport::UserRegistry *m_userRegistry; StorageBackend *m_storageBackend; DiscoInfoResponder *m_discoInfoResponder; - DiscoItemsResponder *m_discoItemsResponder; int m_reconnectCount; Config* m_config; std::string m_protocol; diff --git a/spectrum/src/main.cpp b/spectrum/src/main.cpp index ab5bc790..e8867d45 100644 --- a/spectrum/src/main.cpp +++ b/spectrum/src/main.cpp @@ -14,6 +14,7 @@ #include "transport/util.h" #include "transport/gatewayresponder.h" #include "transport/logging.h" +#include "transport/discoitemsresponder.h" #include "Swiften/EventLoop/SimpleEventLoop.h" #include #include @@ -313,6 +314,9 @@ int main(int argc, char **argv) GatewayResponder gatewayResponder(transport.getIQRouter(), &userManager); gatewayResponder.start(); + DiscoItemsResponder discoItemsResponder(&transport); + discoItemsResponder.start(); + eventLoop_ = &eventLoop; eventLoop.run(); diff --git a/src/transport.cpp b/src/transport.cpp index 24f05ddf..391c8ffa 100644 --- a/src/transport.cpp +++ b/src/transport.cpp @@ -26,7 +26,6 @@ #include "transport/userregistry.h" #include "transport/logging.h" #include "discoinforesponder.h" -#include "transport/discoitemsresponder.h" #include "storageparser.h" #include "Swiften/TLS/OpenSSL/OpenSSLServerContext.h" #include "Swiften/TLS/PKCS12Certificate.h" @@ -149,9 +148,6 @@ Component::Component(Swift::EventLoop *loop, Swift::NetworkFactories *factories, m_discoInfoResponder = new DiscoInfoResponder(m_iqRouter, m_config); m_discoInfoResponder->start(); - m_discoItemsResponder = new DiscoItemsResponder(this); - m_discoItemsResponder->start(); - // // m_registerHandler = new SpectrumRegisterHandler(m_component); // m_registerHandler->start(); @@ -163,7 +159,6 @@ Component::~Component() { delete m_capsManager; delete m_capsMemoryStorage; delete m_discoInfoResponder; - delete m_discoItemsResponder; if (m_component) delete m_component; if (m_server) {