diff --git a/.gitignore b/.gitignore index 1df37d1c8f3528f864fecd97936aaa5a2f4447af..cfe6466d62acee4c3f0048af5b024fd6e2cb6fb3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,28 @@ *.pb.cc *.pb.h -plugin/python/protocol_pb2.py \ No newline at end of file +plugin/python/protocol_pb2.py +Makefile +*.cmake +*.so +*.so.* +*.log +libtransport_test +CMakeFiles +spectrum2 +transport_config.h +Doxyfile +moc_* +CMakeCache.txt +*.patch +*.orig +spectrum2_manager +dfrotz +spectrum2_frotz_backend +spectrum2_libcommuni_backend +spectrum2_libpurple_backend +spectrum2_skype_backend +spectrum2_smstools3_backend +spectrum2_swiften_backend +spectrum2_template_backend +spectrum2_twitter_backend +install_manifest.txt diff --git a/include/transport/buddy.h b/include/transport/buddy.h index 9d47cf6fcec22a70e20b593b1681b4894e7a4c19..c9fade98a730eda52c47383f211324c385660bf1 100644 --- a/include/transport/buddy.h +++ b/include/transport/buddy.h @@ -24,7 +24,7 @@ #include #include "transport/transport.h" #include "Swiften/Elements/VCard.h" - +#include "Swiften/Elements/Presence.h" namespace Transport { diff --git a/include/transport/conversation.h b/include/transport/conversation.h index 241f6662e6ba9ebd6ec1dded054fc0b029a391bc..48e370d2d08b0afd3d8dd73c0aef50a3cf8e76c5 100644 --- a/include/transport/conversation.h +++ b/include/transport/conversation.h @@ -25,6 +25,7 @@ #include "transport/transport.h" #include "Swiften/Elements/Message.h" +#include "Swiften/Elements/Presence.h" namespace Transport { diff --git a/include/transport/frontend.h b/include/transport/frontend.h new file mode 100644 index 0000000000000000000000000000000000000000..72d099a488ae2762be4ed556f227653360d34ca4 --- /dev/null +++ b/include/transport/frontend.h @@ -0,0 +1,95 @@ +/** + * XMPP - libpurple transport + * + * Copyright (C) 2009, Jan Kaluza + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ + +#pragma once + +#include +#include +#include +#include +#include "Swiften/Elements/RosterPayload.h" +#include "Swiften/Elements/VCard.h" +#include "Swiften/Elements/Message.h" +#include "Swiften/Elements/IQ.h" +#include "Swiften/Elements/DiscoInfo.h" +#include "Swiften/Elements/Presence.h" + +#include + +namespace Transport { + +class Config; +class UserRegistry; +class Component; +class User; +class Buddy; +class RosterManager; +class UserManager; +class StorageBackend; + +struct UserInfo; + +class Frontend { + public: + Frontend() {} + + virtual ~Frontend() {} + + virtual void init(Component *component, Swift::EventLoop *loop, Swift::NetworkFactories *factories, Config *config, UserRegistry *userRegistry) = 0; + + virtual void connectToServer() = 0; + + virtual void disconnectFromServer() = 0; + + virtual void sendPresence(Swift::Presence::ref presence) = 0; + + virtual void sendVCard(Swift::VCard::ref vcard, Swift::JID to) = 0; + + virtual void sendRosterRequest(Swift::RosterPayload::ref, Swift::JID to) = 0; + + virtual void sendMessage(boost::shared_ptr message) = 0; + + virtual void sendIQ(boost::shared_ptr) = 0; + + virtual boost::shared_ptr sendCapabilitiesRequest(Swift::JID to) = 0; + + virtual void reconnectUser(const std::string &user) = 0; + + virtual RosterManager *createRosterManager(User *user, Component *component) = 0; + + virtual User *createUser(const Swift::JID &jid, UserInfo &userInfo, Component *component, UserManager *userManager) = 0; + + virtual UserManager *createUserManager(Component *component, UserRegistry *userRegistry, StorageBackend *storageBackend = NULL) = 0; + + virtual void clearRoomList() = 0; + virtual void addRoomToRoomList(const std::string &handle, const std::string &name) = 0; + + boost::signal onVCardRequired; + boost::signal vcard)> onVCardUpdated; + boost::signal onBuddyUpdated; + boost::signal onBuddyRemoved; + boost::signal onBuddyAdded; + boost::signal onMessageReceived; + boost::signal onAvailableChanged; + boost::signal) > onPresenceReceived; + boost::signal info)> onCapabilitiesReceived; +}; + +} diff --git a/include/transport/networkpluginserver.h b/include/transport/networkpluginserver.h index ef8b7f3c6485d848f0206f0736c062209206475f..52461de919980914f51c95789c104b06bb7a8937 100644 --- a/include/transport/networkpluginserver.h +++ b/include/transport/networkpluginserver.h @@ -52,7 +52,6 @@ class RosterResponder; class BlockResponder; class DummyReadBytestream; class AdminInterface; -class DiscoItemsResponder; class NetworkPluginServer : Swift::XMPPParserClient { public: @@ -70,7 +69,7 @@ class NetworkPluginServer : Swift::XMPPParserClient { std::string id; }; - NetworkPluginServer(Component *component, Config *config, UserManager *userManager, FileTransferManager *ftManager, DiscoItemsResponder *discoItemsResponder); + NetworkPluginServer(Component *component, Config *config, UserManager *userManager, FileTransferManager *ftManager); virtual ~NetworkPluginServer(); @@ -187,7 +186,6 @@ class NetworkPluginServer : Swift::XMPPParserClient { std::vector m_crashedBackends; AdminInterface *m_adminInterface; bool m_startingBackend; - DiscoItemsResponder *m_discoItemsResponder; time_t m_lastLogin; Swift::XMPPParser *m_xmppParser; Swift::FullPayloadParserFactoryCollection m_collection; diff --git a/include/transport/presenceoracle.h b/include/transport/presenceoracle.h index f631d8e90297a6696e792fabebf1da72b07cfc1b..39acc77f5ba4629630650a4e617b5c3f273b7e72 100644 --- a/include/transport/presenceoracle.h +++ b/include/transport/presenceoracle.h @@ -30,9 +30,11 @@ namespace Transport { +class Frontend; + class PresenceOracle { public: - PresenceOracle(Swift::StanzaChannel* stanzaChannel); + PresenceOracle(Frontend* frontend); ~PresenceOracle(); Swift::Presence::ref getLastPresence(const Swift::JID&) const; @@ -52,7 +54,7 @@ class PresenceOracle { typedef std::map PresenceMap; typedef std::map PresencesMap; PresencesMap entries_; - Swift::StanzaChannel* stanzaChannel_; + Frontend* frontend_; }; } diff --git a/include/transport/rostermanager.h b/include/transport/rostermanager.h index fbd652ff94353a88443f980555bc5185960022a7..6a36d8a8604a6813f2f277bb3a1e8af370532e7d 100644 --- a/include/transport/rostermanager.h +++ b/include/transport/rostermanager.h @@ -40,16 +40,6 @@ class Component; class StorageBackend; class RosterStorage; -// TODO: Once Swiften GetRosterRequest will support setting to="", this can be removed -class AddressedRosterRequest : public Swift::GenericRequest { - public: - typedef boost::shared_ptr ref; - - AddressedRosterRequest(Swift::IQRouter* router, Swift::JID to) : - Swift::GenericRequest(Swift::IQ::Get, to, boost::shared_ptr(new Swift::RosterPayload()), router) { - } -}; - /// Manages roster of one XMPP user. class RosterManager { public: @@ -62,6 +52,10 @@ class RosterManager { /// Destructor. virtual ~RosterManager(); + virtual void doRemoveBuddy(Buddy *buddy) = 0; + virtual void doAddBuddy(Buddy *buddy) = 0; + virtual void doUpdateBuddy(Buddy *buddy) = 0; + /// Associates the buddy with this roster, /// and if the buddy is not already in XMPP user's server-side roster, the proper requests /// are sent to XMPP user (subscribe presences, Roster Item Exchange stanza or @@ -113,8 +107,6 @@ class RosterManager { void handleSubscription(Swift::Presence::ref presence); - void sendBuddyRosterPush(Buddy *buddy); - void sendBuddyRosterRemove(Buddy *buddy); void sendBuddySubscribePresence(Buddy *buddy); @@ -127,14 +119,10 @@ class RosterManager { void sendUnavailablePresences(const Swift::JID &to); - private: - void setBuddyCallback(Buddy *buddy); - - void sendRIE(); - void handleBuddyRosterPushResponse(Swift::ErrorPayload::ref error, Swift::SetRosterRequest::ref request, const std::string &key); - void handleRemoteRosterResponse(boost::shared_ptr roster, Swift::ErrorPayload::ref error); - + protected: std::map, boost::pool_allocator< std::pair > > m_buddies; + + private: Component *m_component; RosterStorage *m_rosterStorage; User *m_user; @@ -142,7 +130,6 @@ class RosterManager { Swift::Timer::ref m_RIETimer; std::list m_requests; bool m_supportRemoteRoster; - AddressedRosterRequest::ref m_remoteRosterRequest; }; } diff --git a/include/transport/rosterresponder.h b/include/transport/rosterresponder.h index 4aaa21380e774be2a40e158eb944c0dec162b39b..f17a782277c61ae90feb1d666cfe76b98c8d5e7b 100644 --- a/include/transport/rosterresponder.h +++ b/include/transport/rosterresponder.h @@ -46,6 +46,7 @@ class RosterResponder : public Swift::Responder { virtual bool handleGetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr payload); virtual bool handleSetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr payload); UserManager *m_userManager; + Swift::IQRouter *m_router; }; } diff --git a/include/transport/transport.h b/include/transport/transport.h index 318ec673da2cee74b4db07235d2aae1b89998db4..c72094e868353a3fd6d48ecf871387f0b118bec2 100644 --- a/include/transport/transport.h +++ b/include/transport/transport.h @@ -21,40 +21,25 @@ #pragma once #include -#include "Swiften/Server/Server.h" -#include "Swiften/Disco/GetDiscoInfoRequest.h" -#include "Swiften/Disco/EntityCapsManager.h" -#include "Swiften/Disco/CapsManager.h" -#include "Swiften/Disco/CapsMemoryStorage.h" +#include #include "Swiften/Network/BoostTimerFactory.h" #include "Swiften/Network/BoostIOServiceThread.h" -#include "Swiften/Server/UserRegistry.h" -#include "Swiften/Base/SafeByteArray.h" -#include "Swiften/Queries/IQHandler.h" -#include "Swiften/Jingle/JingleSessionManager.h" -#include "Swiften/Component/ComponentError.h" -#include "Swiften/Component/Component.h" -#include "Swiften/Queries/IQHandler.h" - -#include -#include "transport/config.h" -#include "transport/factory.h" -#include "transport/presenceoracle.h" -#include +#include "Swiften/Network/NetworkFactories.h" +#include "Swiften/Elements/DiscoInfo.h" +#include "Swiften/Elements/Presence.h" +#include "Swiften/Elements/IQ.h" namespace Transport { class StorageBackend; class Factory; class UserRegistry; + class Frontend; + class PresenceOracle; + class Factory; + class Config; + class UserManager; - /// Represents one transport instance. - - /// It's used to connect the Jabber server and provides transaction layer - /// between Jabber server and other classes. - /// - /// In server mode it represents Jabber server to which users can connect and use - /// it as transport. - class Component : Swift::IQHandler { + class Component { public: /// Creates new Component instance. @@ -68,32 +53,17 @@ namespace Transport { /// \param factories Swift::NetworkFactories. /// \param factory Transport Abstract factory used to create basic transport structures. /// \param userRegistery UserRegistry class instance. It's needed only when running transport in server-mode. - Component(Swift::EventLoop *loop, Swift::NetworkFactories *factories, Config *config, Factory *factory, Transport::UserRegistry *userRegistry = NULL); + Component(Frontend *frontend, Swift::EventLoop *loop, Swift::NetworkFactories *factories, Config *config, Factory *factory, Transport::UserRegistry *userRegistry = NULL); /// Component destructor. ~Component(); /// Returns Swift::StanzaChannel associated with this Transport::Component. - /// It can be used to send presences and other stanzas. - /// \return Swift::StanzaChannel associated with this Transport::Component. - Swift::StanzaChannel *getStanzaChannel(); - - /// Returns Swift::IQRouter associated with this Component. - - /// \return Swift::IQRouter associated with this Component. - Swift::IQRouter *getIQRouter() { return m_iqRouter; } - - /// Returns Swift::PresenceOracle associated with this Transport::Component. - - /// You can use it to check current resource connected for particular user. - /// \return Swift::PresenceOracle associated with this Transport::Component. - PresenceOracle *getPresenceOracle(); - /// Returns True if the component is in server mode. /// \return True if the component is in server mode. - bool inServerMode() { return m_server != NULL; } + bool inServerMode(); /// Starts the Component. @@ -122,24 +92,18 @@ namespace Transport { /// This signal is emitted when server disconnects the transport because of some error. /// \param error disconnection error - boost::signal onConnectionError; + boost::signal onConnectionError; /// This signal is emitted when transport successfully connects the server. boost::signal onConnected; /// This signal is emitted when XML stanza is sent to server. - /// \param xml xml stanza - boost::signal onXMLOut; - - /// This signal is emitted when XML stanza is received from server. - - /// \param xml xml stanza - boost::signal onXMLIn; - Config *getConfig() { return m_config; } - /// This signal is emitted when presence from XMPP user is received. + bool isRawXMLEnabled() { + return m_rawXML; + } /// It's emitted only for presences addressed to transport itself /// (for example to="j2j.domain.tld") and for presences comming to @@ -147,52 +111,39 @@ namespace Transport { /// \param presence Presence. boost::signal onUserPresenceReceived; - /// Component class asks the XMPP clients automatically for their capabilities. - /// This signal is emitted when capabilities have been received or changed. - /// \param jid JID of the client for which we received capabilities - /// \param info disco#info with response. - boost::signal info)> onUserDiscoInfoReceived; - boost::signal)> onRawIQReceived; + + void handlePresence(Swift::Presence::ref presence); + void handleConnected(); + void handleConnectionError(const std::string &error); + void handleDataRead(const std::string &data); + void handleDataWritten(const std::string &data); - bool isRawXMLEnabled() { - return m_rawXML; + Frontend *getFrontend() { + return m_frontend; } - private: - void handleConnected(); - void handleConnectionError(const Swift::ComponentError &error); - void handleServerStopped(boost::optional e); - void handlePresence(Swift::Presence::ref presence); - void handleDataRead(const Swift::SafeByteArray &data); - void handleDataWritten(const Swift::SafeByteArray &data); + PresenceOracle *getPresenceOracle(); + private: void handleDiscoInfoResponse(boost::shared_ptr info, Swift::ErrorPayload::ref error, const Swift::JID& jid); void handleCapsChanged(const Swift::JID& jid); void handleBackendConfigChanged(); - bool handleIQ(boost::shared_ptr); Swift::NetworkFactories *m_factories; - Swift::Component *m_component; - Swift::Server *m_server; Swift::Timer::ref m_reconnectTimer; - Swift::EntityCapsManager *m_entityCapsManager; - Swift::CapsManager *m_capsManager; - Swift::CapsMemoryStorage *m_capsMemoryStorage; PresenceOracle *m_presenceOracle; - Swift::StanzaChannel *m_stanzaChannel; - Swift::IQRouter *m_iqRouter; Transport::UserRegistry *m_userRegistry; StorageBackend *m_storageBackend; int m_reconnectCount; Config* m_config; - std::string m_protocol; Swift::JID m_jid; Factory *m_factory; Swift::EventLoop *m_loop; bool m_rawXML; + Frontend *m_frontend; friend class User; friend class UserRegistration; diff --git a/include/transport/user.h b/include/transport/user.h index ad2591426c5a3ae8ac420039d7f8899cb8d08fb8..1f3c2a03a2b6cdbb35f22c1aa03de0211e2b483d 100644 --- a/include/transport/user.h +++ b/include/transport/user.h @@ -39,7 +39,7 @@ class PresenceOracle; struct UserInfo; /// Represents online XMPP user. -class User : public Swift::EntityCapsProvider { +class User { public: /// Creates new User class. /// \param jid XMPP JID associated with this user @@ -60,7 +60,7 @@ class User : public Swift::EntityCapsProvider { /// \return full JID which supports particular feature or invalid JID. std::vector getJIDWithFeature(const std::string &feature); - Swift::DiscoInfo::ref getCaps(const Swift::JID &jid) const; +// Swift::DiscoInfo::ref getCaps(const Swift::JID &jid) const; /// Returns UserInfo struct with informations needed to connect the legacy network. /// \return UserInfo struct @@ -73,6 +73,8 @@ class User : public Swift::EntityCapsProvider { Component *getComponent() { return m_component; } UserManager *getUserManager() { return m_userManager; } + + virtual void disconnectUser(const std::string &error, Swift::SpectrumErrorPayload::Error e) = 0; void setData(void *data) { m_data = data; } void *getData() { return m_data; } @@ -146,7 +148,6 @@ class User : public Swift::EntityCapsProvider { RosterManager *m_rosterManager; UserManager *m_userManager; ConversationManager *m_conversationManager; - Swift::EntityCapsManager *m_entityCapsManager; PresenceOracle *m_presenceOracle; UserInfo m_userInfo; void *m_data; diff --git a/include/transport/usermanager.h b/include/transport/usermanager.h index b0fd7605fbe47edc353e3057beaa2051977e59dc..ccd855e369ba1c3cce8949ba130b9089588457cc 100644 --- a/include/transport/usermanager.h +++ b/include/transport/usermanager.h @@ -27,6 +27,7 @@ #include "Swiften/Elements/Presence.h" #include "Swiften/Disco/EntityCapsProvider.h" #include "Swiften/Elements/DiscoInfo.h" +#include "Swiften/Elements/VCard.h" #include "Swiften/Network/Timer.h" namespace Transport { @@ -36,7 +37,7 @@ class Component; class StorageBackend; class StorageResponder; class RosterResponder; -class DiscoItemsResponder; +class UserRegistration; /// Manages online XMPP Users. @@ -55,15 +56,19 @@ class DiscoItemsResponder; UserManager->User [label="handlePresence(...)", URL="\ref User::handlePresence()"]; \endmsc */ -class UserManager : public Swift::EntityCapsProvider { +class UserManager /*: public Swift::EntityCapsProvider*/ { public: /// Creates new UserManager. /// \param component Component which's presence will be handled /// \param storageBackend Storage backend used to fetch UserInfos - UserManager(Component *component, UserRegistry *userRegistry, DiscoItemsResponder *discoItemsResponder, StorageBackend *storageBackend = NULL); + UserManager(Component *component, UserRegistry *userRegistry, StorageBackend *storageBackend = NULL); /// Destroys UserManager. - ~UserManager(); + virtual ~UserManager(); + + virtual void sendVCard(unsigned int id, Swift::VCard::ref vcard) = 0; + + virtual UserRegistration *getUserRegistration() = 0; /// Returns user according to his bare JID. /// \param barejid bare JID of user @@ -87,9 +92,7 @@ class UserManager : public Swift::EntityCapsProvider { void removeAllUsers(bool onUserBehalf = true); - Swift::DiscoInfo::ref getCaps(const Swift::JID&) const; - - DiscoItemsResponder *getDiscoResponder() { return m_discoItemsResponder; } +// Swift::DiscoInfo::ref getCaps(const Swift::JID&) const; /// Called when new User class is created. /// \param user newly created User class @@ -152,7 +155,6 @@ class UserManager : public Swift::EntityCapsProvider { Swift::Timer::ref m_removeTimer; unsigned long m_sentToXMPP; unsigned long m_sentToBackend; - DiscoItemsResponder *m_discoItemsResponder; friend class RosterResponder; }; diff --git a/include/transport/userregistration.h b/include/transport/userregistration.h index e6e614b9304741e4d540025ef178b07a74c14fdc..b4c5a13fef7bdab61ea2e93009e715f56f8148be 100644 --- a/include/transport/userregistration.h +++ b/include/transport/userregistration.h @@ -36,7 +36,7 @@ class UserManager; class Config; /// Allows users to register the transport using service discovery. -class UserRegistration : public Swift::Responder { +class UserRegistration { public: /// Creates new UserRegistration handler. /// \param component Component associated with this class @@ -45,7 +45,7 @@ class UserRegistration : public Swift::Responder onUserRegistered; @@ -71,14 +82,6 @@ class UserRegistration : public Swift::Responder onUserUpdated; private: - virtual bool handleGetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr payload); - virtual bool handleSetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr payload); - - void handleRegisterRemoteRosterResponse(boost::shared_ptr payload, Swift::ErrorPayload::ref error, const UserInfo &row); - void handleUnregisterRemoteRosterResponse(boost::shared_ptr payload, Swift::ErrorPayload::ref error, const std::string &barejid); - boost::shared_ptr generateInBandRegistrationPayload(const Swift::JID& from); - Swift::Form::ref generateRegistrationForm(const UserInfo &res, bool registered); - Component *m_component; StorageBackend *m_storageBackend; UserManager *m_userManager; diff --git a/spectrum/src/CMakeLists.txt b/spectrum/src/CMakeLists.txt index eb62ae98d8da96f8e6df4acb04331b3a24e1ba6c..ac497bb2cca118eccbf64bbc6a16206eba586742 100644 --- a/spectrum/src/CMakeLists.txt +++ b/spectrum/src/CMakeLists.txt @@ -1,5 +1,6 @@ cmake_minimum_required(VERSION 2.6) -FILE(GLOB SRC *.cpp) +FILE(GLOB_RECURSE SRC frontends/*.cpp main.cpp) +include_directories(frontends/xmpp) if (WIN32) FILE(GLOB WIN_SRC win32/*.cpp) diff --git a/src/BlockParser.cpp b/spectrum/src/frontends/xmpp/BlockParser.cpp similarity index 94% rename from src/BlockParser.cpp rename to spectrum/src/frontends/xmpp/BlockParser.cpp index 71d7287b9fe70d5cb3b4e33807dd133c2c363da7..a2c91195ab89d04f5f4f8ccbed1a982d807bb699 100644 --- a/src/BlockParser.cpp +++ b/spectrum/src/frontends/xmpp/BlockParser.cpp @@ -4,7 +4,7 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ -#include +#include namespace Transport { diff --git a/include/transport/BlockParser.h b/spectrum/src/frontends/xmpp/BlockParser.h similarity index 95% rename from include/transport/BlockParser.h rename to spectrum/src/frontends/xmpp/BlockParser.h index bf9c544b2dfeb851780f69f4d0795ee5b53ff968..b8fb343bef6c01a5b738f6baf651d5d31d50204f 100644 --- a/include/transport/BlockParser.h +++ b/spectrum/src/frontends/xmpp/BlockParser.h @@ -6,7 +6,7 @@ #pragma once -#include +#include #include // This payload is NOT part of ANY XEP and it is only diff --git a/src/BlockPayload.cpp b/spectrum/src/frontends/xmpp/BlockPayload.cpp similarity index 89% rename from src/BlockPayload.cpp rename to spectrum/src/frontends/xmpp/BlockPayload.cpp index bc44712c3dd883f31a3d9b17dff53fef5b6c9384..5879a32fa11ab6f4732f759b5ba9c628da525bc3 100644 --- a/src/BlockPayload.cpp +++ b/spectrum/src/frontends/xmpp/BlockPayload.cpp @@ -4,7 +4,7 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ -#include +#include namespace Transport { diff --git a/include/transport/BlockPayload.h b/spectrum/src/frontends/xmpp/BlockPayload.h similarity index 100% rename from include/transport/BlockPayload.h rename to spectrum/src/frontends/xmpp/BlockPayload.h diff --git a/src/BlockSerializer.cpp b/spectrum/src/frontends/xmpp/BlockSerializer.cpp similarity index 95% rename from src/BlockSerializer.cpp rename to spectrum/src/frontends/xmpp/BlockSerializer.cpp index 0a28bc85c5300e12805d1d1c9e30ff2d01ec30ef..8cbc02b7b38a0453310a48afe8365d155c9b2359 100644 --- a/src/BlockSerializer.cpp +++ b/spectrum/src/frontends/xmpp/BlockSerializer.cpp @@ -4,7 +4,7 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ -#include +#include #include diff --git a/include/transport/BlockSerializer.h b/spectrum/src/frontends/xmpp/BlockSerializer.h similarity index 93% rename from include/transport/BlockSerializer.h rename to spectrum/src/frontends/xmpp/BlockSerializer.h index 6f2e4fe835f8ee7130ca0e9ce8f2060b05412519..928e6e1a8e87604f29ac8f9d50394b8f36c4c300 100644 --- a/include/transport/BlockSerializer.h +++ b/spectrum/src/frontends/xmpp/BlockSerializer.h @@ -7,7 +7,7 @@ #pragma once #include -#include +#include // This payload is NOT part of ANY XEP and it is only // libtransport related extension. diff --git a/spectrum/src/frontends/xmpp/XMPPFrontend.cpp b/spectrum/src/frontends/xmpp/XMPPFrontend.cpp new file mode 100644 index 0000000000000000000000000000000000000000..54b1a08aac5eee6d6839ff637d73b7b3b8bba643 --- /dev/null +++ b/spectrum/src/frontends/xmpp/XMPPFrontend.cpp @@ -0,0 +1,390 @@ +/** + * libtransport -- C++ library for easy XMPP Transports development + * + * Copyright (C) 2011, Jan Kaluza + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ + +#include "XMPPFrontend.h" +#include "XMPPRosterManager.h" +#include "XMPPUser.h" +#include "XMPPUserManager.h" +#include "transport/storagebackend.h" +#include +#include +#include +#include "transport/storagebackend.h" +#include "transport/factory.h" +#include "transport/userregistry.h" +#include "transport/logging.h" +#include "transport/config.h" +#include "discoitemsresponder.h" +#include "storageparser.h" +#ifdef _WIN32 +#include +#include "Swiften/TLS/Schannel/SchannelServerContext.h" +#include "Swiften/TLS/Schannel/SchannelServerContextFactory.h" +#else +#include "Swiften/TLS/PKCS12Certificate.h" +#include "Swiften/TLS/CertificateWithKey.h" +#include "Swiften/TLS/OpenSSL/OpenSSLServerContext.h" +#include "Swiften/TLS/OpenSSL/OpenSSLServerContextFactory.h" +#endif +#include "Swiften/Parser/PayloadParsers/AttentionParser.h" +#include "Swiften/Serializer/PayloadSerializers/AttentionSerializer.h" +#include "Swiften/Parser/PayloadParsers/XHTMLIMParser.h" +#include "Swiften/Serializer/PayloadSerializers/XHTMLIMSerializer.h" +#include "Swiften/Parser/PayloadParsers/StatsParser.h" +#include "Swiften/Serializer/PayloadSerializers/StatsSerializer.h" +#include "Swiften/Parser/PayloadParsers/GatewayPayloadParser.h" +#include "Swiften/Serializer/PayloadSerializers/GatewayPayloadSerializer.h" +#include "Swiften/Serializer/PayloadSerializers/SpectrumErrorSerializer.h" +#include "Swiften/Parser/PayloadParsers/MUCPayloadParser.h" +#include "BlockParser.h" +#include "BlockSerializer.h" +#include "Swiften/Parser/PayloadParsers/InvisibleParser.h" +#include "Swiften/Serializer/PayloadSerializers/InvisibleSerializer.h" +#include "Swiften/Parser/GenericPayloadParserFactory.h" +#include "Swiften/Queries/IQRouter.h" +#include "Swiften/Elements/RosterPayload.h" +#include "Swiften/Elements/InBandRegistrationPayload.h" + +using namespace Swift; +using namespace boost; + +namespace Transport { + +DEFINE_LOGGER(logger, "XMPPFrontend"); + +XMPPFrontend::XMPPFrontend() { +} + +void XMPPFrontend::init(Component *transport, Swift::EventLoop *loop, Swift::NetworkFactories *factories, Config *config, Transport::UserRegistry *userRegistry) { + m_transport = transport; + m_component = NULL; + m_server = NULL; + m_rawXML = false; + m_config = transport->getConfig(); + m_jid = Swift::JID(CONFIG_STRING(m_config, "service.jid")); + + m_config->onBackendConfigUpdated.connect(boost::bind(&XMPPFrontend::handleBackendConfigChanged, this)); + + if (CONFIG_BOOL(m_config, "service.server_mode")) { + LOG4CXX_INFO(logger, "Creating component in server mode on port " << CONFIG_INT(m_config, "service.port")); + m_server = new Swift::Server(loop, factories, userRegistry, m_jid, CONFIG_STRING(m_config, "service.server"), CONFIG_INT(m_config, "service.port")); + if (!CONFIG_STRING(m_config, "service.cert").empty()) { +#ifndef _WIN32 +//TODO: fix + LOG4CXX_INFO(logger, "Using PKCS#12 certificate " << CONFIG_STRING(m_config, "service.cert")); + LOG4CXX_INFO(logger, "SSLv23_server_method used."); + TLSServerContextFactory *f = new OpenSSLServerContextFactory(); + CertificateWithKey::ref certificate = boost::make_shared(CONFIG_STRING(m_config, "service.cert"), createSafeByteArray(CONFIG_STRING(m_config, "service.cert_password"))); + m_server->addTLSEncryption(f, certificate); +#endif + + } + else { + LOG4CXX_WARN(logger, "No PKCS#12 certificate used. TLS is disabled."); + } +// m_server->start(); + m_stanzaChannel = m_server->getStanzaChannel(); + m_iqRouter = m_server->getIQRouter(); + + m_server->addPayloadParserFactory(new GenericPayloadParserFactory("private", "jabber:iq:private")); + m_server->addPayloadParserFactory(new GenericPayloadParserFactory("attention", "urn:xmpp:attention:0")); + m_server->addPayloadParserFactory(new GenericPayloadParserFactory("html", "http://jabber.org/protocol/xhtml-im")); + m_server->addPayloadParserFactory(new GenericPayloadParserFactory("block", "urn:xmpp:block:0")); + m_server->addPayloadParserFactory(new GenericPayloadParserFactory("invisible", "urn:xmpp:invisible:0")); + m_server->addPayloadParserFactory(new GenericPayloadParserFactory("query", "http://jabber.org/protocol/stats")); + m_server->addPayloadParserFactory(new GenericPayloadParserFactory("query", "jabber:iq:gateway")); + m_server->addPayloadParserFactory(new GenericPayloadParserFactory("x", "http://jabber.org/protocol/muc")); + + m_server->addPayloadSerializer(new Swift::AttentionSerializer()); + m_server->addPayloadSerializer(new Swift::XHTMLIMSerializer()); + m_server->addPayloadSerializer(new Transport::BlockSerializer()); + m_server->addPayloadSerializer(new Swift::InvisibleSerializer()); + m_server->addPayloadSerializer(new Swift::StatsSerializer()); + m_server->addPayloadSerializer(new Swift::SpectrumErrorSerializer()); + m_server->addPayloadSerializer(new Swift::GatewayPayloadSerializer()); + + m_server->onDataRead.connect(boost::bind(&XMPPFrontend::handleDataRead, this, _1)); + m_server->onDataWritten.connect(boost::bind(&XMPPFrontend::handleDataWritten, this, _1)); + } + else { + LOG4CXX_INFO(logger, "Creating component in gateway mode"); +#if HAVE_SWIFTEN_3 + m_component = new Swift::Component(m_jid, CONFIG_STRING(m_config, "service.password"), factories); +#else + m_component = new Swift::Component(loop, factories, m_jid, CONFIG_STRING(m_config, "service.password")); +#endif + m_component->setSoftwareVersion("Spectrum", SPECTRUM_VERSION); + m_component->onConnected.connect(bind(&XMPPFrontend::handleConnected, this)); + m_component->onError.connect(boost::bind(&XMPPFrontend::handleConnectionError, this, _1)); + m_component->onDataRead.connect(boost::bind(&XMPPFrontend::handleDataRead, this, _1)); + m_component->onDataWritten.connect(boost::bind(&XMPPFrontend::handleDataWritten, this, _1)); + + m_component->addPayloadParserFactory(new GenericPayloadParserFactory("private", "jabber:iq:private")); + m_component->addPayloadParserFactory(new GenericPayloadParserFactory("attention", "urn:xmpp:attention:0")); + m_component->addPayloadParserFactory(new GenericPayloadParserFactory("html", "http://jabber.org/protocol/xhtml-im")); + m_component->addPayloadParserFactory(new GenericPayloadParserFactory("block", "urn:xmpp:block:0")); + m_component->addPayloadParserFactory(new GenericPayloadParserFactory("invisible", "urn:xmpp:invisible:0")); + m_component->addPayloadParserFactory(new GenericPayloadParserFactory("query", "http://jabber.org/protocol/stats")); + m_component->addPayloadParserFactory(new GenericPayloadParserFactory("query", "jabber:iq:gateway")); + m_component->addPayloadParserFactory(new GenericPayloadParserFactory("x", "http://jabber.org/protocol/muc")); + + m_component->addPayloadSerializer(new Swift::AttentionSerializer()); + m_component->addPayloadSerializer(new Swift::XHTMLIMSerializer()); + m_component->addPayloadSerializer(new Transport::BlockSerializer()); + m_component->addPayloadSerializer(new Swift::InvisibleSerializer()); + m_component->addPayloadSerializer(new Swift::StatsSerializer()); + m_component->addPayloadSerializer(new Swift::SpectrumErrorSerializer()); + m_component->addPayloadSerializer(new Swift::GatewayPayloadSerializer()); + + m_stanzaChannel = m_component->getStanzaChannel(); + m_iqRouter = m_component->getIQRouter(); + } + + m_capsMemoryStorage = new CapsMemoryStorage(); +#if HAVE_SWIFTEN_3 + m_capsManager = new CapsManager(m_capsMemoryStorage, m_stanzaChannel, m_iqRouter, factories->getCryptoProvider()); +#else + m_capsManager = new CapsManager(m_capsMemoryStorage, m_stanzaChannel, m_iqRouter); +#endif + m_entityCapsManager = new EntityCapsManager(m_capsManager, m_stanzaChannel); + m_entityCapsManager->onCapsChanged.connect(boost::bind(&XMPPFrontend::handleCapsChanged, this, _1)); + + m_stanzaChannel->onPresenceReceived.connect(bind(&XMPPFrontend::handleGeneralPresence, this, _1)); + m_stanzaChannel->onMessageReceived.connect(bind(&XMPPFrontend::handleMessage, this, _1)); + + m_discoItemsResponder = new DiscoItemsResponder(transport); + m_discoItemsResponder->start(); +} + +XMPPFrontend::~XMPPFrontend() { + delete m_entityCapsManager; + delete m_capsManager; + delete m_capsMemoryStorage; + if (m_component) + delete m_component; + if (m_server) { + m_server->stop(); + delete m_server; + } +} + +void XMPPFrontend::handleGeneralPresence(Swift::Presence::ref presence) { + onPresenceReceived(presence); +} + +void XMPPFrontend::handleMessage(boost::shared_ptr message) { + onMessageReceived(message); +} + + +void XMPPFrontend::clearRoomList() { + m_discoItemsResponder->clearRooms(); +} + +void XMPPFrontend::addRoomToRoomList(const std::string &handle, const std::string &name) { + m_discoItemsResponder->addRoom(handle, name); +} + +void XMPPFrontend::sendPresence(Swift::Presence::ref presence) { + if (!presence->getFrom().getNode().empty()) { + presence->addPayload(boost::shared_ptr(new Swift::CapsInfo(m_discoItemsResponder->getBuddyCapsInfo()))); + } + + m_stanzaChannel->sendPresence(presence); +} + +void XMPPFrontend::sendVCard(Swift::VCard::ref vcard, Swift::JID to) { + boost::shared_ptr > request(new Swift::GenericRequest(Swift::IQ::Result, to, vcard, m_iqRouter)); + request->send(); +} + +void XMPPFrontend::sendRosterRequest(Swift::RosterPayload::ref payload, Swift::JID to) { + Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(payload, to, m_iqRouter); + request->send(); +} + +void XMPPFrontend::sendMessage(boost::shared_ptr message) { + m_stanzaChannel->sendMessage(message); +} + +void XMPPFrontend::sendIQ(boost::shared_ptr iq) { + m_iqRouter->sendIQ(iq); +} + +boost::shared_ptr XMPPFrontend::sendCapabilitiesRequest(Swift::JID to) { + Swift::DiscoInfo::ref caps = m_entityCapsManager->getCaps(to); + if (caps != Swift::DiscoInfo::ref()) { + onCapabilitiesReceived(to, caps); + return caps; + } +#ifdef SUPPORT_LEGACY_CAPS + else { + GetDiscoInfoRequest::ref discoInfoRequest = GetDiscoInfoRequest::create(to, m_iqRouter); + discoInfoRequest->onResponse.connect(boost::bind(&XMPPFrontend::handleDiscoInfoResponse, this, _1, _2, to)); + discoInfoRequest->send(); + } +#endif + + return Swift::DiscoInfo::ref(); +} + +void XMPPFrontend::reconnectUser(const std::string &user) { + LOG4CXX_INFO(logger, "Sending probe presence to " << user); + Swift::Presence::ref response = Swift::Presence::create(); + try { + response->setTo(user); + } + catch (...) { return; } + + response->setFrom(m_component->getJID()); + response->setType(Swift::Presence::Probe); + + m_stanzaChannel->sendPresence(response); +} + +RosterManager *XMPPFrontend::createRosterManager(User *user, Component *component) { + return new XMPPRosterManager(user, component); +} + +User *XMPPFrontend::createUser(const Swift::JID &jid, UserInfo &userInfo, Component *component, UserManager *userManager) { + return new XMPPUser(jid, userInfo, component, userManager); +} + +UserManager *XMPPFrontend::createUserManager(Component *component, UserRegistry *userRegistry, StorageBackend *storageBackend) { + return new XMPPUserManager(component, userRegistry, storageBackend); +} + +bool XMPPFrontend::handleIQ(boost::shared_ptr iq) { + if (!m_rawXML) { + return false; + } + + if (iq->getPayload() != NULL) { return false; } + if (iq->getPayload() != NULL) { return false; } + if (iq->getPayload() != NULL) { return false; } + + if (iq->getTo().getNode().empty()) { + return false; + } + + m_transport->onRawIQReceived(iq); + return true; +} + +void XMPPFrontend::handleBackendConfigChanged() { + if (!m_rawXML && CONFIG_BOOL_DEFAULTED(m_config, "features.rawxml", false)) { + m_rawXML = true; + m_iqRouter->addHandler(this); + } +} + +Swift::StanzaChannel *XMPPFrontend::getStanzaChannel() { + return m_stanzaChannel; +} + +void XMPPFrontend::connectToServer() { + if (m_component && !m_component->isAvailable()) { + LOG4CXX_INFO(logger, "Connecting XMPP server " << CONFIG_STRING(m_config, "service.server") << " port " << CONFIG_INT(m_config, "service.port")); + if (CONFIG_INT(m_config, "service.port") == 5222) { + LOG4CXX_WARN(logger, "Port 5222 is usually used for client connections, not for component connections! Are you sure you are using right port?"); + } + m_component->connect(CONFIG_STRING(m_config, "service.server"), CONFIG_INT(m_config, "service.port")); + } + else if (m_server) { + LOG4CXX_INFO(logger, "Starting XMPPFrontend in server mode on port " << CONFIG_INT(m_config, "service.port")); + m_server->start(); + + //Type casting to BoostConnectionServer since onStopped signal is not defined in ConnectionServer + //Ideally, onStopped must be defined in ConnectionServer + if (boost::dynamic_pointer_cast(m_server->getConnectionServer())) { + boost::dynamic_pointer_cast(m_server->getConnectionServer())->onStopped.connect(boost::bind(&XMPPFrontend::handleServerStopped, this, _1)); + } + + // We're connected right here, because we're in server mode... + handleConnected(); + } +} + +void XMPPFrontend::disconnectFromServer() { + if (m_component) { + // TODO: Call this once swiften will fix assert(!session_); +// m_component->disconnect(); + } + else if (m_server) { + LOG4CXX_INFO(logger, "Stopping component in server mode on port " << CONFIG_INT(m_config, "service.port")); + m_server->stop(); + } +} + +void XMPPFrontend::handleConnected() { + m_transport->handleConnected(); +} + +void XMPPFrontend::handleServerStopped(boost::optional e) { + if(e != NULL ) { + if(*e == Swift::BoostConnectionServer::Conflict) { + LOG4CXX_INFO(logger, "Port "<< CONFIG_INT(m_config, "service.port") << " already in use! Stopping server.."); + if (CONFIG_INT(m_config, "service.port") == 5347) { + LOG4CXX_INFO(logger, "Port 5347 is usually used for components. You are using server_mode=1. Are you sure you don't want to use server_mode=0 and run spectrum as component?"); + } + } + if(*e == Swift::BoostConnectionServer::UnknownError) + LOG4CXX_INFO(logger, "Unknown error occured! Stopping server.."); + exit(1); + } +} + + +void XMPPFrontend::handleConnectionError(const ComponentError &error) { + std::string str = "Unknown error"; + switch (error.getType()) { + case ComponentError::UnknownError: str = "Unknown error"; break; + case ComponentError::ConnectionError: str = "Connection error"; break; + case ComponentError::ConnectionReadError: str = "Connection read error"; break; + case ComponentError::ConnectionWriteError: str = "Connection write error"; break; + case ComponentError::XMLError: str = "XML Error"; break; + case ComponentError::AuthenticationFailedError: str = "Authentication failed error"; break; + case ComponentError::UnexpectedElementError: str = "Unexpected element error"; break; + } + + m_transport->handleConnectionError(str); +} + +void XMPPFrontend::handleDataRead(const Swift::SafeByteArray &data) { + std::string d = safeByteArrayToString(data); + m_transport->handleDataRead(d); +} + +void XMPPFrontend::handleDataWritten(const Swift::SafeByteArray &data) { + std::string d = safeByteArrayToString(data); + m_transport->handleDataWritten(d); +} + +void XMPPFrontend::handleDiscoInfoResponse(boost::shared_ptr info, Swift::ErrorPayload::ref error, const Swift::JID& jid) { +#ifdef SUPPORT_LEGACY_CAPS + onCapabilitiesReceived(jid, info); +#endif +} + +void XMPPFrontend::handleCapsChanged(const Swift::JID& jid) { + onCapabilitiesReceived(jid, m_entityCapsManager->getCaps(jid)); +} + +} diff --git a/spectrum/src/frontends/xmpp/XMPPFrontend.h b/spectrum/src/frontends/xmpp/XMPPFrontend.h new file mode 100644 index 0000000000000000000000000000000000000000..0516ab093acb2890812e768ad220f36b03f3d90f --- /dev/null +++ b/spectrum/src/frontends/xmpp/XMPPFrontend.h @@ -0,0 +1,133 @@ +/** + * libtransport -- C++ library for easy XMPP Transports development + * + * Copyright (C) 2011, Jan Kaluza + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ + +#pragma once + +#include +#include "transport/frontend.h" +#include "Swiften/Server/Server.h" +#include "Swiften/Disco/GetDiscoInfoRequest.h" +#include "Swiften/Disco/EntityCapsManager.h" +#include "Swiften/Disco/CapsManager.h" +#include "Swiften/Disco/CapsMemoryStorage.h" +#include "Swiften/Network/BoostTimerFactory.h" +#include "Swiften/Network/BoostIOServiceThread.h" +#include "Swiften/Server/UserRegistry.h" +#include "Swiften/Base/SafeByteArray.h" +#include "Swiften/Queries/IQHandler.h" +#include "Swiften/Component/ComponentError.h" +#include "Swiften/Component/Component.h" +#include "Swiften/Queries/IQHandler.h" +#include "Swiften/Elements/Presence.h" + +#include +#include + +namespace Transport { + class UserRegistry; + class Frontend; + class Config; + class DiscoItemsResponder; + class VCardResponder; + + class XMPPFrontend : public Frontend, Swift::IQHandler { + public: + XMPPFrontend(); + + virtual ~XMPPFrontend(); + + virtual void init(Component *component, Swift::EventLoop *loop, Swift::NetworkFactories *factories, Config *config, UserRegistry *userRegistry); + + virtual void connectToServer(); + + virtual void disconnectFromServer(); + + virtual void sendPresence(Swift::Presence::ref presence); + + virtual void sendVCard(Swift::VCard::ref vcard, Swift::JID to); + + virtual void sendRosterRequest(Swift::RosterPayload::ref, Swift::JID to); + + virtual void sendMessage(boost::shared_ptr message); + + virtual void sendIQ(boost::shared_ptr); + + virtual void reconnectUser(const std::string &user); + + virtual RosterManager *createRosterManager(User *user, Component *component); + virtual User *createUser(const Swift::JID &jid, UserInfo &userInfo, Component *component, UserManager *userManager); + virtual UserManager *createUserManager(Component *component, UserRegistry *userRegistry, StorageBackend *storageBackend = NULL); + virtual boost::shared_ptr sendCapabilitiesRequest(Swift::JID to); + virtual void clearRoomList(); + virtual void addRoomToRoomList(const std::string &handle, const std::string &name); + + void handleMessage(boost::shared_ptr message); + + + Swift::StanzaChannel *getStanzaChannel(); + + Swift::IQRouter *getIQRouter() { return m_iqRouter; } + + + bool inServerMode() { return m_server != NULL; } + + bool isRawXMLEnabled() { + return m_rawXML; + } + + DiscoItemsResponder *getDiscoItemsResponder() { + return m_discoItemsResponder; + } + + private: + void handleConnected(); + void handleConnectionError(const Swift::ComponentError &error); + void handleServerStopped(boost::optional e); + void handleGeneralPresence(Swift::Presence::ref presence); + void handleDataRead(const Swift::SafeByteArray &data); + void handleDataWritten(const Swift::SafeByteArray &data); + + void handleDiscoInfoResponse(boost::shared_ptr info, Swift::ErrorPayload::ref error, const Swift::JID& jid); + void handleCapsChanged(const Swift::JID& jid); + + void handleBackendConfigChanged(); + bool handleIQ(boost::shared_ptr); + + Swift::NetworkFactories *m_factories; + Swift::Component *m_component; + Swift::Server *m_server; + Swift::EntityCapsManager *m_entityCapsManager; + Swift::CapsManager *m_capsManager; + Swift::CapsMemoryStorage *m_capsMemoryStorage; + Swift::StanzaChannel *m_stanzaChannel; + Swift::IQRouter *m_iqRouter; + DiscoItemsResponder *m_discoItemsResponder; + VCardResponder *m_vcardResponder; + + Config* m_config; + Swift::JID m_jid; + bool m_rawXML; + Component *m_transport; + + friend class XMPPUser; + friend class UserRegistration; + friend class NetworkPluginServer; + }; +} diff --git a/spectrum/src/frontends/xmpp/XMPPRosterManager.cpp b/spectrum/src/frontends/xmpp/XMPPRosterManager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..eb063d2a1e473a72c0525e78867a4314d535736f --- /dev/null +++ b/spectrum/src/frontends/xmpp/XMPPRosterManager.cpp @@ -0,0 +1,288 @@ +/** + * XMPP - libpurple transport + * + * Copyright (C) 2009, Jan Kaluza + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ + +#include "XMPPRosterManager.h" +#include "XMPPFrontend.h" +#include "XMPPUser.h" +#include "transport/rostermanager.h" +#include "transport/rosterstorage.h" +#include "transport/storagebackend.h" +#include "transport/buddy.h" +#include "transport/usermanager.h" +#include "transport/buddy.h" +#include "transport/user.h" +#include "transport/logging.h" +#include "transport/factory.h" +#include "transport/presenceoracle.h" +#include "Swiften/Roster/SetRosterRequest.h" +#include "Swiften/Elements/RosterPayload.h" +#include "Swiften/Elements/RosterItemPayload.h" +#include "Swiften/Elements/RosterItemExchangePayload.h" +#include "Swiften/Elements/Nickname.h" +#include "Swiften/Queries/IQRouter.h" +#include +#include + +#include +#include + +namespace Transport { + +DEFINE_LOGGER(logger, "XMPPRosterManager"); + +XMPPRosterManager::XMPPRosterManager(User *user, Component *component) : RosterManager(user, component){ + m_user = user; + m_component = component; + + m_supportRemoteRoster = false; + m_RIETimer = m_component->getNetworkFactories()->getTimerFactory()->createTimer(5000); + m_RIETimer->onTick.connect(boost::bind(&XMPPRosterManager::sendRIE, this)); + + if (!m_component->inServerMode()) { + m_remoteRosterRequest = AddressedRosterRequest::ref(new AddressedRosterRequest(static_cast(m_component->getFrontend())->getIQRouter(), m_user->getJID().toBare())); + m_remoteRosterRequest->onResponse.connect(boost::bind(&XMPPRosterManager::handleRemoteRosterResponse, this, _1, _2)); + m_remoteRosterRequest->send(); + } +} + +XMPPRosterManager::~XMPPRosterManager() { + m_RIETimer->stop(); + if (m_remoteRosterRequest) { + m_remoteRosterRequest->onResponse.disconnect_all_slots(); + static_cast(m_component->getFrontend())->getIQRouter()->removeHandler(m_remoteRosterRequest); + } + + if (m_requests.size() != 0) { + LOG4CXX_INFO(logger, m_user->getJID().toString() << ": Removing " << m_requests.size() << " unresponded IQs"); + BOOST_FOREACH(Swift::SetRosterRequest::ref request, m_requests) { + request->onResponse.disconnect_all_slots(); + static_cast(m_component->getFrontend())->getIQRouter()->removeHandler(request); + } + m_requests.clear(); + } +} + +void XMPPRosterManager::doRemoveBuddy(Buddy *buddy) { + if (m_component->inServerMode() || m_supportRemoteRoster) { + sendBuddyRosterRemove(buddy); + } + else { + sendBuddyUnsubscribePresence(buddy); + } +} + +void XMPPRosterManager::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(), static_cast(m_component->getFrontend())->getIQRouter()); + request->send(); + } + } + else { + Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(p, m_user->getJID().toBare(), static_cast(m_component->getFrontend())->getIQRouter()); + request->send(); + } +} + +void XMPPRosterManager::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) + if (m_component->inServerMode() && (!m_user->isConnected() || m_user->shouldCacheMessages())) + return; + + Swift::RosterPayload::ref payload = Swift::RosterPayload::ref(new Swift::RosterPayload()); + Swift::RosterItemPayload item; + item.setJID(buddy->getJID().toBare()); + item.setName(buddy->getAlias()); + item.setGroups(buddy->getGroups()); + item.setSubscription(Swift::RosterItemPayload::Both); + + payload->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(payload, presence->getFrom(), static_cast(m_component->getFrontend())->getIQRouter()); + request->onResponse.connect(boost::bind(&XMPPRosterManager::handleBuddyRosterPushResponse, this, _1, request, buddy->getName())); + request->send(); + m_requests.push_back(request); + } + } + else { + Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(payload, m_user->getJID().toBare(), static_cast(m_component->getFrontend())->getIQRouter()); + request->onResponse.connect(boost::bind(&XMPPRosterManager::handleBuddyRosterPushResponse, this, _1, request, buddy->getName())); + request->send(); + m_requests.push_back(request); + } + + if (buddy->getSubscription() != Buddy::Both) { + buddy->setSubscription(Buddy::Both); + storeBuddy(buddy); + } +} + + +void XMPPRosterManager::handleBuddyChanged(Buddy *buddy) { +} + +void XMPPRosterManager::doAddBuddy(Buddy *buddy) { + // In server mode the only way is to send jabber:iq:roster push. + // In component mode we send RIE or Subscribe presences, based on features. + if (m_component->inServerMode()) { + sendBuddyRosterPush(buddy); + } + else { + if (buddy->getSubscription() == Buddy::Both) { + LOG4CXX_INFO(logger, m_user->getJID().toString() << ": Not forwarding this buddy, because subscription=both"); + return; + } + + if (m_supportRemoteRoster) { + sendBuddyRosterPush(buddy); + } + else { + m_RIETimer->start(); + } + } +} + +void XMPPRosterManager::doUpdateBuddy(Buddy *buddy) { + if (m_component->inServerMode() || m_supportRemoteRoster) { + sendBuddyRosterPush(buddy); + } +} + +void XMPPRosterManager::handleBuddyRosterPushResponse(Swift::ErrorPayload::ref error, Swift::SetRosterRequest::ref request, const std::string &key) { + LOG4CXX_INFO(logger, "handleBuddyRosterPushResponse called for buddy " << key); + if (m_buddies[key] != NULL) { + if (m_buddies[key]->isAvailable()) { + std::vector &presences = m_buddies[key]->generatePresenceStanzas(255); + BOOST_FOREACH(Swift::Presence::ref &presence, presences) { + m_component->getFrontend()->sendPresence(presence); + } + } + } + else { + LOG4CXX_WARN(logger, "handleBuddyRosterPushResponse called for unknown buddy " << key); + } + + m_requests.remove(request); + request->onResponse.disconnect_all_slots(); +} + +void XMPPRosterManager::handleRemoteRosterResponse(boost::shared_ptr payload, Swift::ErrorPayload::ref error) { + m_remoteRosterRequest.reset(); + if (error) { + m_supportRemoteRoster = false; + LOG4CXX_INFO(logger, m_user->getJID().toString() << ": This server does not support remote roster protoXEP"); + return; + } + + LOG4CXX_INFO(logger, m_user->getJID().toString() << ": This server supports remote roster protoXEP"); + m_supportRemoteRoster = true; + + //If we receive empty RosterPayload on login (not register) initiate full RosterPush + if(!m_buddies.empty() && payload->getItems().empty()){ + LOG4CXX_INFO(logger, "Received empty Roster upon login. Pushing full Roster."); + for(std::map, boost::pool_allocator< std::pair > >::const_iterator c_it = m_buddies.begin(); + c_it != m_buddies.end(); c_it++) { + sendBuddyRosterPush(c_it->second); + } + } + return; + + BOOST_FOREACH(const Swift::RosterItemPayload &item, payload->getItems()) { + std::string legacyName = Buddy::JIDToLegacyName(item.getJID()); + if (m_buddies.find(legacyName) != m_buddies.end()) { + continue; + } + + if (legacyName.empty()) { + continue; + } + + BuddyInfo buddyInfo; + buddyInfo.id = -1; + buddyInfo.alias = item.getName(); + buddyInfo.legacyName = legacyName; + buddyInfo.subscription = "both"; + buddyInfo.flags = Buddy::buddyFlagsFromJID(item.getJID()); + buddyInfo.groups = item.getGroups(); + + Buddy *buddy = m_component->getFactory()->createBuddy(this, buddyInfo); + if (buddy) { + setBuddy(buddy); + } + } +} + + +void XMPPRosterManager::sendRIE() { + m_RIETimer->stop(); + + // Check the feature, because proper resource could logout during RIETimer. + std::vector jidWithRIE = static_cast(m_user)->getJIDWithFeature("http://jabber.org/protocol/rosterx"); + + // fallback to normal subscribe + if (jidWithRIE.empty()) { + for (std::map, boost::pool_allocator< std::pair > >::iterator it = m_buddies.begin(); it != m_buddies.end(); it++) { + Buddy *buddy = (*it).second; + if (!buddy) { + continue; + } + sendBuddySubscribePresence(buddy); + } + return; + } + + Swift::RosterItemExchangePayload::ref payload = Swift::RosterItemExchangePayload::ref(new Swift::RosterItemExchangePayload()); + for (std::map, boost::pool_allocator< std::pair > >::iterator it = m_buddies.begin(); it != m_buddies.end(); it++) { + Buddy *buddy = (*it).second; + if (!buddy) { + continue; + } + Swift::RosterItemExchangePayload::Item item; + item.setJID(buddy->getJID().toBare()); + item.setName(buddy->getAlias()); + item.setAction(Swift::RosterItemExchangePayload::Item::Add); + item.setGroups(buddy->getGroups()); + + payload->addItem(item); + } + + BOOST_FOREACH(Swift::JID &jid, jidWithRIE) { + LOG4CXX_INFO(logger, "Sending RIE stanza to " << jid.toString()); + boost::shared_ptr > request(new Swift::GenericRequest(Swift::IQ::Set, jid, payload, static_cast(m_component->getFrontend())->getIQRouter())); + request->send(); + } +} + + +} diff --git a/spectrum/src/frontends/xmpp/XMPPRosterManager.h b/spectrum/src/frontends/xmpp/XMPPRosterManager.h new file mode 100644 index 0000000000000000000000000000000000000000..6609ec6e5ec1ae43d5bd779eb259df44c054d6bf --- /dev/null +++ b/spectrum/src/frontends/xmpp/XMPPRosterManager.h @@ -0,0 +1,101 @@ +/** + * XMPP - libpurple transport + * + * Copyright (C) 2009, Jan Kaluza + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ + +#pragma once + +#include +#include +#include +#include +#include +// #include "rosterstorage.h" +#include "Swiften/Elements/RosterPayload.h" +#include "Swiften/Queries/GenericRequest.h" +#include "Swiften/Roster/SetRosterRequest.h" +#include "Swiften/Elements/Presence.h" +#include "transport/rostermanager.h" +#include "Swiften/Network/Timer.h" + +namespace Transport { + +class Buddy; +class User; +class Component; +class StorageBackend; +class RosterStorage; + +// TODO: Once Swiften GetRosterRequest will support setting to="", this can be removed +class AddressedRosterRequest : public Swift::GenericRequest { + public: + typedef boost::shared_ptr ref; + + AddressedRosterRequest(Swift::IQRouter* router, Swift::JID to) : + Swift::GenericRequest(Swift::IQ::Get, to, boost::shared_ptr(new Swift::RosterPayload()), router) { + } +}; + +/// Manages roster of one XMPP user. +class XMPPRosterManager : public RosterManager { + public: + typedef std::map, boost::pool_allocator< std::pair > > BuddiesMap; + /// Creates new XMPPRosterManager. + /// \param user User associated with this XMPPRosterManager. + /// \param component Transport instance associated with this roster. + XMPPRosterManager(User *user, Component *component); + + /// Destructor. + virtual ~XMPPRosterManager(); + + virtual void doRemoveBuddy(Buddy *buddy); + virtual void doAddBuddy(Buddy *buddy); + virtual void doUpdateBuddy(Buddy *buddy); + + + + bool isRemoteRosterSupported() { + return m_supportRemoteRoster; + } + + boost::signal onBuddyAdded; + + boost::signal onBuddyRemoved; + + void handleBuddyChanged(Buddy *buddy); + + void sendBuddyRosterPush(Buddy *buddy); + + void sendBuddyRosterRemove(Buddy *buddy); + + private: + void sendRIE(); + void handleBuddyRosterPushResponse(Swift::ErrorPayload::ref error, Swift::SetRosterRequest::ref request, const std::string &key); + void handleRemoteRosterResponse(boost::shared_ptr roster, Swift::ErrorPayload::ref error); + + Component *m_component; + RosterStorage *m_rosterStorage; + User *m_user; + Swift::Timer::ref m_setBuddyTimer; + Swift::Timer::ref m_RIETimer; + std::list m_requests; + bool m_supportRemoteRoster; + AddressedRosterRequest::ref m_remoteRosterRequest; +}; + +} diff --git a/spectrum/src/frontends/xmpp/XMPPUser.cpp b/spectrum/src/frontends/xmpp/XMPPUser.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5a59d97dd9e597866c4cc24597d42b5ea55c387e --- /dev/null +++ b/spectrum/src/frontends/xmpp/XMPPUser.cpp @@ -0,0 +1,80 @@ +/** + * libtransport -- C++ library for easy XMPP Transports development + * + * Copyright (C) 2011, Jan Kaluza + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ + +#include "XMPPUser.h" +#include "XMPPFrontend.h" +#include "transport/user.h" +#include "transport/frontend.h" +#include "transport/transport.h" +#include "transport/rostermanager.h" +#include "transport/usermanager.h" +#include "transport/logging.h" +#include "Swiften/Server/ServerStanzaChannel.h" +#include "Swiften/Elements/StreamError.h" +#include "Swiften/Elements/SpectrumErrorPayload.h" +#include +#include +#include + +using namespace boost; + +#define foreach BOOST_FOREACH + +namespace Transport { + +DEFINE_LOGGER(logger, "XMPPUser"); + +XMPPUser::XMPPUser(const Swift::JID &jid, UserInfo &userInfo, Component *component, UserManager *userManager) : User(jid, userInfo, component, userManager) { + m_jid = jid.toBare(); + + m_component = component; + m_userManager = userManager; + m_userInfo = userInfo; +} + +XMPPUser::~XMPPUser(){ + if (m_component->inServerMode()) { +#if HAVE_SWIFTEN_3 + dynamic_cast(static_cast(m_component->getFrontend())->getStanzaChannel())->finishSession(m_jid, boost::shared_ptr()); +#else + dynamic_cast(static_cast(m_component->getFrontend())->getStanzaChannel())->finishSession(m_jid, boost::shared_ptr()); +#endif + } +} + +void XMPPUser::disconnectUser(const std::string &error, Swift::SpectrumErrorPayload::Error e) { + // In server mode, server finishes the session and pass unavailable session to userManager if we're connected to legacy network, + // so we can't removeUser() in server mode, because it would be removed twice. + // Once in finishSession and once in m_userManager->removeUser. + if (m_component->inServerMode()) { + // Remove user later just to be sure there won't be double-free. + // We can't be sure finishSession sends unavailable presence everytime, so check if user gets removed + // in finishSession(...) call and if not, remove it here. + std::string jid = m_jid.toBare().toString(); +#if HAVE_SWIFTEN_3 + dynamic_cast(static_cast(m_component->getFrontend())->getStanzaChannel())->finishSession(m_jid, boost::shared_ptr(new Swift::StreamError(Swift::StreamError::UndefinedCondition, error))); +#else + dynamic_cast(static_cast(m_component->getFrontend())->getStanzaChannel())->finishSession(m_jid, boost::shared_ptr(new Swift::StreamError(Swift::StreamError::UndefinedCondition, error))); +#endif + } +} + + +} diff --git a/spectrum/src/frontends/xmpp/XMPPUser.h b/spectrum/src/frontends/xmpp/XMPPUser.h new file mode 100644 index 0000000000000000000000000000000000000000..5feb31a8d1de20446bd079ddbe4146e021b13976 --- /dev/null +++ b/spectrum/src/frontends/xmpp/XMPPUser.h @@ -0,0 +1,67 @@ +/** + * libtransport -- C++ library for easy XMPP Transports development + * + * Copyright (C) 2011, Jan Kaluza + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ + +#pragma once + +#include "transport/user.h" +#include +#include "Swiften/Disco/EntityCapsManager.h" +#include "Swiften/Disco/EntityCapsProvider.h" +#include +#include "Swiften/Elements/SpectrumErrorPayload.h" +#include "Swiften/Network/Timer.h" +#include "Swiften/Network/Connection.h" + +namespace Transport { + +class Component; +class RosterManager; +class ConversationManager; +class UserManager; +class PresenceOracle; +struct UserInfo; + +/// Represents online XMPP user. +class XMPPUser : public User { + public: + /// Creates new User class. + /// \param jid XMPP JID associated with this user + /// \param userInfo UserInfo struct with informations needed to connect + /// this user to legacy network + /// \param component Component associated with this user + XMPPUser(const Swift::JID &jid, UserInfo &userInfo, Component * component, UserManager *userManager); + + /// Destroyes User. + virtual ~XMPPUser(); + + void disconnectUser(const std::string &error, Swift::SpectrumErrorPayload::Error e); + + + + private: + void onConnectingTimeout(); + + Swift::JID m_jid; + Component *m_component; + UserManager *m_userManager; + UserInfo m_userInfo; +}; + +} diff --git a/spectrum/src/frontends/xmpp/XMPPUserManager.cpp b/spectrum/src/frontends/xmpp/XMPPUserManager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..eb29633e74cc8fa2fa6fdab4ffb1488b2684aa4a --- /dev/null +++ b/spectrum/src/frontends/xmpp/XMPPUserManager.cpp @@ -0,0 +1,123 @@ +/** + * libtransport -- C++ library for easy XMPP Transports development + * + * Copyright (C) 2011, Jan Kaluza + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ + +#include "XMPPUserManager.h" +#include "XMPPUserRegistration.h" +#include "transport/user.h" +#include "transport/transport.h" +#include "transport/storagebackend.h" +#include "transport/conversationmanager.h" +#include "transport/rostermanager.h" +#include "transport/userregistry.h" +#include "transport/logging.h" +#include "transport/frontend.h" +#include "transport/presenceoracle.h" +#include "storageresponder.h" +#include "vcardresponder.h" +#include "transport/frontend.h" +#include "XMPPFrontend.h" +#include "gatewayresponder.h" +#include "adhocmanager.h" +#include "settingsadhoccommand.h" + +#include "Swiften/Server/ServerStanzaChannel.h" +#include "Swiften/Elements/StreamError.h" +#include "Swiften/Elements/MUCPayload.h" +#include "Swiften/Elements/ChatState.h" +#ifndef __FreeBSD__ +#ifndef __MACH__ +#include "malloc.h" +#endif +#endif +// #include "valgrind/memcheck.h" + +namespace Transport { + +DEFINE_LOGGER(logger, "XMPPUserManager"); + +XMPPUserManager::XMPPUserManager(Component *component, UserRegistry *userRegistry, StorageBackend *storageBackend) : UserManager(component, userRegistry, storageBackend) { + m_component = component; + + XMPPFrontend *frontend = static_cast(component->getFrontend()); + if (storageBackend) { + m_storageResponder = new StorageResponder(frontend->getIQRouter(), storageBackend, this); + m_storageResponder->start(); + } + + m_vcardResponder = new VCardResponder(frontend->getIQRouter(), component->getNetworkFactories(), this); + m_vcardResponder->onVCardRequired.connect(boost::bind(&XMPPUserManager::handleVCardRequired, this, _1, _2, _3)); + m_vcardResponder->onVCardUpdated.connect(boost::bind(&XMPPUserManager::handleVCardUpdated, this, _1, _2)); + m_vcardResponder->start(); + + if (storageBackend) { + m_userRegistration = new XMPPUserRegistration(component, this, storageBackend); + m_userRegistration->start(); + } + else { + m_userRegistration = NULL; + } + +// StatsResponder statsResponder(component, this, &plugin, storageBackend); +// statsResponder.start(); + + m_gatewayResponder = new GatewayResponder(frontend->getIQRouter(), this); + m_gatewayResponder->start(); + + m_adHocManager = new AdHocManager(component, frontend->getDiscoItemsResponder(), this, storageBackend); + m_adHocManager->start(); + + SettingsAdHocCommandFactory *m_settings = new SettingsAdHocCommandFactory(); + m_adHocManager->addAdHocCommand(m_settings); +} + +XMPPUserManager::~XMPPUserManager() { + if (m_storageResponder) { + m_storageResponder->stop(); + delete m_storageResponder; + } + + if (m_userRegistration) { + m_userRegistration->stop(); + delete m_userRegistration; + } + + delete m_gatewayResponder; + delete m_adHocManager; + delete m_settings; + delete m_vcardResponder; +} + +void XMPPUserManager::sendVCard(unsigned int id, Swift::VCard::ref vcard) { + m_vcardResponder->sendVCard(id, vcard); +} + +void XMPPUserManager::handleVCardRequired(User *user, const std::string &name, unsigned int id) { + m_component->getFrontend()->onVCardRequired(user, name, id); +} + +void XMPPUserManager::handleVCardUpdated(User *user, boost::shared_ptr vcard) { + m_component->getFrontend()->onVCardUpdated(user, vcard); +} + +UserRegistration *XMPPUserManager::getUserRegistration() { + return m_userRegistration; +} + +} diff --git a/spectrum/src/frontends/xmpp/XMPPUserManager.h b/spectrum/src/frontends/xmpp/XMPPUserManager.h new file mode 100644 index 0000000000000000000000000000000000000000..35e76d66aff8655ab73cb71ff72087c51f3ca23d --- /dev/null +++ b/spectrum/src/frontends/xmpp/XMPPUserManager.h @@ -0,0 +1,66 @@ +/** + * libtransport -- C++ library for easy XMPP Transports development + * + * Copyright (C) 2011, Jan Kaluza + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ + +#pragma once + +#include +#include +#include "transport/usermanager.h" +#include "Swiften/Elements/Message.h" +#include "Swiften/Elements/Presence.h" +#include "Swiften/Disco/EntityCapsProvider.h" +#include "Swiften/Elements/DiscoInfo.h" +#include "Swiften/Network/Timer.h" + +namespace Transport { + +class Component; +class StorageBackend; +class StorageResponder; +class VCardResponder; +class XMPPUserRegistration; +class GatewayResponder; +class AdHocManager; +class SettingsAdHocCommandFactory; + +class XMPPUserManager : public UserManager { + public: + XMPPUserManager(Component *component, UserRegistry *userRegistry, StorageBackend *storageBackend = NULL); + + virtual ~XMPPUserManager(); + + virtual void sendVCard(unsigned int id, Swift::VCard::ref vcard); + + UserRegistration *getUserRegistration(); + + private: + void handleVCardRequired(User *, const std::string &name, unsigned int id); + void handleVCardUpdated(User *, boost::shared_ptr vcard); + + StorageResponder *m_storageResponder; + VCardResponder *m_vcardResponder; + Component *m_component; + XMPPUserRegistration *m_userRegistration; + GatewayResponder *m_gatewayResponder; + AdHocManager *m_adHocManager; + SettingsAdHocCommandFactory *m_settings; +}; + +} diff --git a/spectrum/src/frontends/xmpp/XMPPUserRegistration.cpp b/spectrum/src/frontends/xmpp/XMPPUserRegistration.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8995bf025d850a1ac8265e0e3a2d0f0cf9921ba5 --- /dev/null +++ b/spectrum/src/frontends/xmpp/XMPPUserRegistration.cpp @@ -0,0 +1,460 @@ +/** + * libtransport -- C++ library for easy XMPP Transports development + * + * Copyright (C) 2011, Jan Kaluza + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ + +#include "XMPPUserRegistration.h" +#include "XMPPRosterManager.h" +#include "transport/userregistration.h" +#include "transport/usermanager.h" +#include "transport/storagebackend.h" +#include "transport/transport.h" +#include "transport/rostermanager.h" +#include "transport/user.h" +#include "transport/logging.h" +#include "formutils.h" +#include "transport/buddy.h" +#include "Swiften/Elements/ErrorPayload.h" +#include "Swiften/EventLoop/SimpleEventLoop.h" +#include "Swiften/Network/BoostNetworkFactories.h" +#include "Swiften/Client/Client.h" +#include +#include +#include +#include +#if HAVE_SWIFTEN_3 +#include +#endif +#include "XMPPFrontend.h" + +using namespace Swift; + +namespace Transport { + +DEFINE_LOGGER(logger, "XMPPUserRegistration"); + +XMPPUserRegistration::XMPPUserRegistration(Component *component, UserManager *userManager, + StorageBackend *storageBackend) +: UserRegistration(component, userManager, storageBackend), Swift::Responder(static_cast(component->getFrontend())->getIQRouter()) { + m_component = component; + m_config = m_component->getConfig(); + m_storageBackend = storageBackend; + m_userManager = userManager; +} + +XMPPUserRegistration::~XMPPUserRegistration(){ +} + +bool XMPPUserRegistration::doUserRegistration(const UserInfo &row) { + // Check if the server supports remoteroster XEP by sending request for the registered user's roster. + AddressedRosterRequest::ref request = AddressedRosterRequest::ref(new AddressedRosterRequest(static_cast(m_component->getFrontend())->getIQRouter(), row.jid)); + request->onResponse.connect(boost::bind(&XMPPUserRegistration::handleRegisterRemoteRosterResponse, this, _1, _2, row)); + request->send(); + + return true; +} + +bool XMPPUserRegistration::doUserUnregistration(const UserInfo &row) { + // Check if the server supports remoteroster XEP by sending request for the registered user's roster. + AddressedRosterRequest::ref request = AddressedRosterRequest::ref(new AddressedRosterRequest(static_cast(m_component->getFrontend())->getIQRouter(), row.jid)); + request->onResponse.connect(boost::bind(&XMPPUserRegistration::handleUnregisterRemoteRosterResponse, this, _1, _2, row)); + request->send(); + + return true; +} + +void XMPPUserRegistration::handleRegisterRemoteRosterResponse(boost::shared_ptr payload, Swift::ErrorPayload::ref remoteRosterNotSupported, const UserInfo &row){ + if (remoteRosterNotSupported || !payload) { + // Remote roster is not support, so send normal Subscribe presence to add transport. + Swift::Presence::ref response = Swift::Presence::create(); + response->setFrom(m_component->getJID()); + response->setTo(Swift::JID(row.jid)); + response->setType(Swift::Presence::Subscribe); + m_component->getFrontend()->sendPresence(response); + } + else { + // Remote roster is support, so use remoteroster XEP to add transport. + Swift::RosterPayload::ref payload = Swift::RosterPayload::ref(new Swift::RosterPayload()); + Swift::RosterItemPayload item; + item.setJID(m_component->getJID()); + item.setSubscription(Swift::RosterItemPayload::Both); + payload->addItem(item); + Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(payload, row.jid, static_cast(m_component->getFrontend())->getIQRouter()); + request->send(); + } + + onUserRegistered(row); + + // If the JID for registration notification is configured, send the notification message. + std::vector const &x = CONFIG_VECTOR(m_component->getConfig(),"registration.notify_jid"); + BOOST_FOREACH(const std::string ¬ify_jid, x) { + boost::shared_ptr msg(new Swift::Message()); + msg->setBody(std::string("registered: ") + row.jid); + msg->setTo(notify_jid); + msg->setFrom(m_component->getJID()); + m_component->getFrontend()->sendMessage(msg); + } +} + +void XMPPUserRegistration::handleUnregisterRemoteRosterResponse(boost::shared_ptr payload, Swift::ErrorPayload::ref remoteRosterNotSupported, const UserInfo &userInfo) { + if (remoteRosterNotSupported || !payload) { + // Remote roster is ont support, so get the buddies from database + // and send Unsubsribe and Unsubscribed presence to them. + std::list roster; + m_storageBackend->getBuddies(userInfo.id, roster); + for(std::list::iterator u = roster.begin(); u != roster.end() ; u++){ + std::string name = (*u).legacyName; + if ((*u).flags & BUDDY_JID_ESCAPING) { + name = Swift::JID::getEscapedNode((*u).legacyName); + } + else { + if (name.find_last_of("@") != std::string::npos) { + name.replace(name.find_last_of("@"), 1, "%"); + } + } + + Swift::Presence::ref response; + response = Swift::Presence::create(); + response->setTo(Swift::JID(userInfo.jid)); + response->setFrom(Swift::JID(name, m_component->getJID().toString())); + response->setType(Swift::Presence::Unsubscribe); + m_component->getFrontend()->sendPresence(response); + + response = Swift::Presence::create(); + response->setTo(Swift::JID(userInfo.jid)); + response->setFrom(Swift::JID(name, m_component->getJID().toString())); + response->setType(Swift::Presence::Unsubscribed); + m_component->getFrontend()->sendPresence(response); + } + } + else { + // Remote roster is support, so iterate over all buddies we received + // from the XMPP server and remove them using remote roster. + BOOST_FOREACH(Swift::RosterItemPayload it, payload->getItems()) { + Swift::RosterPayload::ref p = Swift::RosterPayload::ref(new Swift::RosterPayload()); + Swift::RosterItemPayload item; + item.setJID(it.getJID()); + item.setSubscription(Swift::RosterItemPayload::Remove); + + p->addItem(item); + + Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(p, userInfo.jid, static_cast(m_component->getFrontend())->getIQRouter()); + request->send(); + } + } + + // Remove user from database + m_storageBackend->removeUser(userInfo.id); + + // Disconnect the user + User *user = m_userManager->getUser(userInfo.jid); + if (user) { + m_userManager->removeUser(user); + } + + // Remove the transport contact itself the same way as the buddies. + if (remoteRosterNotSupported || !payload) { + Swift::Presence::ref response; + response = Swift::Presence::create(); + response->setTo(Swift::JID(userInfo.jid)); + response->setFrom(m_component->getJID()); + response->setType(Swift::Presence::Unsubscribe); + m_component->getFrontend()->sendPresence(response); + + response = Swift::Presence::create(); + response->setTo(Swift::JID(userInfo.jid)); + response->setFrom(m_component->getJID()); + response->setType(Swift::Presence::Unsubscribed); + m_component->getFrontend()->sendPresence(response); + } + else { + Swift::RosterPayload::ref payload = Swift::RosterPayload::ref(new Swift::RosterPayload()); + Swift::RosterItemPayload item; + item.setJID(m_component->getJID()); + item.setSubscription(Swift::RosterItemPayload::Remove); + payload->addItem(item); + + Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(payload, userInfo.jid, static_cast(m_component->getFrontend())->getIQRouter()); + request->send(); + } + + // If the JID for registration notification is configured, send the notification message. + std::vector const &x = CONFIG_VECTOR(m_component->getConfig(),"registration.notify_jid"); + BOOST_FOREACH(const std::string ¬ify_jid, x) { + boost::shared_ptr msg(new Swift::Message()); + msg->setBody(std::string("unregistered: ") + userInfo.jid); + msg->setTo(notify_jid); + msg->setFrom(m_component->getJID()); + m_component->getFrontend()->sendMessage(msg); + } +} + +Form::ref XMPPUserRegistration::generateRegistrationForm(const UserInfo &res, bool registered) { + Form::ref form(new Form(Form::FormType)); + form->setTitle("Registration"); + form->setInstructions(CONFIG_STRING(m_config, "registration.instructions")); + + FormUtils::addHiddenField(form, "FORM_TYPE", "jabber:iq:register"); + FormUtils::addTextSingleField(form, "username", res.uin, + CONFIG_STRING(m_config, "registration.username_label"), + true); + + if (CONFIG_BOOL_DEFAULTED(m_config, "registration.needPassword", true)) { + FormUtils::addTextPrivateField(form, "password", "Password", true); + } + + std::string defLanguage = CONFIG_STRING(m_config, "registration.language"); + Swift::FormField::Option languages(defLanguage, defLanguage); + FormUtils::addListSingleField(form, "language", languages, "Language", + registered ? res.language : defLanguage); + + + if (registered) { + FormUtils::addBooleanField(form, "unregister", "0", "Remove your registration"); + } + else if (CONFIG_BOOL(m_config,"registration.require_local_account")) { + std::string localUsernameField = CONFIG_STRING(m_config, "registration.local_username_label"); + FormUtils::addTextSingleField(form, "local_username", "", localUsernameField, true); + FormUtils::addTextSingleField(form, "local_password", "", "Local password", true); + } + + return form; +} + +boost::shared_ptr XMPPUserRegistration::generateInBandRegistrationPayload(const Swift::JID& from) { + boost::shared_ptr reg(new InBandRegistrationPayload()); + + UserInfo res; + bool registered = m_storageBackend->getUser(from.toBare().toString(), res); + + reg->setInstructions(CONFIG_STRING(m_config, "registration.instructions")); + reg->setRegistered(registered); + reg->setUsername(res.uin); + + if (CONFIG_BOOL_DEFAULTED(m_config, "registration.needPassword", true)) { + reg->setPassword(""); + } + + Form::ref form = generateRegistrationForm(res, registered); + reg->setForm(form); + + return reg; +} + +bool XMPPUserRegistration::handleGetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr payload) { + // TODO: backend should say itself if registration is needed or not... + if (CONFIG_STRING(m_config, "service.protocol") == "irc") { + sendError(from, id, ErrorPayload::BadRequest, ErrorPayload::Modify); + return true; + } + + if (!CONFIG_BOOL(m_config,"registration.enable_public_registration")) { + std::vector const &x = CONFIG_VECTOR(m_config,"service.allowed_servers"); + if (std::find(x.begin(), x.end(), from.getDomain()) == x.end()) { + LOG4CXX_INFO(logger, from.toBare().toString() << ": This user has no permissions to register an account") + sendError(from, id, ErrorPayload::BadRequest, ErrorPayload::Modify); + return true; + } + } + + boost::shared_ptr reg = generateInBandRegistrationPayload(from); + sendResponse(from, id, reg); + + return true; +} + +bool XMPPUserRegistration::handleSetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr payload) { + // TODO: backend should say itself if registration is needed or not... + if (CONFIG_STRING(m_config, "service.protocol") == "irc") { + sendError(from, id, ErrorPayload::BadRequest, ErrorPayload::Modify); + return true; + } + + std::string barejid = from.toBare().toString(); + + if (!CONFIG_BOOL(m_config,"registration.enable_public_registration")) { + std::vector const &x = CONFIG_VECTOR(m_config,"service.allowed_servers"); + if (std::find(x.begin(), x.end(), from.getDomain()) == x.end()) { + LOG4CXX_INFO(logger, barejid << ": This user has no permissions to register an account") + sendError(from, id, ErrorPayload::BadRequest, ErrorPayload::Modify); + return true; + } + } + + UserInfo res; + bool registered = m_storageBackend->getUser(barejid, res); + + std::string encoding; + std::string language; + std::string local_username; + std::string local_password; + + Form::ref form = payload->getForm(); + if (form) { + std::string value; + + value = FormUtils::fieldValue(form, "username", ""); + if (!value.empty()) { + payload->setUsername(value); + } + + value = FormUtils::fieldValue(form, "password", ""); + if (!value.empty()) { + payload->setPassword(value); + } + + value = FormUtils::fieldValue(form, "unregister", ""); + if (value == "1" || value == "true") { + payload->setRemove(true); + } + + encoding = FormUtils::fieldValue(form, "encoding", ""); + local_username = FormUtils::fieldValue(form, "local_username", ""); + local_password = FormUtils::fieldValue(form, "local_password", ""); + language = FormUtils::fieldValue(form, "language", ""); + } + + if (payload->isRemove()) { + unregisterUser(barejid); + sendResponse(from, id, InBandRegistrationPayload::ref()); + return true; + } + + if (CONFIG_BOOL(m_config,"registration.require_local_account")) { + /* if (!local_username || !local_password) { + sendResponse(from, id, InBandRegistrationPayload::ref()); + return true + } else */ if (local_username == "" || local_password == "") { + sendResponse(from, id, InBandRegistrationPayload::ref()); + return true; + } +// Swift::logging = true; + bool validLocal = false; + std::string localLookupServer = CONFIG_STRING(m_config, "registration.local_account_server"); + std::string localLookupJID = local_username + std::string("@") + localLookupServer; + SimpleEventLoop localLookupEventLoop; + BoostNetworkFactories localLookupNetworkFactories(&localLookupEventLoop); + Client localLookupClient(localLookupJID, local_password, &localLookupNetworkFactories); + + // TODO: this is neccessary on my server ... but should maybe omitted + localLookupClient.setAlwaysTrustCertificates(); + localLookupClient.connect(); + + class SimpleLoopRunner { + public: + SimpleLoopRunner() {}; + + static void run(SimpleEventLoop * loop) { + loop->run(); + }; + }; + + // TODO: Really ugly and hacky solution, any other ideas more than welcome! + boost::thread thread(boost::bind(&(SimpleLoopRunner::run), &localLookupEventLoop)); + thread.timed_join(boost::posix_time::millisec(CONFIG_INT(m_config, "registration.local_account_server_timeout"))); + localLookupEventLoop.stop(); + thread.join(); + validLocal = localLookupClient.isAvailable(); + localLookupClient.disconnect(); + if (!validLocal) { + sendError(from, id, ErrorPayload::NotAuthorized, ErrorPayload::Modify); + return true; + } + } + + if (!payload->getUsername() || (!payload->getPassword() && CONFIG_BOOL_DEFAULTED(m_config, "registration.needPassword", true))) { + sendError(from, id, ErrorPayload::NotAcceptable, ErrorPayload::Modify); + return true; + } + + if (!payload->getPassword()) { + payload->setPassword(""); + } + + // Register or change password + if (payload->getUsername()->empty()) { + sendError(from, id, ErrorPayload::NotAcceptable, ErrorPayload::Modify); + return true; + } + + // TODO: Move this check to backend somehow + if (CONFIG_STRING(m_config, "service.protocol") == "prpl-jabber") { + // User tries to register himself. + if ((Swift::JID(*payload->getUsername()).toBare() == from.toBare())) { + sendError(from, id, ErrorPayload::NotAcceptable, ErrorPayload::Modify); + return true; + } + + // User tries to register someone who's already registered. + UserInfo user_row; + bool registered = m_storageBackend->getUser(Swift::JID(*payload->getUsername()).toBare().toString(), user_row); + if (registered) { + sendError(from, id, ErrorPayload::NotAcceptable, ErrorPayload::Modify); + return true; + } + } + + std::string username = *payload->getUsername(); + + std::string newUsername(username); + if (!CONFIG_STRING(m_config, "registration.username_mask").empty()) { + newUsername = CONFIG_STRING(m_config, "registration.username_mask"); + boost::replace_all(newUsername, "$username", username); + } + +//TODO: Part of spectrum1 registration stuff, this should be potentially rewritten for S2 too +// if (!m_component->protocol()->isValidUsername(newUsername)) { +// Log("XMPPUserRegistration", "This is not valid username: "<< newUsername); +// sendError(from, id, ErrorPayload::NotAcceptable, ErrorPayload::Modify); +// return true; +// } + + if (!CONFIG_STRING(m_config, "registration.allowed_usernames").empty()) { + boost::regex expression(CONFIG_STRING(m_config, "registration.allowed_usernames")); + if (!regex_match(newUsername, expression)) { + LOG4CXX_INFO(logger, "This is not valid username: " << newUsername); + sendError(from, id, ErrorPayload::NotAcceptable, ErrorPayload::Modify); + return true; + } + } + + if (!registered) { + res.jid = barejid; + res.uin = newUsername; + res.password = *payload->getPassword(); + res.language = language; + res.encoding = encoding; + res.vip = 0; + res.id = 0; + registerUser(res); + } + else { + res.jid = barejid; + res.uin = newUsername; + res.password = *payload->getPassword(); + res.language = language; + res.encoding = encoding; + m_storageBackend->setUser(res); +// onUserUpdated(res); + } + + sendResponse(from, id, InBandRegistrationPayload::ref()); + return true; +} + +} diff --git a/spectrum/src/frontends/xmpp/XMPPUserRegistration.h b/spectrum/src/frontends/xmpp/XMPPUserRegistration.h new file mode 100644 index 0000000000000000000000000000000000000000..0dfa13f1c87cc3ae73566fe4cea882fd271b4d7c --- /dev/null +++ b/spectrum/src/frontends/xmpp/XMPPUserRegistration.h @@ -0,0 +1,78 @@ +/** + * libtransport -- C++ library for easy XMPP Transports development + * + * Copyright (C) 2011, Jan Kaluza + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ + +#pragma once + +#include "Swiften/Queries/Responder.h" +#include "Swiften/Elements/InBandRegistrationPayload.h" +#include "Swiften/Elements/RosterPayload.h" +#include +#include +#include "transport/userregistration.h" +#define HAVE_SWIFTEN_3 (SWIFTEN_VERSION >= 0x030000) + +namespace Transport { + +struct UserInfo; +class Component; +class StorageBackend; +class UserManager; +class Config; + +/// Allows users to register the transport using service discovery. +class XMPPUserRegistration : public UserRegistration, public Swift::Responder { + public: + /// Creates new XMPPUserRegistration handler. + /// \param component Component associated with this class + /// \param userManager UserManager associated with this class + /// \param storageBackend StorageBackend where the registered users will be stored + XMPPUserRegistration(Component *component, UserManager *userManager, StorageBackend *storageBackend); + + /// Destroys XMPPUserRegistration. + ~XMPPUserRegistration(); + + /// Registers new user. This function stores user into database and subscribe user to transport. + /// \param userInfo UserInfo struct with informations about registered user + /// \return false if user is already registered + virtual bool doUserRegistration(const UserInfo &userInfo); + + /// Unregisters user. This function removes all data about user from databa, unsubscribe all buddies + /// managed by this transport and disconnects user if he's connected. + /// \param barejid bare JID of user to unregister + /// \return false if there is no such user registered + virtual bool doUserUnregistration(const UserInfo &userInfo); + + private: + virtual bool handleGetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr payload); + virtual bool handleSetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr payload); + + void handleRegisterRemoteRosterResponse(boost::shared_ptr payload, Swift::ErrorPayload::ref error, const UserInfo &row); + void handleUnregisterRemoteRosterResponse(boost::shared_ptr payload, Swift::ErrorPayload::ref error, const UserInfo &row); + boost::shared_ptr generateInBandRegistrationPayload(const Swift::JID& from); + Swift::Form::ref generateRegistrationForm(const UserInfo &res, bool registered); + + Component *m_component; + StorageBackend *m_storageBackend; + UserManager *m_userManager; + Config *m_config; + +}; + +} diff --git a/src/adhoccommand.cpp b/spectrum/src/frontends/xmpp/adhoccommand.cpp similarity index 95% rename from src/adhoccommand.cpp rename to spectrum/src/frontends/xmpp/adhoccommand.cpp index b02bc7404bbedff024356933cec0198164ee3013..9e935aabe28ce8986cc2cba15ccb9b0f0384e393 100644 --- a/src/adhoccommand.cpp +++ b/spectrum/src/frontends/xmpp/adhoccommand.cpp @@ -18,8 +18,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ -#include "transport/adhoccommand.h" -#include "transport/adhoccommandfactory.h" +#include "adhoccommand.h" +#include "adhoccommandfactory.h" #include "transport/conversation.h" #include "transport/usermanager.h" #include "transport/storagebackend.h" diff --git a/include/transport/adhoccommand.h b/spectrum/src/frontends/xmpp/adhoccommand.h similarity index 100% rename from include/transport/adhoccommand.h rename to spectrum/src/frontends/xmpp/adhoccommand.h diff --git a/include/transport/adhoccommandfactory.h b/spectrum/src/frontends/xmpp/adhoccommandfactory.h similarity index 97% rename from include/transport/adhoccommandfactory.h rename to spectrum/src/frontends/xmpp/adhoccommandfactory.h index 859421c5c6c64841dbab7c1cd7cec433d11843af..74c1d6c3c9539c0f4ad263502bd1772b917a54fd 100644 --- a/include/transport/adhoccommandfactory.h +++ b/spectrum/src/frontends/xmpp/adhoccommandfactory.h @@ -23,7 +23,7 @@ #include #include #include -#include "transport/adhoccommand.h" +#include "adhoccommand.h" namespace Transport { diff --git a/src/adhocmanager.cpp b/spectrum/src/frontends/xmpp/adhocmanager.cpp similarity index 96% rename from src/adhocmanager.cpp rename to spectrum/src/frontends/xmpp/adhocmanager.cpp index 3313320132c0f11e714625d3d432ad3e6b9b014c..6bdce6d005a5595c5d063e2b69f5232188dbee7c 100644 --- a/src/adhocmanager.cpp +++ b/spectrum/src/frontends/xmpp/adhocmanager.cpp @@ -18,9 +18,11 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ -#include "transport/adhocmanager.h" -#include "transport/adhoccommandfactory.h" -#include "transport/discoitemsresponder.h" +#include "XMPPFrontend.h" + +#include "adhocmanager.h" +#include "adhoccommandfactory.h" +#include "discoitemsresponder.h" #include "transport/conversation.h" #include "transport/usermanager.h" #include "transport/buddy.h" @@ -33,7 +35,7 @@ namespace Transport { DEFINE_LOGGER(logger, "AdHocManager"); -AdHocManager::AdHocManager(Component *component, DiscoItemsResponder *discoItemsResponder, UserManager *userManager, StorageBackend *storageBackend) : Swift::Responder(component->getIQRouter()){ +AdHocManager::AdHocManager(Component *component, DiscoItemsResponder *discoItemsResponder, UserManager *userManager, StorageBackend *storageBackend) : Swift::Responder(static_cast(component->getFrontend())->getIQRouter()){ m_component = component; m_discoItemsResponder = discoItemsResponder; m_userManager = userManager; diff --git a/include/transport/adhocmanager.h b/spectrum/src/frontends/xmpp/adhocmanager.h similarity index 100% rename from include/transport/adhocmanager.h rename to spectrum/src/frontends/xmpp/adhocmanager.h diff --git a/src/blockresponder.cpp b/spectrum/src/frontends/xmpp/blockresponder.cpp similarity index 98% rename from src/blockresponder.cpp rename to spectrum/src/frontends/xmpp/blockresponder.cpp index 6a5ad41c6e4b0328004a899afe4c8b4627184f99..c680937b8b678d50ea8de0ea98fd0fd2cf1dfd05 100644 --- a/src/blockresponder.cpp +++ b/spectrum/src/frontends/xmpp/blockresponder.cpp @@ -23,7 +23,7 @@ #include #include #include "Swiften/Queries/IQRouter.h" -#include "transport/BlockPayload.h" +#include "BlockPayload.h" #include "transport/usermanager.h" #include "transport/user.h" #include "transport/buddy.h" diff --git a/src/blockresponder.h b/spectrum/src/frontends/xmpp/blockresponder.h similarity index 97% rename from src/blockresponder.h rename to spectrum/src/frontends/xmpp/blockresponder.h index ed415502e9bc259c128adceb8ea90110b0baa31e..aee38f6608b3feca0d2db368fcaf8f1b6c97d888 100644 --- a/src/blockresponder.h +++ b/spectrum/src/frontends/xmpp/blockresponder.h @@ -22,7 +22,7 @@ #include #include "Swiften/Queries/SetResponder.h" -#include "transport/BlockPayload.h" +#include "BlockPayload.h" #include namespace Transport { diff --git a/src/discoinforesponder.cpp b/spectrum/src/frontends/xmpp/discoinforesponder.cpp similarity index 99% rename from src/discoinforesponder.cpp rename to spectrum/src/frontends/xmpp/discoinforesponder.cpp index e9a6778c18db19c710369ac27767c6999e50c54f..4ea709dc72617d415edcacb1ce894a0574616399 100644 --- a/src/discoinforesponder.cpp +++ b/spectrum/src/frontends/xmpp/discoinforesponder.cpp @@ -29,6 +29,7 @@ #include "transport/config.h" #include "transport/logging.h" #include "Swiften/Disco/CapsInfoGenerator.h" +#include "XMPPFrontend.h" using namespace Swift; using namespace boost; diff --git a/src/discoinforesponder.h b/spectrum/src/frontends/xmpp/discoinforesponder.h similarity index 100% rename from src/discoinforesponder.h rename to spectrum/src/frontends/xmpp/discoinforesponder.h diff --git a/src/discoitemsresponder.cpp b/spectrum/src/frontends/xmpp/discoitemsresponder.cpp similarity index 88% rename from src/discoitemsresponder.cpp rename to spectrum/src/frontends/xmpp/discoitemsresponder.cpp index 90c153eab17a611f45cfda41ae749abd93c98d29..da533307f54fada865498214b16e7bf4ac8329ba 100644 --- a/src/discoitemsresponder.cpp +++ b/spectrum/src/frontends/xmpp/discoitemsresponder.cpp @@ -18,14 +18,17 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ -#include "transport/discoitemsresponder.h" +#include "discoitemsresponder.h" #include #include #include "Swiften/Queries/IQRouter.h" #include "transport/transport.h" #include "transport/logging.h" +#include "transport/config.h" #include "discoinforesponder.h" +#include "XMPPFrontend.h" +#include "transport/frontend.h" using namespace Swift; using namespace boost; @@ -34,13 +37,13 @@ namespace Transport { DEFINE_LOGGER(logger, "DiscoItemsResponder"); -DiscoItemsResponder::DiscoItemsResponder(Component *component) : Swift::GetResponder(component->getIQRouter()) { +DiscoItemsResponder::DiscoItemsResponder(Component *component) : Swift::GetResponder(static_cast(component->getFrontend())->getIQRouter()) { m_component = component; m_commands = boost::shared_ptr(new DiscoItems()); m_commands->setNode("http://jabber.org/protocol/commands"); m_rooms = boost::shared_ptr(new DiscoItems()); - m_discoInfoResponder = new DiscoInfoResponder(component->getIQRouter(), component->getConfig()); + m_discoInfoResponder = new DiscoInfoResponder(static_cast(component->getFrontend())->getIQRouter(), component->getConfig()); m_discoInfoResponder->start(); } diff --git a/include/transport/discoitemsresponder.h b/spectrum/src/frontends/xmpp/discoitemsresponder.h similarity index 100% rename from include/transport/discoitemsresponder.h rename to spectrum/src/frontends/xmpp/discoitemsresponder.h diff --git a/src/formutils.cpp b/spectrum/src/frontends/xmpp/formutils.cpp similarity index 98% rename from src/formutils.cpp rename to spectrum/src/frontends/xmpp/formutils.cpp index ae07a4f6bdbeb012af6de1c4bead17062be350ec..1ccbe63e6d701b756cd376f9870e933dd33391e2 100644 --- a/src/formutils.cpp +++ b/spectrum/src/frontends/xmpp/formutils.cpp @@ -18,8 +18,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ -#include "transport/formutils.h" -#include "transport/adhoccommand.h" +#include "formutils.h" +#include "adhoccommand.h" #if HAVE_SWIFTEN_3 #include diff --git a/include/transport/formutils.h b/spectrum/src/frontends/xmpp/formutils.h similarity index 100% rename from include/transport/formutils.h rename to spectrum/src/frontends/xmpp/formutils.h diff --git a/src/gatewayresponder.cpp b/spectrum/src/frontends/xmpp/gatewayresponder.cpp similarity index 98% rename from src/gatewayresponder.cpp rename to spectrum/src/frontends/xmpp/gatewayresponder.cpp index fa29711e7a9a0649abe0e5243f8a76e25e938a46..825620a23a97f8a55fa02447278064afd39139e6 100644 --- a/src/gatewayresponder.cpp +++ b/spectrum/src/frontends/xmpp/gatewayresponder.cpp @@ -18,7 +18,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ -#include "transport/gatewayresponder.h" +#include "gatewayresponder.h" #include #include diff --git a/include/transport/gatewayresponder.h b/spectrum/src/frontends/xmpp/gatewayresponder.h similarity index 100% rename from include/transport/gatewayresponder.h rename to spectrum/src/frontends/xmpp/gatewayresponder.h diff --git a/src/rosterresponder.cpp b/spectrum/src/frontends/xmpp/rosterresponder.cpp similarity index 91% rename from src/rosterresponder.cpp rename to spectrum/src/frontends/xmpp/rosterresponder.cpp index 109f30c5d9de633ab8529d032a9a86068923d05b..988ce83d45aaefa097761ba0a07040b16ce0f01a 100644 --- a/src/rosterresponder.cpp +++ b/spectrum/src/frontends/xmpp/rosterresponder.cpp @@ -28,6 +28,9 @@ #include "transport/rostermanager.h" #include "transport/buddy.h" #include "transport/logging.h" +#include "transport/factory.h" +#include "XMPPFrontend.h" +#include "transport/frontend.h" using namespace Swift; using namespace boost; @@ -38,6 +41,7 @@ DEFINE_LOGGER(logger, "RosterResponder"); RosterResponder::RosterResponder(Swift::IQRouter *router, UserManager *userManager) : Swift::Responder(router) { m_userManager = userManager; + m_router = router; } RosterResponder::~RosterResponder() { @@ -81,15 +85,15 @@ bool RosterResponder::handleSetRequest(const Swift::JID& from, const Swift::JID& if (buddy) { if (item.getSubscription() == Swift::RosterItemPayload::Remove) { LOG4CXX_INFO(logger, from.toBare().toString() << ": Removing buddy " << buddy->getName()); - onBuddyRemoved(buddy); + user->getComponent()->getFrontend()->onBuddyRemoved(buddy); // send roster push here - Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(payload, user->getJID().toBare(), user->getComponent()->getIQRouter()); + Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(payload, user->getJID().toBare(), m_router); request->send(); } else { LOG4CXX_INFO(logger, from.toBare().toString() << ": Updating buddy " << buddy->getName()); - onBuddyUpdated(buddy, item); + user->getComponent()->getFrontend()->onBuddyUpdated(buddy, item); } } else if (item.getSubscription() != Swift::RosterItemPayload::Remove) { @@ -104,7 +108,7 @@ bool RosterResponder::handleSetRequest(const Swift::JID& from, const Swift::JID& buddy = user->getComponent()->getFactory()->createBuddy(user->getRosterManager(), buddyInfo); user->getRosterManager()->setBuddy(buddy); - onBuddyAdded(buddy, item); + user->getComponent()->getFrontend()->onBuddyAdded(buddy, item); } return true; diff --git a/src/settingsadhoccommand.cpp b/spectrum/src/frontends/xmpp/settingsadhoccommand.cpp similarity index 98% rename from src/settingsadhoccommand.cpp rename to spectrum/src/frontends/xmpp/settingsadhoccommand.cpp index d888a3b31e4e278b4c38218219a92cd4a1f91d1b..cc93f34554cd504772d288ecdc9eef01e3c2af4e 100644 --- a/src/settingsadhoccommand.cpp +++ b/spectrum/src/frontends/xmpp/settingsadhoccommand.cpp @@ -18,7 +18,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ -#include "transport/settingsadhoccommand.h" +#include "settingsadhoccommand.h" #include "transport/conversation.h" #include "transport/usermanager.h" #include "transport/buddy.h" @@ -26,7 +26,7 @@ #include "transport/user.h" #include "transport/logging.h" #include "transport/storagebackend.h" -#include "transport/formutils.h" +#include "formutils.h" namespace Transport { diff --git a/include/transport/settingsadhoccommand.h b/spectrum/src/frontends/xmpp/settingsadhoccommand.h similarity index 96% rename from include/transport/settingsadhoccommand.h rename to spectrum/src/frontends/xmpp/settingsadhoccommand.h index 1c061269c9d2b6d7e970fa5c788ee70706d33de2..236301252b364c2dc9da2bc590c231e10cd2f2f5 100644 --- a/include/transport/settingsadhoccommand.h +++ b/spectrum/src/frontends/xmpp/settingsadhoccommand.h @@ -23,8 +23,8 @@ #include #include #include -#include "transport/adhoccommand.h" -#include "transport/adhoccommandfactory.h" +#include "adhoccommand.h" +#include "adhoccommandfactory.h" #include #define HAVE_SWIFTEN_3 (SWIFTEN_VERSION >= 0x030000) diff --git a/src/statsresponder.cpp b/spectrum/src/frontends/xmpp/statsresponder.cpp similarity index 96% rename from src/statsresponder.cpp rename to spectrum/src/frontends/xmpp/statsresponder.cpp index faed68b0b18bd321a250c8ec62ad6b6f899c78eb..445b76bb97491dfaedd7dd3a549e6d477ba3a4fd 100644 --- a/src/statsresponder.cpp +++ b/spectrum/src/frontends/xmpp/statsresponder.cpp @@ -18,12 +18,11 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ -#include "transport/statsresponder.h" +#include "statsresponder.h" #include #include #include "Swiften/Queries/IQRouter.h" -#include "transport/BlockPayload.h" #include "transport/usermanager.h" #include "transport/user.h" #include "transport/buddy.h" @@ -34,6 +33,8 @@ #include "transport/usermanager.h" #include "transport/networkpluginserver.h" #include "transport/logging.h" +#include "transport/frontend.h" +#include "XMPPFrontend.h" using namespace Swift; using namespace boost; @@ -42,7 +43,7 @@ namespace Transport { DEFINE_LOGGER(logger, "StatsResponder"); -StatsResponder::StatsResponder(Component *component, UserManager *userManager, NetworkPluginServer *server, StorageBackend *storageBackend) : Swift::Responder(component->getIQRouter()) { +StatsResponder::StatsResponder(Component *component, UserManager *userManager, NetworkPluginServer *server, StorageBackend *storageBackend) : Swift::Responder(static_cast(component->getFrontend())->getIQRouter()) { m_component = component; m_userManager = userManager; m_server = server; diff --git a/include/transport/statsresponder.h b/spectrum/src/frontends/xmpp/statsresponder.h similarity index 100% rename from include/transport/statsresponder.h rename to spectrum/src/frontends/xmpp/statsresponder.h diff --git a/src/storageparser.cpp b/spectrum/src/frontends/xmpp/storageparser.cpp similarity index 100% rename from src/storageparser.cpp rename to spectrum/src/frontends/xmpp/storageparser.cpp diff --git a/src/storageparser.h b/spectrum/src/frontends/xmpp/storageparser.h similarity index 100% rename from src/storageparser.h rename to spectrum/src/frontends/xmpp/storageparser.h diff --git a/src/storageresponder.cpp b/spectrum/src/frontends/xmpp/storageresponder.cpp similarity index 100% rename from src/storageresponder.cpp rename to spectrum/src/frontends/xmpp/storageresponder.cpp diff --git a/src/storageresponder.h b/spectrum/src/frontends/xmpp/storageresponder.h similarity index 100% rename from src/storageresponder.h rename to spectrum/src/frontends/xmpp/storageresponder.h diff --git a/src/vcardresponder.cpp b/spectrum/src/frontends/xmpp/vcardresponder.cpp similarity index 98% rename from src/vcardresponder.cpp rename to spectrum/src/frontends/xmpp/vcardresponder.cpp index f216c92a051185f0b5fa34c0b52e4733e4e8c94a..cb197565dd2ba5842b3b2bd67a512fddcc4a09dd 100644 --- a/src/vcardresponder.cpp +++ b/spectrum/src/frontends/xmpp/vcardresponder.cpp @@ -18,16 +18,17 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ -#include "transport/vcardresponder.h" +#include "vcardresponder.h" #include #include -#include "Swiften/Queries/IQRouter.h" #include "transport/user.h" +#include "transport/buddy.h" #include "transport/usermanager.h" #include "transport/rostermanager.h" #include "transport/transport.h" #include "transport/logging.h" +#include "Swiften/Queries/IQRouter.h" using namespace Swift; using namespace boost; diff --git a/include/transport/vcardresponder.h b/spectrum/src/frontends/xmpp/vcardresponder.h similarity index 100% rename from include/transport/vcardresponder.h rename to spectrum/src/frontends/xmpp/vcardresponder.h diff --git a/spectrum/src/main.cpp b/spectrum/src/main.cpp index ed5d9b5128cc5527e4704aa3330c753778238fc5..042d0dd13b451e7091e534ed2ed41412b24940c5 100644 --- a/spectrum/src/main.cpp +++ b/spectrum/src/main.cpp @@ -8,14 +8,10 @@ #include "transport/userregistration.h" #include "transport/networkpluginserver.h" #include "transport/admininterface.h" -#include "transport/statsresponder.h" #include "transport/usersreconnecter.h" #include "transport/util.h" -#include "transport/gatewayresponder.h" #include "transport/logging.h" -#include "transport/discoitemsresponder.h" -#include "transport/adhocmanager.h" -#include "transport/settingsadhoccommand.h" +#include "frontends/xmpp/XMPPFrontend.h" #include "Swiften/EventLoop/SimpleEventLoop.h" #include "Swiften/Network/BoostNetworkFactories.h" #include @@ -46,11 +42,11 @@ DEFINE_LOGGER(logger, "Spectrum"); Swift::SimpleEventLoop *eventLoop_ = NULL; Component *component_ = NULL; -UserManager *userManager_ = NULL; +UserManager *userManager = NULL; Config *config_ = NULL; static void stop_spectrum() { - userManager_->removeAllUsers(false); + userManager->removeAllUsers(false); component_->stop(); eventLoop_->stop(); } @@ -212,9 +208,10 @@ int mainloop() { Swift::BoostNetworkFactories *factories = new Swift::BoostNetworkFactories(&eventLoop); UserRegistry userRegistry(config_, factories); - Component transport(&eventLoop, factories, config_, NULL, &userRegistry); + XMPPFrontend frontend; + + Component transport(&frontend, &eventLoop, factories, config_, NULL, &userRegistry); component_ = &transport; -// Logger logger(&transport); std::string error; StorageBackend *storageBackend = StorageBackend::createBackend(config_, error); @@ -231,44 +228,25 @@ int mainloop() { Logging::redirect_stderr(); - DiscoItemsResponder discoItemsResponder(&transport); - discoItemsResponder.start(); - - UserManager userManager(&transport, &userRegistry, &discoItemsResponder, storageBackend); - userManager_ = &userManager; + userManager = frontend.createUserManager(&transport, &userRegistry, storageBackend);; + UserRegistration *userRegistration = userManager->getUserRegistration(); - UserRegistration *userRegistration = NULL; UsersReconnecter *usersReconnecter = NULL; if (storageBackend) { - userRegistration = new UserRegistration(&transport, &userManager, storageBackend); - userRegistration->start(); - usersReconnecter = new UsersReconnecter(&transport, storageBackend); } else if (!CONFIG_BOOL(config_, "service.server_mode")) { LOG4CXX_WARN(logger, "Registrations won't work, you have specified [database] type=none in config file."); } - FileTransferManager ftManager(&transport, &userManager); + FileTransferManager ftManager(&transport, userManager); - NetworkPluginServer plugin(&transport, config_, &userManager, &ftManager, &discoItemsResponder); + NetworkPluginServer plugin(&transport, config_, userManager, &ftManager); plugin.start(); - AdminInterface adminInterface(&transport, &userManager, &plugin, storageBackend, userRegistration); + AdminInterface adminInterface(&transport, userManager, &plugin, storageBackend, userRegistration); plugin.setAdminInterface(&adminInterface); - StatsResponder statsResponder(&transport, &userManager, &plugin, storageBackend); - statsResponder.start(); - - GatewayResponder gatewayResponder(transport.getIQRouter(), &userManager); - gatewayResponder.start(); - - AdHocManager adhocmanager(&transport, &discoItemsResponder, &userManager, storageBackend); - adhocmanager.start(); - - SettingsAdHocCommandFactory settings; - adhocmanager.addAdHocCommand(&settings); - eventLoop_ = &eventLoop; eventLoop.run(); @@ -277,10 +255,7 @@ int mainloop() { umask(old_cmask); #endif - if (userRegistration) { - userRegistration->stop(); - delete userRegistration; - } + delete userManager; if (usersReconnecter) { delete usersReconnecter; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 101718529f52f453300288d2147799c3ef730e44..b5ecda4683b21479a6796a72cc0ba3a8aeee4fd4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -13,9 +13,12 @@ FILE(GLOB HEADERS ../include/transport/*.h) if (CPPUNIT_FOUND) FILE(GLOB SRC_TEST tests/*.cpp) + FILE(GLOB SRC_TEST_FRONTEND ../spectrum/src/frontends/xmpp/*.cpp) + include_directories(../spectrum/src/frontends/xmpp/) - ADD_EXECUTABLE(libtransport_test ${SRC_TEST}) + ADD_EXECUTABLE(libtransport_test ${SRC_TEST} ${SRC_TEST_FRONTEND}) set_target_properties(libtransport_test PROPERTIES COMPILE_DEFINITIONS LIBTRANSPORT_TEST=1) + target_link_libraries(libtransport_test transport ${CPPUNIT_LIBRARY} ${Boost_LIBRARIES}) endif() diff --git a/src/admininterface.cpp b/src/admininterface.cpp index d961a0a3cecfcc052bdb1719522fb589aa04c372..e20362c072b3f8a42c0fcabed070a38035b61730 100644 --- a/src/admininterface.cpp +++ b/src/admininterface.cpp @@ -28,6 +28,7 @@ #include "transport/networkpluginserver.h" #include "transport/logging.h" #include "transport/userregistration.h" +#include "transport/frontend.h" #include "storageresponder.h" #include "transport/memoryusage.h" #include @@ -52,7 +53,7 @@ AdminInterface::AdminInterface(Component *component, UserManager *userManager, N m_userRegistration = userRegistration; m_start = time(NULL); - m_component->getStanzaChannel()->onMessageReceived.connect(bind(&AdminInterface::handleMessageReceived, this, _1)); + m_component->getFrontend()->onMessageReceived.connect(bind(&AdminInterface::handleMessageReceived, this, _1)); } AdminInterface::~AdminInterface() { @@ -353,7 +354,7 @@ void AdminInterface::handleMessageReceived(Swift::Message::ref message) { handleQuery(message); - m_component->getStanzaChannel()->sendMessage(message); + m_component->getFrontend()->sendMessage(message); } } diff --git a/src/buddy.cpp b/src/buddy.cpp index 00aea73cbe7a429b7463357ea386ed603f1c0e3c..21951b54458cd9d90855449484cac812b68186d1 100644 --- a/src/buddy.cpp +++ b/src/buddy.cpp @@ -22,9 +22,8 @@ #include "transport/rostermanager.h" #include "transport/user.h" #include "transport/transport.h" -#include "transport/BlockPayload.h" #include "transport/usermanager.h" -#include "transport/discoitemsresponder.h" +#include "transport/frontend.h" #include "Swiften/Elements/VCardUpdate.h" @@ -32,17 +31,15 @@ namespace Transport { Buddy::Buddy(RosterManager *rosterManager, long id, BuddyFlag flags) : m_id(id), m_flags(flags), m_rosterManager(rosterManager), m_subscription(Ask) { -// m_rosterManager->setBuddy(this); } Buddy::~Buddy() { -// m_rosterManager->unsetBuddy(this); } void Buddy::sendPresence() { std::vector &presences = generatePresenceStanzas(255); BOOST_FOREACH(Swift::Presence::ref presence, presences) { - m_rosterManager->getUser()->getComponent()->getStanzaChannel()->sendPresence(presence); + m_rosterManager->getUser()->getComponent()->getFrontend()->sendPresence(presence); } } @@ -98,7 +95,7 @@ void Buddy::handleRawPresence(Swift::Presence::ref presence) { } m_presences.push_back(presence); - m_rosterManager->getUser()->getComponent()->getStanzaChannel()->sendPresence(presence); + m_rosterManager->getUser()->getComponent()->getFrontend()->sendPresence(presence); } std::vector &Buddy::generatePresenceStanzas(int features, bool only_new) { @@ -133,15 +130,14 @@ std::vector &Buddy::generatePresenceStanzas(int features, if (presence->getType() != Swift::Presence::Unavailable) { // caps - - presence->addPayload(boost::shared_ptr(new Swift::CapsInfo(m_rosterManager->getUser()->getUserManager()->getDiscoResponder()->getBuddyCapsInfo()))); + // if (features & 0/*TRANSPORT_FEATURE_AVATARS*/) { presence->addPayload(boost::shared_ptr(new Swift::VCardUpdate (getIconHash()))); // } - if (isBlocked()) { - presence->addPayload(boost::shared_ptr(new Transport::BlockPayload ())); - } +// if (isBlocked()) { +// presence->addPayload(boost::shared_ptr(new Transport::BlockPayload ())); +// } } BOOST_FOREACH(Swift::Presence::ref &p, m_presences) { @@ -186,8 +182,7 @@ std::string Buddy::getSafeName() { } void Buddy::handleVCardReceived(const std::string &id, Swift::VCard::ref vcard) { - boost::shared_ptr > request(new Swift::GenericRequest(Swift::IQ::Result, m_rosterManager->getUser()->getJID(), vcard, m_rosterManager->getUser()->getComponent()->getIQRouter())); - request->send(); + m_rosterManager->getUser()->getComponent()->getFrontend()->sendVCard(vcard, m_rosterManager->getUser()->getJID()); } std::string Buddy::JIDToLegacyName(const Swift::JID &jid) { diff --git a/src/conversation.cpp b/src/conversation.cpp index 387af4ceef80029e7af16903a72c547647539ebf..25c17ae158289aaeb859b318e5f4ebfaac93e4eb 100644 --- a/src/conversation.cpp +++ b/src/conversation.cpp @@ -25,6 +25,8 @@ #include "transport/transport.h" #include "transport/buddy.h" #include "transport/rostermanager.h" +#include "transport/frontend.h" +#include "transport/config.h" #include "Swiften/Elements/MUCItem.h" #include "Swiften/Elements/MUCOccupant.h" @@ -77,7 +79,7 @@ void Conversation::destroyRoom() { presence->addPayload(boost::shared_ptr(p)); BOOST_FOREACH(const Swift::JID &jid, m_jids) { presence->setTo(jid); - m_conversationManager->getComponent()->getStanzaChannel()->sendPresence(presence); + m_conversationManager->getComponent()->getFrontend()->sendPresence(presence); } } } @@ -104,7 +106,7 @@ void Conversation::handleRawMessage(boost::shared_ptr &message) cacheMessage(message); } else { - m_conversationManager->getComponent()->getStanzaChannel()->sendMessage(message); + m_conversationManager->getComponent()->getFrontend()->sendMessage(message); } } else { @@ -119,7 +121,7 @@ void Conversation::handleRawMessage(boost::shared_ptr &message) m_subject = message; return; } - m_conversationManager->getComponent()->getStanzaChannel()->sendMessage(message); + m_conversationManager->getComponent()->getFrontend()->sendMessage(message); } } } @@ -201,7 +203,7 @@ void Conversation::handleMessage(boost::shared_ptr &message, con void Conversation::sendParticipants(const Swift::JID &to) { for (std::map::iterator it = m_participants.begin(); it != m_participants.end(); it++) { (*it).second->setTo(to); - m_conversationManager->getComponent()->getStanzaChannel()->sendPresence((*it).second); + m_conversationManager->getComponent()->getFrontend()->sendPresence((*it).second); } } @@ -213,7 +215,7 @@ void Conversation::sendCachedMessages(const Swift::JID &to) { else { (*it)->setTo(m_jid.toBare()); } - m_conversationManager->getComponent()->getStanzaChannel()->sendMessage(*it); + m_conversationManager->getComponent()->getFrontend()->sendMessage(*it); } if (m_subject) { @@ -223,7 +225,7 @@ void Conversation::sendCachedMessages(const Swift::JID &to) { else { m_subject->setTo(m_jid.toBare()); } - m_conversationManager->getComponent()->getStanzaChannel()->sendMessage(m_subject); + m_conversationManager->getComponent()->getFrontend()->sendMessage(m_subject); } m_cachedMessages.clear(); @@ -322,7 +324,7 @@ void Conversation::setNickname(const std::string &nickname) { void Conversation::handleRawPresence(Swift::Presence::ref presence) { // TODO: Detect nickname change. - m_conversationManager->getComponent()->getStanzaChannel()->sendPresence(presence); + m_conversationManager->getComponent()->getFrontend()->sendPresence(presence); m_participants[presence->getFrom().getResource()] = presence; } @@ -339,14 +341,14 @@ void Conversation::handleParticipantChanged(const std::string &nick, Conversatio BOOST_FOREACH(const Swift::JID &jid, m_jids) { presence->setTo(jid); - m_conversationManager->getComponent()->getStanzaChannel()->sendPresence(presence); + m_conversationManager->getComponent()->getFrontend()->sendPresence(presence); } if (!newname.empty()) { handleParticipantChanged(newname, flag, status, statusMessage); } if (m_sentInitialPresence && m_subject) { - m_conversationManager->getComponent()->getStanzaChannel()->sendMessage(m_subject); + m_conversationManager->getComponent()->getFrontend()->sendMessage(m_subject); m_subject.reset(); } } diff --git a/src/filetransfermanager.cpp b/src/filetransfermanager.cpp index 74bae55f9106afa9001df85f1e11e45d02498d05..007217abb281c8ac5d4b410883b149968c091ee4 100644 --- a/src/filetransfermanager.cpp +++ b/src/filetransfermanager.cpp @@ -31,34 +31,34 @@ namespace Transport { DEFINE_LOGGER(logger, "FileTransferManager"); FileTransferManager::FileTransferManager(Component *component, UserManager *userManager) { - m_component = component; - m_userManager = userManager; - - m_jingleSessionManager = new Swift::JingleSessionManager(m_component->getIQRouter()); -#if !HAVE_SWIFTEN_3 - m_connectivityManager = new Swift::ConnectivityManager(m_component->getNetworkFactories()->getNATTraverser()); -#endif - m_bytestreamRegistry = new Swift::SOCKS5BytestreamRegistry(); -#if !HAVE_SWIFTEN_3 - m_bytestreamProxy = new Swift::SOCKS5BytestreamProxy(m_component->getNetworkFactories()->getConnectionFactory(), m_component->getNetworkFactories()->getTimerFactory()); - m_localCandidateGeneratorFactory = new Swift::DefaultLocalJingleTransportCandidateGeneratorFactory(m_connectivityManager, m_bytestreamRegistry, m_bytestreamProxy, "thishouldnotbeused"); - m_remoteCandidateSelectorFactory = new Swift::DefaultRemoteJingleTransportCandidateSelectorFactory(m_component->getNetworkFactories()->getConnectionFactory(), m_component->getNetworkFactories()->getTimerFactory()); -#else - m_proxyManager = new Swift::SOCKS5BytestreamProxiesManager(m_component->getNetworkFactories()->getConnectionFactory(), m_component->getNetworkFactories()->getTimerFactory(), m_component->getNetworkFactories()->getDomainNameResolver(), m_component->getIQRouter(), "bar.com"); -#endif - boost::shared_ptr server = m_component->getNetworkFactories()->getConnectionServerFactory()->createConnectionServer(19645); - server->start(); -#if HAVE_SWIFTEN_3 - m_proxyServerManager = new Swift::SOCKS5BytestreamServerManager(m_bytestreamRegistry, m_component->getNetworkFactories()->getConnectionServerFactory(), m_component->getNetworkFactories()->getNetworkEnvironment(), m_component->getNetworkFactories()->getNATTraverser()); -#else - m_bytestreamServer = new Swift::SOCKS5BytestreamServer(server, m_bytestreamRegistry); - m_bytestreamServer->start(); - m_outgoingFTManager = new Swift::CombinedOutgoingFileTransferManager(m_jingleSessionManager, m_component->getIQRouter(), - m_userManager, m_remoteCandidateSelectorFactory, - m_localCandidateGeneratorFactory, m_bytestreamRegistry, - m_bytestreamProxy, m_component->getPresenceOracle(), - m_bytestreamServer); -#endif +// m_component = component; +// m_userManager = userManager; +// +// m_jingleSessionManager = new Swift::JingleSessionManager(m_component->getIQRouter()); +// #if !HAVE_SWIFTEN_3 +// m_connectivityManager = new Swift::ConnectivityManager(m_component->getNetworkFactories()->getNATTraverser()); +// #endif +// m_bytestreamRegistry = new Swift::SOCKS5BytestreamRegistry(); +// #if !HAVE_SWIFTEN_3 +// m_bytestreamProxy = new Swift::SOCKS5BytestreamProxy(m_component->getNetworkFactories()->getConnectionFactory(), m_component->getNetworkFactories()->getTimerFactory()); +// m_localCandidateGeneratorFactory = new Swift::DefaultLocalJingleTransportCandidateGeneratorFactory(m_connectivityManager, m_bytestreamRegistry, m_bytestreamProxy, "thishouldnotbeused"); +// m_remoteCandidateSelectorFactory = new Swift::DefaultRemoteJingleTransportCandidateSelectorFactory(m_component->getNetworkFactories()->getConnectionFactory(), m_component->getNetworkFactories()->getTimerFactory()); +// #else +// m_proxyManager = new Swift::SOCKS5BytestreamProxiesManager(m_component->getNetworkFactories()->getConnectionFactory(), m_component->getNetworkFactories()->getTimerFactory(), m_component->getNetworkFactories()->getDomainNameResolver(), m_component->getIQRouter(), "bar.com"); +// #endif +// boost::shared_ptr server = m_component->getNetworkFactories()->getConnectionServerFactory()->createConnectionServer(19645); +// server->start(); +// #if HAVE_SWIFTEN_3 +// m_proxyServerManager = new Swift::SOCKS5BytestreamServerManager(m_bytestreamRegistry, m_component->getNetworkFactories()->getConnectionServerFactory(), m_component->getNetworkFactories()->getNetworkEnvironment(), m_component->getNetworkFactories()->getNATTraverser()); +// #else +// m_bytestreamServer = new Swift::SOCKS5BytestreamServer(server, m_bytestreamRegistry); +// m_bytestreamServer->start(); +// m_outgoingFTManager = new Swift::CombinedOutgoingFileTransferManager(m_jingleSessionManager, m_component->getIQRouter(), +// m_userManager, m_remoteCandidateSelectorFactory, +// m_localCandidateGeneratorFactory, m_bytestreamRegistry, +// m_bytestreamProxy, m_component->getPresenceOracle(), +// m_bytestreamServer); +// #endif @@ -67,36 +67,36 @@ FileTransferManager::FileTransferManager(Component *component, UserManager *user } FileTransferManager::~FileTransferManager() { -#if !HAVE_SWIFTEN_3 - m_bytestreamServer->stop(); - delete m_remoteCandidateSelectorFactory; - delete m_localCandidateGeneratorFactory; -#endif - delete m_outgoingFTManager; - delete m_jingleSessionManager; - delete m_bytestreamRegistry; -#if !HAVE_SWIFTEN_3 - delete m_bytestreamServer; - delete m_bytestreamProxy; - delete m_connectivityManager; -#endif +// #if !HAVE_SWIFTEN_3 +// m_bytestreamServer->stop(); +// delete m_remoteCandidateSelectorFactory; +// delete m_localCandidateGeneratorFactory; +// #endif +// delete m_outgoingFTManager; +// delete m_jingleSessionManager; +// delete m_bytestreamRegistry; +// #if !HAVE_SWIFTEN_3 +// delete m_bytestreamServer; +// delete m_bytestreamProxy; +// delete m_connectivityManager; +// #endif } FileTransferManager::Transfer FileTransferManager::sendFile(User *user, Buddy *buddy, boost::shared_ptr byteStream, const Swift::StreamInitiationFileInfo &info) { - FileTransferManager::Transfer transfer; - transfer.from = buddy->getJID(); - transfer.to = user->getJID(); - transfer.readByteStream = byteStream; - - LOG4CXX_INFO(logger, "Starting FT from '" << transfer.from << "' to '" << transfer.to << "'") - - transfer.ft = m_outgoingFTManager->createOutgoingFileTransfer(transfer.from, transfer.to, transfer.readByteStream, info); -// if (transfer.ft) { -// m_filetransfers.push_back(ft); -// ft->onStateChange.connect(boost::bind(&User::handleFTStateChanged, this, _1, Buddy::JIDToLegacyName(from), info.getName(), info.getSize(), id)); -// transfer.ft->start(); -// } - return transfer; +// FileTransferManager::Transfer transfer; +// transfer.from = buddy->getJID(); +// transfer.to = user->getJID(); +// transfer.readByteStream = byteStream; +// +// LOG4CXX_INFO(logger, "Starting FT from '" << transfer.from << "' to '" << transfer.to << "'") +// +// transfer.ft = m_outgoingFTManager->createOutgoingFileTransfer(transfer.from, transfer.to, transfer.readByteStream, info); +// // if (transfer.ft) { +// // m_filetransfers.push_back(ft); +// // ft->onStateChange.connect(boost::bind(&User::handleFTStateChanged, this, _1, Buddy::JIDToLegacyName(from), info.getName(), info.getSize(), id)); +// // transfer.ft->start(); +// // } +// return transfer; } } diff --git a/src/localbuddy.cpp b/src/localbuddy.cpp index ef695e17cf0fa4bb4e5947e86abea2c034a49b23..c4af3d0516b7d77c1ab12dc72ffca196e4e33f91 100644 --- a/src/localbuddy.cpp +++ b/src/localbuddy.cpp @@ -75,9 +75,7 @@ void LocalBuddy::setAlias(const std::string &alias) { m_alias = alias; if (changed) { - if (getRosterManager()->getUser()->getComponent()->inServerMode() || getRosterManager()->isRemoteRosterSupported()) { - getRosterManager()->sendBuddyRosterPush(this); - } + getRosterManager()->doUpdateBuddy(this); getRosterManager()->storeBuddy(this); } } @@ -95,9 +93,7 @@ void LocalBuddy::setGroups(const std::vector &groups) { m_groups = groups; if (changed) { - if (getRosterManager()->getUser()->getComponent()->inServerMode() || getRosterManager()->isRemoteRosterSupported()) { - getRosterManager()->sendBuddyRosterPush(this); - } + getRosterManager()->doUpdateBuddy(this); getRosterManager()->storeBuddy(this); } } diff --git a/src/networkpluginserver.cpp b/src/networkpluginserver.cpp index bdee11dc38ddf0d471dca87b2dfd0d87b4c80a4e..3ebe7fb25b6f1809bfd871123076f7fc7330dc47 100644 --- a/src/networkpluginserver.cpp +++ b/src/networkpluginserver.cpp @@ -28,11 +28,12 @@ #include "transport/localbuddy.h" #include "transport/config.h" #include "transport/conversation.h" -#include "transport/vcardresponder.h" #include "transport/rosterresponder.h" #include "transport/memoryreadbytestream.h" #include "transport/logging.h" #include "transport/admininterface.h" +#include "transport/frontend.h" +#include "transport/factory.h" #include "blockresponder.h" #include "Swiften/Server/ServerStanzaChannel.h" #include "Swiften/Elements/StreamError.h" @@ -47,7 +48,6 @@ #include "Swiften/Elements/SpectrumErrorPayload.h" #include "transport/protocol.pb.h" #include "transport/util.h" -#include "transport/discoitemsresponder.h" #include "boost/date_time/posix_time/posix_time.hpp" #include "boost/signal.hpp" @@ -259,7 +259,7 @@ static void handleBuddyPayload(LocalBuddy *buddy, const pbnetwork::Buddy &payloa buddy->setBlocked(payload.blocked()); } -NetworkPluginServer::NetworkPluginServer(Component *component, Config *config, UserManager *userManager, FileTransferManager *ftManager, DiscoItemsResponder *discoItemsResponder) { +NetworkPluginServer::NetworkPluginServer(Component *component, Config *config, UserManager *userManager, FileTransferManager *ftManager) { _server = this; m_ftManager = ftManager; m_userManager = userManager; @@ -276,7 +276,6 @@ NetworkPluginServer::NetworkPluginServer(Component *component, Config *config, U #else m_serializer = new Swift::XMPPSerializer(&m_collection2, Swift::ClientStreamType); #endif - m_discoItemsResponder = discoItemsResponder; m_component->m_factory = new NetworkFactory(this); m_userManager->onUserCreated.connect(boost::bind(&NetworkPluginServer::handleUserCreated, this, _1)); m_userManager->onUserDestroyed.connect(boost::bind(&NetworkPluginServer::handleUserDestroyed, this, _1)); @@ -297,20 +296,16 @@ NetworkPluginServer::NetworkPluginServer(Component *component, Config *config, U m_collectTimer->start(); } - m_vcardResponder = new VCardResponder(component->getIQRouter(), component->getNetworkFactories(), userManager); - m_vcardResponder->onVCardRequired.connect(boost::bind(&NetworkPluginServer::handleVCardRequired, this, _1, _2, _3)); - m_vcardResponder->onVCardUpdated.connect(boost::bind(&NetworkPluginServer::handleVCardUpdated, this, _1, _2)); - m_vcardResponder->start(); + m_component->getFrontend()->onVCardRequired.connect(boost::bind(&NetworkPluginServer::handleVCardRequired, this, _1, _2, _3)); + m_component->getFrontend()->onVCardUpdated.connect(boost::bind(&NetworkPluginServer::handleVCardUpdated, this, _1, _2)); - m_rosterResponder = new RosterResponder(component->getIQRouter(), userManager); - m_rosterResponder->onBuddyAdded.connect(boost::bind(&NetworkPluginServer::handleBuddyAdded, this, _1, _2)); - m_rosterResponder->onBuddyRemoved.connect(boost::bind(&NetworkPluginServer::handleBuddyRemoved, this, _1)); - m_rosterResponder->onBuddyUpdated.connect(boost::bind(&NetworkPluginServer::handleBuddyUpdated, this, _1, _2)); - m_rosterResponder->start(); + m_component->getFrontend()->onBuddyAdded.connect(boost::bind(&NetworkPluginServer::handleBuddyAdded, this, _1, _2)); + m_component->getFrontend()->onBuddyRemoved.connect(boost::bind(&NetworkPluginServer::handleBuddyRemoved, this, _1)); + m_component->getFrontend()->onBuddyUpdated.connect(boost::bind(&NetworkPluginServer::handleBuddyUpdated, this, _1, _2)); - m_blockResponder = new BlockResponder(component->getIQRouter(), userManager); - m_blockResponder->onBlockToggled.connect(boost::bind(&NetworkPluginServer::handleBlockToggled, this, _1)); - m_blockResponder->start(); +// // m_blockResponder = new BlockResponder(component->getIQRouter(), userManager); +// // m_blockResponder->onBlockToggled.connect(boost::bind(&NetworkPluginServer::handleBlockToggled, this, _1)); +// // m_blockResponder->start(); m_server = component->getNetworkFactories()->getConnectionServerFactory()->createConnectionServer(Swift::HostAddress(CONFIG_STRING(m_config, "service.backend_host")), boost::lexical_cast(CONFIG_STRING(m_config, "service.backend_port"))); m_server->onNewConnection.connect(boost::bind(&NetworkPluginServer::handleNewClientConnection, this, _1)); @@ -332,9 +327,9 @@ NetworkPluginServer::~NetworkPluginServer() { m_server->stop(); m_server.reset(); delete m_component->m_factory; - delete m_vcardResponder; - delete m_rosterResponder; - delete m_blockResponder; +// delete m_vcardResponder; +// delete m_rosterResponder; +// delete m_blockResponder; } void NetworkPluginServer::start() { @@ -508,7 +503,7 @@ void NetworkPluginServer::handleVCardPayload(const std::string &data) { vcard->setPhoto(Swift::createByteArray(payload.photo())); - m_vcardResponder->sendVCard(payload.id(), vcard); + m_userManager->sendVCard(payload.id(), vcard); } void NetworkPluginServer::handleAuthorizationPayload(const std::string &data) { @@ -538,7 +533,7 @@ void NetworkPluginServer::handleAuthorizationPayload(const std::string &data) { response->setFrom(Swift::JID(name, m_component->getJID().toString())); response->setType(Swift::Presence::Subscribe); - m_component->getStanzaChannel()->sendPresence(response); + m_component->getFrontend()->sendPresence(response); } void NetworkPluginServer::handleChatStatePayload(const std::string &data, Swift::ChatState::ChatStateType type) { @@ -992,9 +987,9 @@ void NetworkPluginServer::handleRoomListPayload(const std::string &data) { return; } - m_discoItemsResponder->clearRooms(); + m_component->getFrontend()->clearRoomList(); for (int i = 0; i < payload.room_size() && i < payload.name_size(); i++) { - m_discoItemsResponder->addRoom(Swift::JID::getEscapedNode(payload.room(i)) + "@" + m_component->getJID().toString(), payload.name(i)); + m_component->getFrontend()->addRoomToRoomList(Swift::JID::getEscapedNode(payload.room(i)) + "@" + m_component->getJID().toString(), payload.name(i)); } } #if HAVE_SWIFTEN_3 @@ -1056,7 +1051,7 @@ void NetworkPluginServer::handleElement(boost::shared_ptr elemen return; } - m_component->getStanzaChannel()->sendMessage(message); + m_component->getFrontend()->sendMessage(message); return; } @@ -1072,29 +1067,30 @@ void NetworkPluginServer::handleElement(boost::shared_ptr elemen conv->handleRawPresence(presence); } else { - m_component->getStanzaChannel()->sendPresence(presence); + m_component->getFrontend()->sendPresence(presence); } return; } - boost::shared_ptr iq = boost::dynamic_pointer_cast(stanza); - if (iq) { - if (m_id2resource.find(stanza->getTo().toBare().toString() + stanza->getID()) != m_id2resource.end()) { - iq->setTo(Swift::JID(iq->getTo().getNode(), iq->getTo().getDomain(), m_id2resource[stanza->getTo().toBare().toString() + stanza->getID()])); - m_id2resource.erase(stanza->getTo().toBare().toString() + stanza->getID()); - } - else { - Swift::Presence::ref highest = m_component->getPresenceOracle()->getHighestPriorityPresence(user->getJID()); - if (highest) { - iq->setTo(highest->getFrom()); - } else { - iq->setTo(user->getJID()); - } - } - m_component->getIQRouter()->sendIQ(iq); - return; - } + // TODO: FIX TO MAKE RAW XML BACKENDS WORKING AGAIN. +// boost::shared_ptr iq = boost::dynamic_pointer_cast(stanza); +// if (iq) { +// if (m_id2resource.find(stanza->getTo().toBare().toString() + stanza->getID()) != m_id2resource.end()) { +// iq->setTo(Swift::JID(iq->getTo().getNode(), iq->getTo().getDomain(), m_id2resource[stanza->getTo().toBare().toString() + stanza->getID()])); +// m_id2resource.erase(stanza->getTo().toBare().toString() + stanza->getID()); +// } +// else { +// Swift::Presence::ref highest = m_component->getPresenceOracle()->getHighestPriorityPresence(user->getJID()); +// if (highest) { +// iq->setTo(highest->getFrom()); +// } else { +// iq->setTo(user->getJID()); +// } +// } +// m_component->getFrontend()->sendIQ(iq); +// return; +// } } void NetworkPluginServer::handleRawXML(const std::string &xml) { diff --git a/src/presenceoracle.cpp b/src/presenceoracle.cpp index f84b0a55795b105c2282ae61066d19ebeb070b3a..642a1b6ee067daa2823392e552dc8bf79161b66f 100644 --- a/src/presenceoracle.cpp +++ b/src/presenceoracle.cpp @@ -19,6 +19,7 @@ */ #include "transport/presenceoracle.h" +#include "transport/frontend.h" #include "Swiften/Elements/MUCPayload.h" #include @@ -27,15 +28,15 @@ using namespace Swift; namespace Transport { -PresenceOracle::PresenceOracle(StanzaChannel* stanzaChannel) { - stanzaChannel_ = stanzaChannel; - stanzaChannel_->onPresenceReceived.connect(boost::bind(&PresenceOracle::handleIncomingPresence, this, _1)); - stanzaChannel_->onAvailableChanged.connect(boost::bind(&PresenceOracle::handleStanzaChannelAvailableChanged, this, _1)); +PresenceOracle::PresenceOracle(Frontend* frontend) { + frontend_ = frontend; + frontend_->onPresenceReceived.connect(boost::bind(&PresenceOracle::handleIncomingPresence, this, _1)); + frontend_->onAvailableChanged.connect(boost::bind(&PresenceOracle::handleStanzaChannelAvailableChanged, this, _1)); } PresenceOracle::~PresenceOracle() { - stanzaChannel_->onPresenceReceived.disconnect(boost::bind(&PresenceOracle::handleIncomingPresence, this, _1)); - stanzaChannel_->onAvailableChanged.disconnect(boost::bind(&PresenceOracle::handleStanzaChannelAvailableChanged, this, _1)); + frontend_->onPresenceReceived.disconnect(boost::bind(&PresenceOracle::handleIncomingPresence, this, _1)); + frontend_->onAvailableChanged.disconnect(boost::bind(&PresenceOracle::handleStanzaChannelAvailableChanged, this, _1)); } void PresenceOracle::handleStanzaChannelAvailableChanged(bool available) { diff --git a/src/rostermanager.cpp b/src/rostermanager.cpp index b91a9e432be1198d9404edabc31446a9328ec9d1..f0c23199350d5e5bbc0310d13c54db70efc50769 100644 --- a/src/rostermanager.cpp +++ b/src/rostermanager.cpp @@ -26,6 +26,8 @@ #include "transport/buddy.h" #include "transport/user.h" #include "transport/logging.h" +#include "transport/frontend.h" +#include "transport/factory.h" #include "Swiften/Roster/SetRosterRequest.h" #include "Swiften/Elements/RosterPayload.h" #include "Swiften/Elements/RosterItemPayload.h" @@ -46,33 +48,15 @@ RosterManager::RosterManager(User *user, Component *component){ m_rosterStorage = NULL; m_user = user; m_component = component; - m_setBuddyTimer = m_component->getNetworkFactories()->getTimerFactory()->createTimer(1000); - m_RIETimer = m_component->getNetworkFactories()->getTimerFactory()->createTimer(5000); - m_RIETimer->onTick.connect(boost::bind(&RosterManager::sendRIE, this)); - - m_supportRemoteRoster = false; - - if (!m_component->inServerMode()) { - m_remoteRosterRequest = AddressedRosterRequest::ref(new AddressedRosterRequest(m_component->getIQRouter(), m_user->getJID().toBare())); - m_remoteRosterRequest->onResponse.connect(boost::bind(&RosterManager::handleRemoteRosterResponse, this, _1, _2)); - m_remoteRosterRequest->send(); - } } RosterManager::~RosterManager() { - m_setBuddyTimer->stop(); - m_RIETimer->stop(); if (m_rosterStorage) { m_rosterStorage->storeBuddies(); } sendUnavailablePresences(m_user->getJID().toBare()); - if (m_remoteRosterRequest) { - m_remoteRosterRequest->onResponse.disconnect_all_slots(); - m_component->getIQRouter()->removeHandler(m_remoteRosterRequest); - } - for (std::map, boost::pool_allocator< std::pair > >::iterator it = m_buddies.begin(); it != m_buddies.end(); it++) { Buddy *buddy = (*it).second; if (!buddy) { @@ -81,27 +65,12 @@ RosterManager::~RosterManager() { delete buddy; } - if (m_requests.size() != 0) { - LOG4CXX_INFO(logger, m_user->getJID().toString() << ": Removing " << m_requests.size() << " unresponded IQs"); - BOOST_FOREACH(Swift::SetRosterRequest::ref request, m_requests) { - request->onResponse.disconnect_all_slots(); - m_component->getIQRouter()->removeHandler(request); - } - m_requests.clear(); - } - boost::singleton_pool::release_memory(); if (m_rosterStorage) delete m_rosterStorage; } -void RosterManager::setBuddy(Buddy *buddy) { -// m_setBuddyTimer->onTick.connect(boost::bind(&RosterManager::setBuddyCallback, this, buddy)); -// m_setBuddyTimer->start(); - setBuddyCallback(buddy); -} - void RosterManager::removeBuddy(const std::string &name) { Buddy *buddy = getBuddy(name); if (!buddy) { @@ -109,12 +78,7 @@ void RosterManager::removeBuddy(const std::string &name) { return; } - if (m_component->inServerMode() || m_supportRemoteRoster) { - sendBuddyRosterRemove(buddy); - } - else { - sendBuddyUnsubscribePresence(buddy); - } + doRemoveBuddy(buddy); if (m_rosterStorage) m_rosterStorage->removeBuddy(buddy); @@ -123,78 +87,19 @@ void RosterManager::removeBuddy(const std::string &name) { 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) - if (m_component->inServerMode() && (!m_user->isConnected() || m_user->shouldCacheMessages())) - return; - - Swift::RosterPayload::ref payload = Swift::RosterPayload::ref(new Swift::RosterPayload()); - Swift::RosterItemPayload item; - item.setJID(buddy->getJID().toBare()); - item.setName(buddy->getAlias()); - item.setGroups(buddy->getGroups()); - item.setSubscription(Swift::RosterItemPayload::Both); - - payload->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(payload, presence->getFrom(), m_component->getIQRouter()); - request->onResponse.connect(boost::bind(&RosterManager::handleBuddyRosterPushResponse, this, _1, request, buddy->getName())); - request->send(); - m_requests.push_back(request); - } - } - else { - Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(payload, m_user->getJID().toBare(), m_component->getIQRouter()); - request->onResponse.connect(boost::bind(&RosterManager::handleBuddyRosterPushResponse, this, _1, request, buddy->getName())); - request->send(); - m_requests.push_back(request); - } - - if (buddy->getSubscription() != Buddy::Both) { - buddy->setSubscription(Buddy::Both); - storeBuddy(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); + m_component->getFrontend()->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); + m_component->getFrontend()->sendPresence(response); } void RosterManager::sendBuddySubscribePresence(Buddy *buddy) { @@ -205,35 +110,18 @@ void RosterManager::sendBuddySubscribePresence(Buddy *buddy) { if (!buddy->getAlias().empty()) { response->addPayload(boost::make_shared(buddy->getAlias())); } - m_component->getStanzaChannel()->sendPresence(response); + m_component->getFrontend()->sendPresence(response); } void RosterManager::handleBuddyChanged(Buddy *buddy) { } -void RosterManager::setBuddyCallback(Buddy *buddy) { +void RosterManager::setBuddy(Buddy *buddy) { LOG4CXX_INFO(logger, "Associating buddy " << buddy->getName() << " with " << m_user->getJID().toString()); m_buddies[buddy->getName()] = buddy; onBuddySet(buddy); - // In server mode the only way is to send jabber:iq:roster push. - // In component mode we send RIE or Subscribe presences, based on features. - if (m_component->inServerMode()) { - sendBuddyRosterPush(buddy); - } - else { - if (buddy->getSubscription() == Buddy::Both) { - LOG4CXX_INFO(logger, m_user->getJID().toString() << ": Not forwarding this buddy, because subscription=both"); - return; - } - - if (m_supportRemoteRoster) { - sendBuddyRosterPush(buddy); - } - else { - m_RIETimer->start(); - } - } + doAddBuddy(buddy); if (m_rosterStorage) m_rosterStorage->storeBuddy(buddy); @@ -252,113 +140,10 @@ void RosterManager::storeBuddy(Buddy *buddy) { } } -void RosterManager::handleBuddyRosterPushResponse(Swift::ErrorPayload::ref error, Swift::SetRosterRequest::ref request, const std::string &key) { - LOG4CXX_INFO(logger, "handleBuddyRosterPushResponse called for buddy " << key); - if (m_buddies[key] != NULL) { - if (m_buddies[key]->isAvailable()) { - std::vector &presences = m_buddies[key]->generatePresenceStanzas(255); - BOOST_FOREACH(Swift::Presence::ref &presence, presences) { - m_component->getStanzaChannel()->sendPresence(presence); - } - } - } - else { - LOG4CXX_WARN(logger, "handleBuddyRosterPushResponse called for unknown buddy " << key); - } - - m_requests.remove(request); - request->onResponse.disconnect_all_slots(); -} - -void RosterManager::handleRemoteRosterResponse(boost::shared_ptr payload, Swift::ErrorPayload::ref error) { - m_remoteRosterRequest.reset(); - if (error) { - m_supportRemoteRoster = false; - LOG4CXX_INFO(logger, m_user->getJID().toString() << ": This server does not support remote roster protoXEP"); - return; - } - - LOG4CXX_INFO(logger, m_user->getJID().toString() << ": This server supports remote roster protoXEP"); - m_supportRemoteRoster = true; - - //If we receive empty RosterPayload on login (not register) initiate full RosterPush - if(!m_buddies.empty() && payload->getItems().empty()){ - LOG4CXX_INFO(logger, "Received empty Roster upon login. Pushing full Roster."); - for(std::map, boost::pool_allocator< std::pair > >::const_iterator c_it = m_buddies.begin(); - c_it != m_buddies.end(); c_it++) { - sendBuddyRosterPush(c_it->second); - } - } - return; - - BOOST_FOREACH(const Swift::RosterItemPayload &item, payload->getItems()) { - std::string legacyName = Buddy::JIDToLegacyName(item.getJID()); - if (m_buddies.find(legacyName) != m_buddies.end()) { - continue; - } - - if (legacyName.empty()) { - continue; - } - - BuddyInfo buddyInfo; - buddyInfo.id = -1; - buddyInfo.alias = item.getName(); - buddyInfo.legacyName = legacyName; - buddyInfo.subscription = "both"; - buddyInfo.flags = Buddy::buddyFlagsFromJID(item.getJID()); - buddyInfo.groups = item.getGroups(); - - Buddy *buddy = m_component->getFactory()->createBuddy(this, buddyInfo); - if (buddy) { - setBuddy(buddy); - } - } -} - Buddy *RosterManager::getBuddy(const std::string &name) { return m_buddies[name]; } -void RosterManager::sendRIE() { - m_RIETimer->stop(); - - // Check the feature, because proper resource could logout during RIETimer. - std::vector jidWithRIE = m_user->getJIDWithFeature("http://jabber.org/protocol/rosterx"); - - // fallback to normal subscribe - if (jidWithRIE.empty()) { - for (std::map, boost::pool_allocator< std::pair > >::iterator it = m_buddies.begin(); it != m_buddies.end(); it++) { - Buddy *buddy = (*it).second; - if (!buddy) { - continue; - } - sendBuddySubscribePresence(buddy); - } - return; - } - - Swift::RosterItemExchangePayload::ref payload = Swift::RosterItemExchangePayload::ref(new Swift::RosterItemExchangePayload()); - for (std::map, boost::pool_allocator< std::pair > >::iterator it = m_buddies.begin(); it != m_buddies.end(); it++) { - Buddy *buddy = (*it).second; - if (!buddy) { - continue; - } - Swift::RosterItemExchangePayload::Item item; - item.setJID(buddy->getJID().toBare()); - item.setName(buddy->getAlias()); - item.setAction(Swift::RosterItemExchangePayload::Item::Add); - item.setGroups(buddy->getGroups()); - - payload->addItem(item); - } - - BOOST_FOREACH(Swift::JID &jid, jidWithRIE) { - LOG4CXX_INFO(logger, "Sending RIE stanza to " << jid.toString()); - boost::shared_ptr > request(new Swift::GenericRequest(Swift::IQ::Set, jid, payload, m_component->getIQRouter())); - request->send(); - } -} void RosterManager::handleSubscription(Swift::Presence::ref presence) { std::string legacyName = Buddy::JIDToLegacyName(presence->getTo()); @@ -392,7 +177,7 @@ void RosterManager::handleSubscription(Swift::Presence::ref presence) { default: return; } - m_component->getStanzaChannel()->sendPresence(response); + m_component->getFrontend()->sendPresence(response); } else { @@ -431,7 +216,7 @@ void RosterManager::handleSubscription(Swift::Presence::ref presence) { default: return; } - m_component->getStanzaChannel()->sendPresence(response); + m_component->getFrontend()->sendPresence(response); } } else { @@ -450,7 +235,7 @@ void RosterManager::handleSubscription(Swift::Presence::ref presence) { response->setType(Swift::Presence::Subscribed); BOOST_FOREACH(Swift::Presence::ref ¤tPresence, presences) { currentPresence->setTo(presence->getFrom()); - m_component->getStanzaChannel()->sendPresence(currentPresence); + m_component->getFrontend()->sendPresence(currentPresence); } if (buddy->getSubscription() != Buddy::Both) { buddy->setSubscription(Buddy::Both); @@ -526,17 +311,17 @@ void RosterManager::handleSubscription(Swift::Presence::ref presence) { } } - m_component->getStanzaChannel()->sendPresence(response); + m_component->getFrontend()->sendPresence(response); // We have to act as buddy and send its subscribe/unsubscribe just to be sure... switch (response->getType()) { case Swift::Presence::Unsubscribed: response->setType(Swift::Presence::Unsubscribe); - m_component->getStanzaChannel()->sendPresence(response); + m_component->getFrontend()->sendPresence(response); break; case Swift::Presence::Subscribed: response->setType(Swift::Presence::Subscribe); - m_component->getStanzaChannel()->sendPresence(response); + m_component->getFrontend()->sendPresence(response); break; default: break; @@ -595,7 +380,7 @@ void RosterManager::sendCurrentPresences(const Swift::JID &to) { std::vector &presences = buddy->generatePresenceStanzas(255); BOOST_FOREACH(Swift::Presence::ref &presence, presences) { presence->setTo(to); - m_component->getStanzaChannel()->sendPresence(presence); + m_component->getFrontend()->sendPresence(presence); } } } @@ -606,7 +391,7 @@ void RosterManager::sendCurrentPresence(const Swift::JID &from, const Swift::JID std::vector &presences = buddy->generatePresenceStanzas(255); BOOST_FOREACH(Swift::Presence::ref &presence, presences) { presence->setTo(to); - m_component->getStanzaChannel()->sendPresence(presence); + m_component->getFrontend()->sendPresence(presence); } } else { @@ -614,7 +399,7 @@ void RosterManager::sendCurrentPresence(const Swift::JID &from, const Swift::JID response->setTo(to); response->setFrom(from); response->setType(Swift::Presence::Unavailable); - m_component->getStanzaChannel()->sendPresence(response); + m_component->getFrontend()->sendPresence(response); } } @@ -634,7 +419,7 @@ void RosterManager::sendUnavailablePresences(const Swift::JID &to) { Swift::Presence::Type type = presence->getType(); presence->setTo(to); presence->setType(Swift::Presence::Unavailable); - m_component->getStanzaChannel()->sendPresence(presence); + m_component->getFrontend()->sendPresence(presence); presence->setType(type); } } @@ -645,7 +430,7 @@ void RosterManager::sendUnavailablePresences(const Swift::JID &to) { response->setTo(to); response->setFrom(m_component->getJID()); response->setType(Swift::Presence::Unavailable); - m_component->getStanzaChannel()->sendPresence(response); + m_component->getFrontend()->sendPresence(response); } } diff --git a/src/tests/basictest.cpp b/src/tests/basictest.cpp index 1931953bc74a8efe3403579144341ad626f898f4..190428e547892530e80c7e1becf7b14bbd799e50 100644 --- a/src/tests/basictest.cpp +++ b/src/tests/basictest.cpp @@ -8,6 +8,9 @@ #include "transport/conversation.h" #include "transport/usermanager.h" #include "transport/localbuddy.h" +#include "XMPPFrontend.h" +#include "XMPPUserRegistration.h" +#include "XMPPUserManager.h" #include #include #include @@ -21,7 +24,7 @@ #include "Swiften/Serializer/GenericPayloadSerializer.h" -#include "../storageparser.h" +#include "storageparser.h" #include "Swiften/Parser/PayloadParsers/AttentionParser.h" #include "Swiften/Serializer/PayloadSerializers/AttentionSerializer.h" #include "Swiften/Parser/PayloadParsers/XHTMLIMParser.h" @@ -32,8 +35,8 @@ #include "Swiften/Serializer/PayloadSerializers/GatewayPayloadSerializer.h" #include "Swiften/Serializer/PayloadSerializers/SpectrumErrorSerializer.h" #include "Swiften/Parser/PayloadParsers/MUCPayloadParser.h" -#include "transport/BlockParser.h" -#include "transport/BlockSerializer.h" +#include "BlockParser.h" +#include "BlockSerializer.h" #include "Swiften/Parser/PayloadParsers/InvisibleParser.h" #include "Swiften/Serializer/PayloadSerializers/InvisibleSerializer.h" @@ -54,16 +57,14 @@ void BasicTest::setMeUp (void) { userRegistry = new UserRegistry(cfg, factories); - component = new Component(loop, factories, cfg, factory, userRegistry); - component->start(); + frontend = new Transport::XMPPFrontend(); - itemsResponder = new DiscoItemsResponder(component); - itemsResponder->start(); + component = new Component(frontend, loop, factories, cfg, factory, userRegistry); + component->start(); - userManager = new UserManager(component, userRegistry, itemsResponder, storage); + userManager = frontend->createUserManager(component, userRegistry, storage); - userRegistration = new UserRegistration(component, userManager, storage); - userRegistration->start(); + itemsResponder = frontend->getDiscoItemsResponder(); payloadSerializers = new Swift::FullPayloadSerializerCollection(); payloadParserFactories = new Swift::FullPayloadParserFactoryCollection(); @@ -94,7 +95,7 @@ void BasicTest::setMeUp (void) { serverFromClientSession->onDataWritten.connect(boost::bind(&BasicTest::handleDataReceived, this, _1)); - dynamic_cast(component->getStanzaChannel())->addSession(serverFromClientSession); + dynamic_cast(static_cast(component->getFrontend())->getStanzaChannel())->addSession(serverFromClientSession); parser->parse(""); parser2->parse(""); received.clear(); @@ -104,12 +105,13 @@ void BasicTest::setMeUp (void) { } void BasicTest::tearMeDown (void) { - dynamic_cast(component->getStanzaChannel())->removeSession(serverFromClientSession); + dynamic_cast(static_cast(component->getFrontend())->getStanzaChannel())->removeSession(serverFromClientSession); if (serverFromClientSession2) { - dynamic_cast(component->getStanzaChannel())->removeSession(serverFromClientSession2); + dynamic_cast(static_cast(component->getFrontend())->getStanzaChannel())->removeSession(serverFromClientSession2); serverFromClientSession2.reset(); } delete component; + delete frontend; delete userRegistry; delete factories; delete factory; @@ -118,8 +120,7 @@ void BasicTest::tearMeDown (void) { delete parser; delete parser2; delete storage; - delete userRegistration; - delete itemsResponder; +// delete userRegistration; received.clear(); received2.clear(); receivedData.clear(); @@ -168,15 +169,15 @@ void BasicTest::handleStreamEnd() { } void BasicTest::injectPresence(boost::shared_ptr &response) { - dynamic_cast(component->getStanzaChannel())->onPresenceReceived(response); + dynamic_cast(static_cast(component->getFrontend())->getStanzaChannel())->onPresenceReceived(response); } void BasicTest::injectIQ(boost::shared_ptr iq) { - dynamic_cast(component->getStanzaChannel())->onIQReceived(iq); + dynamic_cast(static_cast(component->getFrontend())->getStanzaChannel())->onIQReceived(iq); } void BasicTest::injectMessage(boost::shared_ptr msg) { - dynamic_cast(component->getStanzaChannel())->onMessageReceived(msg); + dynamic_cast(static_cast(component->getFrontend())->getStanzaChannel())->onMessageReceived(msg); } Swift::Stanza *BasicTest::getStanza(boost::shared_ptr element) { @@ -217,7 +218,7 @@ void BasicTest::connectSecondResource() { serverFromClientSession2->onDataWritten.connect(boost::bind(&BasicTest::handleDataReceived2, this, _1)); - dynamic_cast(component->getStanzaChannel())->addSession(serverFromClientSession2); + dynamic_cast(static_cast(component->getFrontend())->getStanzaChannel())->addSession(serverFromClientSession2); userRegistry->isValidUserPassword(Swift::JID("user@localhost/resource2"), serverFromClientSession2.get(), Swift::createSafeByteArray("password")); userRegistry->onPasswordValid(Swift::JID("user@localhost/resource2")); diff --git a/src/tests/basictest.h b/src/tests/basictest.h index d3a133fa043447c47874d421b2c8304f9bede167..5023eceb2dd7f4524660da51f688ff403c92efe0 100644 --- a/src/tests/basictest.h +++ b/src/tests/basictest.h @@ -33,9 +33,12 @@ #include "transport/conversation.h" #include "transport/usermanager.h" #include "transport/userregistration.h" -#include "transport/discoitemsresponder.h" +#include "discoitemsresponder.h" #include "transport/localbuddy.h" #include "transport/storagebackend.h" +#include "transport/factory.h" +#include "XMPPFrontend.h" +#include "XMPPUserRegistration.h" #include #include @@ -269,8 +272,9 @@ class BasicTest : public Swift::XMPPParserClient { std::string receivedData; std::string receivedData2; StorageBackend *storage; - UserRegistration *userRegistration; + XMPPUserRegistration *userRegistration; DiscoItemsResponder *itemsResponder; bool stream1_active; + Transport::XMPPFrontend *frontend; }; diff --git a/src/tests/component.cpp b/src/tests/component.cpp index 1ca010ea2c81dc97cd64aae55461bca02e5f52b7..3e9338f87287602918432e1c9f2ae8d0df8a7160 100644 --- a/src/tests/component.cpp +++ b/src/tests/component.cpp @@ -28,11 +28,11 @@ class ComponentTest : public CPPUNIT_NS :: TestFixture, public BasicTest { public: void setUp (void) { onUserPresenceReceived = false; - onUserDiscoInfoReceived = false; + onCapabilitiesReceived = false; setMeUp(); component->onUserPresenceReceived.connect(boost::bind(&ComponentTest::handleUserPresenceReceived, this, _1)); - component->onUserDiscoInfoReceived.connect(boost::bind(&ComponentTest::handleUserDiscoInfoReceived, this, _1, _2)); + component->getFrontend()->onCapabilitiesReceived.connect(boost::bind(&ComponentTest::handleUserDiscoInfoReceived, this, _1, _2)); } void tearDown (void) { @@ -40,7 +40,7 @@ class ComponentTest : public CPPUNIT_NS :: TestFixture, public BasicTest { } void handleUserDiscoInfoReceived(const Swift::JID& jid, boost::shared_ptr info) { - onUserDiscoInfoReceived = true; + onCapabilitiesReceived = true; } void handleUserPresenceReceived(Swift::Presence::ref presence) { @@ -51,7 +51,7 @@ class ComponentTest : public CPPUNIT_NS :: TestFixture, public BasicTest { Swift::Presence::ref response = Swift::Presence::create(); response->setTo("somebody@localhost"); response->setFrom("user@localhost/resource"); - dynamic_cast(component->getStanzaChannel())->onPresenceReceived(response); + dynamic_cast(static_cast(component->getFrontend())->getStanzaChannel())->onPresenceReceived(response); loop->processEvents(); CPPUNIT_ASSERT_EQUAL(0, (int) received.size()); @@ -63,7 +63,7 @@ class ComponentTest : public CPPUNIT_NS :: TestFixture, public BasicTest { response->setTo("localhost"); response->setFrom("user@localhost/resource"); response->setType(Swift::Presence::Error); - dynamic_cast(component->getStanzaChannel())->onPresenceReceived(response); + dynamic_cast(static_cast(component->getFrontend())->getStanzaChannel())->onPresenceReceived(response); loop->processEvents(); CPPUNIT_ASSERT_EQUAL(0, (int) received.size()); @@ -73,16 +73,17 @@ class ComponentTest : public CPPUNIT_NS :: TestFixture, public BasicTest { Swift::Presence::ref response = Swift::Presence::create(); response->setTo("localhost"); response->setFrom("user@localhost/resource"); - dynamic_cast(component->getStanzaChannel())->onPresenceReceived(response); + dynamic_cast(static_cast(component->getFrontend())->getStanzaChannel())->onPresenceReceived(response); loop->processEvents(); + CPPUNIT_ASSERT_EQUAL(1, (int) received.size()); CPPUNIT_ASSERT(getStanza(received[0])->getPayload()); CPPUNIT_ASSERT(onUserPresenceReceived); } private: bool onUserPresenceReceived; - bool onUserDiscoInfoReceived; + bool onCapabilitiesReceived; }; CPPUNIT_TEST_SUITE_REGISTRATION (ComponentTest); diff --git a/src/tests/discoitemsresponder.cpp b/src/tests/discoitemsresponder.cpp index 73c9c8aaec665212bee911b724ba50faa30e5923..e247f8430bafb39891f7e974a3359d429829ca02 100644 --- a/src/tests/discoitemsresponder.cpp +++ b/src/tests/discoitemsresponder.cpp @@ -7,8 +7,6 @@ #include "transport/conversation.h" #include "transport/usermanager.h" #include "transport/localbuddy.h" -#include "transport/settingsadhoccommand.h" -#include "transport/adhocmanager.h" #include #include #include diff --git a/src/tests/gatewayresponder.cpp b/src/tests/gatewayresponder.cpp index 3cefc30649d7e393dafefa8fef9631e5109084de..7d0fbe4bc47959b7c0f26276f7ff4b77b538fe56 100644 --- a/src/tests/gatewayresponder.cpp +++ b/src/tests/gatewayresponder.cpp @@ -7,7 +7,7 @@ #include "transport/rosterresponder.h" #include "transport/usermanager.h" #include "transport/localbuddy.h" -#include "transport/gatewayresponder.h" +#include "gatewayresponder.h" #include #include #include @@ -35,7 +35,7 @@ class GatewayResponderTest : public CPPUNIT_NS :: TestFixture, public BasicTest setMeUp(); connectUser(); - m_gatewayResponder = new GatewayResponder(component->getIQRouter(), userManager); + m_gatewayResponder = new GatewayResponder(static_cast(component->getFrontend())->getIQRouter(), userManager); m_gatewayResponder->start(); received.clear(); diff --git a/src/tests/networkpluginserver.cpp b/src/tests/networkpluginserver.cpp index 8690ce359d9ee579e7db03b3ba0a0138e448e641..c7d9f21fdaa6cc099f0faf1609e7deb735621bc2 100644 --- a/src/tests/networkpluginserver.cpp +++ b/src/tests/networkpluginserver.cpp @@ -7,8 +7,6 @@ #include "transport/conversation.h" #include "transport/usermanager.h" #include "transport/localbuddy.h" -#include "transport/settingsadhoccommand.h" -#include "transport/adhocmanager.h" #include "transport/protocol.pb.h" #include "transport/networkpluginserver.h" #include @@ -54,8 +52,8 @@ class NetworkPluginServerTest : public CPPUNIT_NS :: TestFixture, public BasicTe CPPUNIT_TEST(handleBuddyChangedPayloadUserContactInRoster); CPPUNIT_TEST(handleMessageHeadline); CPPUNIT_TEST(handleConvMessageAckPayload); - CPPUNIT_TEST(handleRawXML); - CPPUNIT_TEST(handleRawXMLSplit); +// CPPUNIT_TEST(handleRawXML); +// CPPUNIT_TEST(handleRawXMLSplit); CPPUNIT_TEST(benchmarkHandleBuddyChangedPayload); CPPUNIT_TEST(benchmarkSendUnavailablePresence); @@ -67,7 +65,7 @@ class NetworkPluginServerTest : public CPPUNIT_NS :: TestFixture, public BasicTe void setUp (void) { setMeUp(); - serv = new NetworkPluginServer(component, cfg, userManager, NULL, NULL); + serv = new NetworkPluginServer(component, cfg, userManager, NULL); connectUser(); received.clear(); } diff --git a/src/tests/rosterresponder.cpp b/src/tests/rosterresponder.cpp index 2c6cf86a008b1f3ac623248d17f6e3716ffd792a..0c2a84d6d268bb9891b3dd13a105164d35fe36ef 100644 --- a/src/tests/rosterresponder.cpp +++ b/src/tests/rosterresponder.cpp @@ -35,7 +35,7 @@ class RosterResponderTest : public CPPUNIT_NS :: TestFixture, public BasicTest { setMeUp(); connectUser(); - m_rosterResponder = new RosterResponder(component->getIQRouter(), userManager); + m_rosterResponder = new RosterResponder(static_cast(component->getFrontend())->getIQRouter(), userManager); m_rosterResponder->onBuddyAdded.connect(boost::bind(&RosterResponderTest::handleBuddyAdded, this, _1, _2)); m_rosterResponder->onBuddyRemoved.connect(boost::bind(&RosterResponderTest::handleBuddyRemoved, this, _1)); m_rosterResponder->onBuddyUpdated.connect(boost::bind(&RosterResponderTest::handleBuddyUpdated, this, _1, _2)); @@ -69,7 +69,7 @@ class RosterResponderTest : public CPPUNIT_NS :: TestFixture, public BasicTest { item.setSubscription(Swift::RosterItemPayload::Both); p->addItem(item); - Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(p, "user@localhost", component->getIQRouter()); + Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(p, "user@localhost", static_cast(component->getFrontend())->getIQRouter()); boost::shared_ptr iq(new Swift::IQ(Swift::IQ::Set)); iq->setTo("icq.localhost"); diff --git a/src/tests/settingsadhoccommand.cpp b/src/tests/settingsadhoccommand.cpp index dd57b3e203a8aac332a5af00ade3ada91a4ca69d..47ffb0aab1c06743be16142b55eab06d6ae9ea6a 100644 --- a/src/tests/settingsadhoccommand.cpp +++ b/src/tests/settingsadhoccommand.cpp @@ -7,8 +7,8 @@ #include "transport/conversation.h" #include "transport/usermanager.h" #include "transport/localbuddy.h" -#include "transport/settingsadhoccommand.h" -#include "transport/adhocmanager.h" +#include "settingsadhoccommand.h" +#include "adhocmanager.h" #include #include #include @@ -39,24 +39,13 @@ class SettingsAdHocCommandTest : public CPPUNIT_NS :: TestFixture, public BasicT CPPUNIT_TEST_SUITE_END(); public: - AdHocManager *adhoc; - SettingsAdHocCommandFactory *settings; - void setUp (void) { setMeUp(); - - adhoc = new AdHocManager(component, itemsResponder, userManager, storage); - adhoc->start(); - settings = new SettingsAdHocCommandFactory(); - adhoc->addAdHocCommand(settings); - received.clear(); } void tearDown (void) { received.clear(); - delete adhoc; - delete settings; tearMeDown(); } diff --git a/src/tests/usermanager.cpp b/src/tests/usermanager.cpp index cbe49747df02056f2e0868eb4519643eb0f2a83b..0bbc7fe42e69f6145f3eb37539c1f5bc6cfc4136 100644 --- a/src/tests/usermanager.cpp +++ b/src/tests/usermanager.cpp @@ -105,7 +105,7 @@ class UserManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTest { response->setTo("localhost"); response->setFrom("user@localhost/resource"); response->setType(Swift::Presence::Probe); - dynamic_cast(component->getStanzaChannel())->onPresenceReceived(response); + dynamic_cast(static_cast(component->getFrontend())->getStanzaChannel())->onPresenceReceived(response); loop->processEvents(); CPPUNIT_ASSERT_EQUAL(3, (int) received.size()); @@ -124,7 +124,7 @@ class UserManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTest { response->setTo("localhost"); response->setFrom("user@localhost"); response->setType(Swift::Presence::Unsubscribed); - dynamic_cast(component->getStanzaChannel())->onPresenceReceived(response); + dynamic_cast(static_cast(component->getFrontend())->getStanzaChannel())->onPresenceReceived(response); loop->processEvents(); CPPUNIT_ASSERT_EQUAL(2, (int) received.size()); @@ -137,7 +137,7 @@ class UserManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTest { response->setTo("localhost"); response->setFrom("user@localhost"); response->setType(Swift::Presence::Error); - dynamic_cast(component->getStanzaChannel())->onPresenceReceived(response); + dynamic_cast(static_cast(component->getFrontend())->getStanzaChannel())->onPresenceReceived(response); loop->processEvents(); CPPUNIT_ASSERT_EQUAL(0, (int) received.size()); @@ -147,7 +147,7 @@ class UserManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTest { response->setFrom("user@localhost"); response->setType(Swift::Presence::Error); response->addPayload(boost::shared_ptr(new Swift::ErrorPayload(Swift::ErrorPayload::SubscriptionRequired))); - dynamic_cast(component->getStanzaChannel())->onPresenceReceived(response); + dynamic_cast(static_cast(component->getFrontend())->getStanzaChannel())->onPresenceReceived(response); loop->processEvents(); CPPUNIT_ASSERT_EQUAL(1, (int) received.size()); @@ -161,7 +161,7 @@ class UserManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTest { response->setTo("localhost"); response->setFrom("user@localhost"); response->setType(Swift::Presence::Unsubscribed); - dynamic_cast(component->getStanzaChannel())->onPresenceReceived(response); + dynamic_cast(static_cast(component->getFrontend())->getStanzaChannel())->onPresenceReceived(response); loop->processEvents(); CPPUNIT_ASSERT_EQUAL(1, (int) received.size()); diff --git a/src/transport.cpp b/src/transport.cpp index 69c2cde700bc7e7d17081fcdc4c96804745b9313..c2b2e571818425d531c96047fd26a91652eb24b4 100644 --- a/src/transport.cpp +++ b/src/transport.cpp @@ -18,297 +18,91 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ + #include "transport/transport.h" +#include "transport/logging.h" +#include "transport/frontend.h" +#include "transport/presenceoracle.h" +#include "transport/config.h" + #include -#include #include -#include "transport/storagebackend.h" -#include "transport/factory.h" -#include "transport/userregistry.h" -#include "transport/logging.h" -#include "storageparser.h" -#ifdef _WIN32 -#include -#include "Swiften/TLS/Schannel/SchannelServerContext.h" -#include "Swiften/TLS/Schannel/SchannelServerContextFactory.h" -#else -#include "Swiften/TLS/PKCS12Certificate.h" -#include "Swiften/TLS/CertificateWithKey.h" -#include "Swiften/TLS/OpenSSL/OpenSSLServerContext.h" -#include "Swiften/TLS/OpenSSL/OpenSSLServerContextFactory.h" -#endif -#include "Swiften/Parser/PayloadParsers/AttentionParser.h" -#include "Swiften/Serializer/PayloadSerializers/AttentionSerializer.h" -#include "Swiften/Parser/PayloadParsers/XHTMLIMParser.h" -#include "Swiften/Serializer/PayloadSerializers/XHTMLIMSerializer.h" -#include "Swiften/Parser/PayloadParsers/StatsParser.h" -#include "Swiften/Serializer/PayloadSerializers/StatsSerializer.h" -#include "Swiften/Parser/PayloadParsers/GatewayPayloadParser.h" -#include "Swiften/Serializer/PayloadSerializers/GatewayPayloadSerializer.h" -#include "Swiften/Serializer/PayloadSerializers/SpectrumErrorSerializer.h" -#include "Swiften/Parser/PayloadParsers/MUCPayloadParser.h" -#include "transport/BlockParser.h" -#include "transport/BlockSerializer.h" -#include "Swiften/Parser/PayloadParsers/InvisibleParser.h" -#include "Swiften/Serializer/PayloadSerializers/InvisibleSerializer.h" -#include "Swiften/Parser/GenericPayloadParserFactory.h" -#include "Swiften/Queries/IQRouter.h" -#include "Swiften/Elements/RosterPayload.h" -#include "Swiften/Elements/InBandRegistrationPayload.h" using namespace Swift; -using namespace boost; namespace Transport { DEFINE_LOGGER(logger, "Component"); -DEFINE_LOGGER(logger_xml, "Component.XML"); +DEFINE_LOGGER(logger_xml, "Component.RAW"); -Component::Component(Swift::EventLoop *loop, Swift::NetworkFactories *factories, Config *config, Factory *factory, Transport::UserRegistry *userRegistry) { - m_component = NULL; +Component::Component(Frontend *frontend, Swift::EventLoop *loop, Swift::NetworkFactories *factories, Config *config, Factory *factory, Transport::UserRegistry *userRegistry) { + m_frontend = frontend; m_userRegistry = NULL; - m_server = NULL; m_reconnectCount = 0; m_config = config; - m_config->onBackendConfigUpdated.connect(boost::bind(&Component::handleBackendConfigChanged, this)); m_factory = factory; m_loop = loop; m_userRegistry = userRegistry; m_rawXML = false; - m_jid = Swift::JID(CONFIG_STRING(m_config, "service.jid")); m_factories = factories; m_reconnectTimer = m_factories->getTimerFactory()->createTimer(3000); - m_reconnectTimer->onTick.connect(bind(&Component::start, this)); - - if (CONFIG_BOOL(m_config, "service.server_mode")) { - LOG4CXX_INFO(logger, "Creating component in server mode on port " << CONFIG_INT(m_config, "service.port")); - m_server = new Swift::Server(loop, m_factories, m_userRegistry, m_jid, CONFIG_STRING(m_config, "service.server"), CONFIG_INT(m_config, "service.port")); - if (!CONFIG_STRING(m_config, "service.cert").empty()) { -#ifndef _WIN32 -//TODO: fix - LOG4CXX_INFO(logger, "Using PKCS#12 certificate " << CONFIG_STRING(m_config, "service.cert")); - LOG4CXX_INFO(logger, "SSLv23_server_method used."); - TLSServerContextFactory *f = new OpenSSLServerContextFactory(); - CertificateWithKey::ref certificate = boost::make_shared(CONFIG_STRING(m_config, "service.cert"), createSafeByteArray(CONFIG_STRING(m_config, "service.cert_password"))); - m_server->addTLSEncryption(f, certificate); -#endif - - } - else { - LOG4CXX_WARN(logger, "No PKCS#12 certificate used. TLS is disabled."); - } -// m_server->start(); - m_stanzaChannel = m_server->getStanzaChannel(); - m_iqRouter = m_server->getIQRouter(); - - m_server->addPayloadParserFactory(new GenericPayloadParserFactory("private", "jabber:iq:private")); - m_server->addPayloadParserFactory(new GenericPayloadParserFactory("attention", "urn:xmpp:attention:0")); - m_server->addPayloadParserFactory(new GenericPayloadParserFactory("html", "http://jabber.org/protocol/xhtml-im")); - m_server->addPayloadParserFactory(new GenericPayloadParserFactory("block", "urn:xmpp:block:0")); - m_server->addPayloadParserFactory(new GenericPayloadParserFactory("invisible", "urn:xmpp:invisible:0")); - m_server->addPayloadParserFactory(new GenericPayloadParserFactory("query", "http://jabber.org/protocol/stats")); - m_server->addPayloadParserFactory(new GenericPayloadParserFactory("query", "jabber:iq:gateway")); - m_server->addPayloadParserFactory(new GenericPayloadParserFactory("x", "http://jabber.org/protocol/muc")); + m_reconnectTimer->onTick.connect(boost::bind(&Component::start, this)); - m_server->addPayloadSerializer(new Swift::AttentionSerializer()); - m_server->addPayloadSerializer(new Swift::XHTMLIMSerializer()); - m_server->addPayloadSerializer(new Transport::BlockSerializer()); - m_server->addPayloadSerializer(new Swift::InvisibleSerializer()); - m_server->addPayloadSerializer(new Swift::StatsSerializer()); - m_server->addPayloadSerializer(new Swift::SpectrumErrorSerializer()); - m_server->addPayloadSerializer(new Swift::GatewayPayloadSerializer()); - - m_server->onDataRead.connect(boost::bind(&Component::handleDataRead, this, _1)); - m_server->onDataWritten.connect(boost::bind(&Component::handleDataWritten, this, _1)); - } - else { - LOG4CXX_INFO(logger, "Creating component in gateway mode"); -#if HAVE_SWIFTEN_3 - m_component = new Swift::Component(m_jid, CONFIG_STRING(m_config, "service.password"), m_factories); -#else - m_component = new Swift::Component(loop, m_factories, m_jid, CONFIG_STRING(m_config, "service.password")); -#endif - m_component->setSoftwareVersion("Spectrum", SPECTRUM_VERSION); - m_component->onConnected.connect(bind(&Component::handleConnected, this)); - m_component->onError.connect(boost::bind(&Component::handleConnectionError, this, _1)); - m_component->onDataRead.connect(boost::bind(&Component::handleDataRead, this, _1)); - m_component->onDataWritten.connect(boost::bind(&Component::handleDataWritten, this, _1)); - - m_component->addPayloadParserFactory(new GenericPayloadParserFactory("private", "jabber:iq:private")); - m_component->addPayloadParserFactory(new GenericPayloadParserFactory("attention", "urn:xmpp:attention:0")); - m_component->addPayloadParserFactory(new GenericPayloadParserFactory("html", "http://jabber.org/protocol/xhtml-im")); - m_component->addPayloadParserFactory(new GenericPayloadParserFactory("block", "urn:xmpp:block:0")); - m_component->addPayloadParserFactory(new GenericPayloadParserFactory("invisible", "urn:xmpp:invisible:0")); - m_component->addPayloadParserFactory(new GenericPayloadParserFactory("query", "http://jabber.org/protocol/stats")); - m_component->addPayloadParserFactory(new GenericPayloadParserFactory("query", "jabber:iq:gateway")); - m_component->addPayloadParserFactory(new GenericPayloadParserFactory("x", "http://jabber.org/protocol/muc")); - - m_component->addPayloadSerializer(new Swift::AttentionSerializer()); - m_component->addPayloadSerializer(new Swift::XHTMLIMSerializer()); - m_component->addPayloadSerializer(new Transport::BlockSerializer()); - m_component->addPayloadSerializer(new Swift::InvisibleSerializer()); - m_component->addPayloadSerializer(new Swift::StatsSerializer()); - m_component->addPayloadSerializer(new Swift::SpectrumErrorSerializer()); - m_component->addPayloadSerializer(new Swift::GatewayPayloadSerializer()); - - m_stanzaChannel = m_component->getStanzaChannel(); - m_iqRouter = m_component->getIQRouter(); - } + m_presenceOracle = new Transport::PresenceOracle(frontend); + m_presenceOracle->onPresenceChange.connect(boost::bind(&Component::handlePresence, this, _1)); - m_capsMemoryStorage = new CapsMemoryStorage(); -#if HAVE_SWIFTEN_3 - m_capsManager = new CapsManager(m_capsMemoryStorage, m_stanzaChannel, m_iqRouter, m_factories->getCryptoProvider()); -#else - m_capsManager = new CapsManager(m_capsMemoryStorage, m_stanzaChannel, m_iqRouter); -#endif - m_entityCapsManager = new EntityCapsManager(m_capsManager, m_stanzaChannel); - m_entityCapsManager->onCapsChanged.connect(boost::bind(&Component::handleCapsChanged, this, _1)); - - m_presenceOracle = new Transport::PresenceOracle(m_stanzaChannel); - m_presenceOracle->onPresenceChange.connect(bind(&Component::handlePresence, this, _1)); - - - -// -// m_registerHandler = new SpectrumRegisterHandler(m_component); -// m_registerHandler->start(); + m_frontend->init(this, loop, factories, config, userRegistry); } Component::~Component() { delete m_presenceOracle; - delete m_entityCapsManager; - delete m_capsManager; - delete m_capsMemoryStorage; - if (m_component) - delete m_component; - if (m_server) { - m_server->stop(); - delete m_server; - } -} - -bool Component::handleIQ(boost::shared_ptr iq) { - if (!m_rawXML) { - return false; - } - - if (iq->getPayload() != NULL) { return false; } - if (iq->getPayload() != NULL) { return false; } - if (iq->getPayload() != NULL) { return false; } - - if (iq->getTo().getNode().empty()) { - return false; - } - - onRawIQReceived(iq); - return true; -} - -void Component::handleBackendConfigChanged() { - if (!m_rawXML && CONFIG_BOOL_DEFAULTED(m_config, "features.rawxml", false)) { - m_rawXML = true; - m_iqRouter->addHandler(this); - } -} - -Swift::StanzaChannel *Component::getStanzaChannel() { - return m_stanzaChannel; } Transport::PresenceOracle *Component::getPresenceOracle() { return m_presenceOracle; } -void Component::start() { - if (m_component && !m_component->isAvailable()) { - LOG4CXX_INFO(logger, "Connecting XMPP server " << CONFIG_STRING(m_config, "service.server") << " port " << CONFIG_INT(m_config, "service.port")); - if (CONFIG_INT(m_config, "service.port") == 5222) { - LOG4CXX_WARN(logger, "Port 5222 is usually used for client connections, not for component connections! Are you sure you are using right port?"); - } - m_reconnectCount++; - m_component->connect(CONFIG_STRING(m_config, "service.server"), CONFIG_INT(m_config, "service.port")); - m_reconnectTimer->stop(); - } - else if (m_server) { - LOG4CXX_INFO(logger, "Starting component in server mode on port " << CONFIG_INT(m_config, "service.port")); - m_server->start(); +bool Component::inServerMode() { + return CONFIG_BOOL_DEFAULTED(m_config, "service.server_mode", true); +} - //Type casting to BoostConnectionServer since onStopped signal is not defined in ConnectionServer - //Ideally, onStopped must be defined in ConnectionServer - if (boost::dynamic_pointer_cast(m_server->getConnectionServer())) { - boost::dynamic_pointer_cast(m_server->getConnectionServer())->onStopped.connect(boost::bind(&Component::handleServerStopped, this, _1)); - } - - // We're connected right here, because we're in server mode... - handleConnected(); - } +void Component::start() { + m_frontend->connectToServer(); + m_reconnectCount++; + m_reconnectTimer->stop(); } void Component::stop() { - if (m_component) { - m_reconnectCount = 0; - // TODO: Call this once swiften will fix assert(!session_); -// m_component->disconnect(); - m_reconnectTimer->stop(); - } - else if (m_server) { - LOG4CXX_INFO(logger, "Stopping component in server mode on port " << CONFIG_INT(m_config, "service.port")); - m_server->stop(); - } + m_reconnectCount = 0; + m_frontend->disconnectFromServer(); + m_reconnectTimer->stop(); } void Component::handleConnected() { onConnected(); m_reconnectCount = 0; m_reconnectTimer->stop(); -} - -void Component::handleServerStopped(boost::optional e) { - if(e != NULL ) { - if(*e == Swift::BoostConnectionServer::Conflict) { - LOG4CXX_INFO(logger, "Port "<< CONFIG_INT(m_config, "service.port") << " already in use! Stopping server.."); - if (CONFIG_INT(m_config, "service.port") == 5347) { - LOG4CXX_INFO(logger, "Port 5347 is usually used for components. You are using server_mode=1. Are you sure you don't want to use server_mode=0 and run spectrum as component?"); - } - } - if(*e == Swift::BoostConnectionServer::UnknownError) - LOG4CXX_INFO(logger, "Unknown error occured! Stopping server.."); - exit(1); - } + LOG4CXX_INFO(logger, "Connected to Frontend server."); } -void Component::handleConnectionError(const ComponentError &error) { +void Component::handleConnectionError(const std::string &error) { onConnectionError(error); -// if (m_reconnectCount == 2) -// Component::instance()->userManager()->removeAllUsers(); - std::string str = "Unknown error"; - switch (error.getType()) { - case ComponentError::UnknownError: str = "Unknown error"; break; - case ComponentError::ConnectionError: str = "Connection error"; break; - case ComponentError::ConnectionReadError: str = "Connection read error"; break; - case ComponentError::ConnectionWriteError: str = "Connection write error"; break; - case ComponentError::XMLError: str = "XML Error"; break; - case ComponentError::AuthenticationFailedError: str = "Authentication failed error"; break; - case ComponentError::UnexpectedElementError: str = "Unexpected element error"; break; - } - LOG4CXX_INFO(logger, "Disconnected from XMPP server. Error: " << str); - + LOG4CXX_INFO(logger, "Disconnected from Frontend server. Error: " << error); m_reconnectTimer->start(); } -void Component::handleDataRead(const Swift::SafeByteArray &data) { - std::string d = safeByteArrayToString(data); - if (!boost::starts_with(d, "getType() != Swift::Presence::Unavailable) { - boost::shared_ptr capsInfo = presence->getPayload(); - if (capsInfo && capsInfo->getHash() == "sha-1") { - /*haveFeatures = */m_entityCapsManager->getCaps(presence->getFrom()) != DiscoInfo::ref(); - } -#ifdef SUPPORT_LEGACY_CAPS - else { - GetDiscoInfoRequest::ref discoInfoRequest = GetDiscoInfoRequest::create(presence->getFrom(), m_iqRouter); - discoInfoRequest->onResponse.connect(boost::bind(&Component::handleDiscoInfoResponse, this, _1, _2, presence->getFrom())); - discoInfoRequest->send(); - } -#endif + m_frontend->sendCapabilitiesRequest(presence->getFrom()); } onUserPresenceReceived(presence); } -void Component::handleDiscoInfoResponse(boost::shared_ptr info, Swift::ErrorPayload::ref error, const Swift::JID& jid) { -#ifdef SUPPORT_LEGACY_CAPS - onUserDiscoInfoReceived(jid, info); -#endif -} - -void Component::handleCapsChanged(const Swift::JID& jid) { - onUserDiscoInfoReceived(jid, m_entityCapsManager->getCaps(jid)); -} - } diff --git a/src/user.cpp b/src/user.cpp index 8e29c7cf192a5095986ae67a87b8f8b28ba571c4..833bf4041ca972f530656cef1c9f5ee1e7b0a03f 100644 --- a/src/user.cpp +++ b/src/user.cpp @@ -19,6 +19,7 @@ */ #include "transport/user.h" +#include "transport/frontend.h" #include "transport/transport.h" #include "transport/storagebackend.h" #include "transport/rostermanager.h" @@ -26,10 +27,12 @@ #include "transport/conversationmanager.h" #include "transport/presenceoracle.h" #include "transport/logging.h" +#include "transport/factory.h" #include "Swiften/Server/ServerStanzaChannel.h" #include "Swiften/Elements/StreamError.h" #include "Swiften/Elements/MUCPayload.h" #include "Swiften/Elements/SpectrumErrorPayload.h" +#include "Swiften/Elements/CapsInfo.h" #include #include #include @@ -49,7 +52,6 @@ User::User(const Swift::JID &jid, UserInfo &userInfo, Component *component, User m_cacheMessages = false; m_component = component; m_presenceOracle = component->m_presenceOracle; - m_entityCapsManager = component->m_entityCapsManager; m_userManager = userManager; m_userInfo = userInfo; m_connected = false; @@ -61,7 +63,7 @@ User::User(const Swift::JID &jid, UserInfo &userInfo, Component *component, User m_reconnectTimer = m_component->getNetworkFactories()->getTimerFactory()->createTimer(5000); m_reconnectTimer->onTick.connect(boost::bind(&User::onConnectingTimeout, this)); - m_rosterManager = new RosterManager(this, m_component); + m_rosterManager = component->getFrontend()->createRosterManager(this, m_component); m_conversationManager = new ConversationManager(this, m_component); LOG4CXX_INFO(logger, m_jid.toString() << ": Created"); updateLastActivity(); @@ -69,13 +71,14 @@ User::User(const Swift::JID &jid, UserInfo &userInfo, Component *component, User User::~User(){ LOG4CXX_INFO(logger, m_jid.toString() << ": Destroying"); - if (m_component->inServerMode()) { -#if HAVE_SWIFTEN_3 - dynamic_cast(m_component->getStanzaChannel())->finishSession(m_jid, boost::shared_ptr()); -#else - dynamic_cast(m_component->getStanzaChannel())->finishSession(m_jid, boost::shared_ptr()); -#endif - } +// if (m_component->inServerMode()) { +// #if HAVE_SWIFTEN_3 +// dynamic_cast(m_component->getFrontend())->finishSession(m_jid, boost::shared_ptr()); +// #else +// dynamic_cast(m_component->getFrontend())->finishSession(m_jid, boost::shared_ptr()); +// #endif +// } + m_reconnectTimer->stop(); delete m_rosterManager; @@ -86,57 +89,6 @@ const Swift::JID &User::getJID() { return m_jid; } -std::vector User::getJIDWithFeature(const std::string &feature) { - std::vector jid; - std::vector presences = m_presenceOracle->getAllPresence(m_jid); - - foreach(Swift::Presence::ref presence, presences) { - if (presence->getType() == Swift::Presence::Unavailable) - continue; - - Swift::DiscoInfo::ref discoInfo = m_entityCapsManager->getCaps(presence->getFrom()); - if (!discoInfo) { -#ifdef SUPPORT_LEGACY_CAPS - if (m_legacyCaps.find(presence->getFrom()) != m_legacyCaps.end()) { - discoInfo = m_legacyCaps[presence->getFrom()]; - } - else { - continue; - } - - if (!discoInfo) { - continue; - } -#else - continue; -#endif - } - - if (discoInfo->hasFeature(feature)) { - LOG4CXX_INFO(logger, m_jid.toString() << ": Found JID with " << feature << " feature: " << presence->getFrom().toString()); - jid.push_back(presence->getFrom()); - } - } - - if (jid.empty()) { - LOG4CXX_INFO(logger, m_jid.toString() << ": No JID with " << feature << " feature " << m_legacyCaps.size()); - } - return jid; -} - -Swift::DiscoInfo::ref User::getCaps(const Swift::JID &jid) const { - Swift::DiscoInfo::ref discoInfo = m_entityCapsManager->getCaps(jid); -#ifdef SUPPORT_LEGACY_CAPS - if (!discoInfo) { - std::map::const_iterator it = m_legacyCaps.find(jid); - if (it != m_legacyCaps.end()) { - discoInfo = it->second; - } - } -#endif - return discoInfo; -} - void User::sendCurrentPresence() { if (m_component->inServerMode()) { return; @@ -154,14 +106,14 @@ void User::sendCurrentPresence() { Swift::Presence::ref response = Swift::Presence::create(highest); response->setTo(presence->getFrom()); response->setFrom(m_component->getJID()); - m_component->getStanzaChannel()->sendPresence(response); + m_component->getFrontend()->sendPresence(response); } else { Swift::Presence::ref response = Swift::Presence::create(); response->setTo(presence->getFrom()); response->setFrom(m_component->getJID()); response->setType(Swift::Presence::Unavailable); - m_component->getStanzaChannel()->sendPresence(response); + m_component->getFrontend()->sendPresence(response); } } else { @@ -170,7 +122,7 @@ void User::sendCurrentPresence() { response->setFrom(m_component->getJID()); response->setType(Swift::Presence::Unavailable); response->setStatus("Connecting"); - m_component->getStanzaChannel()->sendPresence(response); + m_component->getFrontend()->sendPresence(response); } } } @@ -202,14 +154,9 @@ void User::handlePresence(Swift::Presence::ref presence, bool forceJoin) { if (!m_connected) { // we are not connected to legacy network, so we should do it when disco#info arrive :) if (m_readyForConnect == false) { - - // Forward status message to legacy network, but only if it's sent from active resource -// if (m_activeResource == presence->getFrom().getResource().getUTF8String()) { -// forwardStatus(presenceShow, stanzaStatus); -// } boost::shared_ptr capsInfo = presence->getPayload(); if (capsInfo && capsInfo->getHash() == "sha-1") { - if (m_entityCapsManager->getCaps(presence->getFrom()) != Swift::DiscoInfo::ref()) { + if (m_component->getFrontend()->sendCapabilitiesRequest(presence->getFrom()) != Swift::DiscoInfo::ref()) { LOG4CXX_INFO(logger, m_jid.toString() << ": Ready to be connected to legacy network"); m_readyForConnect = true; onReadyToConnect(); @@ -229,7 +176,6 @@ void User::handlePresence(Swift::Presence::ref presence, bool forceJoin) { } } - if (!presence->getTo().getNode().empty()) { bool isMUC = presence->getPayload() != NULL || *presence->getTo().getNode().c_str() == '#'; if (presence->getType() == Swift::Presence::Unavailable) { @@ -364,7 +310,7 @@ void User::handlePresence(Swift::Presence::ref presence, bool forceJoin) { response->setTo(presence->getFrom()); response->setFrom(m_component->getJID()); response->setType(Swift::Presence::Unavailable); - m_component->getStanzaChannel()->sendPresence(response); + m_component->getFrontend()->sendPresence(response); } else { sendCurrentPresence(); @@ -418,13 +364,7 @@ void User::handleSubscription(Swift::Presence::ref presence) { void User::handleDiscoInfo(const Swift::JID& jid, boost::shared_ptr info) { LOG4CXX_INFO(logger, jid.toString() << ": got disco#info"); #ifdef SUPPORT_LEGACY_CAPS - Swift::DiscoInfo::ref discoInfo = m_entityCapsManager->getCaps(jid); - // This is old legacy cap which is not stored in entityCapsManager, - // we have to store it in our user class. - if (!discoInfo) { - LOG4CXX_INFO(logger, jid.toString() << ": LEGACY"); - m_legacyCaps[jid] = info; - } + m_legacyCaps[jid] = info; #endif onConnectingTimeout(); @@ -481,28 +421,65 @@ void User::handleDisconnected(const std::string &error, Swift::SpectrumErrorPayl msg->setTo(m_jid.toBare()); msg->setFrom(m_component->getJID()); msg->addPayload(boost::make_shared(e)); - m_component->getStanzaChannel()->sendMessage(msg); + m_component->getFrontend()->sendMessage(msg); - // In server mode, server finishes the session and pass unavailable session to userManager if we're connected to legacy network, - // so we can't removeUser() in server mode, because it would be removed twice. - // Once in finishSession and once in m_userManager->removeUser. - if (m_component->inServerMode()) { - // Remove user later just to be sure there won't be double-free. - // We can't be sure finishSession sends unavailable presence everytime, so check if user gets removed - // in finishSession(...) call and if not, remove it here. - std::string jid = m_jid.toBare().toString(); -#if HAVE_SWIFTEN_3 - dynamic_cast(m_component->getStanzaChannel())->finishSession(m_jid, boost::shared_ptr(new Swift::StreamError(Swift::StreamError::UndefinedCondition, error))); -#else - dynamic_cast(m_component->getStanzaChannel())->finishSession(m_jid, boost::shared_ptr(new Swift::StreamError(Swift::StreamError::UndefinedCondition, error))); -#endif - if (m_userManager->getUser(jid) != NULL) { - m_userManager->removeUser(this); - } - } - else { + disconnectUser(error, e); + + std::string jid = m_jid.toBare().toString(); + if (m_userManager->getUser(jid) != NULL) { m_userManager->removeUser(this); } } +std::vector User::getJIDWithFeature(const std::string &feature) { + std::vector jid; + std::vector presences = m_presenceOracle->getAllPresence(m_jid); + + foreach(Swift::Presence::ref presence, presences) { + if (presence->getType() == Swift::Presence::Unavailable) + continue; + + Swift::DiscoInfo::ref discoInfo = m_component->getFrontend()->sendCapabilitiesRequest(presence->getFrom()); + if (!discoInfo) { +#ifdef SUPPORT_LEGACY_CAPS + if (m_legacyCaps.find(presence->getFrom()) != m_legacyCaps.end()) { + discoInfo = m_legacyCaps[presence->getFrom()]; + } + else { + continue; + } + + if (!discoInfo) { + continue; + } +#else + continue; +#endif + } + + if (discoInfo->hasFeature(feature)) { + LOG4CXX_INFO(logger, m_jid.toString() << ": Found JID with " << feature << " feature: " << presence->getFrom().toString()); + jid.push_back(presence->getFrom()); + } + } + + if (jid.empty()) { + LOG4CXX_INFO(logger, m_jid.toString() << ": No JID with " << feature << " feature " << m_legacyCaps.size()); + } + return jid; +} + +// Swift::DiscoInfo::ref User::getCaps(const Swift::JID &jid) const { +// Swift::DiscoInfo::ref discoInfo = m_entityCapsManager->getCaps(jid); +// #ifdef SUPPORT_LEGACY_CAPS +// if (!discoInfo) { +// std::map::const_iterator it = m_legacyCaps.find(jid); +// if (it != m_legacyCaps.end()) { +// discoInfo = it->second; +// } +// } +// #endif +// return discoInfo; +// } + } diff --git a/src/usermanager.cpp b/src/usermanager.cpp index 0ef4055a1b7a9a7440f038c75dcaa2e6cdfe2b94..00606e9e45e919563647fa72eabe0ec74a0a164d 100644 --- a/src/usermanager.cpp +++ b/src/usermanager.cpp @@ -26,7 +26,8 @@ #include "transport/rostermanager.h" #include "transport/userregistry.h" #include "transport/logging.h" -#include "transport/discoitemsresponder.h" +#include "transport/frontend.h" +#include "transport/presenceoracle.h" #include "storageresponder.h" #include "Swiften/Server/ServerStanzaChannel.h" @@ -44,7 +45,7 @@ namespace Transport { DEFINE_LOGGER(logger, "UserManager"); -UserManager::UserManager(Component *component, UserRegistry *userRegistry, DiscoItemsResponder *discoItemsResponder, StorageBackend *storageBackend) { +UserManager::UserManager(Component *component, UserRegistry *userRegistry, StorageBackend *storageBackend) { m_cachedUser = NULL; m_onlineBuddies = 0; m_sentToXMPP = 0; @@ -53,17 +54,11 @@ UserManager::UserManager(Component *component, UserRegistry *userRegistry, Disco m_storageBackend = storageBackend; m_storageResponder = NULL; m_userRegistry = userRegistry; - m_discoItemsResponder = discoItemsResponder; - - if (m_storageBackend) { - m_storageResponder = new StorageResponder(component->getIQRouter(), m_storageBackend, this); - m_storageResponder->start(); - } component->onUserPresenceReceived.connect(bind(&UserManager::handlePresence, this, _1)); - component->onUserDiscoInfoReceived.connect(bind(&UserManager::handleDiscoInfo, this, _1, _2)); - m_component->getStanzaChannel()->onMessageReceived.connect(bind(&UserManager::handleMessageReceived, this, _1)); - m_component->getStanzaChannel()->onPresenceReceived.connect(bind(&UserManager::handleGeneralPresenceReceived, this, _1)); + component->getFrontend()->onCapabilitiesReceived.connect(bind(&UserManager::handleDiscoInfo, this, _1, _2)); + m_component->getFrontend()->onMessageReceived.connect(bind(&UserManager::handleMessageReceived, this, _1)); + m_component->getFrontend()->onPresenceReceived.connect(bind(&UserManager::handleGeneralPresenceReceived, this, _1)); m_userRegistry->onConnectUser.connect(bind(&UserManager::connectUser, this, _1)); m_userRegistry->onDisconnectUser.connect(bind(&UserManager::disconnectUser, this, _1)); @@ -72,10 +67,7 @@ UserManager::UserManager(Component *component, UserRegistry *userRegistry, Disco } UserManager::~UserManager(){ - if (m_storageResponder) { - m_storageResponder->stop(); - delete m_storageResponder; - } + } void UserManager::addUser(User *user) { @@ -99,15 +91,15 @@ User *UserManager::getUser(const std::string &barejid){ return NULL; } -Swift::DiscoInfo::ref UserManager::getCaps(const Swift::JID &jid) const { - std::map::const_iterator it = m_users.find(jid.toBare().toString()); - if (it == m_users.end()) { - return Swift::DiscoInfo::ref(); - } - - User *user = it->second; - return user->getCaps(jid); -} +// Swift::DiscoInfo::ref UserManager::getCaps(const Swift::JID &jid) const { +// std::map::const_iterator it = m_users.find(jid.toBare().toString()); +// if (it == m_users.end()) { +// return Swift::DiscoInfo::ref(); +// } +// +// User *user = it->second; +// return user->getCaps(jid); +// } void UserManager::removeUser(User *user, bool onUserBehalf) { m_users.erase(user->getJID().toBare().toString()); @@ -178,13 +170,12 @@ void UserManager::handlePresence(Swift::Presence::ref presence) { item.setSubscription(Swift::RosterItemPayload::Both); payload->addItem(item); - Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(payload, presence->getFrom(), m_component->getIQRouter()); - request->send(); + m_component->getFrontend()->sendRosterRequest(payload, presence->getFrom()); Swift::Presence::ref response = Swift::Presence::create(); response->setTo(presence->getFrom()); response->setFrom(m_component->getJID()); - m_component->getStanzaChannel()->sendPresence(response); + m_component->getFrontend()->sendPresence(response); return; } } @@ -198,7 +189,7 @@ void UserManager::handlePresence(Swift::Presence::ref presence) { response->setTo(presence->getFrom()); response->setFrom(presence->getTo()); response->setType(Swift::Presence::Unavailable); - m_component->getStanzaChannel()->sendPresence(response); + m_component->getFrontend()->sendPresence(response); // bother him with probe presence, just to be // sure he is subscribed to us. @@ -207,7 +198,7 @@ void UserManager::handlePresence(Swift::Presence::ref presence) { response->setTo(presence->getFrom()); response->setFrom(presence->getTo()); response->setType(Swift::Presence::Probe); - m_component->getStanzaChannel()->sendPresence(response); + m_component->getFrontend()->sendPresence(response); } // Set user offline in database @@ -289,7 +280,7 @@ void UserManager::handlePresence(Swift::Presence::ref presence) { msg->setBody(CONFIG_STRING(m_component->getConfig(), "service.vip_message")); msg->setTo(presence->getFrom()); msg->setFrom(m_component->getJID()); - m_component->getStanzaChannel()->sendMessage(msg); + m_component->getFrontend()->sendMessage(msg); } LOG4CXX_WARN(logger, "Non VIP user " << userkey << " tried to login"); @@ -313,7 +304,7 @@ void UserManager::handlePresence(Swift::Presence::ref presence) { } // Create new user class and set storagebackend - user = new User(presence->getFrom(), res, m_component, this); + user = m_component->getFrontend()->createUser(presence->getFrom(), res, m_component, this); user->getRosterManager()->setStorageBackend(m_storageBackend); addUser(user); } @@ -395,6 +386,7 @@ void UserManager::handleMessageReceived(Swift::Message::ref message) { } void UserManager::handleGeneralPresenceReceived(Swift::Presence::ref presence) { + LOG4CXX_INFO(logger, "PRESENCE2 " << presence->getTo().toString()); switch(presence->getType()) { case Swift::Presence::Subscribe: case Swift::Presence::Subscribed: @@ -451,7 +443,7 @@ void UserManager::handleProbePresence(Swift::Presence::ref presence) { response->setFrom(presence->getTo()); response->setTo(presence->getFrom()); response->setType(Swift::Presence::Unavailable); - m_component->getStanzaChannel()->sendPresence(response); + m_component->getFrontend()->sendPresence(response); } } @@ -477,7 +469,7 @@ void UserManager::handleErrorPresence(Swift::Presence::ref presence) { response->setFrom(presence->getTo().toBare()); response->setTo(presence->getFrom().toBare()); response->setType(Swift::Presence::Subscribe); - m_component->getStanzaChannel()->sendPresence(response); + m_component->getFrontend()->sendPresence(response); } } @@ -489,13 +481,13 @@ void UserManager::handleSubscription(Swift::Presence::ref presence) { response->setFrom(presence->getTo().toBare()); response->setTo(presence->getFrom().toBare()); response->setType(Swift::Presence::Subscribed); - m_component->getStanzaChannel()->sendPresence(response); + m_component->getFrontend()->sendPresence(response); // response = Swift::Presence::create(); // response->setFrom(presence->getTo()); // response->setTo(presence->getFrom()); // response->setType(Swift::Presence::Subscribe); -// m_component->getStanzaChannel()->sendPresence(response); +// m_component->getFrontend()->sendPresence(response); return; } else if (presence->getType() == Swift::Presence::Unsubscribed && presence->getTo().getNode().empty()) { @@ -507,7 +499,7 @@ void UserManager::handleSubscription(Swift::Presence::ref presence) { response->setFrom(presence->getTo().toBare()); response->setTo(presence->getFrom().toBare()); response->setType(Swift::Presence::Subscribe); - m_component->getStanzaChannel()->sendPresence(response); + m_component->getFrontend()->sendPresence(response); } return; } @@ -527,7 +519,7 @@ void UserManager::handleSubscription(Swift::Presence::ref presence) { response->setFrom(presence->getTo()); response->setTo(presence->getFrom()); response->setType(Swift::Presence::Unsubscribed); - m_component->getStanzaChannel()->sendPresence(response); + m_component->getFrontend()->sendPresence(response); } // else { // // Log(presence->getFrom().toString().getUTF8String(), "Subscribe presence received, but this user is not logged in"); @@ -560,17 +552,17 @@ void UserManager::connectUser(const Swift::JID &user) { msg->setBody("You have signed on from another location."); msg->setTo(user); msg->setFrom(m_component->getJID()); - m_component->getStanzaChannel()->sendMessage(msg); + m_component->getFrontend()->sendMessage(msg); // Switch the session = accept new one, disconnect old one. // Unavailable presence from old session has to be ignored, otherwise it would disconnect the user from legacy network. m_userRegistry->onPasswordValid(user); m_component->onUserPresenceReceived.disconnect(bind(&UserManager::handlePresence, this, _1)); -#if HAVE_SWIFTEN_3 - dynamic_cast(m_component->getStanzaChannel())->finishSession(user, boost::shared_ptr(new Swift::StreamError()), true); -#else - dynamic_cast(m_component->getStanzaChannel())->finishSession(user, boost::shared_ptr(new Swift::StreamError()), true); -#endif +// #if HAVE_SWIFTEN_3 +// dynamic_cast(m_component->getFrontend())->finishSession(user, boost::shared_ptr(new Swift::StreamError()), true); +// #else +// dynamic_cast(m_component->getFrontend())->finishSession(user, boost::shared_ptr(new Swift::StreamError()), true); +// #endif m_component->onUserPresenceReceived.connect(bind(&UserManager::handlePresence, this, _1)); } } @@ -590,7 +582,7 @@ void UserManager::connectUser(const Swift::JID &user) { response->setTo(m_component->getJID()); response->setFrom(user); response->setType(Swift::Presence::Available); - dynamic_cast(m_component->getStanzaChannel())->onPresenceReceived(response); + m_component->getFrontend()->onPresenceReceived(response); } } @@ -600,7 +592,7 @@ void UserManager::disconnectUser(const Swift::JID &user) { response->setTo(m_component->getJID()); response->setFrom(user); response->setType(Swift::Presence::Unavailable); - dynamic_cast(m_component->getStanzaChannel())->onPresenceReceived(response); + m_component->getFrontend()->onPresenceReceived(response); } } diff --git a/src/userregistration.cpp b/src/userregistration.cpp index ad467755910f15f68648e5ee4d5d19058c89a244..4060de42261e9887e074e5256e3fed338a772efc 100644 --- a/src/userregistration.cpp +++ b/src/userregistration.cpp @@ -25,7 +25,6 @@ #include "transport/rostermanager.h" #include "transport/user.h" #include "transport/logging.h" -#include "transport/formutils.h" #include "Swiften/Elements/ErrorPayload.h" #include "Swiften/EventLoop/SimpleEventLoop.h" #include "Swiften/Network/BoostNetworkFactories.h" @@ -45,8 +44,7 @@ namespace Transport { DEFINE_LOGGER(logger, "UserRegistration"); UserRegistration::UserRegistration(Component *component, UserManager *userManager, - StorageBackend *storageBackend) -: Swift::Responder(component->m_iqRouter) { + StorageBackend *storageBackend) { m_component = component; m_config = m_component->m_config; m_storageBackend = storageBackend; @@ -60,19 +58,11 @@ bool UserRegistration::registerUser(const UserInfo &row) { UserInfo dummy; bool registered = m_storageBackend->getUser(row.jid, dummy); - // This user is already registered, nothing to do - if (registered) { - return false; - } - m_storageBackend->setUser(row); + doUserRegistration(row); + onUserRegistered(row); - // Check if the server supports remoteroster XEP by sending request for the registered user's roster. - AddressedRosterRequest::ref request = AddressedRosterRequest::ref(new AddressedRosterRequest(m_component->getIQRouter(), row.jid)); - request->onResponse.connect(boost::bind(&UserRegistration::handleRegisterRemoteRosterResponse, this, _1, _2, row)); - request->send(); - - return true; + return !registered; } bool UserRegistration::unregisterUser(const std::string &barejid) { @@ -84,102 +74,6 @@ bool UserRegistration::unregisterUser(const std::string &barejid) { return false; } - onUserUnregistered(userInfo); - - // Check if the server supports remoteroster XEP by sending request for the registered user's roster. - AddressedRosterRequest::ref request = AddressedRosterRequest::ref(new AddressedRosterRequest(m_component->getIQRouter(), barejid)); - request->onResponse.connect(boost::bind(&UserRegistration::handleUnregisterRemoteRosterResponse, this, _1, _2, barejid)); - request->send(); - - return true; -} - -void UserRegistration::handleRegisterRemoteRosterResponse(boost::shared_ptr payload, Swift::ErrorPayload::ref remoteRosterNotSupported, const UserInfo &row){ - if (remoteRosterNotSupported || !payload) { - // Remote roster is not support, so send normal Subscribe presence to add transport. - Swift::Presence::ref response = Swift::Presence::create(); - response->setFrom(m_component->getJID()); - response->setTo(Swift::JID(row.jid)); - response->setType(Swift::Presence::Subscribe); - m_component->getStanzaChannel()->sendPresence(response); - } - else { - // Remote roster is support, so use remoteroster XEP to add transport. - Swift::RosterPayload::ref payload = Swift::RosterPayload::ref(new Swift::RosterPayload()); - Swift::RosterItemPayload item; - item.setJID(m_component->getJID()); - item.setSubscription(Swift::RosterItemPayload::Both); - payload->addItem(item); - Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(payload, row.jid, m_component->getIQRouter()); - request->send(); - } - - onUserRegistered(row); - - // If the JID for registration notification is configured, send the notification message. - std::vector const &x = CONFIG_VECTOR(m_component->getConfig(),"registration.notify_jid"); - BOOST_FOREACH(const std::string ¬ify_jid, x) { - boost::shared_ptr msg(new Swift::Message()); - msg->setBody(std::string("registered: ") + row.jid); - msg->setTo(notify_jid); - msg->setFrom(m_component->getJID()); - m_component->getStanzaChannel()->sendMessage(msg); - } -} - -void UserRegistration::handleUnregisterRemoteRosterResponse(boost::shared_ptr payload, Swift::ErrorPayload::ref remoteRosterNotSupported, const std::string &barejid) { - UserInfo userInfo; - bool registered = m_storageBackend->getUser(barejid, userInfo); - // This user is not registered, nothing do to - if (!registered) - return; - - if (remoteRosterNotSupported || !payload) { - // Remote roster is ont support, so get the buddies from database - // and send Unsubsribe and Unsubscribed presence to them. - std::list roster; - m_storageBackend->getBuddies(userInfo.id, roster); - for(std::list::iterator u = roster.begin(); u != roster.end() ; u++){ - std::string name = (*u).legacyName; - if ((*u).flags & BUDDY_JID_ESCAPING) { - name = Swift::JID::getEscapedNode((*u).legacyName); - } - else { - if (name.find_last_of("@") != std::string::npos) { - name.replace(name.find_last_of("@"), 1, "%"); - } - } - - Swift::Presence::ref response; - response = Swift::Presence::create(); - response->setTo(Swift::JID(barejid)); - response->setFrom(Swift::JID(name, m_component->getJID().toString())); - response->setType(Swift::Presence::Unsubscribe); - m_component->getStanzaChannel()->sendPresence(response); - - response = Swift::Presence::create(); - response->setTo(Swift::JID(barejid)); - response->setFrom(Swift::JID(name, m_component->getJID().toString())); - response->setType(Swift::Presence::Unsubscribed); - m_component->getStanzaChannel()->sendPresence(response); - } - } - else { - // Remote roster is support, so iterate over all buddies we received - // from the XMPP server and remove them using remote roster. - BOOST_FOREACH(Swift::RosterItemPayload it, payload->getItems()) { - Swift::RosterPayload::ref p = Swift::RosterPayload::ref(new Swift::RosterPayload()); - Swift::RosterItemPayload item; - item.setJID(it.getJID()); - item.setSubscription(Swift::RosterItemPayload::Remove); - - p->addItem(item); - - Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(p, barejid, m_component->getIQRouter()); - request->send(); - } - } - // Remove user from database m_storageBackend->removeUser(userInfo.id); @@ -189,293 +83,9 @@ void UserRegistration::handleUnregisterRemoteRosterResponse(boost::shared_ptrremoveUser(user); } - // Remove the transport contact itself the same way as the buddies. - if (remoteRosterNotSupported || !payload) { - Swift::Presence::ref response; - response = Swift::Presence::create(); - response->setTo(Swift::JID(barejid)); - response->setFrom(m_component->getJID()); - response->setType(Swift::Presence::Unsubscribe); - m_component->getStanzaChannel()->sendPresence(response); - - response = Swift::Presence::create(); - response->setTo(Swift::JID(barejid)); - response->setFrom(m_component->getJID()); - response->setType(Swift::Presence::Unsubscribed); - m_component->getStanzaChannel()->sendPresence(response); - } - else { - Swift::RosterPayload::ref payload = Swift::RosterPayload::ref(new Swift::RosterPayload()); - Swift::RosterItemPayload item; - item.setJID(m_component->getJID()); - item.setSubscription(Swift::RosterItemPayload::Remove); - payload->addItem(item); - - Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(payload, barejid, m_component->getIQRouter()); - request->send(); - } - - // If the JID for registration notification is configured, send the notification message. - std::vector const &x = CONFIG_VECTOR(m_component->getConfig(),"registration.notify_jid"); - BOOST_FOREACH(const std::string ¬ify_jid, x) { - boost::shared_ptr msg(new Swift::Message()); - msg->setBody(std::string("unregistered: ") + barejid); - msg->setTo(notify_jid); - msg->setFrom(m_component->getJID()); - m_component->getStanzaChannel()->sendMessage(msg); - } -} - -Form::ref UserRegistration::generateRegistrationForm(const UserInfo &res, bool registered) { - Form::ref form(new Form(Form::FormType)); - form->setTitle("Registration"); - form->setInstructions(CONFIG_STRING(m_config, "registration.instructions")); - - FormUtils::addHiddenField(form, "FORM_TYPE", "jabber:iq:register"); - FormUtils::addTextSingleField(form, "username", res.uin, - CONFIG_STRING(m_config, "registration.username_label"), - true); - - if (CONFIG_BOOL_DEFAULTED(m_config, "registration.needPassword", true)) { - FormUtils::addTextPrivateField(form, "password", "Password", true); - } - - std::string defLanguage = CONFIG_STRING(m_config, "registration.language"); - Swift::FormField::Option languages(defLanguage, defLanguage); - FormUtils::addListSingleField(form, "language", languages, "Language", - registered ? res.language : defLanguage); - - - if (registered) { - FormUtils::addBooleanField(form, "unregister", "0", "Remove your registration"); - } - else if (CONFIG_BOOL(m_config,"registration.require_local_account")) { - std::string localUsernameField = CONFIG_STRING(m_config, "registration.local_username_label"); - FormUtils::addTextSingleField(form, "local_username", "", localUsernameField, true); - FormUtils::addTextSingleField(form, "local_password", "", "Local password", true); - } - - return form; -} - -boost::shared_ptr UserRegistration::generateInBandRegistrationPayload(const Swift::JID& from) { - boost::shared_ptr reg(new InBandRegistrationPayload()); - - UserInfo res; - bool registered = m_storageBackend->getUser(from.toBare().toString(), res); - - reg->setInstructions(CONFIG_STRING(m_config, "registration.instructions")); - reg->setRegistered(registered); - reg->setUsername(res.uin); - - if (CONFIG_BOOL_DEFAULTED(m_config, "registration.needPassword", true)) { - reg->setPassword(""); - } - - Form::ref form = generateRegistrationForm(res, registered); - reg->setForm(form); - - return reg; -} - -bool UserRegistration::handleGetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr payload) { - // TODO: backend should say itself if registration is needed or not... - if (CONFIG_STRING(m_config, "service.protocol") == "irc") { - sendError(from, id, ErrorPayload::BadRequest, ErrorPayload::Modify); - return true; - } - - if (!CONFIG_BOOL(m_config,"registration.enable_public_registration")) { - std::vector const &x = CONFIG_VECTOR(m_config,"service.allowed_servers"); - if (std::find(x.begin(), x.end(), from.getDomain()) == x.end()) { - LOG4CXX_INFO(logger, from.toBare().toString() << ": This user has no permissions to register an account") - sendError(from, id, ErrorPayload::BadRequest, ErrorPayload::Modify); - return true; - } - } - - boost::shared_ptr reg = generateInBandRegistrationPayload(from); - sendResponse(from, id, reg); - - return true; -} - -bool UserRegistration::handleSetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr payload) { - // TODO: backend should say itself if registration is needed or not... - if (CONFIG_STRING(m_config, "service.protocol") == "irc") { - sendError(from, id, ErrorPayload::BadRequest, ErrorPayload::Modify); - return true; - } - - std::string barejid = from.toBare().toString(); - - if (!CONFIG_BOOL(m_config,"registration.enable_public_registration")) { - std::vector const &x = CONFIG_VECTOR(m_config,"service.allowed_servers"); - if (std::find(x.begin(), x.end(), from.getDomain()) == x.end()) { - LOG4CXX_INFO(logger, barejid << ": This user has no permissions to register an account") - sendError(from, id, ErrorPayload::BadRequest, ErrorPayload::Modify); - return true; - } - } - - UserInfo res; - bool registered = m_storageBackend->getUser(barejid, res); - - std::string encoding; - std::string language; - std::string local_username; - std::string local_password; - - Form::ref form = payload->getForm(); - if (form) { - std::string value; - - value = FormUtils::fieldValue(form, "username", ""); - if (!value.empty()) { - payload->setUsername(value); - } - - value = FormUtils::fieldValue(form, "password", ""); - if (!value.empty()) { - payload->setPassword(value); - } - - value = FormUtils::fieldValue(form, "unregister", ""); - if (value == "1" || value == "true") { - payload->setRemove(true); - } - - encoding = FormUtils::fieldValue(form, "encoding", ""); - local_username = FormUtils::fieldValue(form, "local_username", ""); - local_password = FormUtils::fieldValue(form, "local_password", ""); - language = FormUtils::fieldValue(form, "language", ""); - } - - if (payload->isRemove()) { - unregisterUser(barejid); - sendResponse(from, id, InBandRegistrationPayload::ref()); - return true; - } - - if (CONFIG_BOOL(m_config,"registration.require_local_account")) { - /* if (!local_username || !local_password) { - sendResponse(from, id, InBandRegistrationPayload::ref()); - return true - } else */ if (local_username == "" || local_password == "") { - sendResponse(from, id, InBandRegistrationPayload::ref()); - return true; - } -// Swift::logging = true; - bool validLocal = false; - std::string localLookupServer = CONFIG_STRING(m_config, "registration.local_account_server"); - std::string localLookupJID = local_username + std::string("@") + localLookupServer; - SimpleEventLoop localLookupEventLoop; - BoostNetworkFactories localLookupNetworkFactories(&localLookupEventLoop); - Client localLookupClient(localLookupJID, local_password, &localLookupNetworkFactories); - - // TODO: this is neccessary on my server ... but should maybe omitted - localLookupClient.setAlwaysTrustCertificates(); - localLookupClient.connect(); - - class SimpleLoopRunner { - public: - SimpleLoopRunner() {}; - - static void run(SimpleEventLoop * loop) { - loop->run(); - }; - }; - - // TODO: Really ugly and hacky solution, any other ideas more than welcome! - boost::thread thread(boost::bind(&(SimpleLoopRunner::run), &localLookupEventLoop)); - thread.timed_join(boost::posix_time::millisec(CONFIG_INT(m_config, "registration.local_account_server_timeout"))); - localLookupEventLoop.stop(); - thread.join(); - validLocal = localLookupClient.isAvailable(); - localLookupClient.disconnect(); - if (!validLocal) { - sendError(from, id, ErrorPayload::NotAuthorized, ErrorPayload::Modify); - return true; - } - } - - if (!payload->getUsername() || (!payload->getPassword() && CONFIG_BOOL_DEFAULTED(m_config, "registration.needPassword", true))) { - sendError(from, id, ErrorPayload::NotAcceptable, ErrorPayload::Modify); - return true; - } - - if (!payload->getPassword()) { - payload->setPassword(""); - } - - // Register or change password - if (payload->getUsername()->empty()) { - sendError(from, id, ErrorPayload::NotAcceptable, ErrorPayload::Modify); - return true; - } - - // TODO: Move this check to backend somehow - if (CONFIG_STRING(m_config, "service.protocol") == "prpl-jabber") { - // User tries to register himself. - if ((Swift::JID(*payload->getUsername()).toBare() == from.toBare())) { - sendError(from, id, ErrorPayload::NotAcceptable, ErrorPayload::Modify); - return true; - } - - // User tries to register someone who's already registered. - UserInfo user_row; - bool registered = m_storageBackend->getUser(Swift::JID(*payload->getUsername()).toBare().toString(), user_row); - if (registered) { - sendError(from, id, ErrorPayload::NotAcceptable, ErrorPayload::Modify); - return true; - } - } - - std::string username = *payload->getUsername(); - - std::string newUsername(username); - if (!CONFIG_STRING(m_config, "registration.username_mask").empty()) { - newUsername = CONFIG_STRING(m_config, "registration.username_mask"); - boost::replace_all(newUsername, "$username", username); - } - -//TODO: Part of spectrum1 registration stuff, this should be potentially rewritten for S2 too -// if (!m_component->protocol()->isValidUsername(newUsername)) { -// Log("UserRegistration", "This is not valid username: "<< newUsername); -// sendError(from, id, ErrorPayload::NotAcceptable, ErrorPayload::Modify); -// return true; -// } - - if (!CONFIG_STRING(m_config, "registration.allowed_usernames").empty()) { - boost::regex expression(CONFIG_STRING(m_config, "registration.allowed_usernames")); - if (!regex_match(newUsername, expression)) { - LOG4CXX_INFO(logger, "This is not valid username: " << newUsername); - sendError(from, id, ErrorPayload::NotAcceptable, ErrorPayload::Modify); - return true; - } - } - - if (!registered) { - res.jid = barejid; - res.uin = newUsername; - res.password = *payload->getPassword(); - res.language = language; - res.encoding = encoding; - res.vip = 0; - res.id = 0; - registerUser(res); - } - else { - res.jid = barejid; - res.uin = newUsername; - res.password = *payload->getPassword(); - res.language = language; - res.encoding = encoding; - m_storageBackend->setUser(res); - onUserUpdated(res); - } + doUserUnregistration(userInfo); + onUserUnregistered(userInfo); - sendResponse(from, id, InBandRegistrationPayload::ref()); return true; } diff --git a/src/usersreconnecter.cpp b/src/usersreconnecter.cpp index 1ba6cfff1d2a994b9550575daf5438b0fc294b29..2ae0112918b31dbf28827f76a08bb327ffd5f3f5 100644 --- a/src/usersreconnecter.cpp +++ b/src/usersreconnecter.cpp @@ -26,6 +26,7 @@ #include "transport/storagebackend.h" #include "transport/transport.h" #include "transport/logging.h" +#include "transport/frontend.h" #include "Swiften/Network/NetworkFactories.h" @@ -62,17 +63,7 @@ void UsersReconnecter::reconnectNextUser() { std::string user = m_users.back(); m_users.pop_back(); - LOG4CXX_INFO(logger, "Sending probe presence to " << user); - Swift::Presence::ref response = Swift::Presence::create(); - try { - response->setTo(user); - } - catch (...) { return; } - - response->setFrom(m_component->getJID()); - response->setType(Swift::Presence::Probe); - - m_component->getStanzaChannel()->sendPresence(response); + m_component->getFrontend()->reconnectUser(user); m_nextUserTimer->start(); }