Browse Source

Split libtransport in two - libtransport and XMPPFrontend (lives in ./spectrum/src/frontends/xmpp). It's first step to allow generic Spectrum 2 frontends.

master
Jan Kaluza 7 years ago
parent
commit
fe47e0979b
  1. 27
      .gitignore
  2. 2
      include/transport/buddy.h
  3. 1
      include/transport/conversation.h
  4. 95
      include/transport/frontend.h
  5. 4
      include/transport/networkpluginserver.h
  6. 6
      include/transport/presenceoracle.h
  7. 27
      include/transport/rostermanager.h
  8. 1
      include/transport/rosterresponder.h
  9. 105
      include/transport/transport.h
  10. 7
      include/transport/user.h
  11. 18
      include/transport/usermanager.h
  12. 23
      include/transport/userregistration.h
  13. 3
      spectrum/src/CMakeLists.txt
  14. 2
      spectrum/src/frontends/xmpp/BlockParser.cpp
  15. 2
      spectrum/src/frontends/xmpp/BlockParser.h
  16. 2
      spectrum/src/frontends/xmpp/BlockPayload.cpp
  17. 0
      spectrum/src/frontends/xmpp/BlockPayload.h
  18. 2
      spectrum/src/frontends/xmpp/BlockSerializer.cpp
  19. 2
      spectrum/src/frontends/xmpp/BlockSerializer.h
  20. 390
      spectrum/src/frontends/xmpp/XMPPFrontend.cpp
  21. 133
      spectrum/src/frontends/xmpp/XMPPFrontend.h
  22. 288
      spectrum/src/frontends/xmpp/XMPPRosterManager.cpp
  23. 101
      spectrum/src/frontends/xmpp/XMPPRosterManager.h
  24. 80
      spectrum/src/frontends/xmpp/XMPPUser.cpp
  25. 67
      spectrum/src/frontends/xmpp/XMPPUser.h
  26. 123
      spectrum/src/frontends/xmpp/XMPPUserManager.cpp
  27. 66
      spectrum/src/frontends/xmpp/XMPPUserManager.h
  28. 460
      spectrum/src/frontends/xmpp/XMPPUserRegistration.cpp
  29. 78
      spectrum/src/frontends/xmpp/XMPPUserRegistration.h
  30. 4
      spectrum/src/frontends/xmpp/adhoccommand.cpp
  31. 0
      spectrum/src/frontends/xmpp/adhoccommand.h
  32. 2
      spectrum/src/frontends/xmpp/adhoccommandfactory.h
  33. 10
      spectrum/src/frontends/xmpp/adhocmanager.cpp
  34. 0
      spectrum/src/frontends/xmpp/adhocmanager.h
  35. 2
      spectrum/src/frontends/xmpp/blockresponder.cpp
  36. 2
      spectrum/src/frontends/xmpp/blockresponder.h
  37. 1
      spectrum/src/frontends/xmpp/discoinforesponder.cpp
  38. 0
      spectrum/src/frontends/xmpp/discoinforesponder.h
  39. 9
      spectrum/src/frontends/xmpp/discoitemsresponder.cpp
  40. 0
      spectrum/src/frontends/xmpp/discoitemsresponder.h
  41. 4
      spectrum/src/frontends/xmpp/formutils.cpp
  42. 0
      spectrum/src/frontends/xmpp/formutils.h
  43. 2
      spectrum/src/frontends/xmpp/gatewayresponder.cpp
  44. 0
      spectrum/src/frontends/xmpp/gatewayresponder.h
  45. 12
      spectrum/src/frontends/xmpp/rosterresponder.cpp
  46. 4
      spectrum/src/frontends/xmpp/settingsadhoccommand.cpp
  47. 4
      spectrum/src/frontends/xmpp/settingsadhoccommand.h
  48. 7
      spectrum/src/frontends/xmpp/statsresponder.cpp
  49. 0
      spectrum/src/frontends/xmpp/statsresponder.h
  50. 0
      spectrum/src/frontends/xmpp/storageparser.cpp
  51. 0
      spectrum/src/frontends/xmpp/storageparser.h
  52. 0
      spectrum/src/frontends/xmpp/storageresponder.cpp
  53. 0
      spectrum/src/frontends/xmpp/storageresponder.h
  54. 5
      spectrum/src/frontends/xmpp/vcardresponder.cpp
  55. 0
      spectrum/src/frontends/xmpp/vcardresponder.h
  56. 49
      spectrum/src/main.cpp
  57. 5
      src/CMakeLists.txt
  58. 5
      src/admininterface.cpp
  59. 21
      src/buddy.cpp
  60. 20
      src/conversation.cpp
  61. 110
      src/filetransfermanager.cpp
  62. 8
      src/localbuddy.cpp
  63. 80
      src/networkpluginserver.cpp
  64. 13
      src/presenceoracle.cpp
  65. 253
      src/rostermanager.cpp
  66. 39
      src/tests/basictest.cpp
  67. 8
      src/tests/basictest.h
  68. 15
      src/tests/component.cpp
  69. 2
      src/tests/discoitemsresponder.cpp
  70. 4
      src/tests/gatewayresponder.cpp
  71. 8
      src/tests/networkpluginserver.cpp
  72. 4
      src/tests/rosterresponder.cpp
  73. 15
      src/tests/settingsadhoccommand.cpp
  74. 10
      src/tests/usermanager.cpp
  75. 290
      src/transport.cpp
  76. 171
      src/user.cpp
  77. 82
      src/usermanager.cpp
  78. 402
      src/userregistration.cpp
  79. 13
      src/usersreconnecter.cpp

27
.gitignore vendored

@ -1,3 +1,28 @@ @@ -1,3 +1,28 @@
*.pb.cc
*.pb.h
plugin/python/protocol_pb2.py
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

2
include/transport/buddy.h

@ -24,7 +24,7 @@ @@ -24,7 +24,7 @@
#include <algorithm>
#include "transport/transport.h"
#include "Swiften/Elements/VCard.h"
#include "Swiften/Elements/Presence.h"
namespace Transport {

1
include/transport/conversation.h

@ -25,6 +25,7 @@ @@ -25,6 +25,7 @@
#include "transport/transport.h"
#include "Swiften/Elements/Message.h"
#include "Swiften/Elements/Presence.h"
namespace Transport {

95
include/transport/frontend.h

@ -0,0 +1,95 @@ @@ -0,0 +1,95 @@
/**
* XMPP - libpurple transport
*
* Copyright (C) 2009, Jan Kaluza <hanzz@soc.pidgin.im>
*
* 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 <string>
#include <algorithm>
#include <Swiften/EventLoop/EventLoop.h>
#include <Swiften/Network/NetworkFactories.h>
#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 <boost/signal.hpp>
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<Swift::Message> message) = 0;
virtual void sendIQ(boost::shared_ptr<Swift::IQ>) = 0;
virtual boost::shared_ptr<Swift::DiscoInfo> 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<void (User *, const std::string &name, unsigned int id)> onVCardRequired;
boost::signal<void (User *, boost::shared_ptr<Swift::VCard> vcard)> onVCardUpdated;
boost::signal<void (Buddy *, const Swift::RosterItemPayload &item)> onBuddyUpdated;
boost::signal<void (Buddy *)> onBuddyRemoved;
boost::signal<void (Buddy *, const Swift::RosterItemPayload &item)> onBuddyAdded;
boost::signal<void (Swift::Message::ref message)> onMessageReceived;
boost::signal<void (bool /* isAvailable */)> onAvailableChanged;
boost::signal<void (boost::shared_ptr<Swift::Presence>) > onPresenceReceived;
boost::signal<void (const Swift::JID& jid, boost::shared_ptr<Swift::DiscoInfo> info)> onCapabilitiesReceived;
};
}

4
include/transport/networkpluginserver.h

@ -52,7 +52,6 @@ class RosterResponder; @@ -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 { @@ -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 { @@ -187,7 +186,6 @@ class NetworkPluginServer : Swift::XMPPParserClient {
std::vector<std::string> m_crashedBackends;
AdminInterface *m_adminInterface;
bool m_startingBackend;
DiscoItemsResponder *m_discoItemsResponder;
time_t m_lastLogin;
Swift::XMPPParser *m_xmppParser;
Swift::FullPayloadParserFactoryCollection m_collection;

6
include/transport/presenceoracle.h

@ -30,9 +30,11 @@ @@ -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 { @@ -52,7 +54,7 @@ class PresenceOracle {
typedef std::map<Swift::JID, Swift::Presence::ref> PresenceMap;
typedef std::map<Swift::JID, PresenceMap> PresencesMap;
PresencesMap entries_;
Swift::StanzaChannel* stanzaChannel_;
Frontend* frontend_;
};
}

27
include/transport/rostermanager.h

@ -40,16 +40,6 @@ class Component; @@ -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<Swift::RosterPayload> {
public:
typedef boost::shared_ptr<AddressedRosterRequest> ref;
AddressedRosterRequest(Swift::IQRouter* router, Swift::JID to) :
Swift::GenericRequest<Swift::RosterPayload>(Swift::IQ::Get, to, boost::shared_ptr<Swift::Payload>(new Swift::RosterPayload()), router) {
}
};
/// Manages roster of one XMPP user.
class RosterManager {
public:
@ -62,6 +52,10 @@ class RosterManager { @@ -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 { @@ -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 { @@ -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<Swift::RosterPayload> roster, Swift::ErrorPayload::ref error);
protected:
std::map<std::string, Buddy *, std::less<std::string>, boost::pool_allocator< std::pair<std::string, Buddy *> > > m_buddies;
private:
Component *m_component;
RosterStorage *m_rosterStorage;
User *m_user;
@ -142,7 +130,6 @@ class RosterManager { @@ -142,7 +130,6 @@ class RosterManager {
Swift::Timer::ref m_RIETimer;
std::list <Swift::SetRosterRequest::ref> m_requests;
bool m_supportRemoteRoster;
AddressedRosterRequest::ref m_remoteRosterRequest;
};
}

1
include/transport/rosterresponder.h

@ -46,6 +46,7 @@ class RosterResponder : public Swift::Responder<Swift::RosterPayload> { @@ -46,6 +46,7 @@ class RosterResponder : public Swift::Responder<Swift::RosterPayload> {
virtual bool handleGetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr<Swift::RosterPayload> payload);
virtual bool handleSetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr<Swift::RosterPayload> payload);
UserManager *m_userManager;
Swift::IQRouter *m_router;
};
}

105
include/transport/transport.h

@ -21,40 +21,25 @@ @@ -21,40 +21,25 @@
#pragma once
#include <vector>
#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 <boost/bind.hpp>
#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 <boost/bind.hpp>
#include "transport/config.h"
#include "transport/factory.h"
#include "transport/presenceoracle.h"
#include <Swiften/Network/BoostConnectionServer.h>
#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 { @@ -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 { @@ -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<void (const Swift::ComponentError &error)> onConnectionError;
boost::signal<void (const std::string &error)> onConnectionError;
/// This signal is emitted when transport successfully connects the server.
boost::signal<void ()> onConnected;
/// This signal is emitted when XML stanza is sent to server.
/// \param xml xml stanza
boost::signal<void (const std::string &xml)> onXMLOut;
/// This signal is emitted when XML stanza is received from server.
/// \param xml xml stanza
boost::signal<void (const std::string &xml)> 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 { @@ -147,52 +111,39 @@ namespace Transport {
/// \param presence Presence.
boost::signal<void (Swift::Presence::ref presence)> 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<void (const Swift::JID& jid, boost::shared_ptr<Swift::DiscoInfo> info)> onUserDiscoInfoReceived;
boost::signal<void (boost::shared_ptr<Swift::IQ>)> 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<Swift::BoostConnectionServer::Error> 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<Swift::DiscoInfo> info, Swift::ErrorPayload::ref error, const Swift::JID& jid);
void handleCapsChanged(const Swift::JID& jid);
void handleBackendConfigChanged();
bool handleIQ(boost::shared_ptr<Swift::IQ>);
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;

7
include/transport/user.h

@ -39,7 +39,7 @@ class PresenceOracle; @@ -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 { @@ -60,7 +60,7 @@ class User : public Swift::EntityCapsProvider {
/// \return full JID which supports particular feature or invalid JID.
std::vector<Swift::JID> 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 { @@ -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 { @@ -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;

18
include/transport/usermanager.h

@ -27,6 +27,7 @@ @@ -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; @@ -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; @@ -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 { @@ -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 { @@ -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;
};

23
include/transport/userregistration.h

@ -36,7 +36,7 @@ class UserManager; @@ -36,7 +36,7 @@ class UserManager;
class Config;
/// Allows users to register the transport using service discovery.
class UserRegistration : public Swift::Responder<Swift::InBandRegistrationPayload> {
class UserRegistration {
public:
/// Creates new UserRegistration handler.
/// \param component Component associated with this class
@ -45,7 +45,7 @@ class UserRegistration : public Swift::Responder<Swift::InBandRegistrationPayloa @@ -45,7 +45,7 @@ class UserRegistration : public Swift::Responder<Swift::InBandRegistrationPayloa
UserRegistration(Component *component, UserManager *userManager, StorageBackend *storageBackend);
/// Destroys UserRegistration.
~UserRegistration();
virtual ~UserRegistration();
/// Registers new user. This function stores user into database and subscribe user to transport.
/// \param userInfo UserInfo struct with informations about registered user
@ -58,6 +58,17 @@ class UserRegistration : public Swift::Responder<Swift::InBandRegistrationPayloa @@ -58,6 +58,17 @@ class UserRegistration : public Swift::Responder<Swift::InBandRegistrationPayloa
/// \return false if there is no such user registered
bool unregisterUser(const std::string &barejid);
/// 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) = 0;
/// 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) = 0;
/// Called when new user has been registered.
/// \param userInfo UserInfo struct with informations about user
boost::signal<void (const UserInfo &userInfo)> onUserRegistered;
@ -71,14 +82,6 @@ class UserRegistration : public Swift::Responder<Swift::InBandRegistrationPayloa @@ -71,14 +82,6 @@ class UserRegistration : public Swift::Responder<Swift::InBandRegistrationPayloa
boost::signal<void (const UserInfo &userInfo)> onUserUpdated;
private:
virtual bool handleGetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr<Swift::InBandRegistrationPayload> payload);
virtual bool handleSetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr<Swift::InBandRegistrationPayload> payload);
void handleRegisterRemoteRosterResponse(boost::shared_ptr<Swift::RosterPayload> payload, Swift::ErrorPayload::ref error, const UserInfo &row);
void handleUnregisterRemoteRosterResponse(boost::shared_ptr<Swift::RosterPayload> payload, Swift::ErrorPayload::ref error, const std::string &barejid);
boost::shared_ptr<Swift::InBandRegistrationPayload> generateInBandRegistrationPayload(const Swift::JID& from);
Swift::Form::ref generateRegistrationForm(const UserInfo &res, bool registered);
Component *m_component;
StorageBackend *m_storageBackend;
UserManager *m_userManager;

3
spectrum/src/CMakeLists.txt

@ -1,5 +1,6 @@ @@ -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)

2
src/BlockParser.cpp → spectrum/src/frontends/xmpp/BlockParser.cpp

@ -4,7 +4,7 @@ @@ -4,7 +4,7 @@
* See Documentation/Licenses/BSD-simplified.txt for more information.
*/
#include <transport/BlockParser.h>
#include <BlockParser.h>
namespace Transport {

2
include/transport/BlockParser.h → spectrum/src/frontends/xmpp/BlockParser.h

@ -6,7 +6,7 @@ @@ -6,7 +6,7 @@
#pragma once
#include <transport/BlockPayload.h>
#include <BlockPayload.h>
#include <Swiften/Parser/GenericPayloadParser.h>
// This payload is NOT part of ANY XEP and it is only

2
src/BlockPayload.cpp → spectrum/src/frontends/xmpp/BlockPayload.cpp

@ -4,7 +4,7 @@ @@ -4,7 +4,7 @@
* See Documentation/Licenses/BSD-simplified.txt for more information.
*/
#include <transport/BlockPayload.h>
#include <BlockPayload.h>
namespace Transport {

0
include/transport/BlockPayload.h → spectrum/src/frontends/xmpp/BlockPayload.h

2
src/BlockSerializer.cpp → spectrum/src/frontends/xmpp/BlockSerializer.cpp

@ -4,7 +4,7 @@ @@ -4,7 +4,7 @@
* See Documentation/Licenses/BSD-simplified.txt for more information.
*/
#include <transport/BlockSerializer.h>
#include <BlockSerializer.h>
#include <boost/shared_ptr.hpp>

2
include/transport/BlockSerializer.h → spectrum/src/frontends/xmpp/BlockSerializer.h

@ -7,7 +7,7 @@ @@ -7,7 +7,7 @@
#pragma once
#include <Swiften/Serializer/GenericPayloadSerializer.h>
#include <transport/BlockPayload.h>
#include <BlockPayload.h>
// This payload is NOT part of ANY XEP and it is only
// libtransport related extension.

390
spectrum/src/frontends/xmpp/XMPPFrontend.cpp

@ -0,0 +1,390 @@ @@ -0,0 +1,390 @@
/**
* libtransport -- C++ library for easy XMPP Transports development
*
* Copyright (C) 2011, Jan Kaluza <hanzz.k@gmail.com>
*
* 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 <boost/bind.hpp>
#include <boost/smart_ptr/make_shared.hpp>
#include <boost/algorithm/string/predicate.hpp>
#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 <Swiften/TLS/CAPICertificate.h>
#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<PKCS12Certificate>(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<StorageParser>("private", "jabber:iq:private"));
m_server->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::AttentionParser>("attention", "urn:xmpp:attention:0"));
m_server->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::XHTMLIMParser>("html", "http://jabber.org/protocol/xhtml-im"));
m_server->addPayloadParserFactory(new GenericPayloadParserFactory<Transport::BlockParser>("block", "urn:xmpp:block:0"));
m_server->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::InvisibleParser>("invisible", "urn:xmpp:invisible:0"));
m_server->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::StatsParser>("query", "http://jabber.org/protocol/stats"));
m_server->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::GatewayPayloadParser>("query", "jabber:iq:gateway"));
m_server->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::MUCPayloadParser>("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<StorageParser>("private", "jabber:iq:private"));
m_component->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::AttentionParser>("attention", "urn:xmpp:attention:0"));
m_component->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::XHTMLIMParser>("html", "http://jabber.org/protocol/xhtml-im"));
m_component->addPayloadParserFactory(new GenericPayloadParserFactory<Transport::BlockParser>("block", "urn:xmpp:block:0"));
m_component->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::InvisibleParser>("invisible", "urn:xmpp:invisible:0"));
m_component->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::StatsParser>("query", "http://jabber.org/protocol/stats"));
m_component->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::GatewayPayloadParser>("query", "jabber:iq:gateway"));
m_component->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::MUCPayloadParser>("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<Swift::Message> 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<Swift::Payload>(new Swift::CapsInfo(m_discoItemsResponder->getBuddyCapsInfo())));
}
m_stanzaChannel->sendPresence(presence);
}
void XMPPFrontend::sendVCard(Swift::VCard::ref vcard, Swift::JID to) {
boost::shared_ptr<Swift::GenericRequest<Swift::VCard> > request(new Swift::GenericRequest<Swift::VCard>(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<Swift::Message> message) {
m_stanzaChannel->sendMessage(message);
}
void XMPPFrontend::sendIQ(boost::shared_ptr<Swift::IQ> iq) {
m_iqRouter->sendIQ(iq);
}
boost::shared_ptr<Swift::DiscoInfo> 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<Swift::IQ> iq) {
if (!m_rawXML) {
return false;
}
if (iq->getPayload<Swift::RosterPayload>() != NULL) { return false; }
if (iq->getPayload<Swift::InBandRegistrationPayload>() != NULL) { return false; }
if (iq->getPayload<Swift::StatsPayload>() != 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<Swift::BoostConnectionServer>(m_server->getConnectionServer())) {
boost::dynamic_pointer_cast<Swift::BoostConnectionServer>(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<Swift::BoostConnectionServer::Error> 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<Swift::DiscoInfo> 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));
}
}

133
spectrum/src/frontends/xmpp/XMPPFrontend.h

@ -0,0 +1,133 @@ @@ -0,0 +1,133 @@
/**
* libtransport -- C++ library for easy XMPP Transports development
*
* Copyright (C) 2011, Jan Kaluza <hanzz.k@gmail.com>
*
* 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 <vector>
#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 <boost/bind.hpp>
#include <Swiften/Network/BoostConnectionServer.h>
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<Swift::Message> message);
virtual void sendIQ(boost::shared_ptr<Swift::IQ>);
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<Swift::DiscoInfo> sendCapabilitiesRequest(Swift::JID to);
virtual void clearRoomList();
virtual void addRoomToRoomList(const std::string &handle, const std::string &name);
void handleMessage(boost::shared_ptr<Swift::Message> 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<Swift::BoostConnectionServer::Error> e);
void handleGeneralPresence(Swift::Presence::ref presence);
void handleDataRead(const Swift::SafeByteArray &data);
void handleDataWritten(const Swift::SafeByteArray &data);
void handleDiscoInfoResponse(boost::shared_ptr<Swift::DiscoInfo> info, Swift::ErrorPayload::ref error, const Swift::JID& jid);
void handleCapsChanged(const Swift::JID& jid);
void handleBackendConfigChanged();
bool handleIQ(boost::shared_ptr<Swift::IQ>);
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;
};
}

288
spectrum/src/frontends/xmpp/XMPPRosterManager.cpp

@ -0,0 +1,288 @@ @@ -0,0 +1,288 @@
/**
* XMPP - libpurple transport
*
* Copyright (C) 2009, Jan Kaluza <hanzz@soc.pidgin.im>
*
* 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 <boost/foreach.hpp>
#include <boost/make_shared.hpp>
#include <map>
#include <iterator>
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<XMPPFrontend *>(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<XMPPFrontend *>(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<XMPPFrontend *>(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());