diff options
Diffstat (limited to 'Swiften/Client')
35 files changed, 3412 insertions, 3412 deletions
diff --git a/Swiften/Client/BlockList.cpp b/Swiften/Client/BlockList.cpp index abf9412..cb77080 100644 --- a/Swiften/Client/BlockList.cpp +++ b/Swiften/Client/BlockList.cpp @@ -15,8 +15,8 @@ BlockList::~BlockList() { } bool BlockList::isBlocked(const JID& jid) const { - const std::vector<JID>& items = getItems(); - return (std::find(items.begin(), items.end(), jid.toBare()) != items.end()) || - (std::find(items.begin(), items.end(), JID(jid.getDomain())) != items.end()) || - (std::find(items.begin(), items.end(), jid) != items.end()); + const std::vector<JID>& items = getItems(); + return (std::find(items.begin(), items.end(), jid.toBare()) != items.end()) || + (std::find(items.begin(), items.end(), JID(jid.getDomain())) != items.end()) || + (std::find(items.begin(), items.end(), jid) != items.end()); } diff --git a/Swiften/Client/BlockList.h b/Swiften/Client/BlockList.h index 1ee1ad9..c200f20 100644 --- a/Swiften/Client/BlockList.h +++ b/Swiften/Client/BlockList.h @@ -13,25 +13,25 @@ #include <Swiften/JID/JID.h> namespace Swift { - class SWIFTEN_API BlockList { - public: - enum State { - Init, - Requesting, - Available, - Error - }; - virtual ~BlockList(); - - virtual State getState() const = 0; - - virtual const std::vector<JID>& getItems() const = 0; - - bool isBlocked(const JID& jid) const; - - public: - boost::signal<void ()> onStateChanged; - boost::signal<void (const JID&)> onItemAdded; - boost::signal<void (const JID&)> onItemRemoved; - }; + class SWIFTEN_API BlockList { + public: + enum State { + Init, + Requesting, + Available, + Error + }; + virtual ~BlockList(); + + virtual State getState() const = 0; + + virtual const std::vector<JID>& getItems() const = 0; + + bool isBlocked(const JID& jid) const; + + public: + boost::signal<void ()> onStateChanged; + boost::signal<void (const JID&)> onItemAdded; + boost::signal<void (const JID&)> onItemRemoved; + }; } diff --git a/Swiften/Client/BlockListImpl.cpp b/Swiften/Client/BlockListImpl.cpp index 4abaa37..ebffff8 100644 --- a/Swiften/Client/BlockListImpl.cpp +++ b/Swiften/Client/BlockListImpl.cpp @@ -17,58 +17,58 @@ BlockListImpl::BlockListImpl() : state(Init) { } void BlockListImpl::setItems(const std::vector<JID>& newItems) { - // JIDs which are in the current list but not in the new list, are removed. - foreach (const JID& jid, items) { - if (std::find(newItems.begin(), newItems.end(), jid) == newItems.end()) { - onItemRemoved(jid); - } - } + // JIDs which are in the current list but not in the new list, are removed. + foreach (const JID& jid, items) { + if (std::find(newItems.begin(), newItems.end(), jid) == newItems.end()) { + onItemRemoved(jid); + } + } - // JIDs which are in the new list but not in the current list, are added. - foreach (const JID& jid, newItems) { - if (std::find(items.begin(), items.end(), jid) == items.end()) { - onItemAdded(jid); - } - } - items = newItems; + // JIDs which are in the new list but not in the current list, are added. + foreach (const JID& jid, newItems) { + if (std::find(items.begin(), items.end(), jid) == items.end()) { + onItemAdded(jid); + } + } + items = newItems; } void BlockListImpl::addItem(const JID& item) { - if (std::find(items.begin(), items.end(), item) == items.end()) { - items.push_back(item); - onItemAdded(item); - } + if (std::find(items.begin(), items.end(), item) == items.end()) { + items.push_back(item); + onItemAdded(item); + } } void BlockListImpl::removeItem(const JID& item) { - size_t oldSize = items.size(); - items.erase(std::remove(items.begin(), items.end(), item), items.end()); - if (items.size() != oldSize) { - onItemRemoved(item); - } + size_t oldSize = items.size(); + items.erase(std::remove(items.begin(), items.end(), item), items.end()); + if (items.size() != oldSize) { + onItemRemoved(item); + } } void BlockListImpl::setState(State state) { - if (this->state != state) { - this->state = state; - onStateChanged(); - } + if (this->state != state) { + this->state = state; + onStateChanged(); + } } void BlockListImpl::addItems(const std::vector<JID>& items) { - foreach (const JID& item, items) { - addItem(item); - } + foreach (const JID& item, items) { + addItem(item); + } } void BlockListImpl::removeItems(const std::vector<JID>& items) { - std::vector<JID> itemsToRemove = items; - foreach (const JID& item, itemsToRemove) { - removeItem(item); - } + std::vector<JID> itemsToRemove = items; + foreach (const JID& item, itemsToRemove) { + removeItem(item); + } } void BlockListImpl::removeAllItems() { - removeItems(items); + removeItems(items); } diff --git a/Swiften/Client/BlockListImpl.h b/Swiften/Client/BlockListImpl.h index e203d68..edf459a 100644 --- a/Swiften/Client/BlockListImpl.h +++ b/Swiften/Client/BlockListImpl.h @@ -9,29 +9,29 @@ #include <Swiften/Client/BlockList.h> namespace Swift { - class BlockListImpl : public BlockList { - public: - BlockListImpl(); - - virtual State getState() const { - return state; - } - - void setState(State state); - - virtual const std::vector<JID>& getItems() const { - return items; - } - - void setItems(const std::vector<JID>& newItems); - void addItem(const JID& item); - void removeItem(const JID& item); - void addItems(const std::vector<JID>& items); - void removeItems(const std::vector<JID>& items); - void removeAllItems(); - - private: - State state; - std::vector<JID> items; - }; + class BlockListImpl : public BlockList { + public: + BlockListImpl(); + + virtual State getState() const { + return state; + } + + void setState(State state); + + virtual const std::vector<JID>& getItems() const { + return items; + } + + void setItems(const std::vector<JID>& newItems); + void addItem(const JID& item); + void removeItem(const JID& item); + void addItems(const std::vector<JID>& items); + void removeItems(const std::vector<JID>& items); + void removeAllItems(); + + private: + State state; + std::vector<JID> items; + }; } diff --git a/Swiften/Client/Client.cpp b/Swiften/Client/Client.cpp index f1266e9..89b66b8 100644 --- a/Swiften/Client/Client.cpp +++ b/Swiften/Client/Client.cpp @@ -39,160 +39,160 @@ namespace Swift { Client::Client(const JID& jid, const SafeString& password, NetworkFactories* networkFactories, Storages* storages) : CoreClient(jid, password, networkFactories), storages(storages) { - memoryStorages = new MemoryStorages(networkFactories->getCryptoProvider()); + memoryStorages = new MemoryStorages(networkFactories->getCryptoProvider()); - softwareVersionResponder = new SoftwareVersionResponder(getIQRouter()); - softwareVersionResponder->start(); + softwareVersionResponder = new SoftwareVersionResponder(getIQRouter()); + softwareVersionResponder->start(); - roster = new XMPPRosterImpl(); - rosterController = new XMPPRosterController(getIQRouter(), roster, getStorages()->getRosterStorage()); + roster = new XMPPRosterImpl(); + rosterController = new XMPPRosterController(getIQRouter(), roster, getStorages()->getRosterStorage()); - subscriptionManager = new SubscriptionManager(getStanzaChannel()); + subscriptionManager = new SubscriptionManager(getStanzaChannel()); - presenceOracle = new PresenceOracle(getStanzaChannel(), roster); - presenceOracle->onPresenceChange.connect(boost::ref(onPresenceChange)); + presenceOracle = new PresenceOracle(getStanzaChannel(), roster); + presenceOracle->onPresenceChange.connect(boost::ref(onPresenceChange)); - stanzaChannelPresenceSender = new StanzaChannelPresenceSender(getStanzaChannel()); - directedPresenceSender = new DirectedPresenceSender(stanzaChannelPresenceSender); - discoManager = new ClientDiscoManager(getIQRouter(), directedPresenceSender, networkFactories->getCryptoProvider()); + stanzaChannelPresenceSender = new StanzaChannelPresenceSender(getStanzaChannel()); + directedPresenceSender = new DirectedPresenceSender(stanzaChannelPresenceSender); + discoManager = new ClientDiscoManager(getIQRouter(), directedPresenceSender, networkFactories->getCryptoProvider()); - mucRegistry = new MUCRegistry(); - mucManager = new MUCManager(getStanzaChannel(), getIQRouter(), directedPresenceSender, mucRegistry); + mucRegistry = new MUCRegistry(); + mucManager = new MUCManager(getStanzaChannel(), getIQRouter(), directedPresenceSender, mucRegistry); - vcardManager = new VCardManager(jid, getIQRouter(), getStorages()->getVCardStorage()); - avatarManager = new AvatarManagerImpl(vcardManager, getStanzaChannel(), getStorages()->getAvatarStorage(), networkFactories->getCryptoProvider(), mucRegistry); - capsManager = new CapsManager(getStorages()->getCapsStorage(), getStanzaChannel(), getIQRouter(), networkFactories->getCryptoProvider()); - entityCapsManager = new EntityCapsManager(capsManager, getStanzaChannel()); + vcardManager = new VCardManager(jid, getIQRouter(), getStorages()->getVCardStorage()); + avatarManager = new AvatarManagerImpl(vcardManager, getStanzaChannel(), getStorages()->getAvatarStorage(), networkFactories->getCryptoProvider(), mucRegistry); + capsManager = new CapsManager(getStorages()->getCapsStorage(), getStanzaChannel(), getIQRouter(), networkFactories->getCryptoProvider()); + entityCapsManager = new EntityCapsManager(capsManager, getStanzaChannel()); - nickManager = new NickManagerImpl(jid.toBare(), vcardManager); - nickResolver = new NickResolver(jid.toBare(), roster, vcardManager, mucRegistry); + nickManager = new NickManagerImpl(jid.toBare(), vcardManager); + nickResolver = new NickResolver(jid.toBare(), roster, vcardManager, mucRegistry); - blindCertificateTrustChecker = new BlindCertificateTrustChecker(); - - jingleSessionManager = new JingleSessionManager(getIQRouter()); - blockListManager = new ClientBlockListManager(getIQRouter()); + blindCertificateTrustChecker = new BlindCertificateTrustChecker(); - whiteboardSessionManager = NULL; + jingleSessionManager = new JingleSessionManager(getIQRouter()); + blockListManager = new ClientBlockListManager(getIQRouter()); + + whiteboardSessionManager = NULL; #ifdef SWIFT_EXPERIMENTAL_WB - whiteboardSessionManager = new WhiteboardSessionManager(getIQRouter(), getStanzaChannel(), presenceOracle, getEntityCapsProvider()); + whiteboardSessionManager = new WhiteboardSessionManager(getIQRouter(), getStanzaChannel(), presenceOracle, getEntityCapsProvider()); #endif - pubsubManager = new PubSubManagerImpl(getStanzaChannel(), getIQRouter()); + pubsubManager = new PubSubManagerImpl(getStanzaChannel(), getIQRouter()); #ifdef SWIFT_EXPERIMENTAL_FT - fileTransferManager = new FileTransferManagerImpl( - getJID(), - jingleSessionManager, - getIQRouter(), - getEntityCapsProvider(), - presenceOracle, - getNetworkFactories()->getConnectionFactory(), - getNetworkFactories()->getConnectionServerFactory(), - getNetworkFactories()->getTimerFactory(), - getNetworkFactories()->getDomainNameResolver(), - getNetworkFactories()->getNetworkEnvironment(), - getNetworkFactories()->getNATTraverser(), - getNetworkFactories()->getCryptoProvider()); + fileTransferManager = new FileTransferManagerImpl( + getJID(), + jingleSessionManager, + getIQRouter(), + getEntityCapsProvider(), + presenceOracle, + getNetworkFactories()->getConnectionFactory(), + getNetworkFactories()->getConnectionServerFactory(), + getNetworkFactories()->getTimerFactory(), + getNetworkFactories()->getDomainNameResolver(), + getNetworkFactories()->getNetworkEnvironment(), + getNetworkFactories()->getNATTraverser(), + getNetworkFactories()->getCryptoProvider()); #else - fileTransferManager = new DummyFileTransferManager(); + fileTransferManager = new DummyFileTransferManager(); #endif } Client::~Client() { - delete pubsubManager; - delete whiteboardSessionManager; + delete pubsubManager; + delete whiteboardSessionManager; + + delete fileTransferManager; + delete blockListManager; + delete jingleSessionManager; - delete fileTransferManager; - delete blockListManager; - delete jingleSessionManager; - - delete blindCertificateTrustChecker; + delete blindCertificateTrustChecker; - delete nickResolver; - delete nickManager; + delete nickResolver; + delete nickManager; - delete entityCapsManager; - delete capsManager; - delete avatarManager; - delete vcardManager; + delete entityCapsManager; + delete capsManager; + delete avatarManager; + delete vcardManager; - delete mucManager; - delete mucRegistry; + delete mucManager; + delete mucRegistry; - delete discoManager; - delete directedPresenceSender; - delete stanzaChannelPresenceSender; + delete discoManager; + delete directedPresenceSender; + delete stanzaChannelPresenceSender; - delete presenceOracle; - delete subscriptionManager; - delete rosterController; - delete roster; + delete presenceOracle; + delete subscriptionManager; + delete rosterController; + delete roster; - softwareVersionResponder->stop(); - delete softwareVersionResponder; + softwareVersionResponder->stop(); + delete softwareVersionResponder; - delete memoryStorages; + delete memoryStorages; } XMPPRoster* Client::getRoster() const { - return roster; + return roster; } void Client::setSoftwareVersion(const std::string& name, const std::string& version, const std::string& os) { - softwareVersionResponder->setVersion(name, version, os); + softwareVersionResponder->setVersion(name, version, os); } void Client::handleConnected() { - discoManager->handleConnected(); + discoManager->handleConnected(); } void Client::requestRoster() { - // FIXME: We should set this once when the session is finished, but there - // is currently no callback for this - if (getSession()) { - rosterController->setUseVersioning(getSession()->getRosterVersioningSupported()); - } - rosterController->requestRoster(); + // FIXME: We should set this once when the session is finished, but there + // is currently no callback for this + if (getSession()) { + rosterController->setUseVersioning(getSession()->getRosterVersioningSupported()); + } + rosterController->requestRoster(); } Presence::ref Client::getLastPresence(const JID& jid) const { - return presenceOracle->getLastPresence(jid); + return presenceOracle->getLastPresence(jid); } Presence::ref Client::getHighestPriorityPresence(const JID& bareJID) const { - return presenceOracle->getHighestPriorityPresence(bareJID); + return presenceOracle->getHighestPriorityPresence(bareJID); } Storages* Client::getStorages() const { - if (storages) { - return storages; - } - return memoryStorages; + if (storages) { + return storages; + } + return memoryStorages; } PresenceSender* Client::getPresenceSender() const { - return discoManager->getPresenceSender(); + return discoManager->getPresenceSender(); } EntityCapsProvider* Client::getEntityCapsProvider() const { - return entityCapsManager; + return entityCapsManager; } void Client::setAlwaysTrustCertificates() { - setCertificateTrustChecker(blindCertificateTrustChecker); + setCertificateTrustChecker(blindCertificateTrustChecker); } NickManager* Client::getNickManager() const { - return nickManager; + return nickManager; } FileTransferManager* Client::getFileTransferManager() const { - return fileTransferManager; + return fileTransferManager; } WhiteboardSessionManager* Client::getWhiteboardSessionManager() const { - return whiteboardSessionManager; + return whiteboardSessionManager; } } diff --git a/Swiften/Client/Client.h b/Swiften/Client/Client.h index f7a372e..a3d11a1 100644 --- a/Swiften/Client/Client.h +++ b/Swiften/Client/Client.h @@ -11,196 +11,196 @@ #include <Swiften/Client/CoreClient.h> namespace Swift { - class SoftwareVersionResponder; - class BlindCertificateTrustChecker; - class XMPPRoster; - class XMPPRosterImpl; - class MUCManager; - class XMPPRosterController; - class PresenceOracle; - class PresenceSender; - class DirectedPresenceSender; - class StanzaChannelPresenceSender; - class MUCRegistry; - class Storages; - class MemoryStorages; - class VCardManager; - class AvatarManager; - class CapsManager; - class EntityCapsManager; - class EntityCapsProvider; - class NickResolver; - class SubscriptionManager; - class ClientDiscoManager; - class NickManager; - class FileTransferManager; - class JingleSessionManager; - class FileTransferManager; - class WhiteboardSessionManager; - class ClientBlockListManager; - class PubSubManager; - - /** - * Provides the core functionality for writing XMPP client software. - * - * Besides connecting to an XMPP server, this class also provides interfaces for - * performing most tasks on the XMPP network. - */ - class SWIFTEN_API Client : public CoreClient { - public: - /** - * Constructs a client for the given JID with the given password. - * - * \param storages The interfaces for storing cache information etc. If - * this is NULL, - * all data will be stored in memory (and be lost on shutdown) - */ - Client(const JID& jid, const SafeString& password, NetworkFactories* networkFactories, Storages* storages = NULL); - virtual ~Client(); - - - /** - * Sets the software version of the client. - * - * This will be used to respond to version queries from other entities. - */ - void setSoftwareVersion(const std::string& name, const std::string& version, const std::string& os = ""); - - /** - * Returns a representation of the roster. - * - * The roster is initially empty. To populate it, call requestRoster(), - * which will request the roster from the server. When the roster has - * been requested, it will also be kept up to date when it is updated on - * the server side. - * - * This pointer remains the same across the lifetime of Client. All - * changes to the roster (e.g. after the initial roster request, or after - * subsequent roster updates) are notified through the XMPPRoster's - * signals. - * - * \see requestRoster() - */ - XMPPRoster* getRoster() const; - - /** - * Requests the roster from the server. - * - * \see getRoster() - */ - void requestRoster(); - - /** - * Returns the last received presence for the given (full) JID. - */ - boost::shared_ptr<Presence> getLastPresence(const JID& jid) const; - - /** - * Returns the presence with the highest priority received for the given JID. - */ - boost::shared_ptr<Presence> getHighestPriorityPresence(const JID& bareJID) const; - - PresenceOracle* getPresenceOracle() const { - return presenceOracle; - } - - PresenceSender* getPresenceSender() const; - - MUCManager* getMUCManager() const { - return mucManager; - } - - MUCRegistry* getMUCRegistry() const { - return mucRegistry; - } - - VCardManager* getVCardManager() const { - return vcardManager; - } - - AvatarManager* getAvatarManager() const { - return avatarManager; - } - - EntityCapsProvider* getEntityCapsProvider() const; - - NickManager* getNickManager() const; - - NickResolver* getNickResolver() const { - return nickResolver; - } - - SubscriptionManager* getSubscriptionManager() const { - return subscriptionManager; - } - - ClientDiscoManager* getDiscoManager() const { - return discoManager; - } - - ClientBlockListManager* getClientBlockListManager() const { - return blockListManager; - } - - /** - * Returns a FileTransferManager for the client. This is only available after the onConnected - * signal has been fired. - * - * WARNING: File transfer will only work if Swiften is built in 'experimental' mode. - */ - FileTransferManager* getFileTransferManager() const; - - /** - * Configures the client to always trust a non-validating - * TLS certificate from the server. - * This is equivalent to setting a BlindCertificateTrustChecker - * using setCertificateTrustChecker(). - */ - void setAlwaysTrustCertificates(); - - WhiteboardSessionManager* getWhiteboardSessionManager() const; - - PubSubManager* getPubSubManager() const { - return pubsubManager; - } - - - public: - /** - * This signal is emitted when a JID changes presence. - */ - boost::signal<void (boost::shared_ptr<Presence>)> onPresenceChange; - - private: - Storages* getStorages() const; - - protected: - void handleConnected(); - - private: - Storages* storages; - MemoryStorages* memoryStorages; - SoftwareVersionResponder* softwareVersionResponder; - XMPPRosterImpl* roster; - XMPPRosterController* rosterController; - PresenceOracle* presenceOracle; - DirectedPresenceSender* directedPresenceSender; - StanzaChannelPresenceSender* stanzaChannelPresenceSender; - MUCRegistry* mucRegistry; - VCardManager* vcardManager; - AvatarManager* avatarManager; - CapsManager* capsManager; - EntityCapsManager* entityCapsManager; - NickManager* nickManager; - NickResolver* nickResolver; - SubscriptionManager* subscriptionManager; - MUCManager* mucManager; - ClientDiscoManager* discoManager; - JingleSessionManager* jingleSessionManager; - FileTransferManager* fileTransferManager; - BlindCertificateTrustChecker* blindCertificateTrustChecker; - WhiteboardSessionManager* whiteboardSessionManager; - ClientBlockListManager* blockListManager; - PubSubManager* pubsubManager; - }; + class SoftwareVersionResponder; + class BlindCertificateTrustChecker; + class XMPPRoster; + class XMPPRosterImpl; + class MUCManager; + class XMPPRosterController; + class PresenceOracle; + class PresenceSender; + class DirectedPresenceSender; + class StanzaChannelPresenceSender; + class MUCRegistry; + class Storages; + class MemoryStorages; + class VCardManager; + class AvatarManager; + class CapsManager; + class EntityCapsManager; + class EntityCapsProvider; + class NickResolver; + class SubscriptionManager; + class ClientDiscoManager; + class NickManager; + class FileTransferManager; + class JingleSessionManager; + class FileTransferManager; + class WhiteboardSessionManager; + class ClientBlockListManager; + class PubSubManager; + + /** + * Provides the core functionality for writing XMPP client software. + * + * Besides connecting to an XMPP server, this class also provides interfaces for + * performing most tasks on the XMPP network. + */ + class SWIFTEN_API Client : public CoreClient { + public: + /** + * Constructs a client for the given JID with the given password. + * + * \param storages The interfaces for storing cache information etc. If + * this is NULL, + * all data will be stored in memory (and be lost on shutdown) + */ + Client(const JID& jid, const SafeString& password, NetworkFactories* networkFactories, Storages* storages = NULL); + virtual ~Client(); + + + /** + * Sets the software version of the client. + * + * This will be used to respond to version queries from other entities. + */ + void setSoftwareVersion(const std::string& name, const std::string& version, const std::string& os = ""); + + /** + * Returns a representation of the roster. + * + * The roster is initially empty. To populate it, call requestRoster(), + * which will request the roster from the server. When the roster has + * been requested, it will also be kept up to date when it is updated on + * the server side. + * + * This pointer remains the same across the lifetime of Client. All + * changes to the roster (e.g. after the initial roster request, or after + * subsequent roster updates) are notified through the XMPPRoster's + * signals. + * + * \see requestRoster() + */ + XMPPRoster* getRoster() const; + + /** + * Requests the roster from the server. + * + * \see getRoster() + */ + void requestRoster(); + + /** + * Returns the last received presence for the given (full) JID. + */ + boost::shared_ptr<Presence> getLastPresence(const JID& jid) const; + + /** + * Returns the presence with the highest priority received for the given JID. + */ + boost::shared_ptr<Presence> getHighestPriorityPresence(const JID& bareJID) const; + + PresenceOracle* getPresenceOracle() const { + return presenceOracle; + } + + PresenceSender* getPresenceSender() const; + + MUCManager* getMUCManager() const { + return mucManager; + } + + MUCRegistry* getMUCRegistry() const { + return mucRegistry; + } + + VCardManager* getVCardManager() const { + return vcardManager; + } + + AvatarManager* getAvatarManager() const { + return avatarManager; + } + + EntityCapsProvider* getEntityCapsProvider() const; + + NickManager* getNickManager() const; + + NickResolver* getNickResolver() const { + return nickResolver; + } + + SubscriptionManager* getSubscriptionManager() const { + return subscriptionManager; + } + + ClientDiscoManager* getDiscoManager() const { + return discoManager; + } + + ClientBlockListManager* getClientBlockListManager() const { + return blockListManager; + } + + /** + * Returns a FileTransferManager for the client. This is only available after the onConnected + * signal has been fired. + * + * WARNING: File transfer will only work if Swiften is built in 'experimental' mode. + */ + FileTransferManager* getFileTransferManager() const; + + /** + * Configures the client to always trust a non-validating + * TLS certificate from the server. + * This is equivalent to setting a BlindCertificateTrustChecker + * using setCertificateTrustChecker(). + */ + void setAlwaysTrustCertificates(); + + WhiteboardSessionManager* getWhiteboardSessionManager() const; + + PubSubManager* getPubSubManager() const { + return pubsubManager; + } + + + public: + /** + * This signal is emitted when a JID changes presence. + */ + boost::signal<void (boost::shared_ptr<Presence>)> onPresenceChange; + + private: + Storages* getStorages() const; + + protected: + void handleConnected(); + + private: + Storages* storages; + MemoryStorages* memoryStorages; + SoftwareVersionResponder* softwareVersionResponder; + XMPPRosterImpl* roster; + XMPPRosterController* rosterController; + PresenceOracle* presenceOracle; + DirectedPresenceSender* directedPresenceSender; + StanzaChannelPresenceSender* stanzaChannelPresenceSender; + MUCRegistry* mucRegistry; + VCardManager* vcardManager; + AvatarManager* avatarManager; + CapsManager* capsManager; + EntityCapsManager* entityCapsManager; + NickManager* nickManager; + NickResolver* nickResolver; + SubscriptionManager* subscriptionManager; + MUCManager* mucManager; + ClientDiscoManager* discoManager; + JingleSessionManager* jingleSessionManager; + FileTransferManager* fileTransferManager; + BlindCertificateTrustChecker* blindCertificateTrustChecker; + WhiteboardSessionManager* whiteboardSessionManager; + ClientBlockListManager* blockListManager; + PubSubManager* pubsubManager; + }; } diff --git a/Swiften/Client/ClientBlockListManager.cpp b/Swiften/Client/ClientBlockListManager.cpp index fa7cd42..84a5639 100644 --- a/Swiften/Client/ClientBlockListManager.cpp +++ b/Swiften/Client/ClientBlockListManager.cpp @@ -16,54 +16,54 @@ using namespace Swift; namespace { - class BlockResponder : public SetResponder<BlockPayload> { - public: - BlockResponder(boost::shared_ptr<BlockListImpl> blockList, IQRouter* iqRouter) : SetResponder<BlockPayload>(iqRouter), blockList(blockList) { - } - - virtual bool handleSetRequest(const JID& from, const JID&, const std::string& id, boost::shared_ptr<BlockPayload> payload) { - if (getIQRouter()->isAccountJID(from)) { - if (payload) { - blockList->addItems(payload->getItems()); - } - sendResponse(from, id, boost::shared_ptr<BlockPayload>()); - } - else { - sendError(from, id, ErrorPayload::NotAuthorized, ErrorPayload::Cancel); - } - return true; - } - - private: - boost::shared_ptr<BlockListImpl> blockList; - }; - - class UnblockResponder : public SetResponder<UnblockPayload> { - public: - UnblockResponder(boost::shared_ptr<BlockListImpl> blockList, IQRouter* iqRouter) : SetResponder<UnblockPayload>(iqRouter), blockList(blockList) { - } - - virtual bool handleSetRequest(const JID& from, const JID&, const std::string& id, boost::shared_ptr<UnblockPayload> payload) { - if (getIQRouter()->isAccountJID(from)) { - if (payload) { - if (payload->getItems().empty()) { - blockList->removeAllItems(); - } - else { - blockList->removeItems(payload->getItems()); - } - } - sendResponse(from, id, boost::shared_ptr<UnblockPayload>()); - } - else { - sendError(from, id, ErrorPayload::NotAuthorized, ErrorPayload::Cancel); - } - return true; - } - - private: - boost::shared_ptr<BlockListImpl> blockList; - }; + class BlockResponder : public SetResponder<BlockPayload> { + public: + BlockResponder(boost::shared_ptr<BlockListImpl> blockList, IQRouter* iqRouter) : SetResponder<BlockPayload>(iqRouter), blockList(blockList) { + } + + virtual bool handleSetRequest(const JID& from, const JID&, const std::string& id, boost::shared_ptr<BlockPayload> payload) { + if (getIQRouter()->isAccountJID(from)) { + if (payload) { + blockList->addItems(payload->getItems()); + } + sendResponse(from, id, boost::shared_ptr<BlockPayload>()); + } + else { + sendError(from, id, ErrorPayload::NotAuthorized, ErrorPayload::Cancel); + } + return true; + } + + private: + boost::shared_ptr<BlockListImpl> blockList; + }; + + class UnblockResponder : public SetResponder<UnblockPayload> { + public: + UnblockResponder(boost::shared_ptr<BlockListImpl> blockList, IQRouter* iqRouter) : SetResponder<UnblockPayload>(iqRouter), blockList(blockList) { + } + + virtual bool handleSetRequest(const JID& from, const JID&, const std::string& id, boost::shared_ptr<UnblockPayload> payload) { + if (getIQRouter()->isAccountJID(from)) { + if (payload) { + if (payload->getItems().empty()) { + blockList->removeAllItems(); + } + else { + blockList->removeItems(payload->getItems()); + } + } + sendResponse(from, id, boost::shared_ptr<UnblockPayload>()); + } + else { + sendError(from, id, ErrorPayload::NotAuthorized, ErrorPayload::Cancel); + } + return true; + } + + private: + boost::shared_ptr<BlockListImpl> blockList; + }; } ClientBlockListManager::ClientBlockListManager(IQRouter* iqRouter) : iqRouter(iqRouter) { @@ -71,69 +71,69 @@ ClientBlockListManager::ClientBlockListManager(IQRouter* iqRouter) : iqRouter(iq } ClientBlockListManager::~ClientBlockListManager() { - if (blockList && blockList->getState() == BlockList::Available) { - unblockResponder->stop(); - blockResponder->stop(); - } + if (blockList && blockList->getState() == BlockList::Available) { + unblockResponder->stop(); + blockResponder->stop(); + } } boost::shared_ptr<BlockList> ClientBlockListManager::getBlockList() { - if (!blockList) { - blockList = boost::make_shared<BlockListImpl>(); - blockList->setState(BlockList::Init); - } - return blockList; + if (!blockList) { + blockList = boost::make_shared<BlockListImpl>(); + blockList->setState(BlockList::Init); + } + return blockList; } boost::shared_ptr<BlockList> ClientBlockListManager::requestBlockList() { - if (!blockList) { - blockList = boost::make_shared<BlockListImpl>(); - } - blockList->setState(BlockList::Requesting); - boost::shared_ptr<GenericRequest<BlockListPayload> > getRequest = boost::make_shared< GenericRequest<BlockListPayload> >(IQ::Get, JID(), boost::make_shared<BlockListPayload>(), iqRouter); - getRequest->onResponse.connect(boost::bind(&ClientBlockListManager::handleBlockListReceived, this, _1, _2)); - getRequest->send(); - return blockList; + if (!blockList) { + blockList = boost::make_shared<BlockListImpl>(); + } + blockList->setState(BlockList::Requesting); + boost::shared_ptr<GenericRequest<BlockListPayload> > getRequest = boost::make_shared< GenericRequest<BlockListPayload> >(IQ::Get, JID(), boost::make_shared<BlockListPayload>(), iqRouter); + getRequest->onResponse.connect(boost::bind(&ClientBlockListManager::handleBlockListReceived, this, _1, _2)); + getRequest->send(); + return blockList; } GenericRequest<BlockPayload>::ref ClientBlockListManager::createBlockJIDRequest(const JID& jid) { - return createBlockJIDsRequest(std::vector<JID>(1, jid)); + return createBlockJIDsRequest(std::vector<JID>(1, jid)); } GenericRequest<BlockPayload>::ref ClientBlockListManager::createBlockJIDsRequest(const std::vector<JID>& jids) { - boost::shared_ptr<BlockPayload> payload = boost::make_shared<BlockPayload>(jids); - return boost::make_shared< GenericRequest<BlockPayload> >(IQ::Set, JID(), payload, iqRouter); + boost::shared_ptr<BlockPayload> payload = boost::make_shared<BlockPayload>(jids); + return boost::make_shared< GenericRequest<BlockPayload> >(IQ::Set, JID(), payload, iqRouter); } GenericRequest<UnblockPayload>::ref ClientBlockListManager::createUnblockJIDRequest(const JID& jid) { - return createUnblockJIDsRequest(std::vector<JID>(1, jid)); + return createUnblockJIDsRequest(std::vector<JID>(1, jid)); } GenericRequest<UnblockPayload>::ref ClientBlockListManager::createUnblockJIDsRequest(const std::vector<JID>& jids) { - boost::shared_ptr<UnblockPayload> payload = boost::make_shared<UnblockPayload>(jids); - return boost::make_shared< GenericRequest<UnblockPayload> >(IQ::Set, JID(), payload, iqRouter); + boost::shared_ptr<UnblockPayload> payload = boost::make_shared<UnblockPayload>(jids); + return boost::make_shared< GenericRequest<UnblockPayload> >(IQ::Set, JID(), payload, iqRouter); } GenericRequest<UnblockPayload>::ref ClientBlockListManager::createUnblockAllRequest() { - return createUnblockJIDsRequest(std::vector<JID>()); + return createUnblockJIDsRequest(std::vector<JID>()); } void ClientBlockListManager::handleBlockListReceived(boost::shared_ptr<BlockListPayload> payload, ErrorPayload::ref error) { - if (error || !payload) { - blockList->setState(BlockList::Error); - } - else { - blockList->setItems(payload->getItems()); - blockList->setState(BlockList::Available); - if (!blockResponder) { - blockResponder = boost::make_shared<BlockResponder>(blockList, iqRouter); - blockResponder->start(); - } - if (!unblockResponder) { - unblockResponder = boost::make_shared<UnblockResponder>(blockList, iqRouter); - unblockResponder->start(); - } - } + if (error || !payload) { + blockList->setState(BlockList::Error); + } + else { + blockList->setItems(payload->getItems()); + blockList->setState(BlockList::Available); + if (!blockResponder) { + blockResponder = boost::make_shared<BlockResponder>(blockList, iqRouter); + blockResponder->start(); + } + if (!unblockResponder) { + unblockResponder = boost::make_shared<UnblockResponder>(blockList, iqRouter); + unblockResponder->start(); + } + } } diff --git a/Swiften/Client/ClientBlockListManager.h b/Swiften/Client/ClientBlockListManager.h index 1aafdc6..63ff1cd 100644 --- a/Swiften/Client/ClientBlockListManager.h +++ b/Swiften/Client/ClientBlockListManager.h @@ -20,38 +20,38 @@ #include <Swiften/Queries/SetResponder.h> namespace Swift { - class IQRouter; - - class SWIFTEN_API ClientBlockListManager { - public: - ClientBlockListManager(IQRouter *iqRouter); - ~ClientBlockListManager(); - - /** - * Returns the blocklist. - */ - boost::shared_ptr<BlockList> getBlockList(); - - /** - * Get the blocklist from the server. - */ - boost::shared_ptr<BlockList> requestBlockList(); - - GenericRequest<BlockPayload>::ref createBlockJIDRequest(const JID& jid); - GenericRequest<BlockPayload>::ref createBlockJIDsRequest(const std::vector<JID>& jids); - - GenericRequest<UnblockPayload>::ref createUnblockJIDRequest(const JID& jid); - GenericRequest<UnblockPayload>::ref createUnblockJIDsRequest(const std::vector<JID>& jids); - GenericRequest<UnblockPayload>::ref createUnblockAllRequest(); - - private: - void handleBlockListReceived(boost::shared_ptr<BlockListPayload> payload, ErrorPayload::ref); - - private: - IQRouter* iqRouter; - boost::shared_ptr<SetResponder<BlockPayload> > blockResponder; - boost::shared_ptr<SetResponder<UnblockPayload> > unblockResponder; - boost::shared_ptr<BlockListImpl> blockList; - }; + class IQRouter; + + class SWIFTEN_API ClientBlockListManager { + public: + ClientBlockListManager(IQRouter *iqRouter); + ~ClientBlockListManager(); + + /** + * Returns the blocklist. + */ + boost::shared_ptr<BlockList> getBlockList(); + + /** + * Get the blocklist from the server. + */ + boost::shared_ptr<BlockList> requestBlockList(); + + GenericRequest<BlockPayload>::ref createBlockJIDRequest(const JID& jid); + GenericRequest<BlockPayload>::ref createBlockJIDsRequest(const std::vector<JID>& jids); + + GenericRequest<UnblockPayload>::ref createUnblockJIDRequest(const JID& jid); + GenericRequest<UnblockPayload>::ref createUnblockJIDsRequest(const std::vector<JID>& jids); + GenericRequest<UnblockPayload>::ref createUnblockAllRequest(); + + private: + void handleBlockListReceived(boost::shared_ptr<BlockListPayload> payload, ErrorPayload::ref); + + private: + IQRouter* iqRouter; + boost::shared_ptr<SetResponder<BlockPayload> > blockResponder; + boost::shared_ptr<SetResponder<UnblockPayload> > unblockResponder; + boost::shared_ptr<BlockListImpl> blockList; + }; } diff --git a/Swiften/Client/ClientError.h b/Swiften/Client/ClientError.h index 19de42b..5ae1086 100644 --- a/Swiften/Client/ClientError.h +++ b/Swiften/Client/ClientError.h @@ -10,56 +10,56 @@ #include <boost/system/system_error.hpp> namespace Swift { - class ClientError { - public: - enum Type { - UnknownError, - DomainNameResolveError, - ConnectionError, - ConnectionReadError, - ConnectionWriteError, - XMLError, - AuthenticationFailedError, - CompressionFailedError, - ServerVerificationFailedError, - NoSupportedAuthMechanismsError, - UnexpectedElementError, - ResourceBindError, - SessionStartError, - StreamError, - TLSError, - ClientCertificateLoadError, - ClientCertificateError, + class ClientError { + public: + enum Type { + UnknownError, + DomainNameResolveError, + ConnectionError, + ConnectionReadError, + ConnectionWriteError, + XMLError, + AuthenticationFailedError, + CompressionFailedError, + ServerVerificationFailedError, + NoSupportedAuthMechanismsError, + UnexpectedElementError, + ResourceBindError, + SessionStartError, + StreamError, + TLSError, + ClientCertificateLoadError, + ClientCertificateError, - // Certifate on smartcard was removed - CertificateCardRemoved, + // Certifate on smartcard was removed + CertificateCardRemoved, - // Certificate verification errors - UnknownCertificateError, - CertificateExpiredError, - CertificateNotYetValidError, - CertificateSelfSignedError, - CertificateRejectedError, - CertificateUntrustedError, - InvalidCertificatePurposeError, - CertificatePathLengthExceededError, - InvalidCertificateSignatureError, - InvalidCAError, - InvalidServerIdentityError, - RevokedError, - RevocationCheckFailedError - }; + // Certificate verification errors + UnknownCertificateError, + CertificateExpiredError, + CertificateNotYetValidError, + CertificateSelfSignedError, + CertificateRejectedError, + CertificateUntrustedError, + InvalidCertificatePurposeError, + CertificatePathLengthExceededError, + InvalidCertificateSignatureError, + InvalidCAError, + InvalidServerIdentityError, + RevokedError, + RevocationCheckFailedError + }; - ClientError(Type type = UnknownError) : type_(type) {} + ClientError(Type type = UnknownError) : type_(type) {} - Type getType() const { return type_; } + Type getType() const { return type_; } - void setErrorCode(boost::shared_ptr<boost::system::error_code> errorCode) { errorCode_ = errorCode; } + void setErrorCode(boost::shared_ptr<boost::system::error_code> errorCode) { errorCode_ = errorCode; } - boost::shared_ptr<boost::system::error_code> getErrorCode() const { return errorCode_; } + boost::shared_ptr<boost::system::error_code> getErrorCode() const { return errorCode_; } - private: - Type type_; - boost::shared_ptr<boost::system::error_code> errorCode_; - }; + private: + Type type_; + boost::shared_ptr<boost::system::error_code> errorCode_; + }; } diff --git a/Swiften/Client/ClientOptions.h b/Swiften/Client/ClientOptions.h index bef5833..c902388 100644 --- a/Swiften/Client/ClientOptions.h +++ b/Swiften/Client/ClientOptions.h @@ -14,149 +14,149 @@ #include <Swiften/TLS/TLSOptions.h> namespace Swift { - class HTTPTrafficFilter; - - struct SWIFTEN_API ClientOptions { - enum UseTLS { - NeverUseTLS, - UseTLSWhenAvailable, - RequireTLS - }; - - enum ProxyType { - NoProxy, - SystemConfiguredProxy, - SOCKS5Proxy, - HTTPConnectProxy - }; - - ClientOptions() : - useStreamCompression(true), - useTLS(UseTLSWhenAvailable), - allowPLAINWithoutTLS(false), - useStreamResumption(false), - forgetPassword(false), - useAcks(true), - singleSignOn(false), - manualHostname(""), - manualPort(-1), - proxyType(SystemConfiguredProxy), - manualProxyHostname(""), - manualProxyPort(-1), - boshHTTPConnectProxyAuthID(""), - boshHTTPConnectProxyAuthPassword("") { - } - - /** - * Whether ZLib stream compression should be used when available. - * - * Default: true - */ - bool useStreamCompression; - - /** - * Sets whether TLS encryption should be used. - * - * Default: UseTLSWhenAvailable - */ - UseTLS useTLS; - - /** - * Sets whether plaintext authentication is - * allowed over non-TLS-encrypted connections. - * - * Default: false - */ - bool allowPLAINWithoutTLS; - - /** - * Use XEP-196 stream resumption when available. - * - * Default: false - */ - bool useStreamResumption; - - /** - * Forget the password once it's used. - * This makes the Client useless after the first login attempt. - * - * FIXME: This is a temporary workaround. - * - * Default: false - */ - bool forgetPassword; - - /** - * Use XEP-0198 acks in the stream when available. - * Default: true - */ - bool useAcks; - - /** - * Use Single Sign On. - * Default: false - */ - bool singleSignOn; - - /** - * The hostname to connect to. - * Leave this empty for standard XMPP connection, based on the JID domain. - */ - std::string manualHostname; - - /** - * The port to connect to. - * Leave this to -1 to use the port discovered by SRV lookups, and 5222 as a - * fallback. - */ - int manualPort; - - /** - * The type of proxy to use for connecting to the XMPP - * server. - */ - ProxyType proxyType; - - /** - * Override the system-configured proxy hostname. - */ - std::string manualProxyHostname; - - /** - * Override the system-configured proxy port. - */ - int manualProxyPort; - - /** - * If non-empty, use BOSH instead of direct TCP, with the given URL. - * Default: empty (no BOSH) - */ - URL boshURL; - - /** - * If non-empty, BOSH connections will try to connect over this HTTP CONNECT - * proxy instead of directly. - * Default: empty (no proxy) - */ - URL boshHTTPConnectProxyURL; - - /** - * If this and matching Password are non-empty, BOSH connections over - * HTTP CONNECT proxies will use these credentials for proxy access. - * Default: empty (no authentication needed by the proxy) - */ - SafeString boshHTTPConnectProxyAuthID; - SafeString boshHTTPConnectProxyAuthPassword; - - /** - * This can be initialized with a custom HTTPTrafficFilter, which allows HTTP CONNECT - * proxy initialization to be customized. - */ - boost::shared_ptr<HTTPTrafficFilter> httpTrafficFilter; - - /** - * Options passed to the TLS stack - */ - TLSOptions tlsOptions; - }; + class HTTPTrafficFilter; + + struct SWIFTEN_API ClientOptions { + enum UseTLS { + NeverUseTLS, + UseTLSWhenAvailable, + RequireTLS + }; + + enum ProxyType { + NoProxy, + SystemConfiguredProxy, + SOCKS5Proxy, + HTTPConnectProxy + }; + + ClientOptions() : + useStreamCompression(true), + useTLS(UseTLSWhenAvailable), + allowPLAINWithoutTLS(false), + useStreamResumption(false), + forgetPassword(false), + useAcks(true), + singleSignOn(false), + manualHostname(""), + manualPort(-1), + proxyType(SystemConfiguredProxy), + manualProxyHostname(""), + manualProxyPort(-1), + boshHTTPConnectProxyAuthID(""), + boshHTTPConnectProxyAuthPassword("") { + } + + /** + * Whether ZLib stream compression should be used when available. + * + * Default: true + */ + bool useStreamCompression; + + /** + * Sets whether TLS encryption should be used. + * + * Default: UseTLSWhenAvailable + */ + UseTLS useTLS; + + /** + * Sets whether plaintext authentication is + * allowed over non-TLS-encrypted connections. + * + * Default: false + */ + bool allowPLAINWithoutTLS; + + /** + * Use XEP-196 stream resumption when available. + * + * Default: false + */ + bool useStreamResumption; + + /** + * Forget the password once it's used. + * This makes the Client useless after the first login attempt. + * + * FIXME: This is a temporary workaround. + * + * Default: false + */ + bool forgetPassword; + + /** + * Use XEP-0198 acks in the stream when available. + * Default: true + */ + bool useAcks; + + /** + * Use Single Sign On. + * Default: false + */ + bool singleSignOn; + + /** + * The hostname to connect to. + * Leave this empty for standard XMPP connection, based on the JID domain. + */ + std::string manualHostname; + + /** + * The port to connect to. + * Leave this to -1 to use the port discovered by SRV lookups, and 5222 as a + * fallback. + */ + int manualPort; + + /** + * The type of proxy to use for connecting to the XMPP + * server. + */ + ProxyType proxyType; + + /** + * Override the system-configured proxy hostname. + */ + std::string manualProxyHostname; + + /** + * Override the system-configured proxy port. + */ + int manualProxyPort; + + /** + * If non-empty, use BOSH instead of direct TCP, with the given URL. + * Default: empty (no BOSH) + */ + URL boshURL; + + /** + * If non-empty, BOSH connections will try to connect over this HTTP CONNECT + * proxy instead of directly. + * Default: empty (no proxy) + */ + URL boshHTTPConnectProxyURL; + + /** + * If this and matching Password are non-empty, BOSH connections over + * HTTP CONNECT proxies will use these credentials for proxy access. + * Default: empty (no authentication needed by the proxy) + */ + SafeString boshHTTPConnectProxyAuthID; + SafeString boshHTTPConnectProxyAuthPassword; + + /** + * This can be initialized with a custom HTTPTrafficFilter, which allows HTTP CONNECT + * proxy initialization to be customized. + */ + boost::shared_ptr<HTTPTrafficFilter> httpTrafficFilter; + + /** + * Options passed to the TLS stack + */ + TLSOptions tlsOptions; + }; } diff --git a/Swiften/Client/ClientSession.cpp b/Swiften/Client/ClientSession.cpp index 52b8cfb..e38dde8 100644 --- a/Swiften/Client/ClientSession.cpp +++ b/Swiften/Client/ClientSession.cpp @@ -51,35 +51,35 @@ #endif #define CHECK_STATE_OR_RETURN(a) \ - if (!checkState(a)) { return; } + if (!checkState(a)) { return; } namespace Swift { ClientSession::ClientSession( - const JID& jid, - boost::shared_ptr<SessionStream> stream, - IDNConverter* idnConverter, - CryptoProvider* crypto) : - localJID(jid), - state(Initial), - stream(stream), - idnConverter(idnConverter), - crypto(crypto), - allowPLAINOverNonTLS(false), - useStreamCompression(true), - useTLS(UseTLSWhenAvailable), - useAcks(true), - needSessionStart(false), - needResourceBind(false), - needAcking(false), - rosterVersioningSupported(false), - authenticator(NULL), - certificateTrustChecker(NULL), - singleSignOn(false), - authenticationPort(-1) { + const JID& jid, + boost::shared_ptr<SessionStream> stream, + IDNConverter* idnConverter, + CryptoProvider* crypto) : + localJID(jid), + state(Initial), + stream(stream), + idnConverter(idnConverter), + crypto(crypto), + allowPLAINOverNonTLS(false), + useStreamCompression(true), + useTLS(UseTLSWhenAvailable), + useAcks(true), + needSessionStart(false), + needResourceBind(false), + needAcking(false), + rosterVersioningSupported(false), + authenticator(NULL), + certificateTrustChecker(NULL), + singleSignOn(false), + authenticationPort(-1) { #ifdef SWIFTEN_PLATFORM_WIN32 if (WindowsRegistry::isFIPSEnabled()) { - SWIFT_LOG(info) << "Windows is running in FIPS-140 mode. Some authentication methods will be unavailable." << std::endl; + SWIFT_LOG(info) << "Windows is running in FIPS-140 mode. Some authentication methods will be unavailable." << std::endl; } #endif } @@ -88,427 +88,427 @@ ClientSession::~ClientSession() { } void ClientSession::start() { - stream->onStreamStartReceived.connect(boost::bind(&ClientSession::handleStreamStart, shared_from_this(), _1)); - stream->onElementReceived.connect(boost::bind(&ClientSession::handleElement, shared_from_this(), _1)); - stream->onClosed.connect(boost::bind(&ClientSession::handleStreamClosed, shared_from_this(), _1)); - stream->onTLSEncrypted.connect(boost::bind(&ClientSession::handleTLSEncrypted, shared_from_this())); - - assert(state == Initial); - state = WaitingForStreamStart; - sendStreamHeader(); + stream->onStreamStartReceived.connect(boost::bind(&ClientSession::handleStreamStart, shared_from_this(), _1)); + stream->onElementReceived.connect(boost::bind(&ClientSession::handleElement, shared_from_this(), _1)); + stream->onClosed.connect(boost::bind(&ClientSession::handleStreamClosed, shared_from_this(), _1)); + stream->onTLSEncrypted.connect(boost::bind(&ClientSession::handleTLSEncrypted, shared_from_this())); + + assert(state == Initial); + state = WaitingForStreamStart; + sendStreamHeader(); } void ClientSession::sendStreamHeader() { - ProtocolHeader header; - header.setTo(getRemoteJID()); - stream->writeHeader(header); + ProtocolHeader header; + header.setTo(getRemoteJID()); + stream->writeHeader(header); } void ClientSession::sendStanza(boost::shared_ptr<Stanza> stanza) { - stream->writeElement(stanza); - if (stanzaAckRequester_) { - stanzaAckRequester_->handleStanzaSent(stanza); - } + stream->writeElement(stanza); + if (stanzaAckRequester_) { + stanzaAckRequester_->handleStanzaSent(stanza); + } } void ClientSession::handleStreamStart(const ProtocolHeader&) { - CHECK_STATE_OR_RETURN(WaitingForStreamStart); - state = Negotiating; + CHECK_STATE_OR_RETURN(WaitingForStreamStart); + state = Negotiating; } void ClientSession::handleElement(boost::shared_ptr<ToplevelElement> element) { - if (boost::shared_ptr<Stanza> stanza = boost::dynamic_pointer_cast<Stanza>(element)) { - if (stanzaAckResponder_) { - stanzaAckResponder_->handleStanzaReceived(); - } - if (getState() == Initialized) { - onStanzaReceived(stanza); - } - else if (boost::shared_ptr<IQ> iq = boost::dynamic_pointer_cast<IQ>(element)) { - if (state == BindingResource) { - boost::shared_ptr<ResourceBind> resourceBind(iq->getPayload<ResourceBind>()); - if (iq->getType() == IQ::Error && iq->getID() == "session-bind") { - finishSession(Error::ResourceBindError); - } - else if (!resourceBind) { - finishSession(Error::UnexpectedElementError); - } - else if (iq->getType() == IQ::Result) { - localJID = resourceBind->getJID(); - if (!localJID.isValid()) { - finishSession(Error::ResourceBindError); - } - needResourceBind = false; - continueSessionInitialization(); - } - else { - finishSession(Error::UnexpectedElementError); - } - } - else if (state == StartingSession) { - if (iq->getType() == IQ::Result) { - needSessionStart = false; - continueSessionInitialization(); - } - else if (iq->getType() == IQ::Error) { - finishSession(Error::SessionStartError); - } - else { - finishSession(Error::UnexpectedElementError); - } - } - else { - finishSession(Error::UnexpectedElementError); - } - } - } - else if (boost::dynamic_pointer_cast<StanzaAckRequest>(element)) { - if (stanzaAckResponder_) { - stanzaAckResponder_->handleAckRequestReceived(); - } - } - else if (boost::shared_ptr<StanzaAck> ack = boost::dynamic_pointer_cast<StanzaAck>(element)) { - if (stanzaAckRequester_) { - if (ack->isValid()) { - stanzaAckRequester_->handleAckReceived(ack->getHandledStanzasCount()); - } - else { - SWIFT_LOG(warning) << "Got invalid ack from server"; - } - } - else { - SWIFT_LOG(warning) << "Ignoring ack"; - } - } - else if (StreamError::ref streamError = boost::dynamic_pointer_cast<StreamError>(element)) { - finishSession(Error::StreamError); - } - else if (getState() == Initialized) { - boost::shared_ptr<Stanza> stanza = boost::dynamic_pointer_cast<Stanza>(element); - if (stanza) { - if (stanzaAckResponder_) { - stanzaAckResponder_->handleStanzaReceived(); - } - onStanzaReceived(stanza); - } - } - else if (StreamFeatures* streamFeatures = dynamic_cast<StreamFeatures*>(element.get())) { - CHECK_STATE_OR_RETURN(Negotiating); - - if (streamFeatures->hasStartTLS() && stream->supportsTLSEncryption() && useTLS != NeverUseTLS) { - state = WaitingForEncrypt; - stream->writeElement(boost::make_shared<StartTLSRequest>()); - } - else if (useTLS == RequireTLS && !stream->isTLSEncrypted()) { - finishSession(Error::NoSupportedAuthMechanismsError); - } - else if (useStreamCompression && stream->supportsZLibCompression() && streamFeatures->hasCompressionMethod("zlib")) { - state = Compressing; - stream->writeElement(boost::make_shared<CompressRequest>("zlib")); - } - else if (streamFeatures->hasAuthenticationMechanisms()) { + if (boost::shared_ptr<Stanza> stanza = boost::dynamic_pointer_cast<Stanza>(element)) { + if (stanzaAckResponder_) { + stanzaAckResponder_->handleStanzaReceived(); + } + if (getState() == Initialized) { + onStanzaReceived(stanza); + } + else if (boost::shared_ptr<IQ> iq = boost::dynamic_pointer_cast<IQ>(element)) { + if (state == BindingResource) { + boost::shared_ptr<ResourceBind> resourceBind(iq->getPayload<ResourceBind>()); + if (iq->getType() == IQ::Error && iq->getID() == "session-bind") { + finishSession(Error::ResourceBindError); + } + else if (!resourceBind) { + finishSession(Error::UnexpectedElementError); + } + else if (iq->getType() == IQ::Result) { + localJID = resourceBind->getJID(); + if (!localJID.isValid()) { + finishSession(Error::ResourceBindError); + } + needResourceBind = false; + continueSessionInitialization(); + } + else { + finishSession(Error::UnexpectedElementError); + } + } + else if (state == StartingSession) { + if (iq->getType() == IQ::Result) { + needSessionStart = false; + continueSessionInitialization(); + } + else if (iq->getType() == IQ::Error) { + finishSession(Error::SessionStartError); + } + else { + finishSession(Error::UnexpectedElementError); + } + } + else { + finishSession(Error::UnexpectedElementError); + } + } + } + else if (boost::dynamic_pointer_cast<StanzaAckRequest>(element)) { + if (stanzaAckResponder_) { + stanzaAckResponder_->handleAckRequestReceived(); + } + } + else if (boost::shared_ptr<StanzaAck> ack = boost::dynamic_pointer_cast<StanzaAck>(element)) { + if (stanzaAckRequester_) { + if (ack->isValid()) { + stanzaAckRequester_->handleAckReceived(ack->getHandledStanzasCount()); + } + else { + SWIFT_LOG(warning) << "Got invalid ack from server"; + } + } + else { + SWIFT_LOG(warning) << "Ignoring ack"; + } + } + else if (StreamError::ref streamError = boost::dynamic_pointer_cast<StreamError>(element)) { + finishSession(Error::StreamError); + } + else if (getState() == Initialized) { + boost::shared_ptr<Stanza> stanza = boost::dynamic_pointer_cast<Stanza>(element); + if (stanza) { + if (stanzaAckResponder_) { + stanzaAckResponder_->handleStanzaReceived(); + } + onStanzaReceived(stanza); + } + } + else if (StreamFeatures* streamFeatures = dynamic_cast<StreamFeatures*>(element.get())) { + CHECK_STATE_OR_RETURN(Negotiating); + + if (streamFeatures->hasStartTLS() && stream->supportsTLSEncryption() && useTLS != NeverUseTLS) { + state = WaitingForEncrypt; + stream->writeElement(boost::make_shared<StartTLSRequest>()); + } + else if (useTLS == RequireTLS && !stream->isTLSEncrypted()) { + finishSession(Error::NoSupportedAuthMechanismsError); + } + else if (useStreamCompression && stream->supportsZLibCompression() && streamFeatures->hasCompressionMethod("zlib")) { + state = Compressing; + stream->writeElement(boost::make_shared<CompressRequest>("zlib")); + } + else if (streamFeatures->hasAuthenticationMechanisms()) { #ifdef SWIFTEN_PLATFORM_WIN32 - if (singleSignOn) { - const boost::optional<std::string> authenticationHostname = streamFeatures->getAuthenticationHostname(); - bool gssapiSupported = streamFeatures->hasAuthenticationMechanism("GSSAPI") && authenticationHostname && !authenticationHostname->empty(); - - if (!gssapiSupported) { - finishSession(Error::NoSupportedAuthMechanismsError); - } - else { - WindowsGSSAPIClientAuthenticator* gssapiAuthenticator = new WindowsGSSAPIClientAuthenticator(*authenticationHostname, localJID.getDomain(), authenticationPort); - boost::shared_ptr<Error> error = boost::make_shared<Error>(Error::AuthenticationFailedError); - - authenticator = gssapiAuthenticator; - - if (!gssapiAuthenticator->isError()) { - state = Authenticating; - stream->writeElement(boost::make_shared<AuthRequest>(authenticator->getName(), authenticator->getResponse())); - } - else { - error->errorCode = gssapiAuthenticator->getErrorCode(); - finishSession(error); - } - } - } - else + if (singleSignOn) { + const boost::optional<std::string> authenticationHostname = streamFeatures->getAuthenticationHostname(); + bool gssapiSupported = streamFeatures->hasAuthenticationMechanism("GSSAPI") && authenticationHostname && !authenticationHostname->empty(); + + if (!gssapiSupported) { + finishSession(Error::NoSupportedAuthMechanismsError); + } + else { + WindowsGSSAPIClientAuthenticator* gssapiAuthenticator = new WindowsGSSAPIClientAuthenticator(*authenticationHostname, localJID.getDomain(), authenticationPort); + boost::shared_ptr<Error> error = boost::make_shared<Error>(Error::AuthenticationFailedError); + + authenticator = gssapiAuthenticator; + + if (!gssapiAuthenticator->isError()) { + state = Authenticating; + stream->writeElement(boost::make_shared<AuthRequest>(authenticator->getName(), authenticator->getResponse())); + } + else { + error->errorCode = gssapiAuthenticator->getErrorCode(); + finishSession(error); + } + } + } + else #endif - if (stream->hasTLSCertificate()) { - if (streamFeatures->hasAuthenticationMechanism("EXTERNAL")) { - authenticator = new EXTERNALClientAuthenticator(); - state = Authenticating; - stream->writeElement(boost::make_shared<AuthRequest>("EXTERNAL", createSafeByteArray(""))); - } - else { - finishSession(Error::TLSClientCertificateError); - } - } - else if (streamFeatures->hasAuthenticationMechanism("EXTERNAL")) { - authenticator = new EXTERNALClientAuthenticator(); - state = Authenticating; - stream->writeElement(boost::make_shared<AuthRequest>("EXTERNAL", createSafeByteArray(""))); - } - else if (streamFeatures->hasAuthenticationMechanism("SCRAM-SHA-1") || streamFeatures->hasAuthenticationMechanism("SCRAM-SHA-1-PLUS")) { - std::ostringstream s; - ByteArray finishMessage; - bool plus = streamFeatures->hasAuthenticationMechanism("SCRAM-SHA-1-PLUS"); - if (stream->isTLSEncrypted()) { - finishMessage = stream->getTLSFinishMessage(); - plus &= !finishMessage.empty(); - } - s << boost::uuids::random_generator()(); - SCRAMSHA1ClientAuthenticator* scramAuthenticator = new SCRAMSHA1ClientAuthenticator(s.str(), plus, idnConverter, crypto); - if (!finishMessage.empty()) { - scramAuthenticator->setTLSChannelBindingData(finishMessage); - } - authenticator = scramAuthenticator; - state = WaitingForCredentials; - onNeedCredentials(); - } - else if ((stream->isTLSEncrypted() || allowPLAINOverNonTLS) && streamFeatures->hasAuthenticationMechanism("PLAIN")) { - authenticator = new PLAINClientAuthenticator(); - state = WaitingForCredentials; - onNeedCredentials(); - } - else if (streamFeatures->hasAuthenticationMechanism("DIGEST-MD5") && crypto->isMD5AllowedForCrypto()) { - std::ostringstream s; - s << boost::uuids::random_generator()(); - // FIXME: Host should probably be the actual host - authenticator = new DIGESTMD5ClientAuthenticator(localJID.getDomain(), s.str(), crypto); - state = WaitingForCredentials; - onNeedCredentials(); - } - else { - finishSession(Error::NoSupportedAuthMechanismsError); - } - } - else { - // Start the session - rosterVersioningSupported = streamFeatures->hasRosterVersioning(); - stream->setWhitespacePingEnabled(true); - needSessionStart = streamFeatures->hasSession(); - needResourceBind = streamFeatures->hasResourceBind(); - needAcking = streamFeatures->hasStreamManagement() && useAcks; - if (!needResourceBind) { - // Resource binding is a MUST - finishSession(Error::ResourceBindError); - } - else { - continueSessionInitialization(); - } - } - } - else if (boost::dynamic_pointer_cast<Compressed>(element)) { - CHECK_STATE_OR_RETURN(Compressing); - state = WaitingForStreamStart; - stream->addZLibCompression(); - stream->resetXMPPParser(); - sendStreamHeader(); - } - else if (boost::dynamic_pointer_cast<CompressFailure>(element)) { - finishSession(Error::CompressionFailedError); - } - else if (boost::dynamic_pointer_cast<StreamManagementEnabled>(element)) { - stanzaAckRequester_ = boost::make_shared<StanzaAckRequester>(); - stanzaAckRequester_->onRequestAck.connect(boost::bind(&ClientSession::requestAck, shared_from_this())); - stanzaAckRequester_->onStanzaAcked.connect(boost::bind(&ClientSession::handleStanzaAcked, shared_from_this(), _1)); - stanzaAckResponder_ = boost::make_shared<StanzaAckResponder>(); - stanzaAckResponder_->onAck.connect(boost::bind(&ClientSession::ack, shared_from_this(), _1)); - needAcking = false; - continueSessionInitialization(); - } - else if (boost::dynamic_pointer_cast<StreamManagementFailed>(element)) { - needAcking = false; - continueSessionInitialization(); - } - else if (AuthChallenge* challenge = dynamic_cast<AuthChallenge*>(element.get())) { - CHECK_STATE_OR_RETURN(Authenticating); - assert(authenticator); - if (authenticator->setChallenge(challenge->getValue())) { - stream->writeElement(boost::make_shared<AuthResponse>(authenticator->getResponse())); - } + if (stream->hasTLSCertificate()) { + if (streamFeatures->hasAuthenticationMechanism("EXTERNAL")) { + authenticator = new EXTERNALClientAuthenticator(); + state = Authenticating; + stream->writeElement(boost::make_shared<AuthRequest>("EXTERNAL", createSafeByteArray(""))); + } + else { + finishSession(Error::TLSClientCertificateError); + } + } + else if (streamFeatures->hasAuthenticationMechanism("EXTERNAL")) { + authenticator = new EXTERNALClientAuthenticator(); + state = Authenticating; + stream->writeElement(boost::make_shared<AuthRequest>("EXTERNAL", createSafeByteArray(""))); + } + else if (streamFeatures->hasAuthenticationMechanism("SCRAM-SHA-1") || streamFeatures->hasAuthenticationMechanism("SCRAM-SHA-1-PLUS")) { + std::ostringstream s; + ByteArray finishMessage; + bool plus = streamFeatures->hasAuthenticationMechanism("SCRAM-SHA-1-PLUS"); + if (stream->isTLSEncrypted()) { + finishMessage = stream->getTLSFinishMessage(); + plus &= !finishMessage.empty(); + } + s << boost::uuids::random_generator()(); + SCRAMSHA1ClientAuthenticator* scramAuthenticator = new SCRAMSHA1ClientAuthenticator(s.str(), plus, idnConverter, crypto); + if (!finishMessage.empty()) { + scramAuthenticator->setTLSChannelBindingData(finishMessage); + } + authenticator = scramAuthenticator; + state = WaitingForCredentials; + onNeedCredentials(); + } + else if ((stream->isTLSEncrypted() || allowPLAINOverNonTLS) && streamFeatures->hasAuthenticationMechanism("PLAIN")) { + authenticator = new PLAINClientAuthenticator(); + state = WaitingForCredentials; + onNeedCredentials(); + } + else if (streamFeatures->hasAuthenticationMechanism("DIGEST-MD5") && crypto->isMD5AllowedForCrypto()) { + std::ostringstream s; + s << boost::uuids::random_generator()(); + // FIXME: Host should probably be the actual host + authenticator = new DIGESTMD5ClientAuthenticator(localJID.getDomain(), s.str(), crypto); + state = WaitingForCredentials; + onNeedCredentials(); + } + else { + finishSession(Error::NoSupportedAuthMechanismsError); + } + } + else { + // Start the session + rosterVersioningSupported = streamFeatures->hasRosterVersioning(); + stream->setWhitespacePingEnabled(true); + needSessionStart = streamFeatures->hasSession(); + needResourceBind = streamFeatures->hasResourceBind(); + needAcking = streamFeatures->hasStreamManagement() && useAcks; + if (!needResourceBind) { + // Resource binding is a MUST + finishSession(Error::ResourceBindError); + } + else { + continueSessionInitialization(); + } + } + } + else if (boost::dynamic_pointer_cast<Compressed>(element)) { + CHECK_STATE_OR_RETURN(Compressing); + state = WaitingForStreamStart; + stream->addZLibCompression(); + stream->resetXMPPParser(); + sendStreamHeader(); + } + else if (boost::dynamic_pointer_cast<CompressFailure>(element)) { + finishSession(Error::CompressionFailedError); + } + else if (boost::dynamic_pointer_cast<StreamManagementEnabled>(element)) { + stanzaAckRequester_ = boost::make_shared<StanzaAckRequester>(); + stanzaAckRequester_->onRequestAck.connect(boost::bind(&ClientSession::requestAck, shared_from_this())); + stanzaAckRequester_->onStanzaAcked.connect(boost::bind(&ClientSession::handleStanzaAcked, shared_from_this(), _1)); + stanzaAckResponder_ = boost::make_shared<StanzaAckResponder>(); + stanzaAckResponder_->onAck.connect(boost::bind(&ClientSession::ack, shared_from_this(), _1)); + needAcking = false; + continueSessionInitialization(); + } + else if (boost::dynamic_pointer_cast<StreamManagementFailed>(element)) { + needAcking = false; + continueSessionInitialization(); + } + else if (AuthChallenge* challenge = dynamic_cast<AuthChallenge*>(element.get())) { + CHECK_STATE_OR_RETURN(Authenticating); + assert(authenticator); + if (authenticator->setChallenge(challenge->getValue())) { + stream->writeElement(boost::make_shared<AuthResponse>(authenticator->getResponse())); + } #ifdef SWIFTEN_PLATFORM_WIN32 - else if (WindowsGSSAPIClientAuthenticator* gssapiAuthenticator = dynamic_cast<WindowsGSSAPIClientAuthenticator*>(authenticator)) { - boost::shared_ptr<Error> error = boost::make_shared<Error>(Error::AuthenticationFailedError); + else if (WindowsGSSAPIClientAuthenticator* gssapiAuthenticator = dynamic_cast<WindowsGSSAPIClientAuthenticator*>(authenticator)) { + boost::shared_ptr<Error> error = boost::make_shared<Error>(Error::AuthenticationFailedError); - error->errorCode = gssapiAuthenticator->getErrorCode(); - finishSession(error); - } + error->errorCode = gssapiAuthenticator->getErrorCode(); + finishSession(error); + } #endif - else { - finishSession(Error::AuthenticationFailedError); - } - } - else if (AuthSuccess* authSuccess = dynamic_cast<AuthSuccess*>(element.get())) { - CHECK_STATE_OR_RETURN(Authenticating); - assert(authenticator); - if (!authenticator->setChallenge(authSuccess->getValue())) { - finishSession(Error::ServerVerificationFailedError); - } - else { - state = WaitingForStreamStart; - delete authenticator; - authenticator = NULL; - stream->resetXMPPParser(); - sendStreamHeader(); - } - } - else if (dynamic_cast<AuthFailure*>(element.get())) { - finishSession(Error::AuthenticationFailedError); - } - else if (dynamic_cast<TLSProceed*>(element.get())) { - CHECK_STATE_OR_RETURN(WaitingForEncrypt); - state = Encrypting; - stream->addTLSEncryption(); - } - else if (dynamic_cast<StartTLSFailure*>(element.get())) { - finishSession(Error::TLSError); - } - else { - // FIXME Not correct? - state = Initialized; - onInitialized(); - } + else { + finishSession(Error::AuthenticationFailedError); + } + } + else if (AuthSuccess* authSuccess = dynamic_cast<AuthSuccess*>(element.get())) { + CHECK_STATE_OR_RETURN(Authenticating); + assert(authenticator); + if (!authenticator->setChallenge(authSuccess->getValue())) { + finishSession(Error::ServerVerificationFailedError); + } + else { + state = WaitingForStreamStart; + delete authenticator; + authenticator = NULL; + stream->resetXMPPParser(); + sendStreamHeader(); + } + } + else if (dynamic_cast<AuthFailure*>(element.get())) { + finishSession(Error::AuthenticationFailedError); + } + else if (dynamic_cast<TLSProceed*>(element.get())) { + CHECK_STATE_OR_RETURN(WaitingForEncrypt); + state = Encrypting; + stream->addTLSEncryption(); + } + else if (dynamic_cast<StartTLSFailure*>(element.get())) { + finishSession(Error::TLSError); + } + else { + // FIXME Not correct? + state = Initialized; + onInitialized(); + } } void ClientSession::continueSessionInitialization() { - if (needResourceBind) { - state = BindingResource; - boost::shared_ptr<ResourceBind> resourceBind(boost::make_shared<ResourceBind>()); - if (!localJID.getResource().empty()) { - resourceBind->setResource(localJID.getResource()); - } - sendStanza(IQ::createRequest(IQ::Set, JID(), "session-bind", resourceBind)); - } - else if (needAcking) { - state = EnablingSessionManagement; - stream->writeElement(boost::make_shared<EnableStreamManagement>()); - } - else if (needSessionStart) { - state = StartingSession; - sendStanza(IQ::createRequest(IQ::Set, JID(), "session-start", boost::make_shared<StartSession>())); - } - else { - state = Initialized; - onInitialized(); - } + if (needResourceBind) { + state = BindingResource; + boost::shared_ptr<ResourceBind> resourceBind(boost::make_shared<ResourceBind>()); + if (!localJID.getResource().empty()) { + resourceBind->setResource(localJID.getResource()); + } + sendStanza(IQ::createRequest(IQ::Set, JID(), "session-bind", resourceBind)); + } + else if (needAcking) { + state = EnablingSessionManagement; + stream->writeElement(boost::make_shared<EnableStreamManagement>()); + } + else if (needSessionStart) { + state = StartingSession; + sendStanza(IQ::createRequest(IQ::Set, JID(), "session-start", boost::make_shared<StartSession>())); + } + else { + state = Initialized; + onInitialized(); + } } bool ClientSession::checkState(State state) { - if (this->state != state) { - finishSession(Error::UnexpectedElementError); - return false; - } - return true; + if (this->state != state) { + finishSession(Error::UnexpectedElementError); + return false; + } + return true; } void ClientSession::sendCredentials(const SafeByteArray& password) { - assert(WaitingForCredentials); - assert(authenticator); - state = Authenticating; - authenticator->setCredentials(localJID.getNode(), password); - stream->writeElement(boost::make_shared<AuthRequest>(authenticator->getName(), authenticator->getResponse())); + assert(WaitingForCredentials); + assert(authenticator); + state = Authenticating; + authenticator->setCredentials(localJID.getNode(), password); + stream->writeElement(boost::make_shared<AuthRequest>(authenticator->getName(), authenticator->getResponse())); } void ClientSession::handleTLSEncrypted() { - CHECK_STATE_OR_RETURN(Encrypting); - - std::vector<Certificate::ref> certificateChain = stream->getPeerCertificateChain(); - boost::shared_ptr<CertificateVerificationError> verificationError = stream->getPeerCertificateVerificationError(); - if (verificationError) { - checkTrustOrFinish(certificateChain, verificationError); - } - else { - ServerIdentityVerifier identityVerifier(localJID, idnConverter); - if (!certificateChain.empty() && identityVerifier.certificateVerifies(certificateChain[0])) { - continueAfterTLSEncrypted(); - } - else { - checkTrustOrFinish(certificateChain, boost::make_shared<CertificateVerificationError>(CertificateVerificationError::InvalidServerIdentity)); - } - } + CHECK_STATE_OR_RETURN(Encrypting); + + std::vector<Certificate::ref> certificateChain = stream->getPeerCertificateChain(); + boost::shared_ptr<CertificateVerificationError> verificationError = stream->getPeerCertificateVerificationError(); + if (verificationError) { + checkTrustOrFinish(certificateChain, verificationError); + } + else { + ServerIdentityVerifier identityVerifier(localJID, idnConverter); + if (!certificateChain.empty() && identityVerifier.certificateVerifies(certificateChain[0])) { + continueAfterTLSEncrypted(); + } + else { + checkTrustOrFinish(certificateChain, boost::make_shared<CertificateVerificationError>(CertificateVerificationError::InvalidServerIdentity)); + } + } } void ClientSession::checkTrustOrFinish(const std::vector<Certificate::ref>& certificateChain, boost::shared_ptr<CertificateVerificationError> error) { - if (certificateTrustChecker && certificateTrustChecker->isCertificateTrusted(certificateChain)) { - continueAfterTLSEncrypted(); - } - else { - finishSession(error); - } + if (certificateTrustChecker && certificateTrustChecker->isCertificateTrusted(certificateChain)) { + continueAfterTLSEncrypted(); + } + else { + finishSession(error); + } } void ClientSession::continueAfterTLSEncrypted() { - state = WaitingForStreamStart; - stream->resetXMPPParser(); - sendStreamHeader(); + state = WaitingForStreamStart; + stream->resetXMPPParser(); + sendStreamHeader(); } void ClientSession::handleStreamClosed(boost::shared_ptr<Swift::Error> streamError) { - State previousState = state; - state = Finished; - - if (stanzaAckRequester_) { - stanzaAckRequester_->onRequestAck.disconnect(boost::bind(&ClientSession::requestAck, shared_from_this())); - stanzaAckRequester_->onStanzaAcked.disconnect(boost::bind(&ClientSession::handleStanzaAcked, shared_from_this(), _1)); - stanzaAckRequester_.reset(); - } - if (stanzaAckResponder_) { - stanzaAckResponder_->onAck.disconnect(boost::bind(&ClientSession::ack, shared_from_this(), _1)); - stanzaAckResponder_.reset(); - } - stream->setWhitespacePingEnabled(false); - stream->onStreamStartReceived.disconnect(boost::bind(&ClientSession::handleStreamStart, shared_from_this(), _1)); - stream->onElementReceived.disconnect(boost::bind(&ClientSession::handleElement, shared_from_this(), _1)); - stream->onClosed.disconnect(boost::bind(&ClientSession::handleStreamClosed, shared_from_this(), _1)); - stream->onTLSEncrypted.disconnect(boost::bind(&ClientSession::handleTLSEncrypted, shared_from_this())); - - if (previousState == Finishing) { - onFinished(error_); - } - else { - onFinished(streamError); - } + State previousState = state; + state = Finished; + + if (stanzaAckRequester_) { + stanzaAckRequester_->onRequestAck.disconnect(boost::bind(&ClientSession::requestAck, shared_from_this())); + stanzaAckRequester_->onStanzaAcked.disconnect(boost::bind(&ClientSession::handleStanzaAcked, shared_from_this(), _1)); + stanzaAckRequester_.reset(); + } + if (stanzaAckResponder_) { + stanzaAckResponder_->onAck.disconnect(boost::bind(&ClientSession::ack, shared_from_this(), _1)); + stanzaAckResponder_.reset(); + } + stream->setWhitespacePingEnabled(false); + stream->onStreamStartReceived.disconnect(boost::bind(&ClientSession::handleStreamStart, shared_from_this(), _1)); + stream->onElementReceived.disconnect(boost::bind(&ClientSession::handleElement, shared_from_this(), _1)); + stream->onClosed.disconnect(boost::bind(&ClientSession::handleStreamClosed, shared_from_this(), _1)); + stream->onTLSEncrypted.disconnect(boost::bind(&ClientSession::handleTLSEncrypted, shared_from_this())); + + if (previousState == Finishing) { + onFinished(error_); + } + else { + onFinished(streamError); + } } void ClientSession::finish() { - finishSession(boost::shared_ptr<Error>()); + finishSession(boost::shared_ptr<Error>()); } void ClientSession::finishSession(Error::Type error) { - finishSession(boost::make_shared<Swift::ClientSession::Error>(error)); + finishSession(boost::make_shared<Swift::ClientSession::Error>(error)); } void ClientSession::finishSession(boost::shared_ptr<Swift::Error> error) { - state = Finishing; - if (!error_) { - error_ = error; - } - else { - SWIFT_LOG(warning) << "Session finished twice"; - } - assert(stream->isOpen()); - if (stanzaAckResponder_) { - stanzaAckResponder_->handleAckRequestReceived(); - } - if (authenticator) { - delete authenticator; - authenticator = NULL; - } - stream->writeFooter(); - stream->close(); + state = Finishing; + if (!error_) { + error_ = error; + } + else { + SWIFT_LOG(warning) << "Session finished twice"; + } + assert(stream->isOpen()); + if (stanzaAckResponder_) { + stanzaAckResponder_->handleAckRequestReceived(); + } + if (authenticator) { + delete authenticator; + authenticator = NULL; + } + stream->writeFooter(); + stream->close(); } void ClientSession::requestAck() { - stream->writeElement(boost::make_shared<StanzaAckRequest>()); + stream->writeElement(boost::make_shared<StanzaAckRequest>()); } void ClientSession::handleStanzaAcked(boost::shared_ptr<Stanza> stanza) { - onStanzaAcked(stanza); + onStanzaAcked(stanza); } void ClientSession::ack(unsigned int handledStanzasCount) { - stream->writeElement(boost::make_shared<StanzaAck>(handledStanzasCount)); + stream->writeElement(boost::make_shared<StanzaAck>(handledStanzasCount)); } } diff --git a/Swiften/Client/ClientSession.h b/Swiften/Client/ClientSession.h index a125c71..b1b6755 100644 --- a/Swiften/Client/ClientSession.h +++ b/Swiften/Client/ClientSession.h @@ -21,182 +21,182 @@ #include <Swiften/StreamManagement/StanzaAckResponder.h> namespace Swift { - class ClientAuthenticator; - class CertificateTrustChecker; - class IDNConverter; - class CryptoProvider; - - class SWIFTEN_API ClientSession : public boost::enable_shared_from_this<ClientSession> { - public: - enum State { - Initial, - WaitingForStreamStart, - Negotiating, - Compressing, - WaitingForEncrypt, - Encrypting, - WaitingForCredentials, - Authenticating, - EnablingSessionManagement, - BindingResource, - StartingSession, - Initialized, - Finishing, - Finished - }; - - struct Error : public Swift::Error { - enum Type { - AuthenticationFailedError, - CompressionFailedError, - ServerVerificationFailedError, - NoSupportedAuthMechanismsError, - UnexpectedElementError, - ResourceBindError, - SessionStartError, - TLSClientCertificateError, - TLSError, - StreamError - } type; - boost::shared_ptr<boost::system::error_code> errorCode; - Error(Type type) : type(type) {} - }; - - enum UseTLS { - NeverUseTLS, - UseTLSWhenAvailable, - RequireTLS - }; - - ~ClientSession(); - - static boost::shared_ptr<ClientSession> create(const JID& jid, boost::shared_ptr<SessionStream> stream, IDNConverter* idnConverter, CryptoProvider* crypto) { - return boost::shared_ptr<ClientSession>(new ClientSession(jid, stream, idnConverter, crypto)); - } - - State getState() const { - return state; - } - - void setAllowPLAINOverNonTLS(bool b) { - allowPLAINOverNonTLS = b; - } - - void setUseStreamCompression(bool b) { - useStreamCompression = b; - } - - void setUseTLS(UseTLS b) { - useTLS = b; - } - - void setUseAcks(bool b) { - useAcks = b; - } - - - bool getStreamManagementEnabled() const { - // Explicitly convert to bool. In C++11, it would be cleaner to - // compare to nullptr. - return static_cast<bool>(stanzaAckRequester_); - } - - bool getRosterVersioningSupported() const { - return rosterVersioningSupported; - } - - std::vector<Certificate::ref> getPeerCertificateChain() const { - return stream->getPeerCertificateChain(); - } - - const JID& getLocalJID() const { - return localJID; - } - - void start(); - void finish(); - - bool isFinished() const { - return getState() == Finished; - } - - void sendCredentials(const SafeByteArray& password); - void sendStanza(boost::shared_ptr<Stanza>); - - void setCertificateTrustChecker(CertificateTrustChecker* checker) { - certificateTrustChecker = checker; - } - - void setSingleSignOn(bool b) { - singleSignOn = b; - } - - /** - * Sets the port number used in Kerberos authentication - * Does not affect network connectivity. - */ - void setAuthenticationPort(int i) { - authenticationPort = i; - } - - public: - boost::signal<void ()> onNeedCredentials; - boost::signal<void ()> onInitialized; - boost::signal<void (boost::shared_ptr<Swift::Error>)> onFinished; - boost::signal<void (boost::shared_ptr<Stanza>)> onStanzaReceived; - boost::signal<void (boost::shared_ptr<Stanza>)> onStanzaAcked; - - private: - ClientSession( - const JID& jid, - boost::shared_ptr<SessionStream>, - IDNConverter* idnConverter, - CryptoProvider* crypto); - - void finishSession(Error::Type error); - void finishSession(boost::shared_ptr<Swift::Error> error); - - JID getRemoteJID() const { - return JID("", localJID.getDomain()); - } - - void sendStreamHeader(); - - void handleElement(boost::shared_ptr<ToplevelElement>); - void handleStreamStart(const ProtocolHeader&); - void handleStreamClosed(boost::shared_ptr<Swift::Error>); - - void handleTLSEncrypted(); - - bool checkState(State); - void continueSessionInitialization(); - - void requestAck(); - void handleStanzaAcked(boost::shared_ptr<Stanza> stanza); - void ack(unsigned int handledStanzasCount); - void continueAfterTLSEncrypted(); - void checkTrustOrFinish(const std::vector<Certificate::ref>& certificateChain, boost::shared_ptr<CertificateVerificationError> error); - - private: - JID localJID; - State state; - boost::shared_ptr<SessionStream> stream; - IDNConverter* idnConverter; - CryptoProvider* crypto; - bool allowPLAINOverNonTLS; - bool useStreamCompression; - UseTLS useTLS; - bool useAcks; - bool needSessionStart; - bool needResourceBind; - bool needAcking; - bool rosterVersioningSupported; - ClientAuthenticator* authenticator; - boost::shared_ptr<StanzaAckRequester> stanzaAckRequester_; - boost::shared_ptr<StanzaAckResponder> stanzaAckResponder_; - boost::shared_ptr<Swift::Error> error_; - CertificateTrustChecker* certificateTrustChecker; - bool singleSignOn; - int authenticationPort; - }; + class ClientAuthenticator; + class CertificateTrustChecker; + class IDNConverter; + class CryptoProvider; + + class SWIFTEN_API ClientSession : public boost::enable_shared_from_this<ClientSession> { + public: + enum State { + Initial, + WaitingForStreamStart, + Negotiating, + Compressing, + WaitingForEncrypt, + Encrypting, + WaitingForCredentials, + Authenticating, + EnablingSessionManagement, + BindingResource, + StartingSession, + Initialized, + Finishing, + Finished + }; + + struct Error : public Swift::Error { + enum Type { + AuthenticationFailedError, + CompressionFailedError, + ServerVerificationFailedError, + NoSupportedAuthMechanismsError, + UnexpectedElementError, + ResourceBindError, + SessionStartError, + TLSClientCertificateError, + TLSError, + StreamError + } type; + boost::shared_ptr<boost::system::error_code> errorCode; + Error(Type type) : type(type) {} + }; + + enum UseTLS { + NeverUseTLS, + UseTLSWhenAvailable, + RequireTLS + }; + + ~ClientSession(); + + static boost::shared_ptr<ClientSession> create(const JID& jid, boost::shared_ptr<SessionStream> stream, IDNConverter* idnConverter, CryptoProvider* crypto) { + return boost::shared_ptr<ClientSession>(new ClientSession(jid, stream, idnConverter, crypto)); + } + + State getState() const { + return state; + } + + void setAllowPLAINOverNonTLS(bool b) { + allowPLAINOverNonTLS = b; + } + + void setUseStreamCompression(bool b) { + useStreamCompression = b; + } + + void setUseTLS(UseTLS b) { + useTLS = b; + } + + void setUseAcks(bool b) { + useAcks = b; + } + + + bool getStreamManagementEnabled() const { + // Explicitly convert to bool. In C++11, it would be cleaner to + // compare to nullptr. + return static_cast<bool>(stanzaAckRequester_); + } + + bool getRosterVersioningSupported() const { + return rosterVersioningSupported; + } + + std::vector<Certificate::ref> getPeerCertificateChain() const { + return stream->getPeerCertificateChain(); + } + + const JID& getLocalJID() const { + return localJID; + } + + void start(); + void finish(); + + bool isFinished() const { + return getState() == Finished; + } + + void sendCredentials(const SafeByteArray& password); + void sendStanza(boost::shared_ptr<Stanza>); + + void setCertificateTrustChecker(CertificateTrustChecker* checker) { + certificateTrustChecker = checker; + } + + void setSingleSignOn(bool b) { + singleSignOn = b; + } + + /** + * Sets the port number used in Kerberos authentication + * Does not affect network connectivity. + */ + void setAuthenticationPort(int i) { + authenticationPort = i; + } + + public: + boost::signal<void ()> onNeedCredentials; + boost::signal<void ()> onInitialized; + boost::signal<void (boost::shared_ptr<Swift::Error>)> onFinished; + boost::signal<void (boost::shared_ptr<Stanza>)> onStanzaReceived; + boost::signal<void (boost::shared_ptr<Stanza>)> onStanzaAcked; + + private: + ClientSession( + const JID& jid, + boost::shared_ptr<SessionStream>, + IDNConverter* idnConverter, + CryptoProvider* crypto); + + void finishSession(Error::Type error); + void finishSession(boost::shared_ptr<Swift::Error> error); + + JID getRemoteJID() const { + return JID("", localJID.getDomain()); + } + + void sendStreamHeader(); + + void handleElement(boost::shared_ptr<ToplevelElement>); + void handleStreamStart(const ProtocolHeader&); + void handleStreamClosed(boost::shared_ptr<Swift::Error>); + + void handleTLSEncrypted(); + + bool checkState(State); + void continueSessionInitialization(); + + void requestAck(); + void handleStanzaAcked(boost::shared_ptr<Stanza> stanza); + void ack(unsigned int handledStanzasCount); + void continueAfterTLSEncrypted(); + void checkTrustOrFinish(const std::vector<Certificate::ref>& certificateChain, boost::shared_ptr<CertificateVerificationError> error); + + private: + JID localJID; + State state; + boost::shared_ptr<SessionStream> stream; + IDNConverter* idnConverter; + CryptoProvider* crypto; + bool allowPLAINOverNonTLS; + bool useStreamCompression; + UseTLS useTLS; + bool useAcks; + bool needSessionStart; + bool needResourceBind; + bool needAcking; + bool rosterVersioningSupported; + ClientAuthenticator* authenticator; + boost::shared_ptr<StanzaAckRequester> stanzaAckRequester_; + boost::shared_ptr<StanzaAckResponder> stanzaAckResponder_; + boost::shared_ptr<Swift::Error> error_; + CertificateTrustChecker* certificateTrustChecker; + bool singleSignOn; + int authenticationPort; + }; } diff --git a/Swiften/Client/ClientSessionStanzaChannel.cpp b/Swiften/Client/ClientSessionStanzaChannel.cpp index 3dc8c59..1340b7c 100644 --- a/Swiften/Client/ClientSessionStanzaChannel.cpp +++ b/Swiften/Client/ClientSessionStanzaChannel.cpp @@ -13,100 +13,100 @@ namespace Swift { ClientSessionStanzaChannel::~ClientSessionStanzaChannel() { - if (session) { - session->onFinished.disconnect(boost::bind(&ClientSessionStanzaChannel::handleSessionFinished, this, _1)); - session->onStanzaReceived.disconnect(boost::bind(&ClientSessionStanzaChannel::handleStanza, this, _1)); - session->onStanzaAcked.disconnect(boost::bind(&ClientSessionStanzaChannel::handleStanzaAcked, this, _1)); - session->onInitialized.disconnect(boost::bind(&ClientSessionStanzaChannel::handleSessionInitialized, this)); - session.reset(); - } + if (session) { + session->onFinished.disconnect(boost::bind(&ClientSessionStanzaChannel::handleSessionFinished, this, _1)); + session->onStanzaReceived.disconnect(boost::bind(&ClientSessionStanzaChannel::handleStanza, this, _1)); + session->onStanzaAcked.disconnect(boost::bind(&ClientSessionStanzaChannel::handleStanzaAcked, this, _1)); + session->onInitialized.disconnect(boost::bind(&ClientSessionStanzaChannel::handleSessionInitialized, this)); + session.reset(); + } } void ClientSessionStanzaChannel::setSession(boost::shared_ptr<ClientSession> session) { - assert(!this->session); - this->session = session; - session->onInitialized.connect(boost::bind(&ClientSessionStanzaChannel::handleSessionInitialized, this)); - session->onFinished.connect(boost::bind(&ClientSessionStanzaChannel::handleSessionFinished, this, _1)); - session->onStanzaReceived.connect(boost::bind(&ClientSessionStanzaChannel::handleStanza, this, _1)); - session->onStanzaAcked.connect(boost::bind(&ClientSessionStanzaChannel::handleStanzaAcked, this, _1)); + assert(!this->session); + this->session = session; + session->onInitialized.connect(boost::bind(&ClientSessionStanzaChannel::handleSessionInitialized, this)); + session->onFinished.connect(boost::bind(&ClientSessionStanzaChannel::handleSessionFinished, this, _1)); + session->onStanzaReceived.connect(boost::bind(&ClientSessionStanzaChannel::handleStanza, this, _1)); + session->onStanzaAcked.connect(boost::bind(&ClientSessionStanzaChannel::handleStanzaAcked, this, _1)); } void ClientSessionStanzaChannel::sendIQ(boost::shared_ptr<IQ> iq) { - send(iq); + send(iq); } void ClientSessionStanzaChannel::sendMessage(boost::shared_ptr<Message> message) { - send(message); + send(message); } void ClientSessionStanzaChannel::sendPresence(boost::shared_ptr<Presence> presence) { - send(presence); + send(presence); } std::string ClientSessionStanzaChannel::getNewIQID() { - return idGenerator.generateID(); + return idGenerator.generateID(); } void ClientSessionStanzaChannel::send(boost::shared_ptr<Stanza> stanza) { - if (!isAvailable()) { - std::cerr << "Warning: Client: Trying to send a stanza while disconnected." << std::endl; - return; - } - session->sendStanza(stanza); + if (!isAvailable()) { + std::cerr << "Warning: Client: Trying to send a stanza while disconnected." << std::endl; + return; + } + session->sendStanza(stanza); } void ClientSessionStanzaChannel::handleSessionFinished(boost::shared_ptr<Error>) { - session->onFinished.disconnect(boost::bind(&ClientSessionStanzaChannel::handleSessionFinished, this, _1)); - session->onStanzaReceived.disconnect(boost::bind(&ClientSessionStanzaChannel::handleStanza, this, _1)); - session->onStanzaAcked.disconnect(boost::bind(&ClientSessionStanzaChannel::handleStanzaAcked, this, _1)); - session->onInitialized.disconnect(boost::bind(&ClientSessionStanzaChannel::handleSessionInitialized, this)); - session.reset(); + session->onFinished.disconnect(boost::bind(&ClientSessionStanzaChannel::handleSessionFinished, this, _1)); + session->onStanzaReceived.disconnect(boost::bind(&ClientSessionStanzaChannel::handleStanza, this, _1)); + session->onStanzaAcked.disconnect(boost::bind(&ClientSessionStanzaChannel::handleStanzaAcked, this, _1)); + session->onInitialized.disconnect(boost::bind(&ClientSessionStanzaChannel::handleSessionInitialized, this)); + session.reset(); - onAvailableChanged(false); + onAvailableChanged(false); } void ClientSessionStanzaChannel::handleStanza(boost::shared_ptr<Stanza> stanza) { - boost::shared_ptr<Message> message = boost::dynamic_pointer_cast<Message>(stanza); - if (message) { - onMessageReceived(message); - return; - } - - boost::shared_ptr<Presence> presence = boost::dynamic_pointer_cast<Presence>(stanza); - if (presence) { - onPresenceReceived(presence); - return; - } - - boost::shared_ptr<IQ> iq = boost::dynamic_pointer_cast<IQ>(stanza); - if (iq) { - onIQReceived(iq); - return; - } + boost::shared_ptr<Message> message = boost::dynamic_pointer_cast<Message>(stanza); + if (message) { + onMessageReceived(message); + return; + } + + boost::shared_ptr<Presence> presence = boost::dynamic_pointer_cast<Presence>(stanza); + if (presence) { + onPresenceReceived(presence); + return; + } + + boost::shared_ptr<IQ> iq = boost::dynamic_pointer_cast<IQ>(stanza); + if (iq) { + onIQReceived(iq); + return; + } } bool ClientSessionStanzaChannel::getStreamManagementEnabled() const { - if (session) { - return session->getStreamManagementEnabled(); - } - return false; + if (session) { + return session->getStreamManagementEnabled(); + } + return false; } std::vector<Certificate::ref> ClientSessionStanzaChannel::getPeerCertificateChain() const { - if (session) { - return session->getPeerCertificateChain(); - } - return std::vector<Certificate::ref>(); + if (session) { + return session->getPeerCertificateChain(); + } + return std::vector<Certificate::ref>(); } void ClientSessionStanzaChannel::handleStanzaAcked(boost::shared_ptr<Stanza> stanza) { - onStanzaAcked(stanza); + onStanzaAcked(stanza); } void ClientSessionStanzaChannel::handleSessionInitialized() { - onAvailableChanged(true); + onAvailableChanged(true); } } diff --git a/Swiften/Client/ClientSessionStanzaChannel.h b/Swiften/Client/ClientSessionStanzaChannel.h index 0ffcd9d..d3b302b 100644 --- a/Swiften/Client/ClientSessionStanzaChannel.h +++ b/Swiften/Client/ClientSessionStanzaChannel.h @@ -17,36 +17,36 @@ #include <Swiften/Elements/Presence.h> namespace Swift { - /** - * StanzaChannel implementation around a ClientSession. - */ - class SWIFTEN_API ClientSessionStanzaChannel : public StanzaChannel { - public: - virtual ~ClientSessionStanzaChannel(); - - void setSession(boost::shared_ptr<ClientSession> session); - - void sendIQ(boost::shared_ptr<IQ> iq); - void sendMessage(boost::shared_ptr<Message> message); - void sendPresence(boost::shared_ptr<Presence> presence); - bool getStreamManagementEnabled() const; - virtual std::vector<Certificate::ref> getPeerCertificateChain() const; - - bool isAvailable() const { - return session && session->getState() == ClientSession::Initialized; - } - - private: - std::string getNewIQID(); - void send(boost::shared_ptr<Stanza> stanza); - void handleSessionFinished(boost::shared_ptr<Error> error); - void handleStanza(boost::shared_ptr<Stanza> stanza); - void handleStanzaAcked(boost::shared_ptr<Stanza> stanza); - void handleSessionInitialized(); - - private: - IDGenerator idGenerator; - boost::shared_ptr<ClientSession> session; - }; + /** + * StanzaChannel implementation around a ClientSession. + */ + class SWIFTEN_API ClientSessionStanzaChannel : public StanzaChannel { + public: + virtual ~ClientSessionStanzaChannel(); + + void setSession(boost::shared_ptr<ClientSession> session); + + void sendIQ(boost::shared_ptr<IQ> iq); + void sendMessage(boost::shared_ptr<Message> message); + void sendPresence(boost::shared_ptr<Presence> presence); + bool getStreamManagementEnabled() const; + virtual std::vector<Certificate::ref> getPeerCertificateChain() const; + + bool isAvailable() const { + return session && session->getState() == ClientSession::Initialized; + } + + private: + std::string getNewIQID(); + void send(boost::shared_ptr<Stanza> stanza); + void handleSessionFinished(boost::shared_ptr<Error> error); + void handleStanza(boost::shared_ptr<Stanza> stanza); + void handleStanzaAcked(boost::shared_ptr<Stanza> stanza); + void handleSessionInitialized(); + + private: + IDGenerator idGenerator; + boost::shared_ptr<ClientSession> session; + }; } diff --git a/Swiften/Client/ClientXMLTracer.cpp b/Swiften/Client/ClientXMLTracer.cpp index a34aecc..4852aa1 100644 --- a/Swiften/Client/ClientXMLTracer.cpp +++ b/Swiften/Client/ClientXMLTracer.cpp @@ -16,41 +16,41 @@ namespace Swift { ClientXMLTracer::ClientXMLTracer(CoreClient* client, bool bosh) : bosh(bosh) { #ifdef SWIFTEN_PLATFORM_WIN32 - beautifier = new XMLBeautifier(true, false); + beautifier = new XMLBeautifier(true, false); #else - beautifier = new XMLBeautifier(true, true); + beautifier = new XMLBeautifier(true, true); #endif - onDataReadConnection = client->onDataRead.connect(boost::bind(&ClientXMLTracer::printData, this, '<', _1)); - onDataWrittenConnection = client->onDataWritten.connect(boost::bind(&ClientXMLTracer::printData, this, '>', _1)); + onDataReadConnection = client->onDataRead.connect(boost::bind(&ClientXMLTracer::printData, this, '<', _1)); + onDataWrittenConnection = client->onDataWritten.connect(boost::bind(&ClientXMLTracer::printData, this, '>', _1)); } ClientXMLTracer::~ClientXMLTracer() { - delete beautifier; + delete beautifier; } void ClientXMLTracer::printData(char direction, const SafeByteArray& data) { - printLine(direction); - if (bosh) { - std::string line = byteArrayToString(ByteArray(data.begin(), data.end())); + printLine(direction); + if (bosh) { + std::string line = byteArrayToString(ByteArray(data.begin(), data.end())); // Disabled because it swallows bits of XML (namespaces, if I recall) -// size_t endOfHTTP = line.find("\r\n\r\n"); -// if (false && endOfHTTP != std::string::npos) { -// std::cerr << line.substr(0, endOfHTTP) << std::endl << beautifier->beautify(line.substr(endOfHTTP)) << std::endl; -// } -// else { - std::cerr << line << std::endl; -// } - } - else { - std::cerr << beautifier->beautify(byteArrayToString(ByteArray(data.begin(), data.end()))) << std::endl; - } +// size_t endOfHTTP = line.find("\r\n\r\n"); +// if (false && endOfHTTP != std::string::npos) { +// std::cerr << line.substr(0, endOfHTTP) << std::endl << beautifier->beautify(line.substr(endOfHTTP)) << std::endl; +// } +// else { + std::cerr << line << std::endl; +// } + } + else { + std::cerr << beautifier->beautify(byteArrayToString(ByteArray(data.begin(), data.end()))) << std::endl; + } } void ClientXMLTracer::printLine(char c) { - for (unsigned int i = 0; i < 80; ++i) { - std::cerr << c; - } - std::cerr << std::endl; + for (unsigned int i = 0; i < 80; ++i) { + std::cerr << c; + } + std::cerr << std::endl; } } diff --git a/Swiften/Client/ClientXMLTracer.h b/Swiften/Client/ClientXMLTracer.h index bbaced9..ccecb41 100644 --- a/Swiften/Client/ClientXMLTracer.h +++ b/Swiften/Client/ClientXMLTracer.h @@ -12,19 +12,19 @@ #include <Swiften/Client/XMLBeautifier.h> namespace Swift { - class SWIFTEN_API ClientXMLTracer { - public: - ClientXMLTracer(CoreClient* client, bool bosh = false); - ~ClientXMLTracer(); + class SWIFTEN_API ClientXMLTracer { + public: + ClientXMLTracer(CoreClient* client, bool bosh = false); + ~ClientXMLTracer(); - private: - void printData(char direction, const SafeByteArray& data); - void printLine(char c); + private: + void printData(char direction, const SafeByteArray& data); + void printLine(char c); - private: - XMLBeautifier *beautifier; - bool bosh; - boost::bsignals::scoped_connection onDataReadConnection; - boost::bsignals::scoped_connection onDataWrittenConnection; - }; + private: + XMLBeautifier *beautifier; + bool bosh; + boost::bsignals::scoped_connection onDataReadConnection; + boost::bsignals::scoped_connection onDataWrittenConnection; + }; } diff --git a/Swiften/Client/CoreClient.cpp b/Swiften/Client/CoreClient.cpp index 6fc491c..fd7f894 100644 --- a/Swiften/Client/CoreClient.cpp +++ b/Swiften/Client/CoreClient.cpp @@ -32,448 +32,448 @@ namespace Swift { CoreClient::CoreClient(const JID& jid, const SafeByteArray& password, NetworkFactories* networkFactories) : jid_(jid), password_(password), networkFactories(networkFactories), disconnectRequested_(false), certificateTrustChecker(NULL) { - stanzaChannel_ = new ClientSessionStanzaChannel(); - stanzaChannel_->onMessageReceived.connect(boost::bind(&CoreClient::handleMessageReceived, this, _1)); - stanzaChannel_->onPresenceReceived.connect(boost::bind(&CoreClient::handlePresenceReceived, this, _1)); - stanzaChannel_->onStanzaAcked.connect(boost::bind(&CoreClient::handleStanzaAcked, this, _1)); - stanzaChannel_->onAvailableChanged.connect(boost::bind(&CoreClient::handleStanzaChannelAvailableChanged, this, _1)); - - iqRouter_ = new IQRouter(stanzaChannel_); - iqRouter_->setJID(jid); + stanzaChannel_ = new ClientSessionStanzaChannel(); + stanzaChannel_->onMessageReceived.connect(boost::bind(&CoreClient::handleMessageReceived, this, _1)); + stanzaChannel_->onPresenceReceived.connect(boost::bind(&CoreClient::handlePresenceReceived, this, _1)); + stanzaChannel_->onStanzaAcked.connect(boost::bind(&CoreClient::handleStanzaAcked, this, _1)); + stanzaChannel_->onAvailableChanged.connect(boost::bind(&CoreClient::handleStanzaChannelAvailableChanged, this, _1)); + + iqRouter_ = new IQRouter(stanzaChannel_); + iqRouter_->setJID(jid); } CoreClient::~CoreClient() { - forceReset(); - delete iqRouter_; - - stanzaChannel_->onAvailableChanged.disconnect(boost::bind(&CoreClient::handleStanzaChannelAvailableChanged, this, _1)); - stanzaChannel_->onMessageReceived.disconnect(boost::bind(&CoreClient::handleMessageReceived, this, _1)); - stanzaChannel_->onPresenceReceived.disconnect(boost::bind(&CoreClient::handlePresenceReceived, this, _1)); - stanzaChannel_->onStanzaAcked.disconnect(boost::bind(&CoreClient::handleStanzaAcked, this, _1)); - delete stanzaChannel_; + forceReset(); + delete iqRouter_; + + stanzaChannel_->onAvailableChanged.disconnect(boost::bind(&CoreClient::handleStanzaChannelAvailableChanged, this, _1)); + stanzaChannel_->onMessageReceived.disconnect(boost::bind(&CoreClient::handleMessageReceived, this, _1)); + stanzaChannel_->onPresenceReceived.disconnect(boost::bind(&CoreClient::handlePresenceReceived, this, _1)); + stanzaChannel_->onStanzaAcked.disconnect(boost::bind(&CoreClient::handleStanzaAcked, this, _1)); + delete stanzaChannel_; } void CoreClient::connect(const ClientOptions& o) { - SWIFT_LOG(debug) << "Connecting "; - - forceReset(); - disconnectRequested_ = false; - - options = o; - - - // Determine connection types to use - assert(proxyConnectionFactories.empty()); - bool useDirectConnection = true; - HostAddressPort systemSOCKS5Proxy = networkFactories->getProxyProvider()->getSOCKS5Proxy(); - HostAddressPort systemHTTPConnectProxy = networkFactories->getProxyProvider()->getHTTPConnectProxy(); - switch (o.proxyType) { - case ClientOptions::NoProxy: - SWIFT_LOG(debug) << " without a proxy" << std::endl; - break; - case ClientOptions::SystemConfiguredProxy: - SWIFT_LOG(debug) << " with a system configured proxy" << std::endl; - if (systemSOCKS5Proxy.isValid()) { - SWIFT_LOG(debug) << "Found SOCK5 Proxy: " << systemSOCKS5Proxy.getAddress().toString() << ":" << systemSOCKS5Proxy.getPort() << std::endl; - proxyConnectionFactories.push_back(new SOCKS5ProxiedConnectionFactory(networkFactories->getDomainNameResolver(), networkFactories->getConnectionFactory(), networkFactories->getTimerFactory(), systemSOCKS5Proxy.getAddress().toString(), systemSOCKS5Proxy.getPort())); - } - if (systemHTTPConnectProxy.isValid()) { - SWIFT_LOG(debug) << "Found HTTPConnect Proxy: " << systemHTTPConnectProxy.getAddress().toString() << ":" << systemHTTPConnectProxy.getPort() << std::endl; - proxyConnectionFactories.push_back(new HTTPConnectProxiedConnectionFactory(networkFactories->getDomainNameResolver(), networkFactories->getConnectionFactory(), networkFactories->getTimerFactory(), systemHTTPConnectProxy.getAddress().toString(), systemHTTPConnectProxy.getPort())); - } - break; - case ClientOptions::SOCKS5Proxy: { - SWIFT_LOG(debug) << " with manual configured SOCKS5 proxy" << std::endl; - std::string proxyHostname = o.manualProxyHostname.empty() ? systemSOCKS5Proxy.getAddress().toString() : o.manualProxyHostname; - int proxyPort = o.manualProxyPort == -1 ? systemSOCKS5Proxy.getPort() : o.manualProxyPort; - SWIFT_LOG(debug) << "Proxy: " << proxyHostname << ":" << proxyPort << std::endl; - proxyConnectionFactories.push_back(new SOCKS5ProxiedConnectionFactory(networkFactories->getDomainNameResolver(), networkFactories->getConnectionFactory(), networkFactories->getTimerFactory(), proxyHostname, proxyPort)); - useDirectConnection = false; - break; - } - case ClientOptions::HTTPConnectProxy: { - SWIFT_LOG(debug) << " with manual configured HTTPConnect proxy" << std::endl; - std::string proxyHostname = o.manualProxyHostname.empty() ? systemHTTPConnectProxy.getAddress().toString() : o.manualProxyHostname; - int proxyPort = o.manualProxyPort == -1 ? systemHTTPConnectProxy.getPort() : o.manualProxyPort; - SWIFT_LOG(debug) << "Proxy: " << proxyHostname << ":" << proxyPort << std::endl; - proxyConnectionFactories.push_back(new HTTPConnectProxiedConnectionFactory(networkFactories->getDomainNameResolver(), networkFactories->getConnectionFactory(), networkFactories->getTimerFactory(), proxyHostname, proxyPort, o.httpTrafficFilter)); - useDirectConnection = false; - break; - } - } - std::vector<ConnectionFactory*> connectionFactories(proxyConnectionFactories); - if (useDirectConnection) { - connectionFactories.push_back(networkFactories->getConnectionFactory()); - } - - // Create connector - std::string host = o.manualHostname.empty() ? jid_.getDomain() : o.manualHostname; - int port = o.manualPort; - boost::optional<std::string> serviceLookupPrefix; - if (o.manualHostname.empty()) { - serviceLookupPrefix = "_xmpp-client._tcp."; - } - assert(!connector_); - if (options.boshURL.isEmpty()) { - connector_ = boost::make_shared<ChainedConnector>(host, port, serviceLookupPrefix, networkFactories->getDomainNameResolver(), connectionFactories, networkFactories->getTimerFactory()); - connector_->onConnectFinished.connect(boost::bind(&CoreClient::handleConnectorFinished, this, _1, _2)); - connector_->setTimeoutMilliseconds(2*60*1000); - connector_->start(); - } - else { - /* Autodiscovery of which proxy works is largely ok with a TCP session, because this is a one-off. With BOSH - * it would be quite painful given that potentially every stanza could be sent on a new connection. - */ - boost::shared_ptr<BOSHSessionStream> boshSessionStream_ = boost::shared_ptr<BOSHSessionStream>(new BOSHSessionStream( - options.boshURL, - getPayloadParserFactories(), - getPayloadSerializers(), - networkFactories->getConnectionFactory(), - networkFactories->getTLSContextFactory(), - networkFactories->getTimerFactory(), - networkFactories->getXMLParserFactory(), - networkFactories->getEventLoop(), - networkFactories->getDomainNameResolver(), - host, - options.boshHTTPConnectProxyURL, - options.boshHTTPConnectProxyAuthID, - options.boshHTTPConnectProxyAuthPassword, - options.tlsOptions, - options.httpTrafficFilter)); - sessionStream_ = boshSessionStream_; - sessionStream_->onDataRead.connect(boost::bind(&CoreClient::handleDataRead, this, _1)); - sessionStream_->onDataWritten.connect(boost::bind(&CoreClient::handleDataWritten, this, _1)); - if (certificate_ && !certificate_->isNull()) { - SWIFT_LOG(debug) << "set certificate" << std::endl; - sessionStream_->setTLSCertificate(certificate_); - } - boshSessionStream_->open(); - bindSessionToStream(); - } + SWIFT_LOG(debug) << "Connecting "; + + forceReset(); + disconnectRequested_ = false; + + options = o; + + + // Determine connection types to use + assert(proxyConnectionFactories.empty()); + bool useDirectConnection = true; + HostAddressPort systemSOCKS5Proxy = networkFactories->getProxyProvider()->getSOCKS5Proxy(); + HostAddressPort systemHTTPConnectProxy = networkFactories->getProxyProvider()->getHTTPConnectProxy(); + switch (o.proxyType) { + case ClientOptions::NoProxy: + SWIFT_LOG(debug) << " without a proxy" << std::endl; + break; + case ClientOptions::SystemConfiguredProxy: + SWIFT_LOG(debug) << " with a system configured proxy" << std::endl; + if (systemSOCKS5Proxy.isValid()) { + SWIFT_LOG(debug) << "Found SOCK5 Proxy: " << systemSOCKS5Proxy.getAddress().toString() << ":" << systemSOCKS5Proxy.getPort() << std::endl; + proxyConnectionFactories.push_back(new SOCKS5ProxiedConnectionFactory(networkFactories->getDomainNameResolver(), networkFactories->getConnectionFactory(), networkFactories->getTimerFactory(), systemSOCKS5Proxy.getAddress().toString(), systemSOCKS5Proxy.getPort())); + } + if (systemHTTPConnectProxy.isValid()) { + SWIFT_LOG(debug) << "Found HTTPConnect Proxy: " << systemHTTPConnectProxy.getAddress().toString() << ":" << systemHTTPConnectProxy.getPort() << std::endl; + proxyConnectionFactories.push_back(new HTTPConnectProxiedConnectionFactory(networkFactories->getDomainNameResolver(), networkFactories->getConnectionFactory(), networkFactories->getTimerFactory(), systemHTTPConnectProxy.getAddress().toString(), systemHTTPConnectProxy.getPort())); + } + break; + case ClientOptions::SOCKS5Proxy: { + SWIFT_LOG(debug) << " with manual configured SOCKS5 proxy" << std::endl; + std::string proxyHostname = o.manualProxyHostname.empty() ? systemSOCKS5Proxy.getAddress().toString() : o.manualProxyHostname; + int proxyPort = o.manualProxyPort == -1 ? systemSOCKS5Proxy.getPort() : o.manualProxyPort; + SWIFT_LOG(debug) << "Proxy: " << proxyHostname << ":" << proxyPort << std::endl; + proxyConnectionFactories.push_back(new SOCKS5ProxiedConnectionFactory(networkFactories->getDomainNameResolver(), networkFactories->getConnectionFactory(), networkFactories->getTimerFactory(), proxyHostname, proxyPort)); + useDirectConnection = false; + break; + } + case ClientOptions::HTTPConnectProxy: { + SWIFT_LOG(debug) << " with manual configured HTTPConnect proxy" << std::endl; + std::string proxyHostname = o.manualProxyHostname.empty() ? systemHTTPConnectProxy.getAddress().toString() : o.manualProxyHostname; + int proxyPort = o.manualProxyPort == -1 ? systemHTTPConnectProxy.getPort() : o.manualProxyPort; + SWIFT_LOG(debug) << "Proxy: " << proxyHostname << ":" << proxyPort << std::endl; + proxyConnectionFactories.push_back(new HTTPConnectProxiedConnectionFactory(networkFactories->getDomainNameResolver(), networkFactories->getConnectionFactory(), networkFactories->getTimerFactory(), proxyHostname, proxyPort, o.httpTrafficFilter)); + useDirectConnection = false; + break; + } + } + std::vector<ConnectionFactory*> connectionFactories(proxyConnectionFactories); + if (useDirectConnection) { + connectionFactories.push_back(networkFactories->getConnectionFactory()); + } + + // Create connector + std::string host = o.manualHostname.empty() ? jid_.getDomain() : o.manualHostname; + int port = o.manualPort; + boost::optional<std::string> serviceLookupPrefix; + if (o.manualHostname.empty()) { + serviceLookupPrefix = "_xmpp-client._tcp."; + } + assert(!connector_); + if (options.boshURL.isEmpty()) { + connector_ = boost::make_shared<ChainedConnector>(host, port, serviceLookupPrefix, networkFactories->getDomainNameResolver(), connectionFactories, networkFactories->getTimerFactory()); + connector_->onConnectFinished.connect(boost::bind(&CoreClient::handleConnectorFinished, this, _1, _2)); + connector_->setTimeoutMilliseconds(2*60*1000); + connector_->start(); + } + else { + /* Autodiscovery of which proxy works is largely ok with a TCP session, because this is a one-off. With BOSH + * it would be quite painful given that potentially every stanza could be sent on a new connection. + */ + boost::shared_ptr<BOSHSessionStream> boshSessionStream_ = boost::shared_ptr<BOSHSessionStream>(new BOSHSessionStream( + options.boshURL, + getPayloadParserFactories(), + getPayloadSerializers(), + networkFactories->getConnectionFactory(), + networkFactories->getTLSContextFactory(), + networkFactories->getTimerFactory(), + networkFactories->getXMLParserFactory(), + networkFactories->getEventLoop(), + networkFactories->getDomainNameResolver(), + host, + options.boshHTTPConnectProxyURL, + options.boshHTTPConnectProxyAuthID, + options.boshHTTPConnectProxyAuthPassword, + options.tlsOptions, + options.httpTrafficFilter)); + sessionStream_ = boshSessionStream_; + sessionStream_->onDataRead.connect(boost::bind(&CoreClient::handleDataRead, this, _1)); + sessionStream_->onDataWritten.connect(boost::bind(&CoreClient::handleDataWritten, this, _1)); + if (certificate_ && !certificate_->isNull()) { + SWIFT_LOG(debug) << "set certificate" << std::endl; + sessionStream_->setTLSCertificate(certificate_); + } + boshSessionStream_->open(); + bindSessionToStream(); + } } void CoreClient::bindSessionToStream() { - session_ = ClientSession::create(jid_, sessionStream_, networkFactories->getIDNConverter(), networkFactories->getCryptoProvider()); - session_->setCertificateTrustChecker(certificateTrustChecker); - session_->setUseStreamCompression(options.useStreamCompression); - session_->setAllowPLAINOverNonTLS(options.allowPLAINWithoutTLS); - session_->setSingleSignOn(options.singleSignOn); - session_->setAuthenticationPort(options.manualPort); - switch(options.useTLS) { - case ClientOptions::UseTLSWhenAvailable: - session_->setUseTLS(ClientSession::UseTLSWhenAvailable); - break; - case ClientOptions::NeverUseTLS: - session_->setUseTLS(ClientSession::NeverUseTLS); - break; - case ClientOptions::RequireTLS: - session_->setUseTLS(ClientSession::RequireTLS); - break; - } - session_->setUseAcks(options.useAcks); - stanzaChannel_->setSession(session_); - session_->onFinished.connect(boost::bind(&CoreClient::handleSessionFinished, this, _1)); - session_->onNeedCredentials.connect(boost::bind(&CoreClient::handleNeedCredentials, this)); - session_->start(); + session_ = ClientSession::create(jid_, sessionStream_, networkFactories->getIDNConverter(), networkFactories->getCryptoProvider()); + session_->setCertificateTrustChecker(certificateTrustChecker); + session_->setUseStreamCompression(options.useStreamCompression); + session_->setAllowPLAINOverNonTLS(options.allowPLAINWithoutTLS); + session_->setSingleSignOn(options.singleSignOn); + session_->setAuthenticationPort(options.manualPort); + switch(options.useTLS) { + case ClientOptions::UseTLSWhenAvailable: + session_->setUseTLS(ClientSession::UseTLSWhenAvailable); + break; + case ClientOptions::NeverUseTLS: + session_->setUseTLS(ClientSession::NeverUseTLS); + break; + case ClientOptions::RequireTLS: + session_->setUseTLS(ClientSession::RequireTLS); + break; + } + session_->setUseAcks(options.useAcks); + stanzaChannel_->setSession(session_); + session_->onFinished.connect(boost::bind(&CoreClient::handleSessionFinished, this, _1)); + session_->onNeedCredentials.connect(boost::bind(&CoreClient::handleNeedCredentials, this)); + session_->start(); } /** * Only called for TCP sessions. BOSH is handled inside the BOSHSessionStream. */ void CoreClient::handleConnectorFinished(boost::shared_ptr<Connection> connection, boost::shared_ptr<Error> error) { - resetConnector(); - if (!connection) { - if (options.forgetPassword) { - purgePassword(); - } - boost::optional<ClientError> clientError; - if (!disconnectRequested_) { - clientError = boost::dynamic_pointer_cast<DomainNameResolveError>(error) ? boost::optional<ClientError>(ClientError::DomainNameResolveError) : boost::optional<ClientError>(ClientError::ConnectionError); - } - onDisconnected(clientError); - } - else { - assert(!connection_); - assert(!sessionStream_); - - if (certificate_ && certificate_->isNull()) { - //certificate cannot be read so do not initailise session - onDisconnected(boost::optional<ClientError>(ClientError::ClientCertificateLoadError)); - return; - } - - connection_ = connection; - - sessionStream_ = boost::make_shared<BasicSessionStream>(ClientStreamType, connection_, getPayloadParserFactories(), getPayloadSerializers(), networkFactories->getTLSContextFactory(), networkFactories->getTimerFactory(), networkFactories->getXMLParserFactory(), options.tlsOptions); - if (certificate_) { - sessionStream_->setTLSCertificate(certificate_); - } - sessionStream_->onDataRead.connect(boost::bind(&CoreClient::handleDataRead, this, _1)); - sessionStream_->onDataWritten.connect(boost::bind(&CoreClient::handleDataWritten, this, _1)); - - bindSessionToStream(); - } + resetConnector(); + if (!connection) { + if (options.forgetPassword) { + purgePassword(); + } + boost::optional<ClientError> clientError; + if (!disconnectRequested_) { + clientError = boost::dynamic_pointer_cast<DomainNameResolveError>(error) ? boost::optional<ClientError>(ClientError::DomainNameResolveError) : boost::optional<ClientError>(ClientError::ConnectionError); + } + onDisconnected(clientError); + } + else { + assert(!connection_); + assert(!sessionStream_); + + if (certificate_ && certificate_->isNull()) { + //certificate cannot be read so do not initailise session + onDisconnected(boost::optional<ClientError>(ClientError::ClientCertificateLoadError)); + return; + } + + connection_ = connection; + + sessionStream_ = boost::make_shared<BasicSessionStream>(ClientStreamType, connection_, getPayloadParserFactories(), getPayloadSerializers(), networkFactories->getTLSContextFactory(), networkFactories->getTimerFactory(), networkFactories->getXMLParserFactory(), options.tlsOptions); + if (certificate_) { + sessionStream_->setTLSCertificate(certificate_); + } + sessionStream_->onDataRead.connect(boost::bind(&CoreClient::handleDataRead, this, _1)); + sessionStream_->onDataWritten.connect(boost::bind(&CoreClient::handleDataWritten, this, _1)); + + bindSessionToStream(); + } } void CoreClient::disconnect() { - // FIXME: We should be able to do without this boolean. We just have to make sure we can tell the difference between - // connector finishing without a connection due to an error or because of a disconnect. - disconnectRequested_ = true; - if (session_ && !session_->isFinished()) { - session_->finish(); - } - else if (connector_) { - connector_->stop(); - } + // FIXME: We should be able to do without this boolean. We just have to make sure we can tell the difference between + // connector finishing without a connection due to an error or because of a disconnect. + disconnectRequested_ = true; + if (session_ && !session_->isFinished()) { + session_->finish(); + } + else if (connector_) { + connector_->stop(); + } } void CoreClient::setCertificate(CertificateWithKey::ref certificate) { - certificate_ = certificate; + certificate_ = certificate; } void CoreClient::handleSessionFinished(boost::shared_ptr<Error> error) { - if (options.forgetPassword) { - purgePassword(); - } - resetSession(); - - boost::optional<ClientError> actualError; - if (error) { - ClientError clientError; - if (boost::shared_ptr<ClientSession::Error> actualError = boost::dynamic_pointer_cast<ClientSession::Error>(error)) { - switch(actualError->type) { - case ClientSession::Error::AuthenticationFailedError: - clientError = ClientError(ClientError::AuthenticationFailedError); - break; - case ClientSession::Error::CompressionFailedError: - clientError = ClientError(ClientError::CompressionFailedError); - break; - case ClientSession::Error::ServerVerificationFailedError: - clientError = ClientError(ClientError::ServerVerificationFailedError); - break; - case ClientSession::Error::NoSupportedAuthMechanismsError: - clientError = ClientError(ClientError::NoSupportedAuthMechanismsError); - break; - case ClientSession::Error::UnexpectedElementError: - clientError = ClientError(ClientError::UnexpectedElementError); - break; - case ClientSession::Error::ResourceBindError: - clientError = ClientError(ClientError::ResourceBindError); - break; - case ClientSession::Error::SessionStartError: - clientError = ClientError(ClientError::SessionStartError); - break; - case ClientSession::Error::TLSError: - clientError = ClientError(ClientError::TLSError); - break; - case ClientSession::Error::TLSClientCertificateError: - clientError = ClientError(ClientError::ClientCertificateError); - break; - case ClientSession::Error::StreamError: - clientError = ClientError(ClientError::StreamError); - break; - } - clientError.setErrorCode(actualError->errorCode); - } - else if (boost::shared_ptr<TLSError> actualError = boost::dynamic_pointer_cast<TLSError>(error)) { - switch(actualError->getType()) { - case TLSError::CertificateCardRemoved: - clientError = ClientError(ClientError::CertificateCardRemoved); - break; - case TLSError::UnknownError: - clientError = ClientError(ClientError::TLSError); - break; - } - } - else if (boost::shared_ptr<SessionStream::SessionStreamError> actualError = boost::dynamic_pointer_cast<SessionStream::SessionStreamError>(error)) { - switch(actualError->type) { - case SessionStream::SessionStreamError::ParseError: - clientError = ClientError(ClientError::XMLError); - break; - case SessionStream::SessionStreamError::TLSError: - clientError = ClientError(ClientError::TLSError); - break; - case SessionStream::SessionStreamError::InvalidTLSCertificateError: - clientError = ClientError(ClientError::ClientCertificateLoadError); - break; - case SessionStream::SessionStreamError::ConnectionReadError: - clientError = ClientError(ClientError::ConnectionReadError); - break; - case SessionStream::SessionStreamError::ConnectionWriteError: - clientError = ClientError(ClientError::ConnectionWriteError); - break; - } - } - else if (boost::shared_ptr<CertificateVerificationError> verificationError = boost::dynamic_pointer_cast<CertificateVerificationError>(error)) { - switch(verificationError->getType()) { - case CertificateVerificationError::UnknownError: - clientError = ClientError(ClientError::UnknownCertificateError); - break; - case CertificateVerificationError::Expired: - clientError = ClientError(ClientError::CertificateExpiredError); - break; - case CertificateVerificationError::NotYetValid: - clientError = ClientError(ClientError::CertificateNotYetValidError); - break; - case CertificateVerificationError::SelfSigned: - clientError = ClientError(ClientError::CertificateSelfSignedError); - break; - case CertificateVerificationError::Rejected: - clientError = ClientError(ClientError::CertificateRejectedError); - break; - case CertificateVerificationError::Untrusted: - clientError = ClientError(ClientError::CertificateUntrustedError); - break; - case CertificateVerificationError::InvalidPurpose: - clientError = ClientError(ClientError::InvalidCertificatePurposeError); - break; - case CertificateVerificationError::PathLengthExceeded: - clientError = ClientError(ClientError::CertificatePathLengthExceededError); - break; - case CertificateVerificationError::InvalidSignature: - clientError = ClientError(ClientError::InvalidCertificateSignatureError); - break; - case CertificateVerificationError::InvalidCA: - clientError = ClientError(ClientError::InvalidCAError); - break; - case CertificateVerificationError::InvalidServerIdentity: - clientError = ClientError(ClientError::InvalidServerIdentityError); - break; - case CertificateVerificationError::Revoked: - clientError = ClientError(ClientError::RevokedError); - break; - case CertificateVerificationError::RevocationCheckFailed: - clientError = ClientError(ClientError::RevocationCheckFailedError); - break; - } - } - actualError = boost::optional<ClientError>(clientError); - } - onDisconnected(actualError); + if (options.forgetPassword) { + purgePassword(); + } + resetSession(); + + boost::optional<ClientError> actualError; + if (error) { + ClientError clientError; + if (boost::shared_ptr<ClientSession::Error> actualError = boost::dynamic_pointer_cast<ClientSession::Error>(error)) { + switch(actualError->type) { + case ClientSession::Error::AuthenticationFailedError: + clientError = ClientError(ClientError::AuthenticationFailedError); + break; + case ClientSession::Error::CompressionFailedError: + clientError = ClientError(ClientError::CompressionFailedError); + break; + case ClientSession::Error::ServerVerificationFailedError: + clientError = ClientError(ClientError::ServerVerificationFailedError); + break; + case ClientSession::Error::NoSupportedAuthMechanismsError: + clientError = ClientError(ClientError::NoSupportedAuthMechanismsError); + break; + case ClientSession::Error::UnexpectedElementError: + clientError = ClientError(ClientError::UnexpectedElementError); + break; + case ClientSession::Error::ResourceBindError: + clientError = ClientError(ClientError::ResourceBindError); + break; + case ClientSession::Error::SessionStartError: + clientError = ClientError(ClientError::SessionStartError); + break; + case ClientSession::Error::TLSError: + clientError = ClientError(ClientError::TLSError); + break; + case ClientSession::Error::TLSClientCertificateError: + clientError = ClientError(ClientError::ClientCertificateError); + break; + case ClientSession::Error::StreamError: + clientError = ClientError(ClientError::StreamError); + break; + } + clientError.setErrorCode(actualError->errorCode); + } + else if (boost::shared_ptr<TLSError> actualError = boost::dynamic_pointer_cast<TLSError>(error)) { + switch(actualError->getType()) { + case TLSError::CertificateCardRemoved: + clientError = ClientError(ClientError::CertificateCardRemoved); + break; + case TLSError::UnknownError: + clientError = ClientError(ClientError::TLSError); + break; + } + } + else if (boost::shared_ptr<SessionStream::SessionStreamError> actualError = boost::dynamic_pointer_cast<SessionStream::SessionStreamError>(error)) { + switch(actualError->type) { + case SessionStream::SessionStreamError::ParseError: + clientError = ClientError(ClientError::XMLError); + break; + case SessionStream::SessionStreamError::TLSError: + clientError = ClientError(ClientError::TLSError); + break; + case SessionStream::SessionStreamError::InvalidTLSCertificateError: + clientError = ClientError(ClientError::ClientCertificateLoadError); + break; + case SessionStream::SessionStreamError::ConnectionReadError: + clientError = ClientError(ClientError::ConnectionReadError); + break; + case SessionStream::SessionStreamError::ConnectionWriteError: + clientError = ClientError(ClientError::ConnectionWriteError); + break; + } + } + else if (boost::shared_ptr<CertificateVerificationError> verificationError = boost::dynamic_pointer_cast<CertificateVerificationError>(error)) { + switch(verificationError->getType()) { + case CertificateVerificationError::UnknownError: + clientError = ClientError(ClientError::UnknownCertificateError); + break; + case CertificateVerificationError::Expired: + clientError = ClientError(ClientError::CertificateExpiredError); + break; + case CertificateVerificationError::NotYetValid: + clientError = ClientError(ClientError::CertificateNotYetValidError); + break; + case CertificateVerificationError::SelfSigned: + clientError = ClientError(ClientError::CertificateSelfSignedError); + break; + case CertificateVerificationError::Rejected: + clientError = ClientError(ClientError::CertificateRejectedError); + break; + case CertificateVerificationError::Untrusted: + clientError = ClientError(ClientError::CertificateUntrustedError); + break; + case CertificateVerificationError::InvalidPurpose: + clientError = ClientError(ClientError::InvalidCertificatePurposeError); + break; + case CertificateVerificationError::PathLengthExceeded: + clientError = ClientError(ClientError::CertificatePathLengthExceededError); + break; + case CertificateVerificationError::InvalidSignature: + clientError = ClientError(ClientError::InvalidCertificateSignatureError); + break; + case CertificateVerificationError::InvalidCA: + clientError = ClientError(ClientError::InvalidCAError); + break; + case CertificateVerificationError::InvalidServerIdentity: + clientError = ClientError(ClientError::InvalidServerIdentityError); + break; + case CertificateVerificationError::Revoked: + clientError = ClientError(ClientError::RevokedError); + break; + case CertificateVerificationError::RevocationCheckFailed: + clientError = ClientError(ClientError::RevocationCheckFailedError); + break; + } + } + actualError = boost::optional<ClientError>(clientError); + } + onDisconnected(actualError); } void CoreClient::handleNeedCredentials() { - assert(session_); - session_->sendCredentials(password_); - if (options.forgetPassword) { - purgePassword(); - } + assert(session_); + session_->sendCredentials(password_); + if (options.forgetPassword) { + purgePassword(); + } } void CoreClient::handleDataRead(const SafeByteArray& data) { - onDataRead(data); + onDataRead(data); } void CoreClient::handleDataWritten(const SafeByteArray& data) { - onDataWritten(data); + onDataWritten(data); } void CoreClient::handleStanzaChannelAvailableChanged(bool available) { - if (available) { - iqRouter_->setJID(session_->getLocalJID()); - handleConnected(); - onConnected(); - } + if (available) { + iqRouter_->setJID(session_->getLocalJID()); + handleConnected(); + onConnected(); + } } void CoreClient::sendMessage(boost::shared_ptr<Message> message) { - stanzaChannel_->sendMessage(message); + stanzaChannel_->sendMessage(message); } void CoreClient::sendPresence(boost::shared_ptr<Presence> presence) { - stanzaChannel_->sendPresence(presence); + stanzaChannel_->sendPresence(presence); } void CoreClient::sendData(const std::string& data) { - sessionStream_->writeData(data); + sessionStream_->writeData(data); } bool CoreClient::isActive() const { - return (session_ && !session_->isFinished()) || connector_; + return (session_ && !session_->isFinished()) || connector_; } void CoreClient::setCertificateTrustChecker(CertificateTrustChecker* checker) { - certificateTrustChecker = checker; + certificateTrustChecker = checker; } void CoreClient::handlePresenceReceived(Presence::ref presence) { - onPresenceReceived(presence); + onPresenceReceived(presence); } void CoreClient::handleMessageReceived(Message::ref message) { - onMessageReceived(message); + onMessageReceived(message); } void CoreClient::handleStanzaAcked(Stanza::ref stanza) { - onStanzaAcked(stanza); + onStanzaAcked(stanza); } bool CoreClient::isAvailable() const { - return stanzaChannel_->isAvailable(); + return stanzaChannel_->isAvailable(); } bool CoreClient::getStreamManagementEnabled() const { - return stanzaChannel_->getStreamManagementEnabled(); + return stanzaChannel_->getStreamManagementEnabled(); } bool CoreClient::isStreamEncrypted() const { - return sessionStream_->isTLSEncrypted(); + return sessionStream_->isTLSEncrypted(); } StanzaChannel* CoreClient::getStanzaChannel() const { - return stanzaChannel_; + return stanzaChannel_; } const JID& CoreClient::getJID() const { - if (session_) { - return session_->getLocalJID(); - } - else { - return jid_; - } + if (session_) { + return session_->getLocalJID(); + } + else { + return jid_; + } } void CoreClient::purgePassword() { - safeClear(password_); + safeClear(password_); } void CoreClient::resetConnector() { - connector_->onConnectFinished.disconnect(boost::bind(&CoreClient::handleConnectorFinished, this, _1, _2)); - connector_.reset(); - foreach(ConnectionFactory* f, proxyConnectionFactories) { - delete f; - } - proxyConnectionFactories.clear(); + connector_->onConnectFinished.disconnect(boost::bind(&CoreClient::handleConnectorFinished, this, _1, _2)); + connector_.reset(); + foreach(ConnectionFactory* f, proxyConnectionFactories) { + delete f; + } + proxyConnectionFactories.clear(); } void CoreClient::resetSession() { - session_->onFinished.disconnect(boost::bind(&CoreClient::handleSessionFinished, this, _1)); - session_->onNeedCredentials.disconnect(boost::bind(&CoreClient::handleNeedCredentials, this)); - - sessionStream_->onDataRead.disconnect(boost::bind(&CoreClient::handleDataRead, this, _1)); - sessionStream_->onDataWritten.disconnect(boost::bind(&CoreClient::handleDataWritten, this, _1)); - - if (connection_) { - connection_->disconnect(); - } - else if (boost::dynamic_pointer_cast<BOSHSessionStream>(sessionStream_)) { - sessionStream_->close(); - } - sessionStream_.reset(); - connection_.reset(); + session_->onFinished.disconnect(boost::bind(&CoreClient::handleSessionFinished, this, _1)); + session_->onNeedCredentials.disconnect(boost::bind(&CoreClient::handleNeedCredentials, this)); + + sessionStream_->onDataRead.disconnect(boost::bind(&CoreClient::handleDataRead, this, _1)); + sessionStream_->onDataWritten.disconnect(boost::bind(&CoreClient::handleDataWritten, this, _1)); + + if (connection_) { + connection_->disconnect(); + } + else if (boost::dynamic_pointer_cast<BOSHSessionStream>(sessionStream_)) { + sessionStream_->close(); + } + sessionStream_.reset(); + connection_.reset(); } void CoreClient::forceReset() { - if (connector_) { - SWIFT_LOG(warning) << "Client not disconnected properly: Connector still active" << std::endl; - resetConnector(); - } - if (sessionStream_ || connection_) { - SWIFT_LOG(warning) << "Client not disconnected properly: Session still active" << std::endl; - resetSession(); - } + if (connector_) { + SWIFT_LOG(warning) << "Client not disconnected properly: Connector still active" << std::endl; + resetConnector(); + } + if (sessionStream_ || connection_) { + SWIFT_LOG(warning) << "Client not disconnected properly: Session still active" << std::endl; + resetSession(); + } } } diff --git a/Swiften/Client/CoreClient.h b/Swiften/Client/CoreClient.h index 002a704..3efc38f 100644 --- a/Swiften/Client/CoreClient.h +++ b/Swiften/Client/CoreClient.h @@ -20,223 +20,223 @@ #include <Swiften/TLS/CertificateWithKey.h> namespace Swift { - class ChainedConnector; - class Message; - class Presence; - class Error; - class IQRouter; - class TLSContextFactory; - class ConnectionFactory; - class Connection; - class TimerFactory; - class ClientSession; - class StanzaChannel; - class Stanza; - class SessionStream; - class CertificateTrustChecker; - class NetworkFactories; - class ClientSessionStanzaChannel; - - /** - * The central class for communicating with an XMPP server. - * - * This class is responsible for setting up the connection with the XMPP - * server, authenticating, and initializing the session. - * - * This class can be used directly in your application, although the Client - * subclass provides more functionality and interfaces, and is better suited - * for most needs. - */ - class SWIFTEN_API CoreClient : public Entity { - public: - /** - * Constructs a client for the given JID with the given password. - */ - CoreClient(const JID& jid, const SafeByteArray& password, NetworkFactories* networkFactories); - virtual ~CoreClient(); - - /** - * Set a client certificate to use for strong authentication with the server. - * Ensure that it is of the correct type for the TLS engine in use. - * This means, largely, PKCS12Certificate for OpenSSL and CAPICertificate for CAPI. - */ - void setCertificate(CertificateWithKey::ref certificate); - - /** - * Connects the client to the server. - * - * After the connection is established, the client will set - * initialize the stream and authenticate. - */ - void connect(const ClientOptions& = ClientOptions()); - - /** - * Disconnects the client from the server. - */ - void disconnect(); - - /** - * Sends a message. - */ - void sendMessage(boost::shared_ptr<Message>); - - /** - * Sends a presence stanza. - */ - void sendPresence(boost::shared_ptr<Presence>); - - /** - * Sends raw, unchecked data. - */ - void sendData(const std::string& data); - - /** - * Returns the IQ router for this client. - */ - IQRouter* getIQRouter() const { - return iqRouter_; - } - - /** - * Checks whether the client is connected to the server, - * and stanzas can be sent. - */ - bool isAvailable() const; - - /** - * Checks whether the client is active. - * - * A client is active when it is connected or connecting to the server. - */ - bool isActive() const; - - /** - * Returns the JID of the client. - * After the session was initialized, this returns the bound JID. - */ - const JID& getJID() const; - - /** - * Checks whether stream management is enabled. - * - * If stream management is enabled, onStanzaAcked will be - * emitted when a stanza is received by the server. - * - * \see onStanzaAcked - */ - bool getStreamManagementEnabled() const; - - /** - * Checks whether stream encryption (TLS) is currently active. - */ - bool isStreamEncrypted() const; - - StanzaChannel* getStanzaChannel() const; - - /** - * Sets the certificate trust checker. - * - * This checker will be called when the server sends a - * TLS certificate that does not validate. If the trust checker - * says the certificate is trusted, then connecting will proceed; - * if not, the connection will end with an error. - */ - void setCertificateTrustChecker(CertificateTrustChecker*); - - public: - /** - * Emitted when the client was disconnected from the network. - * - * If the connection was due to a non-recoverable error, the type - * of error will be passed as a parameter. - */ - boost::signal<void (const boost::optional<ClientError>&)> onDisconnected; - - /** - * Emitted when the client is connected and authenticated, - * and stanzas can be sent. - */ - boost::signal<void ()> onConnected; - - /** - * Emitted when the client receives data. - * - * This signal is emitted before the XML data is parsed, - * so this data is unformatted. - */ - boost::signal<void (const SafeByteArray&)> onDataRead; - - /** - * Emitted when the client sends data. - * - * This signal is emitted after the XML was serialized, and - * is unformatted. - */ - boost::signal<void (const SafeByteArray&)> onDataWritten; - - /** - * Emitted when a message is received. - */ - boost::signal<void (boost::shared_ptr<Message>)> onMessageReceived; - - /** - * Emitted when a presence stanza is received. - */ - boost::signal<void (boost::shared_ptr<Presence>) > onPresenceReceived; - - /** - * Emitted when the server acknowledges receipt of a - * stanza (if acknowledgements are available). - * - * \see getStreamManagementEnabled() - */ - boost::signal<void (boost::shared_ptr<Stanza>)> onStanzaAcked; - - protected: - boost::shared_ptr<ClientSession> getSession() const { - return session_; - } - - NetworkFactories* getNetworkFactories() const { - return networkFactories; - } - - /** - * Called before onConnected signal is emmitted. - */ - virtual void handleConnected() {} - - private: - void handleConnectorFinished(boost::shared_ptr<Connection>, boost::shared_ptr<Error> error); - void handleStanzaChannelAvailableChanged(bool available); - void handleSessionFinished(boost::shared_ptr<Error>); - void handleNeedCredentials(); - void handleDataRead(const SafeByteArray&); - void handleDataWritten(const SafeByteArray&); - void handlePresenceReceived(boost::shared_ptr<Presence>); - void handleMessageReceived(boost::shared_ptr<Message>); - void handleStanzaAcked(boost::shared_ptr<Stanza>); - void purgePassword(); - void bindSessionToStream(); - - void resetConnector(); - void resetSession(); - void forceReset(); - - private: - JID jid_; - SafeByteArray password_; - NetworkFactories* networkFactories; - ClientSessionStanzaChannel* stanzaChannel_; - IQRouter* iqRouter_; - ClientOptions options; - boost::shared_ptr<ChainedConnector> connector_; - std::vector<ConnectionFactory*> proxyConnectionFactories; - boost::shared_ptr<Connection> connection_; - boost::shared_ptr<SessionStream> sessionStream_; - boost::shared_ptr<ClientSession> session_; - CertificateWithKey::ref certificate_; - bool disconnectRequested_; - CertificateTrustChecker* certificateTrustChecker; - }; + class ChainedConnector; + class Message; + class Presence; + class Error; + class IQRouter; + class TLSContextFactory; + class ConnectionFactory; + class Connection; + class TimerFactory; + class ClientSession; + class StanzaChannel; + class Stanza; + class SessionStream; + class CertificateTrustChecker; + class NetworkFactories; + class ClientSessionStanzaChannel; + + /** + * The central class for communicating with an XMPP server. + * + * This class is responsible for setting up the connection with the XMPP + * server, authenticating, and initializing the session. + * + * This class can be used directly in your application, although the Client + * subclass provides more functionality and interfaces, and is better suited + * for most needs. + */ + class SWIFTEN_API CoreClient : public Entity { + public: + /** + * Constructs a client for the given JID with the given password. + */ + CoreClient(const JID& jid, const SafeByteArray& password, NetworkFactories* networkFactories); + virtual ~CoreClient(); + + /** + * Set a client certificate to use for strong authentication with the server. + * Ensure that it is of the correct type for the TLS engine in use. + * This means, largely, PKCS12Certificate for OpenSSL and CAPICertificate for CAPI. + */ + void setCertificate(CertificateWithKey::ref certificate); + + /** + * Connects the client to the server. + * + * After the connection is established, the client will set + * initialize the stream and authenticate. + */ + void connect(const ClientOptions& = ClientOptions()); + + /** + * Disconnects the client from the server. + */ + void disconnect(); + + /** + * Sends a message. + */ + void sendMessage(boost::shared_ptr<Message>); + + /** + * Sends a presence stanza. + */ + void sendPresence(boost::shared_ptr<Presence>); + + /** + * Sends raw, unchecked data. + */ + void sendData(const std::string& data); + + /** + * Returns the IQ router for this client. + */ + IQRouter* getIQRouter() const { + return iqRouter_; + } + + /** + * Checks whether the client is connected to the server, + * and stanzas can be sent. + */ + bool isAvailable() const; + + /** + * Checks whether the client is active. + * + * A client is active when it is connected or connecting to the server. + */ + bool isActive() const; + + /** + * Returns the JID of the client. + * After the session was initialized, this returns the bound JID. + */ + const JID& getJID() const; + + /** + * Checks whether stream management is enabled. + * + * If stream management is enabled, onStanzaAcked will be + * emitted when a stanza is received by the server. + * + * \see onStanzaAcked + */ + bool getStreamManagementEnabled() const; + + /** + * Checks whether stream encryption (TLS) is currently active. + */ + bool isStreamEncrypted() const; + + StanzaChannel* getStanzaChannel() const; + + /** + * Sets the certificate trust checker. + * + * This checker will be called when the server sends a + * TLS certificate that does not validate. If the trust checker + * says the certificate is trusted, then connecting will proceed; + * if not, the connection will end with an error. + */ + void setCertificateTrustChecker(CertificateTrustChecker*); + + public: + /** + * Emitted when the client was disconnected from the network. + * + * If the connection was due to a non-recoverable error, the type + * of error will be passed as a parameter. + */ + boost::signal<void (const boost::optional<ClientError>&)> onDisconnected; + + /** + * Emitted when the client is connected and authenticated, + * and stanzas can be sent. + */ + boost::signal<void ()> onConnected; + + /** + * Emitted when the client receives data. + * + * This signal is emitted before the XML data is parsed, + * so this data is unformatted. + */ + boost::signal<void (const SafeByteArray&)> onDataRead; + + /** + * Emitted when the client sends data. + * + * This signal is emitted after the XML was serialized, and + * is unformatted. + */ + boost::signal<void (const SafeByteArray&)> onDataWritten; + + /** + * Emitted when a message is received. + */ + boost::signal<void (boost::shared_ptr<Message>)> onMessageReceived; + + /** + * Emitted when a presence stanza is received. + */ + boost::signal<void (boost::shared_ptr<Presence>) > onPresenceReceived; + + /** + * Emitted when the server acknowledges receipt of a + * stanza (if acknowledgements are available). + * + * \see getStreamManagementEnabled() + */ + boost::signal<void (boost::shared_ptr<Stanza>)> onStanzaAcked; + + protected: + boost::shared_ptr<ClientSession> getSession() const { + return session_; + } + + NetworkFactories* getNetworkFactories() const { + return networkFactories; + } + + /** + * Called before onConnected signal is emmitted. + */ + virtual void handleConnected() {} + + private: + void handleConnectorFinished(boost::shared_ptr<Connection>, boost::shared_ptr<Error> error); + void handleStanzaChannelAvailableChanged(bool available); + void handleSessionFinished(boost::shared_ptr<Error>); + void handleNeedCredentials(); + void handleDataRead(const SafeByteArray&); + void handleDataWritten(const SafeByteArray&); + void handlePresenceReceived(boost::shared_ptr<Presence>); + void handleMessageReceived(boost::shared_ptr<Message>); + void handleStanzaAcked(boost::shared_ptr<Stanza>); + void purgePassword(); + void bindSessionToStream(); + + void resetConnector(); + void resetSession(); + void forceReset(); + + private: + JID jid_; + SafeByteArray password_; + NetworkFactories* networkFactories; + ClientSessionStanzaChannel* stanzaChannel_; + IQRouter* iqRouter_; + ClientOptions options; + boost::shared_ptr<ChainedConnector> connector_; + std::vector<ConnectionFactory*> proxyConnectionFactories; + boost::shared_ptr<Connection> connection_; + boost::shared_ptr<SessionStream> sessionStream_; + boost::shared_ptr<ClientSession> session_; + CertificateWithKey::ref certificate_; + bool disconnectRequested_; + CertificateTrustChecker* certificateTrustChecker; + }; } diff --git a/Swiften/Client/DummyNickManager.h b/Swiften/Client/DummyNickManager.h index 2f5f13f..52a8401 100644 --- a/Swiften/Client/DummyNickManager.h +++ b/Swiften/Client/DummyNickManager.h @@ -9,15 +9,15 @@ #include <Swiften/Client/NickManager.h> namespace Swift { - class VCardManager; + class VCardManager; - class DummyNickManager : public NickManager { - public: - std::string getOwnNick() const { - return ""; - } + class DummyNickManager : public NickManager { + public: + std::string getOwnNick() const { + return ""; + } - void setOwnNick(const std::string&) { - } - }; + void setOwnNick(const std::string&) { + } + }; } diff --git a/Swiften/Client/DummyStanzaChannel.h b/Swiften/Client/DummyStanzaChannel.h index 0373cc4..0e52f62 100644 --- a/Swiften/Client/DummyStanzaChannel.h +++ b/Swiften/Client/DummyStanzaChannel.h @@ -11,79 +11,79 @@ #include <Swiften/Client/StanzaChannel.h> namespace Swift { - class DummyStanzaChannel : public StanzaChannel { - public: - DummyStanzaChannel() : available_(true) {} - - virtual void sendStanza(boost::shared_ptr<Stanza> stanza) { - sentStanzas.push_back(stanza); - } - - void setAvailable(bool available) { - available_ = available; - onAvailableChanged(available); - } - - virtual void sendIQ(boost::shared_ptr<IQ> iq) { - sentStanzas.push_back(iq); - } - - virtual void sendMessage(boost::shared_ptr<Message> message) { - sentStanzas.push_back(message); - } - - virtual void sendPresence(boost::shared_ptr<Presence> presence) { - sentStanzas.push_back(presence); - } - - virtual std::string getNewIQID() { - return "test-id"; - } - - virtual bool isAvailable() const { - return available_; - } - - virtual bool getStreamManagementEnabled() const { - return false; - } - - template<typename T> bool isRequestAtIndex(size_t index, const JID& jid, IQ::Type type) { - if (index >= sentStanzas.size()) { - return false; - } - boost::shared_ptr<IQ> iqStanza = boost::dynamic_pointer_cast<IQ>(sentStanzas[index]); - return iqStanza && iqStanza->getType() == type && iqStanza->getTo() == jid && iqStanza->getPayload<T>(); - } - - bool isResultAtIndex(size_t index, const std::string& id) { - if (index >= sentStanzas.size()) { - return false; - } - boost::shared_ptr<IQ> iqStanza = boost::dynamic_pointer_cast<IQ>(sentStanzas[index]); - return iqStanza && iqStanza->getType() == IQ::Result && iqStanza->getID() == id; - } - - bool isErrorAtIndex(size_t index, const std::string& id) { - if (index >= sentStanzas.size()) { - return false; - } - boost::shared_ptr<IQ> iqStanza = boost::dynamic_pointer_cast<IQ>(sentStanzas[index]); - return iqStanza && iqStanza->getType() == IQ::Error && iqStanza->getID() == id; - } - - template<typename T> boost::shared_ptr<T> getStanzaAtIndex(size_t index) { - if (sentStanzas.size() <= index) { - return boost::shared_ptr<T>(); - } - return boost::dynamic_pointer_cast<T>(sentStanzas[index]); - } - - std::vector<Certificate::ref> getPeerCertificateChain() const { - return std::vector<Certificate::ref>(); - } - - std::vector<boost::shared_ptr<Stanza> > sentStanzas; - bool available_; - }; + class DummyStanzaChannel : public StanzaChannel { + public: + DummyStanzaChannel() : available_(true) {} + + virtual void sendStanza(boost::shared_ptr<Stanza> stanza) { + sentStanzas.push_back(stanza); + } + + void setAvailable(bool available) { + available_ = available; + onAvailableChanged(available); + } + + virtual void sendIQ(boost::shared_ptr<IQ> iq) { + sentStanzas.push_back(iq); + } + + virtual void sendMessage(boost::shared_ptr<Message> message) { + sentStanzas.push_back(message); + } + + virtual void sendPresence(boost::shared_ptr<Presence> presence) { + sentStanzas.push_back(presence); + } + + virtual std::string getNewIQID() { + return "test-id"; + } + + virtual bool isAvailable() const { + return available_; + } + + virtual bool getStreamManagementEnabled() const { + return false; + } + + template<typename T> bool isRequestAtIndex(size_t index, const JID& jid, IQ::Type type) { + if (index >= sentStanzas.size()) { + return false; + } + boost::shared_ptr<IQ> iqStanza = boost::dynamic_pointer_cast<IQ>(sentStanzas[index]); + return iqStanza && iqStanza->getType() == type && iqStanza->getTo() == jid && iqStanza->getPayload<T>(); + } + + bool isResultAtIndex(size_t index, const std::string& id) { + if (index >= sentStanzas.size()) { + return false; + } + boost::shared_ptr<IQ> iqStanza = boost::dynamic_pointer_cast<IQ>(sentStanzas[index]); + return iqStanza && iqStanza->getType() == IQ::Result && iqStanza->getID() == id; + } + + bool isErrorAtIndex(size_t index, const std::string& id) { + if (index >= sentStanzas.size()) { + return false; + } + boost::shared_ptr<IQ> iqStanza = boost::dynamic_pointer_cast<IQ>(sentStanzas[index]); + return iqStanza && iqStanza->getType() == IQ::Error && iqStanza->getID() == id; + } + + template<typename T> boost::shared_ptr<T> getStanzaAtIndex(size_t index) { + if (sentStanzas.size() <= index) { + return boost::shared_ptr<T>(); + } + return boost::dynamic_pointer_cast<T>(sentStanzas[index]); + } + + std::vector<Certificate::ref> getPeerCertificateChain() const { + return std::vector<Certificate::ref>(); + } + + std::vector<boost::shared_ptr<Stanza> > sentStanzas; + bool available_; + }; } diff --git a/Swiften/Client/MemoryStorages.cpp b/Swiften/Client/MemoryStorages.cpp index 8825fa2..14aa63a 100644 --- a/Swiften/Client/MemoryStorages.cpp +++ b/Swiften/Client/MemoryStorages.cpp @@ -16,48 +16,48 @@ namespace Swift { MemoryStorages::MemoryStorages(CryptoProvider* crypto) { - vcardStorage = new VCardMemoryStorage(crypto); - capsStorage = new CapsMemoryStorage(); - avatarStorage = new AvatarMemoryStorage(); - rosterStorage = new RosterMemoryStorage(); + vcardStorage = new VCardMemoryStorage(crypto); + capsStorage = new CapsMemoryStorage(); + avatarStorage = new AvatarMemoryStorage(); + rosterStorage = new RosterMemoryStorage(); #ifdef SWIFT_EXPERIMENTAL_HISTORY - historyStorage = new SQLiteHistoryStorage(":memory:"); + historyStorage = new SQLiteHistoryStorage(":memory:"); #else - historyStorage = NULL; + historyStorage = NULL; #endif } MemoryStorages::~MemoryStorages() { - delete rosterStorage; - delete avatarStorage; - delete capsStorage; - delete vcardStorage; + delete rosterStorage; + delete avatarStorage; + delete capsStorage; + delete vcardStorage; #ifdef SWIFT_EXPERIMENTAL_HISTORY - delete historyStorage; + delete historyStorage; #endif } VCardStorage* MemoryStorages::getVCardStorage() const { - return vcardStorage; + return vcardStorage; } CapsStorage* MemoryStorages::getCapsStorage() const { - return capsStorage; + return capsStorage; } AvatarStorage* MemoryStorages::getAvatarStorage() const { - return avatarStorage; + return avatarStorage; } RosterStorage* MemoryStorages::getRosterStorage() const { - return rosterStorage; + return rosterStorage; } HistoryStorage* MemoryStorages::getHistoryStorage() const { #ifdef SWIFT_EXPERIMENTAL_HISTORY - return historyStorage; + return historyStorage; #else - return NULL; + return NULL; #endif } diff --git a/Swiften/Client/MemoryStorages.h b/Swiften/Client/MemoryStorages.h index 49f18f5..b905ed9 100644 --- a/Swiften/Client/MemoryStorages.h +++ b/Swiften/Client/MemoryStorages.h @@ -10,29 +10,29 @@ #include <Swiften/Client/Storages.h> namespace Swift { - class VCardMemoryStorage; - class CryptoProvider; + class VCardMemoryStorage; + class CryptoProvider; - /** - * An implementation of Storages for storing all - * controller data in memory. - */ - class SWIFTEN_API MemoryStorages : public Storages { - public: - MemoryStorages(CryptoProvider*); - virtual ~MemoryStorages(); + /** + * An implementation of Storages for storing all + * controller data in memory. + */ + class SWIFTEN_API MemoryStorages : public Storages { + public: + MemoryStorages(CryptoProvider*); + virtual ~MemoryStorages(); - virtual VCardStorage* getVCardStorage() const; - virtual AvatarStorage* getAvatarStorage() const; - virtual CapsStorage* getCapsStorage() const; - virtual RosterStorage* getRosterStorage() const; - virtual HistoryStorage* getHistoryStorage() const; + virtual VCardStorage* getVCardStorage() const; + virtual AvatarStorage* getAvatarStorage() const; + virtual CapsStorage* getCapsStorage() const; + virtual RosterStorage* getRosterStorage() const; + virtual HistoryStorage* getHistoryStorage() const; - private: - VCardMemoryStorage* vcardStorage; - AvatarStorage* avatarStorage; - CapsStorage* capsStorage; - RosterStorage* rosterStorage; - HistoryStorage* historyStorage; - }; + private: + VCardMemoryStorage* vcardStorage; + AvatarStorage* avatarStorage; + CapsStorage* capsStorage; + RosterStorage* rosterStorage; + HistoryStorage* historyStorage; + }; } diff --git a/Swiften/Client/NickManager.h b/Swiften/Client/NickManager.h index f05c122..4769bad 100644 --- a/Swiften/Client/NickManager.h +++ b/Swiften/Client/NickManager.h @@ -12,13 +12,13 @@ #include <Swiften/Base/boost_bsignals.h> namespace Swift { - class SWIFTEN_API NickManager { - public: - virtual ~NickManager(); + class SWIFTEN_API NickManager { + public: + virtual ~NickManager(); - virtual std::string getOwnNick() const = 0; - virtual void setOwnNick(const std::string& nick) = 0; + virtual std::string getOwnNick() const = 0; + virtual void setOwnNick(const std::string& nick) = 0; - boost::signal<void (const std::string&)> onOwnNickChanged; - }; + boost::signal<void (const std::string&)> onOwnNickChanged; + }; } diff --git a/Swiften/Client/NickManagerImpl.cpp b/Swiften/Client/NickManagerImpl.cpp index f755424..f8fef39 100644 --- a/Swiften/Client/NickManagerImpl.cpp +++ b/Swiften/Client/NickManagerImpl.cpp @@ -13,38 +13,38 @@ namespace Swift { NickManagerImpl::NickManagerImpl(const JID& ownJID, VCardManager* vcardManager) : ownJID(ownJID), vcardManager(vcardManager) { - vcardManager->onVCardChanged.connect(boost::bind(&NickManagerImpl::handleVCardReceived, this, _1, _2)); + vcardManager->onVCardChanged.connect(boost::bind(&NickManagerImpl::handleVCardReceived, this, _1, _2)); - updateOwnNickFromVCard(vcardManager->getVCard(ownJID.toBare())); + updateOwnNickFromVCard(vcardManager->getVCard(ownJID.toBare())); } NickManagerImpl::~NickManagerImpl() { - vcardManager->onVCardChanged.disconnect(boost::bind(&NickManagerImpl::handleVCardReceived, this, _1, _2)); + vcardManager->onVCardChanged.disconnect(boost::bind(&NickManagerImpl::handleVCardReceived, this, _1, _2)); } std::string NickManagerImpl::getOwnNick() const { - return ownNick; + return ownNick; } void NickManagerImpl::setOwnNick(const std::string&) { } void NickManagerImpl::handleVCardReceived(const JID& jid, VCard::ref vcard) { - if (!jid.equals(ownJID, JID::WithoutResource)) { - return; - } - updateOwnNickFromVCard(vcard); + if (!jid.equals(ownJID, JID::WithoutResource)) { + return; + } + updateOwnNickFromVCard(vcard); } void NickManagerImpl::updateOwnNickFromVCard(VCard::ref vcard) { - std::string nick; - if (vcard && !vcard->getNickname().empty()) { - nick = vcard->getNickname(); - } - if (ownNick != nick) { - ownNick = nick; - onOwnNickChanged(ownNick); - } + std::string nick; + if (vcard && !vcard->getNickname().empty()) { + nick = vcard->getNickname(); + } + if (ownNick != nick) { + ownNick = nick; + onOwnNickChanged(ownNick); + } } } diff --git a/Swiften/Client/NickManagerImpl.h b/Swiften/Client/NickManagerImpl.h index 51a8624..a413378 100644 --- a/Swiften/Client/NickManagerImpl.h +++ b/Swiften/Client/NickManagerImpl.h @@ -13,23 +13,23 @@ #include <Swiften/JID/JID.h> namespace Swift { - class VCardManager; + class VCardManager; - class NickManagerImpl : public NickManager { - public: - NickManagerImpl(const JID& ownJID, VCardManager* vcardManager); - virtual ~NickManagerImpl(); + class NickManagerImpl : public NickManager { + public: + NickManagerImpl(const JID& ownJID, VCardManager* vcardManager); + virtual ~NickManagerImpl(); - std::string getOwnNick() const; - void setOwnNick(const std::string& nick); + std::string getOwnNick() const; + void setOwnNick(const std::string& nick); - private: - void handleVCardReceived(const JID& jid, VCard::ref vCard); - void updateOwnNickFromVCard(VCard::ref vcard); + private: + void handleVCardReceived(const JID& jid, VCard::ref vCard); + void updateOwnNickFromVCard(VCard::ref vcard); - private: - JID ownJID; - VCardManager* vcardManager; - std::string ownNick; - }; + private: + JID ownJID; + VCardManager* vcardManager; + std::string ownNick; + }; } diff --git a/Swiften/Client/NickResolver.cpp b/Swiften/Client/NickResolver.cpp index 4136a42..c424447 100644 --- a/Swiften/Client/NickResolver.cpp +++ b/Swiften/Client/NickResolver.cpp @@ -21,59 +21,59 @@ namespace Swift { NickResolver::NickResolver(const JID& ownJID, XMPPRoster* xmppRoster, VCardManager* vcardManager, MUCRegistry* mucRegistry) : ownJID_(ownJID) { - xmppRoster_ = xmppRoster; - vcardManager_ = vcardManager; - if (vcardManager_) { - vcardManager_->onVCardChanged.connect(boost::bind(&NickResolver::handleVCardReceived, this, _1, _2)); - } - mucRegistry_ = mucRegistry; - xmppRoster_->onJIDUpdated.connect(boost::bind(&NickResolver::handleJIDUpdated, this, _1, _2, _3)); - xmppRoster_->onJIDAdded.connect(boost::bind(&NickResolver::handleJIDAdded, this, _1)); + xmppRoster_ = xmppRoster; + vcardManager_ = vcardManager; + if (vcardManager_) { + vcardManager_->onVCardChanged.connect(boost::bind(&NickResolver::handleVCardReceived, this, _1, _2)); + } + mucRegistry_ = mucRegistry; + xmppRoster_->onJIDUpdated.connect(boost::bind(&NickResolver::handleJIDUpdated, this, _1, _2, _3)); + xmppRoster_->onJIDAdded.connect(boost::bind(&NickResolver::handleJIDAdded, this, _1)); } void NickResolver::handleJIDUpdated(const JID& jid, const std::string& previousNick, const std::vector<std::string>& /*groups*/) { - onNickChanged(jid, previousNick); + onNickChanged(jid, previousNick); } void NickResolver::handleJIDAdded(const JID& jid) { - std::string oldNick(jidToNick(jid)); - onNickChanged(jid, oldNick); + std::string oldNick(jidToNick(jid)); + onNickChanged(jid, oldNick); } std::string NickResolver::jidToNick(const JID& jid) { - if (jid.toBare() == ownJID_) { - if (!ownNick_.empty()) { - return ownNick_; - } - } - std::string nick; + if (jid.toBare() == ownJID_) { + if (!ownNick_.empty()) { + return ownNick_; + } + } + std::string nick; - if (mucRegistry_ && mucRegistry_->isMUC(jid.toBare()) ) { - return jid.getResource().empty() ? jid.toBare().toString() : jid.getResource(); - } + if (mucRegistry_ && mucRegistry_->isMUC(jid.toBare()) ) { + return jid.getResource().empty() ? jid.toBare().toString() : jid.getResource(); + } - if (xmppRoster_->containsJID(jid) && !xmppRoster_->getNameForJID(jid).empty()) { - return xmppRoster_->getNameForJID(jid); - } + if (xmppRoster_->containsJID(jid) && !xmppRoster_->getNameForJID(jid).empty()) { + return xmppRoster_->getNameForJID(jid); + } - return jid.toBare(); + return jid.toBare(); } void NickResolver::handleVCardReceived(const JID& jid, VCard::ref ownVCard) { - if (!jid.equals(ownJID_, JID::WithoutResource)) { - return; - } - std::string initialNick = ownNick_; - ownNick_ = ownJID_.toString(); - if (ownVCard) { - if (!ownVCard->getNickname().empty()) { - ownNick_ = ownVCard->getNickname(); - } else if (!ownVCard->getGivenName().empty()) { - ownNick_ = ownVCard->getGivenName(); - } else if (!ownVCard->getFullName().empty()) { - ownNick_ = ownVCard->getFullName(); - } - } + if (!jid.equals(ownJID_, JID::WithoutResource)) { + return; + } + std::string initialNick = ownNick_; + ownNick_ = ownJID_.toString(); + if (ownVCard) { + if (!ownVCard->getNickname().empty()) { + ownNick_ = ownVCard->getNickname(); + } else if (!ownVCard->getGivenName().empty()) { + ownNick_ = ownVCard->getGivenName(); + } else if (!ownVCard->getFullName().empty()) { + ownNick_ = ownVCard->getFullName(); + } + } } } diff --git a/Swiften/Client/NickResolver.h b/Swiften/Client/NickResolver.h index c3e6f05..b187796 100644 --- a/Swiften/Client/NickResolver.h +++ b/Swiften/Client/NickResolver.h @@ -17,28 +17,28 @@ #include <Swiften/JID/JID.h> namespace Swift { - class XMPPRoster; - class MUCRegistry; - class VCardManager; - - class SWIFTEN_API NickResolver { - public: - NickResolver(const JID& ownJID, XMPPRoster* xmppRoster, VCardManager* vcardManager, MUCRegistry* mucRegistry); - - std::string jidToNick(const JID& jid); - - boost::signal<void (const JID&, const std::string& /*previousNick*/)> onNickChanged; - - private: - void handleVCardReceived(const JID& jid, VCard::ref vCard); - void handleJIDUpdated(const JID& jid, const std::string& previousNick, const std::vector<std::string>& groups); - void handleJIDAdded(const JID& jid); - - private: - JID ownJID_; - std::string ownNick_; - XMPPRoster* xmppRoster_; - MUCRegistry* mucRegistry_; - VCardManager* vcardManager_; - }; + class XMPPRoster; + class MUCRegistry; + class VCardManager; + + class SWIFTEN_API NickResolver { + public: + NickResolver(const JID& ownJID, XMPPRoster* xmppRoster, VCardManager* vcardManager, MUCRegistry* mucRegistry); + + std::string jidToNick(const JID& jid); + + boost::signal<void (const JID&, const std::string& /*previousNick*/)> onNickChanged; + + private: + void handleVCardReceived(const JID& jid, VCard::ref vCard); + void handleJIDUpdated(const JID& jid, const std::string& previousNick, const std::vector<std::string>& groups); + void handleJIDAdded(const JID& jid); + + private: + JID ownJID_; + std::string ownNick_; + XMPPRoster* xmppRoster_; + MUCRegistry* mucRegistry_; + VCardManager* vcardManager_; + }; } diff --git a/Swiften/Client/StanzaChannel.h b/Swiften/Client/StanzaChannel.h index bf81c6a..ec36634 100644 --- a/Swiften/Client/StanzaChannel.h +++ b/Swiften/Client/StanzaChannel.h @@ -16,17 +16,17 @@ #include <Swiften/TLS/Certificate.h> namespace Swift { - class SWIFTEN_API StanzaChannel : public IQChannel { - public: - virtual void sendMessage(boost::shared_ptr<Message>) = 0; - virtual void sendPresence(boost::shared_ptr<Presence>) = 0; - virtual bool isAvailable() const = 0; - virtual bool getStreamManagementEnabled() const = 0; - virtual std::vector<Certificate::ref> getPeerCertificateChain() const = 0; + class SWIFTEN_API StanzaChannel : public IQChannel { + public: + virtual void sendMessage(boost::shared_ptr<Message>) = 0; + virtual void sendPresence(boost::shared_ptr<Presence>) = 0; + virtual bool isAvailable() const = 0; + virtual bool getStreamManagementEnabled() const = 0; + virtual std::vector<Certificate::ref> getPeerCertificateChain() const = 0; - boost::signal<void (bool /* isAvailable */)> onAvailableChanged; - boost::signal<void (boost::shared_ptr<Message>)> onMessageReceived; - boost::signal<void (boost::shared_ptr<Presence>) > onPresenceReceived; - boost::signal<void (boost::shared_ptr<Stanza>)> onStanzaAcked; - }; + boost::signal<void (bool /* isAvailable */)> onAvailableChanged; + boost::signal<void (boost::shared_ptr<Message>)> onMessageReceived; + boost::signal<void (boost::shared_ptr<Presence>) > onPresenceReceived; + boost::signal<void (boost::shared_ptr<Stanza>)> onStanzaAcked; + }; } diff --git a/Swiften/Client/Storages.h b/Swiften/Client/Storages.h index 3187cf7..9485831 100644 --- a/Swiften/Client/Storages.h +++ b/Swiften/Client/Storages.h @@ -9,24 +9,24 @@ #include <Swiften/Base/API.h> namespace Swift { - class VCardStorage; - class AvatarStorage; - class CapsStorage; - class RosterStorage; - class HistoryStorage; + class VCardStorage; + class AvatarStorage; + class CapsStorage; + class RosterStorage; + class HistoryStorage; - /** - * An interface to hold storage classes for different - * controllers. - */ - class SWIFTEN_API Storages { - public: - virtual ~Storages(); + /** + * An interface to hold storage classes for different + * controllers. + */ + class SWIFTEN_API Storages { + public: + virtual ~Storages(); - virtual VCardStorage* getVCardStorage() const = 0; - virtual AvatarStorage* getAvatarStorage() const = 0; - virtual CapsStorage* getCapsStorage() const = 0; - virtual RosterStorage* getRosterStorage() const = 0; - virtual HistoryStorage* getHistoryStorage() const = 0; - }; + virtual VCardStorage* getVCardStorage() const = 0; + virtual AvatarStorage* getAvatarStorage() const = 0; + virtual CapsStorage* getCapsStorage() const = 0; + virtual RosterStorage* getRosterStorage() const = 0; + virtual HistoryStorage* getHistoryStorage() const = 0; + }; } diff --git a/Swiften/Client/UnitTest/BlockListImplTest.cpp b/Swiften/Client/UnitTest/BlockListImplTest.cpp index 9e5bc1a..0502f46 100644 --- a/Swiften/Client/UnitTest/BlockListImplTest.cpp +++ b/Swiften/Client/UnitTest/BlockListImplTest.cpp @@ -17,75 +17,75 @@ using namespace Swift; class BlockListImplTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(BlockListImplTest); - CPPUNIT_TEST(testSetItemsToSubset); - CPPUNIT_TEST(testSetItemsToSuperset); - CPPUNIT_TEST(testSetItemsAllDifferent); - CPPUNIT_TEST_SUITE_END(); - - public: - - void testSetItemsToSubset() { - std::vector<JID> subset; - subset.push_back(JID("a@example.com")); - - blockList_->setItems(subset); - - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), addedJIDs_.size()); - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), removedJIDs_.size()); - } - - void testSetItemsToSuperset() { - std::vector<JID> superset; - superset.push_back(JID("a@example.com")); - superset.push_back(JID("b@example.com")); - superset.push_back(JID("c@example.com")); - - blockList_->setItems(superset); - - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), addedJIDs_.size()); - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), removedJIDs_.size()); - } - - void testSetItemsAllDifferent() { - std::vector<JID> newBlockList; - newBlockList.push_back(JID("x@example.com")); - newBlockList.push_back(JID("y@example.com")); - newBlockList.push_back(JID("z@example.com")); - - blockList_->setItems(newBlockList); - - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), addedJIDs_.size()); - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), removedJIDs_.size()); - } - - void setUp() { - blockList_ = boost::make_shared<BlockListImpl>(); - addedJIDs_.clear(); - removedJIDs_.clear(); - blockList_->addItem(JID("a@example.com")); - blockList_->addItem(JID("b@example.com")); - - blockList_->onItemAdded.connect(boost::bind(&BlockListImplTest::handleBlockListItemAdded, this, _1)); - blockList_->onItemRemoved.connect(boost::bind(&BlockListImplTest::handleBlockListItemRemoved, this, _1)); - } - - void tearDown() { - blockList_.reset(); - } - - void handleBlockListItemAdded(const JID& jid) { - addedJIDs_.push_back(jid); - } - - void handleBlockListItemRemoved(const JID& jid) { - removedJIDs_.push_back(jid); - } - - private: - boost::shared_ptr<BlockListImpl> blockList_; - std::vector<JID> addedJIDs_; - std::vector<JID> removedJIDs_; + CPPUNIT_TEST_SUITE(BlockListImplTest); + CPPUNIT_TEST(testSetItemsToSubset); + CPPUNIT_TEST(testSetItemsToSuperset); + CPPUNIT_TEST(testSetItemsAllDifferent); + CPPUNIT_TEST_SUITE_END(); + + public: + + void testSetItemsToSubset() { + std::vector<JID> subset; + subset.push_back(JID("a@example.com")); + + blockList_->setItems(subset); + + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), addedJIDs_.size()); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), removedJIDs_.size()); + } + + void testSetItemsToSuperset() { + std::vector<JID> superset; + superset.push_back(JID("a@example.com")); + superset.push_back(JID("b@example.com")); + superset.push_back(JID("c@example.com")); + + blockList_->setItems(superset); + + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), addedJIDs_.size()); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), removedJIDs_.size()); + } + + void testSetItemsAllDifferent() { + std::vector<JID> newBlockList; + newBlockList.push_back(JID("x@example.com")); + newBlockList.push_back(JID("y@example.com")); + newBlockList.push_back(JID("z@example.com")); + + blockList_->setItems(newBlockList); + + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), addedJIDs_.size()); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), removedJIDs_.size()); + } + + void setUp() { + blockList_ = boost::make_shared<BlockListImpl>(); + addedJIDs_.clear(); + removedJIDs_.clear(); + blockList_->addItem(JID("a@example.com")); + blockList_->addItem(JID("b@example.com")); + + blockList_->onItemAdded.connect(boost::bind(&BlockListImplTest::handleBlockListItemAdded, this, _1)); + blockList_->onItemRemoved.connect(boost::bind(&BlockListImplTest::handleBlockListItemRemoved, this, _1)); + } + + void tearDown() { + blockList_.reset(); + } + + void handleBlockListItemAdded(const JID& jid) { + addedJIDs_.push_back(jid); + } + + void handleBlockListItemRemoved(const JID& jid) { + removedJIDs_.push_back(jid); + } + + private: + boost::shared_ptr<BlockListImpl> blockList_; + std::vector<JID> addedJIDs_; + std::vector<JID> removedJIDs_; }; CPPUNIT_TEST_SUITE_REGISTRATION(BlockListImplTest); diff --git a/Swiften/Client/UnitTest/ClientBlockListManagerTest.cpp b/Swiften/Client/UnitTest/ClientBlockListManagerTest.cpp index 53c39b5..ef2f537 100644 --- a/Swiften/Client/UnitTest/ClientBlockListManagerTest.cpp +++ b/Swiften/Client/UnitTest/ClientBlockListManagerTest.cpp @@ -25,170 +25,170 @@ using namespace Swift; class ClientBlockListManagerTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(ClientBlockListManagerTest); - CPPUNIT_TEST(testFetchBlockList); - CPPUNIT_TEST(testBlockCommand); - CPPUNIT_TEST(testUnblockCommand); - CPPUNIT_TEST(testUnblockAllCommand); - CPPUNIT_TEST_SUITE_END(); - - public: - void setUp() { - ownJID_ = JID("kev@wonderland.lit"); - stanzaChannel_ = new DummyStanzaChannel(); - iqRouter_ = new IQRouter(stanzaChannel_); - iqRouter_->setJID(ownJID_); - clientBlockListManager_ = new ClientBlockListManager(iqRouter_); - } - - void testFetchBlockList() { - std::vector<JID> blockJids; - blockJids.push_back(JID("romeo@montague.net")); - blockJids.push_back(JID("iago@shakespeare.lit")); - helperInitialBlockListFetch(blockJids); - - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), clientBlockListManager_->getBlockList()->getItems().size()); - } - - void testBlockCommand() { - // start with an already fetched block list - helperInitialBlockListFetch(std::vector<JID>(1, JID("iago@shakespeare.lit"))); - - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), clientBlockListManager_->getBlockList()->getItems().size()); - CPPUNIT_ASSERT_EQUAL(BlockList::Available, clientBlockListManager_->getBlockList()->getState()); - - GenericRequest<BlockPayload>::ref blockRequest = clientBlockListManager_->createBlockJIDRequest(JID("romeo@montague.net")); - blockRequest->send(); - IQ::ref request = stanzaChannel_->getStanzaAtIndex<IQ>(2); - CPPUNIT_ASSERT(request.get() != NULL); - boost::shared_ptr<BlockPayload> blockPayload = request->getPayload<BlockPayload>(); - CPPUNIT_ASSERT(blockPayload.get() != NULL); - CPPUNIT_ASSERT_EQUAL(JID("romeo@montague.net"), blockPayload->getItems().at(0)); - - IQ::ref blockRequestResponse = IQ::createResult(request->getFrom(), JID(), request->getID()); - stanzaChannel_->sendIQ(blockRequestResponse); - stanzaChannel_->onIQReceived(blockRequestResponse); - - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), clientBlockListManager_->getBlockList()->getItems().size()); - - // send block push - boost::shared_ptr<BlockPayload> pushPayload = boost::make_shared<BlockPayload>(); - pushPayload->addItem(JID("romeo@montague.net")); - IQ::ref blockPush = IQ::createRequest(IQ::Set, ownJID_, "push1", pushPayload); - stanzaChannel_->sendIQ(blockPush); - stanzaChannel_->onIQReceived(blockPush); - - std::vector<JID> blockedJIDs = clientBlockListManager_->getBlockList()->getItems(); - CPPUNIT_ASSERT(blockedJIDs.end() != std::find(blockedJIDs.begin(), blockedJIDs.end(), JID("romeo@montague.net"))); - } - - void testUnblockCommand() { - // start with an already fetched block list - std::vector<JID> initialBlockList = std::vector<JID>(1, JID("iago@shakespeare.lit")); - initialBlockList.push_back(JID("romeo@montague.net")); - helperInitialBlockListFetch(initialBlockList); - - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), clientBlockListManager_->getBlockList()->getItems().size()); - CPPUNIT_ASSERT_EQUAL(BlockList::Available, clientBlockListManager_->getBlockList()->getState()); - - GenericRequest<UnblockPayload>::ref unblockRequest = clientBlockListManager_->createUnblockJIDRequest(JID("romeo@montague.net")); - unblockRequest->send(); - IQ::ref request = stanzaChannel_->getStanzaAtIndex<IQ>(2); - CPPUNIT_ASSERT(request.get() != NULL); - boost::shared_ptr<UnblockPayload> unblockPayload = request->getPayload<UnblockPayload>(); - CPPUNIT_ASSERT(unblockPayload.get() != NULL); - CPPUNIT_ASSERT_EQUAL(JID("romeo@montague.net"), unblockPayload->getItems().at(0)); - - IQ::ref unblockRequestResponse = IQ::createResult(request->getFrom(), JID(), request->getID()); - stanzaChannel_->sendIQ(unblockRequestResponse); - stanzaChannel_->onIQReceived(unblockRequestResponse); - - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), clientBlockListManager_->getBlockList()->getItems().size()); - - // send block push - boost::shared_ptr<UnblockPayload> pushPayload = boost::make_shared<UnblockPayload>(); - pushPayload->addItem(JID("romeo@montague.net")); - IQ::ref unblockPush = IQ::createRequest(IQ::Set, ownJID_, "push1", pushPayload); - stanzaChannel_->sendIQ(unblockPush); - stanzaChannel_->onIQReceived(unblockPush); - - std::vector<JID> blockedJIDs = clientBlockListManager_->getBlockList()->getItems(); - CPPUNIT_ASSERT(blockedJIDs.end() == std::find(blockedJIDs.begin(), blockedJIDs.end(), JID("romeo@montague.net"))); - } - - void testUnblockAllCommand() { - // start with an already fetched block list - std::vector<JID> initialBlockList = std::vector<JID>(1, JID("iago@shakespeare.lit")); - initialBlockList.push_back(JID("romeo@montague.net")); - initialBlockList.push_back(JID("benvolio@montague.net")); - helperInitialBlockListFetch(initialBlockList); - - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), clientBlockListManager_->getBlockList()->getItems().size()); - CPPUNIT_ASSERT_EQUAL(BlockList::Available, clientBlockListManager_->getBlockList()->getState()); - - GenericRequest<UnblockPayload>::ref unblockRequest = clientBlockListManager_->createUnblockAllRequest(); - unblockRequest->send(); - IQ::ref request = stanzaChannel_->getStanzaAtIndex<IQ>(2); - CPPUNIT_ASSERT(request.get() != NULL); - boost::shared_ptr<UnblockPayload> unblockPayload = request->getPayload<UnblockPayload>(); - CPPUNIT_ASSERT(unblockPayload.get() != NULL); - CPPUNIT_ASSERT_EQUAL(true, unblockPayload->getItems().empty()); - - IQ::ref unblockRequestResponse = IQ::createResult(request->getFrom(), JID(), request->getID()); - stanzaChannel_->sendIQ(unblockRequestResponse); - stanzaChannel_->onIQReceived(unblockRequestResponse); - - CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), clientBlockListManager_->getBlockList()->getItems().size()); - - // send block push - boost::shared_ptr<UnblockPayload> pushPayload = boost::make_shared<UnblockPayload>(); - IQ::ref unblockPush = IQ::createRequest(IQ::Set, ownJID_, "push1", pushPayload); - stanzaChannel_->sendIQ(unblockPush); - stanzaChannel_->onIQReceived(unblockPush); - - CPPUNIT_ASSERT_EQUAL(true, clientBlockListManager_->getBlockList()->getItems().empty()); - } - - void tearDown() { - delete clientBlockListManager_; - delete iqRouter_; - delete stanzaChannel_; - } - - private: - void helperInitialBlockListFetch(const std::vector<JID>& blockedJids) { - boost::shared_ptr<BlockList> blockList = clientBlockListManager_->requestBlockList(); - CPPUNIT_ASSERT(blockList); - - // check for IQ request - IQ::ref request = stanzaChannel_->getStanzaAtIndex<IQ>(0); - CPPUNIT_ASSERT(request.get() != NULL); - boost::shared_ptr<BlockListPayload> requestPayload = request->getPayload<BlockListPayload>(); - CPPUNIT_ASSERT(requestPayload.get() != NULL); - - CPPUNIT_ASSERT_EQUAL(BlockList::Requesting, blockList->getState()); - CPPUNIT_ASSERT_EQUAL(BlockList::Requesting, clientBlockListManager_->getBlockList()->getState()); - - // build IQ response - boost::shared_ptr<BlockListPayload> responsePayload = boost::make_shared<BlockListPayload>(); - foreach(const JID& jid, blockedJids) { - responsePayload->addItem(jid); - } - - IQ::ref response = IQ::createResult(ownJID_, JID(), request->getID(), responsePayload); - stanzaChannel_->sendIQ(response); - stanzaChannel_->onIQReceived(response); - - CPPUNIT_ASSERT_EQUAL(BlockList::Available, clientBlockListManager_->getBlockList()->getState()); - CPPUNIT_ASSERT(responsePayload->getItems() == clientBlockListManager_->getBlockList()->getItems()); - } - - - private: - JID ownJID_; - IQRouter* iqRouter_; - DummyStanzaChannel* stanzaChannel_; - ClientBlockListManager* clientBlockListManager_; + CPPUNIT_TEST_SUITE(ClientBlockListManagerTest); + CPPUNIT_TEST(testFetchBlockList); + CPPUNIT_TEST(testBlockCommand); + CPPUNIT_TEST(testUnblockCommand); + CPPUNIT_TEST(testUnblockAllCommand); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + ownJID_ = JID("kev@wonderland.lit"); + stanzaChannel_ = new DummyStanzaChannel(); + iqRouter_ = new IQRouter(stanzaChannel_); + iqRouter_->setJID(ownJID_); + clientBlockListManager_ = new ClientBlockListManager(iqRouter_); + } + + void testFetchBlockList() { + std::vector<JID> blockJids; + blockJids.push_back(JID("romeo@montague.net")); + blockJids.push_back(JID("iago@shakespeare.lit")); + helperInitialBlockListFetch(blockJids); + + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), clientBlockListManager_->getBlockList()->getItems().size()); + } + + void testBlockCommand() { + // start with an already fetched block list + helperInitialBlockListFetch(std::vector<JID>(1, JID("iago@shakespeare.lit"))); + + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), clientBlockListManager_->getBlockList()->getItems().size()); + CPPUNIT_ASSERT_EQUAL(BlockList::Available, clientBlockListManager_->getBlockList()->getState()); + + GenericRequest<BlockPayload>::ref blockRequest = clientBlockListManager_->createBlockJIDRequest(JID("romeo@montague.net")); + blockRequest->send(); + IQ::ref request = stanzaChannel_->getStanzaAtIndex<IQ>(2); + CPPUNIT_ASSERT(request.get() != NULL); + boost::shared_ptr<BlockPayload> blockPayload = request->getPayload<BlockPayload>(); + CPPUNIT_ASSERT(blockPayload.get() != NULL); + CPPUNIT_ASSERT_EQUAL(JID("romeo@montague.net"), blockPayload->getItems().at(0)); + + IQ::ref blockRequestResponse = IQ::createResult(request->getFrom(), JID(), request->getID()); + stanzaChannel_->sendIQ(blockRequestResponse); + stanzaChannel_->onIQReceived(blockRequestResponse); + + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), clientBlockListManager_->getBlockList()->getItems().size()); + + // send block push + boost::shared_ptr<BlockPayload> pushPayload = boost::make_shared<BlockPayload>(); + pushPayload->addItem(JID("romeo@montague.net")); + IQ::ref blockPush = IQ::createRequest(IQ::Set, ownJID_, "push1", pushPayload); + stanzaChannel_->sendIQ(blockPush); + stanzaChannel_->onIQReceived(blockPush); + + std::vector<JID> blockedJIDs = clientBlockListManager_->getBlockList()->getItems(); + CPPUNIT_ASSERT(blockedJIDs.end() != std::find(blockedJIDs.begin(), blockedJIDs.end(), JID("romeo@montague.net"))); + } + + void testUnblockCommand() { + // start with an already fetched block list + std::vector<JID> initialBlockList = std::vector<JID>(1, JID("iago@shakespeare.lit")); + initialBlockList.push_back(JID("romeo@montague.net")); + helperInitialBlockListFetch(initialBlockList); + + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), clientBlockListManager_->getBlockList()->getItems().size()); + CPPUNIT_ASSERT_EQUAL(BlockList::Available, clientBlockListManager_->getBlockList()->getState()); + + GenericRequest<UnblockPayload>::ref unblockRequest = clientBlockListManager_->createUnblockJIDRequest(JID("romeo@montague.net")); + unblockRequest->send(); + IQ::ref request = stanzaChannel_->getStanzaAtIndex<IQ>(2); + CPPUNIT_ASSERT(request.get() != NULL); + boost::shared_ptr<UnblockPayload> unblockPayload = request->getPayload<UnblockPayload>(); + CPPUNIT_ASSERT(unblockPayload.get() != NULL); + CPPUNIT_ASSERT_EQUAL(JID("romeo@montague.net"), unblockPayload->getItems().at(0)); + + IQ::ref unblockRequestResponse = IQ::createResult(request->getFrom(), JID(), request->getID()); + stanzaChannel_->sendIQ(unblockRequestResponse); + stanzaChannel_->onIQReceived(unblockRequestResponse); + + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), clientBlockListManager_->getBlockList()->getItems().size()); + + // send block push + boost::shared_ptr<UnblockPayload> pushPayload = boost::make_shared<UnblockPayload>(); + pushPayload->addItem(JID("romeo@montague.net")); + IQ::ref unblockPush = IQ::createRequest(IQ::Set, ownJID_, "push1", pushPayload); + stanzaChannel_->sendIQ(unblockPush); + stanzaChannel_->onIQReceived(unblockPush); + + std::vector<JID> blockedJIDs = clientBlockListManager_->getBlockList()->getItems(); + CPPUNIT_ASSERT(blockedJIDs.end() == std::find(blockedJIDs.begin(), blockedJIDs.end(), JID("romeo@montague.net"))); + } + + void testUnblockAllCommand() { + // start with an already fetched block list + std::vector<JID> initialBlockList = std::vector<JID>(1, JID("iago@shakespeare.lit")); + initialBlockList.push_back(JID("romeo@montague.net")); + initialBlockList.push_back(JID("benvolio@montague.net")); + helperInitialBlockListFetch(initialBlockList); + + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), clientBlockListManager_->getBlockList()->getItems().size()); + CPPUNIT_ASSERT_EQUAL(BlockList::Available, clientBlockListManager_->getBlockList()->getState()); + + GenericRequest<UnblockPayload>::ref unblockRequest = clientBlockListManager_->createUnblockAllRequest(); + unblockRequest->send(); + IQ::ref request = stanzaChannel_->getStanzaAtIndex<IQ>(2); + CPPUNIT_ASSERT(request.get() != NULL); + boost::shared_ptr<UnblockPayload> unblockPayload = request->getPayload<UnblockPayload>(); + CPPUNIT_ASSERT(unblockPayload.get() != NULL); + CPPUNIT_ASSERT_EQUAL(true, unblockPayload->getItems().empty()); + + IQ::ref unblockRequestResponse = IQ::createResult(request->getFrom(), JID(), request->getID()); + stanzaChannel_->sendIQ(unblockRequestResponse); + stanzaChannel_->onIQReceived(unblockRequestResponse); + + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), clientBlockListManager_->getBlockList()->getItems().size()); + + // send block push + boost::shared_ptr<UnblockPayload> pushPayload = boost::make_shared<UnblockPayload>(); + IQ::ref unblockPush = IQ::createRequest(IQ::Set, ownJID_, "push1", pushPayload); + stanzaChannel_->sendIQ(unblockPush); + stanzaChannel_->onIQReceived(unblockPush); + + CPPUNIT_ASSERT_EQUAL(true, clientBlockListManager_->getBlockList()->getItems().empty()); + } + + void tearDown() { + delete clientBlockListManager_; + delete iqRouter_; + delete stanzaChannel_; + } + + private: + void helperInitialBlockListFetch(const std::vector<JID>& blockedJids) { + boost::shared_ptr<BlockList> blockList = clientBlockListManager_->requestBlockList(); + CPPUNIT_ASSERT(blockList); + + // check for IQ request + IQ::ref request = stanzaChannel_->getStanzaAtIndex<IQ>(0); + CPPUNIT_ASSERT(request.get() != NULL); + boost::shared_ptr<BlockListPayload> requestPayload = request->getPayload<BlockListPayload>(); + CPPUNIT_ASSERT(requestPayload.get() != NULL); + + CPPUNIT_ASSERT_EQUAL(BlockList::Requesting, blockList->getState()); + CPPUNIT_ASSERT_EQUAL(BlockList::Requesting, clientBlockListManager_->getBlockList()->getState()); + + // build IQ response + boost::shared_ptr<BlockListPayload> responsePayload = boost::make_shared<BlockListPayload>(); + foreach(const JID& jid, blockedJids) { + responsePayload->addItem(jid); + } + + IQ::ref response = IQ::createResult(ownJID_, JID(), request->getID(), responsePayload); + stanzaChannel_->sendIQ(response); + stanzaChannel_->onIQReceived(response); + + CPPUNIT_ASSERT_EQUAL(BlockList::Available, clientBlockListManager_->getBlockList()->getState()); + CPPUNIT_ASSERT(responsePayload->getItems() == clientBlockListManager_->getBlockList()->getItems()); + } + + + private: + JID ownJID_; + IQRouter* iqRouter_; + DummyStanzaChannel* stanzaChannel_; + ClientBlockListManager* clientBlockListManager_; }; CPPUNIT_TEST_SUITE_REGISTRATION(ClientBlockListManagerTest); diff --git a/Swiften/Client/UnitTest/ClientSessionTest.cpp b/Swiften/Client/UnitTest/ClientSessionTest.cpp index 396edf6..335b537 100644 --- a/Swiften/Client/UnitTest/ClientSessionTest.cpp +++ b/Swiften/Client/UnitTest/ClientSessionTest.cpp @@ -41,789 +41,789 @@ using namespace Swift; class ClientSessionTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(ClientSessionTest); - CPPUNIT_TEST(testStart_Error); - CPPUNIT_TEST(testStart_StreamError); - CPPUNIT_TEST(testStartTLS); - CPPUNIT_TEST(testStartTLS_ServerError); - CPPUNIT_TEST(testStartTLS_ConnectError); - CPPUNIT_TEST(testStartTLS_InvalidIdentity); - CPPUNIT_TEST(testStart_StreamFeaturesWithoutResourceBindingFails); - CPPUNIT_TEST(testAuthenticate); - CPPUNIT_TEST(testAuthenticate_Unauthorized); - CPPUNIT_TEST(testAuthenticate_NoValidAuthMechanisms); - CPPUNIT_TEST(testAuthenticate_PLAINOverNonTLS); - CPPUNIT_TEST(testAuthenticate_RequireTLS); - CPPUNIT_TEST(testAuthenticate_EXTERNAL); - CPPUNIT_TEST(testStreamManagement); - CPPUNIT_TEST(testStreamManagement_Failed); - CPPUNIT_TEST(testUnexpectedChallenge); - CPPUNIT_TEST(testFinishAcksStanzas); - /* - CPPUNIT_TEST(testResourceBind); - CPPUNIT_TEST(testResourceBind_ChangeResource); - CPPUNIT_TEST(testResourceBind_EmptyResource); - CPPUNIT_TEST(testResourceBind_Error); - CPPUNIT_TEST(testSessionStart); - CPPUNIT_TEST(testSessionStart_Error); - CPPUNIT_TEST(testSessionStart_AfterResourceBind); - CPPUNIT_TEST(testWhitespacePing); - CPPUNIT_TEST(testReceiveElementAfterSessionStarted); - CPPUNIT_TEST(testSendElement); - */ - CPPUNIT_TEST_SUITE_END(); - - public: - void setUp() { - crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); - idnConverter = boost::shared_ptr<IDNConverter>(PlatformIDNConverter::create()); - server = boost::make_shared<MockSessionStream>(); - sessionFinishedReceived = false; - needCredentials = false; - blindCertificateTrustChecker = new BlindCertificateTrustChecker(); - } - - void tearDown() { - delete blindCertificateTrustChecker; - } - - void testStart_Error() { - boost::shared_ptr<ClientSession> session(createSession()); - session->start(); - server->breakConnection(); - - CPPUNIT_ASSERT_EQUAL(ClientSession::Finished, session->getState()); - CPPUNIT_ASSERT(sessionFinishedReceived); - CPPUNIT_ASSERT(sessionFinishedError); - } - - void testStart_StreamError() { - boost::shared_ptr<ClientSession> session(createSession()); - session->start(); - server->sendStreamStart(); - server->sendStreamError(); - - CPPUNIT_ASSERT_EQUAL(ClientSession::Finished, session->getState()); - CPPUNIT_ASSERT(sessionFinishedReceived); - CPPUNIT_ASSERT(sessionFinishedError); - } - - void testStartTLS() { - boost::shared_ptr<ClientSession> session(createSession()); - session->setCertificateTrustChecker(blindCertificateTrustChecker); - session->start(); - server->receiveStreamStart(); - server->sendStreamStart(); - server->sendStreamFeaturesWithStartTLS(); - server->receiveStartTLS(); - CPPUNIT_ASSERT(!server->tlsEncrypted); - server->sendTLSProceed(); - CPPUNIT_ASSERT(server->tlsEncrypted); - server->onTLSEncrypted(); - server->receiveStreamStart(); - server->sendStreamStart(); - - session->finish(); - } - - void testStartTLS_ServerError() { - boost::shared_ptr<ClientSession> session(createSession()); - session->start(); - server->receiveStreamStart(); - server->sendStreamStart(); - server->sendStreamFeaturesWithStartTLS(); - server->receiveStartTLS(); - server->sendTLSFailure(); - - CPPUNIT_ASSERT(!server->tlsEncrypted); - CPPUNIT_ASSERT_EQUAL(ClientSession::Finished, session->getState()); - CPPUNIT_ASSERT(sessionFinishedReceived); - CPPUNIT_ASSERT(sessionFinishedError); - } - - void testStartTLS_ConnectError() { - boost::shared_ptr<ClientSession> session(createSession()); - session->start(); - server->receiveStreamStart(); - server->sendStreamStart(); - server->sendStreamFeaturesWithStartTLS(); - server->receiveStartTLS(); - server->sendTLSProceed(); - server->breakTLS(); - - CPPUNIT_ASSERT_EQUAL(ClientSession::Finished, session->getState()); - CPPUNIT_ASSERT(sessionFinishedReceived); - CPPUNIT_ASSERT(sessionFinishedError); - } - - void testStartTLS_InvalidIdentity() { - boost::shared_ptr<ClientSession> session(createSession()); - session->start(); - server->receiveStreamStart(); - server->sendStreamStart(); - server->sendStreamFeaturesWithStartTLS(); - server->receiveStartTLS(); - CPPUNIT_ASSERT(!server->tlsEncrypted); - server->sendTLSProceed(); - CPPUNIT_ASSERT(server->tlsEncrypted); - server->onTLSEncrypted(); - - CPPUNIT_ASSERT_EQUAL(ClientSession::Finished, session->getState()); - CPPUNIT_ASSERT(sessionFinishedReceived); - CPPUNIT_ASSERT(sessionFinishedError); - CPPUNIT_ASSERT_EQUAL(CertificateVerificationError::InvalidServerIdentity, boost::dynamic_pointer_cast<CertificateVerificationError>(sessionFinishedError)->getType()); - } - - void testStart_StreamFeaturesWithoutResourceBindingFails() { - boost::shared_ptr<ClientSession> session(createSession()); - session->start(); - server->receiveStreamStart(); - server->sendStreamStart(); - server->sendEmptyStreamFeatures(); - - CPPUNIT_ASSERT_EQUAL(ClientSession::Finished, session->getState()); - CPPUNIT_ASSERT(sessionFinishedReceived); - CPPUNIT_ASSERT(sessionFinishedError); - } - - void testAuthenticate() { - boost::shared_ptr<ClientSession> session(createSession()); - session->start(); - server->receiveStreamStart(); - server->sendStreamStart(); - server->sendStreamFeaturesWithPLAINAuthentication(); - CPPUNIT_ASSERT(needCredentials); - CPPUNIT_ASSERT_EQUAL(ClientSession::WaitingForCredentials, session->getState()); - session->sendCredentials(createSafeByteArray("mypass")); - server->receiveAuthRequest("PLAIN"); - server->sendAuthSuccess(); - server->receiveStreamStart(); - - session->finish(); - } - - void testAuthenticate_Unauthorized() { - boost::shared_ptr<ClientSession> session(createSession()); - session->start(); - server->receiveStreamStart(); - server->sendStreamStart(); - server->sendStreamFeaturesWithPLAINAuthentication(); - CPPUNIT_ASSERT(needCredentials); - CPPUNIT_ASSERT_EQUAL(ClientSession::WaitingForCredentials, session->getState()); - session->sendCredentials(createSafeByteArray("mypass")); - server->receiveAuthRequest("PLAIN"); - server->sendAuthFailure(); - - CPPUNIT_ASSERT_EQUAL(ClientSession::Finished, session->getState()); - CPPUNIT_ASSERT(sessionFinishedReceived); - CPPUNIT_ASSERT(sessionFinishedError); - } - - void testAuthenticate_PLAINOverNonTLS() { - boost::shared_ptr<ClientSession> session(createSession()); - session->setAllowPLAINOverNonTLS(false); - session->start(); - server->receiveStreamStart(); - server->sendStreamStart(); - server->sendStreamFeaturesWithPLAINAuthentication(); - - CPPUNIT_ASSERT_EQUAL(ClientSession::Finished, session->getState()); - CPPUNIT_ASSERT(sessionFinishedReceived); - CPPUNIT_ASSERT(sessionFinishedError); - } - - void testAuthenticate_RequireTLS() { - boost::shared_ptr<ClientSession> session(createSession()); - session->setUseTLS(ClientSession::RequireTLS); - session->setAllowPLAINOverNonTLS(true); - session->start(); - server->receiveStreamStart(); - server->sendStreamStart(); - server->sendStreamFeaturesWithMultipleAuthentication(); - - CPPUNIT_ASSERT_EQUAL(ClientSession::Finished, session->getState()); - CPPUNIT_ASSERT(sessionFinishedReceived); - CPPUNIT_ASSERT(sessionFinishedError); - } - - void testAuthenticate_NoValidAuthMechanisms() { - boost::shared_ptr<ClientSession> session(createSession()); - session->start(); - server->receiveStreamStart(); - server->sendStreamStart(); - server->sendStreamFeaturesWithUnknownAuthentication(); - - CPPUNIT_ASSERT_EQUAL(ClientSession::Finished, session->getState()); - CPPUNIT_ASSERT(sessionFinishedReceived); - CPPUNIT_ASSERT(sessionFinishedError); - } - - void testAuthenticate_EXTERNAL() { - boost::shared_ptr<ClientSession> session(createSession()); - session->start(); - server->receiveStreamStart(); - server->sendStreamStart(); - server->sendStreamFeaturesWithEXTERNALAuthentication(); - server->receiveAuthRequest("EXTERNAL"); - server->sendAuthSuccess(); - server->receiveStreamStart(); - - session->finish(); - } - - void testUnexpectedChallenge() { - boost::shared_ptr<ClientSession> session(createSession()); - session->start(); - server->receiveStreamStart(); - server->sendStreamStart(); - server->sendStreamFeaturesWithEXTERNALAuthentication(); - server->receiveAuthRequest("EXTERNAL"); - server->sendChallenge(); - server->sendChallenge(); - - CPPUNIT_ASSERT_EQUAL(ClientSession::Finished, session->getState()); - CPPUNIT_ASSERT(sessionFinishedReceived); - CPPUNIT_ASSERT(sessionFinishedError); - } - - void testStreamManagement() { - boost::shared_ptr<ClientSession> session(createSession()); - session->start(); - server->receiveStreamStart(); - server->sendStreamStart(); - server->sendStreamFeaturesWithPLAINAuthentication(); - session->sendCredentials(createSafeByteArray("mypass")); - server->receiveAuthRequest("PLAIN"); - server->sendAuthSuccess(); - server->receiveStreamStart(); - server->sendStreamStart(); - server->sendStreamFeaturesWithBindAndStreamManagement(); - server->receiveBind(); - server->sendBindResult(); - server->receiveStreamManagementEnable(); - server->sendStreamManagementEnabled(); - - CPPUNIT_ASSERT(session->getStreamManagementEnabled()); - // TODO: Test if the requesters & responders do their work - CPPUNIT_ASSERT_EQUAL(ClientSession::Initialized, session->getState()); - - session->finish(); - } - - void testStreamManagement_Failed() { - boost::shared_ptr<ClientSession> session(createSession()); - session->start(); - server->receiveStreamStart(); - server->sendStreamStart(); - server->sendStreamFeaturesWithPLAINAuthentication(); - session->sendCredentials(createSafeByteArray("mypass")); - server->receiveAuthRequest("PLAIN"); - server->sendAuthSuccess(); - server->receiveStreamStart(); - server->sendStreamStart(); - server->sendStreamFeaturesWithBindAndStreamManagement(); - server->receiveBind(); - server->sendBindResult(); - server->receiveStreamManagementEnable(); - server->sendStreamManagementFailed(); - - CPPUNIT_ASSERT(!session->getStreamManagementEnabled()); - CPPUNIT_ASSERT_EQUAL(ClientSession::Initialized, session->getState()); - - session->finish(); - } - - void testFinishAcksStanzas() { - boost::shared_ptr<ClientSession> session(createSession()); - initializeSession(session); - server->sendMessage(); - server->sendMessage(); - server->sendMessage(); - - session->finish(); - - server->receiveAck(3); - } - - private: - boost::shared_ptr<ClientSession> createSession() { - boost::shared_ptr<ClientSession> session = ClientSession::create(JID("me@foo.com"), server, idnConverter.get(), crypto.get()); - session->onFinished.connect(boost::bind(&ClientSessionTest::handleSessionFinished, this, _1)); - session->onNeedCredentials.connect(boost::bind(&ClientSessionTest::handleSessionNeedCredentials, this)); - session->setAllowPLAINOverNonTLS(true); - return session; - } - - void initializeSession(boost::shared_ptr<ClientSession> session) { - session->start(); - server->receiveStreamStart(); - server->sendStreamStart(); - server->sendStreamFeaturesWithPLAINAuthentication(); - session->sendCredentials(createSafeByteArray("mypass")); - server->receiveAuthRequest("PLAIN"); - server->sendAuthSuccess(); - server->receiveStreamStart(); - server->sendStreamStart(); - server->sendStreamFeaturesWithBindAndStreamManagement(); - server->receiveBind(); - server->sendBindResult(); - server->receiveStreamManagementEnable(); - server->sendStreamManagementEnabled(); - } - - void handleSessionFinished(boost::shared_ptr<Error> error) { - sessionFinishedReceived = true; - sessionFinishedError = error; - } - - void handleSessionNeedCredentials() { - needCredentials = true; - } - - class MockSessionStream : public SessionStream { - public: - struct Event { - Event(boost::shared_ptr<ToplevelElement> element) : element(element), footer(false) {} - Event(const ProtocolHeader& header) : header(header), footer(false) {} - Event() : footer(true) {} - - boost::shared_ptr<ToplevelElement> element; - boost::optional<ProtocolHeader> header; - bool footer; - }; - - MockSessionStream() : available(true), canTLSEncrypt(true), tlsEncrypted(false), compressed(false), whitespacePingEnabled(false), resetCount(0) { - } - - virtual void close() { - onClosed(boost::shared_ptr<Error>()); - } - - virtual bool isOpen() { - return available; - } - - virtual void writeHeader(const ProtocolHeader& header) { - receivedEvents.push_back(Event(header)); - } - - virtual void writeFooter() { - receivedEvents.push_back(Event()); - } - - virtual void writeElement(boost::shared_ptr<ToplevelElement> element) { - receivedEvents.push_back(Event(element)); - } - - virtual void writeData(const std::string&) { - } - - virtual bool supportsTLSEncryption() { - return canTLSEncrypt; - } - - virtual void addTLSEncryption() { - tlsEncrypted = true; - } - - virtual bool isTLSEncrypted() { - return tlsEncrypted; - } - - virtual ByteArray getTLSFinishMessage() const { - return ByteArray(); - } - - virtual Certificate::ref getPeerCertificate() const { - return Certificate::ref(new SimpleCertificate()); - } - - virtual std::vector<Certificate::ref> getPeerCertificateChain() const { - return std::vector<Certificate::ref>(); - } - - virtual boost::shared_ptr<CertificateVerificationError> getPeerCertificateVerificationError() const { - return boost::shared_ptr<CertificateVerificationError>(); - } - - virtual bool supportsZLibCompression() { - return true; - } - - virtual void addZLibCompression() { - compressed = true; - } - - virtual void setWhitespacePingEnabled(bool enabled) { - whitespacePingEnabled = enabled; - } - - virtual void resetXMPPParser() { - resetCount++; - } - - void breakConnection() { - onClosed(boost::make_shared<SessionStream::SessionStreamError>(SessionStream::SessionStreamError::ConnectionReadError)); - } - - void breakTLS() { - onClosed(boost::make_shared<SessionStream::SessionStreamError>(SessionStream::SessionStreamError::TLSError)); - } - - - void sendStreamStart() { - ProtocolHeader header; - header.setTo("foo.com"); - return onStreamStartReceived(header); - } - - void sendStreamFeaturesWithStartTLS() { - boost::shared_ptr<StreamFeatures> streamFeatures(new StreamFeatures()); - streamFeatures->setHasStartTLS(); - onElementReceived(streamFeatures); - } - - void sendChallenge() { - onElementReceived(boost::make_shared<AuthChallenge>()); - } - - void sendStreamError() { - onElementReceived(boost::make_shared<StreamError>()); - } - - void sendTLSProceed() { - onElementReceived(boost::make_shared<TLSProceed>()); - } - - void sendTLSFailure() { - onElementReceived(boost::make_shared<StartTLSFailure>()); - } - - void sendStreamFeaturesWithMultipleAuthentication() { - boost::shared_ptr<StreamFeatures> streamFeatures(new StreamFeatures()); - streamFeatures->addAuthenticationMechanism("PLAIN"); - streamFeatures->addAuthenticationMechanism("DIGEST-MD5"); - streamFeatures->addAuthenticationMechanism("SCRAM-SHA1"); - onElementReceived(streamFeatures); - } - - void sendStreamFeaturesWithPLAINAuthentication() { - boost::shared_ptr<StreamFeatures> streamFeatures(new StreamFeatures()); - streamFeatures->addAuthenticationMechanism("PLAIN"); - onElementReceived(streamFeatures); - } - - void sendStreamFeaturesWithEXTERNALAuthentication() { - boost::shared_ptr<StreamFeatures> streamFeatures(new StreamFeatures()); - streamFeatures->addAuthenticationMechanism("EXTERNAL"); - onElementReceived(streamFeatures); - } - - void sendStreamFeaturesWithUnknownAuthentication() { - boost::shared_ptr<StreamFeatures> streamFeatures(new StreamFeatures()); - streamFeatures->addAuthenticationMechanism("UNKNOWN"); - onElementReceived(streamFeatures); - } - - void sendStreamFeaturesWithBindAndStreamManagement() { - boost::shared_ptr<StreamFeatures> streamFeatures(new StreamFeatures()); - streamFeatures->setHasResourceBind(); - streamFeatures->setHasStreamManagement(); - onElementReceived(streamFeatures); - } - - void sendEmptyStreamFeatures() { - onElementReceived(boost::make_shared<StreamFeatures>()); - } - - void sendAuthSuccess() { - onElementReceived(boost::make_shared<AuthSuccess>()); - } - - void sendAuthFailure() { - onElementReceived(boost::make_shared<AuthFailure>()); - } - - void sendStreamManagementEnabled() { - onElementReceived(boost::make_shared<StreamManagementEnabled>()); - } - - void sendStreamManagementFailed() { - onElementReceived(boost::make_shared<StreamManagementFailed>()); - } - - void sendBindResult() { - boost::shared_ptr<ResourceBind> resourceBind(new ResourceBind()); - resourceBind->setJID(JID("foo@bar.com/bla")); - boost::shared_ptr<IQ> iq = IQ::createResult(JID("foo@bar.com"), bindID, resourceBind); - onElementReceived(iq); - } - - void sendMessage() { - boost::shared_ptr<Message> message = boost::make_shared<Message>(); - message->setTo(JID("foo@bar.com/bla")); - onElementReceived(message); - } - - void receiveStreamStart() { - Event event = popEvent(); - CPPUNIT_ASSERT(event.header); - } - - void receiveStartTLS() { - Event event = popEvent(); - CPPUNIT_ASSERT(event.element); - CPPUNIT_ASSERT(boost::dynamic_pointer_cast<StartTLSRequest>(event.element)); - } - - void receiveAuthRequest(const std::string& mech) { - Event event = popEvent(); - CPPUNIT_ASSERT(event.element); - boost::shared_ptr<AuthRequest> request(boost::dynamic_pointer_cast<AuthRequest>(event.element)); - CPPUNIT_ASSERT(request); - CPPUNIT_ASSERT_EQUAL(mech, request->getMechanism()); - } - - void receiveStreamManagementEnable() { - Event event = popEvent(); - CPPUNIT_ASSERT(event.element); - CPPUNIT_ASSERT(boost::dynamic_pointer_cast<EnableStreamManagement>(event.element)); - } - - void receiveBind() { - Event event = popEvent(); - CPPUNIT_ASSERT(event.element); - boost::shared_ptr<IQ> iq = boost::dynamic_pointer_cast<IQ>(event.element); - CPPUNIT_ASSERT(iq); - CPPUNIT_ASSERT(iq->getPayload<ResourceBind>()); - bindID = iq->getID(); - } - - void receiveAck(unsigned int n) { - Event event = popEvent(); - CPPUNIT_ASSERT(event.element); - boost::shared_ptr<StanzaAck> ack = boost::dynamic_pointer_cast<StanzaAck>(event.element); - CPPUNIT_ASSERT(ack); - CPPUNIT_ASSERT_EQUAL(n, ack->getHandledStanzasCount()); - } - - Event popEvent() { - CPPUNIT_ASSERT(!receivedEvents.empty()); - Event event = receivedEvents.front(); - receivedEvents.pop_front(); - return event; - } - - bool available; - bool canTLSEncrypt; - bool tlsEncrypted; - bool compressed; - bool whitespacePingEnabled; - std::string bindID; - int resetCount; - std::deque<Event> receivedEvents; - }; - - boost::shared_ptr<IDNConverter> idnConverter; - boost::shared_ptr<MockSessionStream> server; - bool sessionFinishedReceived; - bool needCredentials; - boost::shared_ptr<Error> sessionFinishedError; - BlindCertificateTrustChecker* blindCertificateTrustChecker; - boost::shared_ptr<CryptoProvider> crypto; + CPPUNIT_TEST_SUITE(ClientSessionTest); + CPPUNIT_TEST(testStart_Error); + CPPUNIT_TEST(testStart_StreamError); + CPPUNIT_TEST(testStartTLS); + CPPUNIT_TEST(testStartTLS_ServerError); + CPPUNIT_TEST(testStartTLS_ConnectError); + CPPUNIT_TEST(testStartTLS_InvalidIdentity); + CPPUNIT_TEST(testStart_StreamFeaturesWithoutResourceBindingFails); + CPPUNIT_TEST(testAuthenticate); + CPPUNIT_TEST(testAuthenticate_Unauthorized); + CPPUNIT_TEST(testAuthenticate_NoValidAuthMechanisms); + CPPUNIT_TEST(testAuthenticate_PLAINOverNonTLS); + CPPUNIT_TEST(testAuthenticate_RequireTLS); + CPPUNIT_TEST(testAuthenticate_EXTERNAL); + CPPUNIT_TEST(testStreamManagement); + CPPUNIT_TEST(testStreamManagement_Failed); + CPPUNIT_TEST(testUnexpectedChallenge); + CPPUNIT_TEST(testFinishAcksStanzas); + /* + CPPUNIT_TEST(testResourceBind); + CPPUNIT_TEST(testResourceBind_ChangeResource); + CPPUNIT_TEST(testResourceBind_EmptyResource); + CPPUNIT_TEST(testResourceBind_Error); + CPPUNIT_TEST(testSessionStart); + CPPUNIT_TEST(testSessionStart_Error); + CPPUNIT_TEST(testSessionStart_AfterResourceBind); + CPPUNIT_TEST(testWhitespacePing); + CPPUNIT_TEST(testReceiveElementAfterSessionStarted); + CPPUNIT_TEST(testSendElement); + */ + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); + idnConverter = boost::shared_ptr<IDNConverter>(PlatformIDNConverter::create()); + server = boost::make_shared<MockSessionStream>(); + sessionFinishedReceived = false; + needCredentials = false; + blindCertificateTrustChecker = new BlindCertificateTrustChecker(); + } + + void tearDown() { + delete blindCertificateTrustChecker; + } + + void testStart_Error() { + boost::shared_ptr<ClientSession> session(createSession()); + session->start(); + server->breakConnection(); + + CPPUNIT_ASSERT_EQUAL(ClientSession::Finished, session->getState()); + CPPUNIT_ASSERT(sessionFinishedReceived); + CPPUNIT_ASSERT(sessionFinishedError); + } + + void testStart_StreamError() { + boost::shared_ptr<ClientSession> session(createSession()); + session->start(); + server->sendStreamStart(); + server->sendStreamError(); + + CPPUNIT_ASSERT_EQUAL(ClientSession::Finished, session->getState()); + CPPUNIT_ASSERT(sessionFinishedReceived); + CPPUNIT_ASSERT(sessionFinishedError); + } + + void testStartTLS() { + boost::shared_ptr<ClientSession> session(createSession()); + session->setCertificateTrustChecker(blindCertificateTrustChecker); + session->start(); + server->receiveStreamStart(); + server->sendStreamStart(); + server->sendStreamFeaturesWithStartTLS(); + server->receiveStartTLS(); + CPPUNIT_ASSERT(!server->tlsEncrypted); + server->sendTLSProceed(); + CPPUNIT_ASSERT(server->tlsEncrypted); + server->onTLSEncrypted(); + server->receiveStreamStart(); + server->sendStreamStart(); + + session->finish(); + } + + void testStartTLS_ServerError() { + boost::shared_ptr<ClientSession> session(createSession()); + session->start(); + server->receiveStreamStart(); + server->sendStreamStart(); + server->sendStreamFeaturesWithStartTLS(); + server->receiveStartTLS(); + server->sendTLSFailure(); + + CPPUNIT_ASSERT(!server->tlsEncrypted); + CPPUNIT_ASSERT_EQUAL(ClientSession::Finished, session->getState()); + CPPUNIT_ASSERT(sessionFinishedReceived); + CPPUNIT_ASSERT(sessionFinishedError); + } + + void testStartTLS_ConnectError() { + boost::shared_ptr<ClientSession> session(createSession()); + session->start(); + server->receiveStreamStart(); + server->sendStreamStart(); + server->sendStreamFeaturesWithStartTLS(); + server->receiveStartTLS(); + server->sendTLSProceed(); + server->breakTLS(); + + CPPUNIT_ASSERT_EQUAL(ClientSession::Finished, session->getState()); + CPPUNIT_ASSERT(sessionFinishedReceived); + CPPUNIT_ASSERT(sessionFinishedError); + } + + void testStartTLS_InvalidIdentity() { + boost::shared_ptr<ClientSession> session(createSession()); + session->start(); + server->receiveStreamStart(); + server->sendStreamStart(); + server->sendStreamFeaturesWithStartTLS(); + server->receiveStartTLS(); + CPPUNIT_ASSERT(!server->tlsEncrypted); + server->sendTLSProceed(); + CPPUNIT_ASSERT(server->tlsEncrypted); + server->onTLSEncrypted(); + + CPPUNIT_ASSERT_EQUAL(ClientSession::Finished, session->getState()); + CPPUNIT_ASSERT(sessionFinishedReceived); + CPPUNIT_ASSERT(sessionFinishedError); + CPPUNIT_ASSERT_EQUAL(CertificateVerificationError::InvalidServerIdentity, boost::dynamic_pointer_cast<CertificateVerificationError>(sessionFinishedError)->getType()); + } + + void testStart_StreamFeaturesWithoutResourceBindingFails() { + boost::shared_ptr<ClientSession> session(createSession()); + session->start(); + server->receiveStreamStart(); + server->sendStreamStart(); + server->sendEmptyStreamFeatures(); + + CPPUNIT_ASSERT_EQUAL(ClientSession::Finished, session->getState()); + CPPUNIT_ASSERT(sessionFinishedReceived); + CPPUNIT_ASSERT(sessionFinishedError); + } + + void testAuthenticate() { + boost::shared_ptr<ClientSession> session(createSession()); + session->start(); + server->receiveStreamStart(); + server->sendStreamStart(); + server->sendStreamFeaturesWithPLAINAuthentication(); + CPPUNIT_ASSERT(needCredentials); + CPPUNIT_ASSERT_EQUAL(ClientSession::WaitingForCredentials, session->getState()); + session->sendCredentials(createSafeByteArray("mypass")); + server->receiveAuthRequest("PLAIN"); + server->sendAuthSuccess(); + server->receiveStreamStart(); + + session->finish(); + } + + void testAuthenticate_Unauthorized() { + boost::shared_ptr<ClientSession> session(createSession()); + session->start(); + server->receiveStreamStart(); + server->sendStreamStart(); + server->sendStreamFeaturesWithPLAINAuthentication(); + CPPUNIT_ASSERT(needCredentials); + CPPUNIT_ASSERT_EQUAL(ClientSession::WaitingForCredentials, session->getState()); + session->sendCredentials(createSafeByteArray("mypass")); + server->receiveAuthRequest("PLAIN"); + server->sendAuthFailure(); + + CPPUNIT_ASSERT_EQUAL(ClientSession::Finished, session->getState()); + CPPUNIT_ASSERT(sessionFinishedReceived); + CPPUNIT_ASSERT(sessionFinishedError); + } + + void testAuthenticate_PLAINOverNonTLS() { + boost::shared_ptr<ClientSession> session(createSession()); + session->setAllowPLAINOverNonTLS(false); + session->start(); + server->receiveStreamStart(); + server->sendStreamStart(); + server->sendStreamFeaturesWithPLAINAuthentication(); + + CPPUNIT_ASSERT_EQUAL(ClientSession::Finished, session->getState()); + CPPUNIT_ASSERT(sessionFinishedReceived); + CPPUNIT_ASSERT(sessionFinishedError); + } + + void testAuthenticate_RequireTLS() { + boost::shared_ptr<ClientSession> session(createSession()); + session->setUseTLS(ClientSession::RequireTLS); + session->setAllowPLAINOverNonTLS(true); + session->start(); + server->receiveStreamStart(); + server->sendStreamStart(); + server->sendStreamFeaturesWithMultipleAuthentication(); + + CPPUNIT_ASSERT_EQUAL(ClientSession::Finished, session->getState()); + CPPUNIT_ASSERT(sessionFinishedReceived); + CPPUNIT_ASSERT(sessionFinishedError); + } + + void testAuthenticate_NoValidAuthMechanisms() { + boost::shared_ptr<ClientSession> session(createSession()); + session->start(); + server->receiveStreamStart(); + server->sendStreamStart(); + server->sendStreamFeaturesWithUnknownAuthentication(); + + CPPUNIT_ASSERT_EQUAL(ClientSession::Finished, session->getState()); + CPPUNIT_ASSERT(sessionFinishedReceived); + CPPUNIT_ASSERT(sessionFinishedError); + } + + void testAuthenticate_EXTERNAL() { + boost::shared_ptr<ClientSession> session(createSession()); + session->start(); + server->receiveStreamStart(); + server->sendStreamStart(); + server->sendStreamFeaturesWithEXTERNALAuthentication(); + server->receiveAuthRequest("EXTERNAL"); + server->sendAuthSuccess(); + server->receiveStreamStart(); + + session->finish(); + } + + void testUnexpectedChallenge() { + boost::shared_ptr<ClientSession> session(createSession()); + session->start(); + server->receiveStreamStart(); + server->sendStreamStart(); + server->sendStreamFeaturesWithEXTERNALAuthentication(); + server->receiveAuthRequest("EXTERNAL"); + server->sendChallenge(); + server->sendChallenge(); + + CPPUNIT_ASSERT_EQUAL(ClientSession::Finished, session->getState()); + CPPUNIT_ASSERT(sessionFinishedReceived); + CPPUNIT_ASSERT(sessionFinishedError); + } + + void testStreamManagement() { + boost::shared_ptr<ClientSession> session(createSession()); + session->start(); + server->receiveStreamStart(); + server->sendStreamStart(); + server->sendStreamFeaturesWithPLAINAuthentication(); + session->sendCredentials(createSafeByteArray("mypass")); + server->receiveAuthRequest("PLAIN"); + server->sendAuthSuccess(); + server->receiveStreamStart(); + server->sendStreamStart(); + server->sendStreamFeaturesWithBindAndStreamManagement(); + server->receiveBind(); + server->sendBindResult(); + server->receiveStreamManagementEnable(); + server->sendStreamManagementEnabled(); + + CPPUNIT_ASSERT(session->getStreamManagementEnabled()); + // TODO: Test if the requesters & responders do their work + CPPUNIT_ASSERT_EQUAL(ClientSession::Initialized, session->getState()); + + session->finish(); + } + + void testStreamManagement_Failed() { + boost::shared_ptr<ClientSession> session(createSession()); + session->start(); + server->receiveStreamStart(); + server->sendStreamStart(); + server->sendStreamFeaturesWithPLAINAuthentication(); + session->sendCredentials(createSafeByteArray("mypass")); + server->receiveAuthRequest("PLAIN"); + server->sendAuthSuccess(); + server->receiveStreamStart(); + server->sendStreamStart(); + server->sendStreamFeaturesWithBindAndStreamManagement(); + server->receiveBind(); + server->sendBindResult(); + server->receiveStreamManagementEnable(); + server->sendStreamManagementFailed(); + + CPPUNIT_ASSERT(!session->getStreamManagementEnabled()); + CPPUNIT_ASSERT_EQUAL(ClientSession::Initialized, session->getState()); + + session->finish(); + } + + void testFinishAcksStanzas() { + boost::shared_ptr<ClientSession> session(createSession()); + initializeSession(session); + server->sendMessage(); + server->sendMessage(); + server->sendMessage(); + + session->finish(); + + server->receiveAck(3); + } + + private: + boost::shared_ptr<ClientSession> createSession() { + boost::shared_ptr<ClientSession> session = ClientSession::create(JID("me@foo.com"), server, idnConverter.get(), crypto.get()); + session->onFinished.connect(boost::bind(&ClientSessionTest::handleSessionFinished, this, _1)); + session->onNeedCredentials.connect(boost::bind(&ClientSessionTest::handleSessionNeedCredentials, this)); + session->setAllowPLAINOverNonTLS(true); + return session; + } + + void initializeSession(boost::shared_ptr<ClientSession> session) { + session->start(); + server->receiveStreamStart(); + server->sendStreamStart(); + server->sendStreamFeaturesWithPLAINAuthentication(); + session->sendCredentials(createSafeByteArray("mypass")); + server->receiveAuthRequest("PLAIN"); + server->sendAuthSuccess(); + server->receiveStreamStart(); + server->sendStreamStart(); + server->sendStreamFeaturesWithBindAndStreamManagement(); + server->receiveBind(); + server->sendBindResult(); + server->receiveStreamManagementEnable(); + server->sendStreamManagementEnabled(); + } + + void handleSessionFinished(boost::shared_ptr<Error> error) { + sessionFinishedReceived = true; + sessionFinishedError = error; + } + + void handleSessionNeedCredentials() { + needCredentials = true; + } + + class MockSessionStream : public SessionStream { + public: + struct Event { + Event(boost::shared_ptr<ToplevelElement> element) : element(element), footer(false) {} + Event(const ProtocolHeader& header) : header(header), footer(false) {} + Event() : footer(true) {} + + boost::shared_ptr<ToplevelElement> element; + boost::optional<ProtocolHeader> header; + bool footer; + }; + + MockSessionStream() : available(true), canTLSEncrypt(true), tlsEncrypted(false), compressed(false), whitespacePingEnabled(false), resetCount(0) { + } + + virtual void close() { + onClosed(boost::shared_ptr<Error>()); + } + + virtual bool isOpen() { + return available; + } + + virtual void writeHeader(const ProtocolHeader& header) { + receivedEvents.push_back(Event(header)); + } + + virtual void writeFooter() { + receivedEvents.push_back(Event()); + } + + virtual void writeElement(boost::shared_ptr<ToplevelElement> element) { + receivedEvents.push_back(Event(element)); + } + + virtual void writeData(const std::string&) { + } + + virtual bool supportsTLSEncryption() { + return canTLSEncrypt; + } + + virtual void addTLSEncryption() { + tlsEncrypted = true; + } + + virtual bool isTLSEncrypted() { + return tlsEncrypted; + } + + virtual ByteArray getTLSFinishMessage() const { + return ByteArray(); + } + + virtual Certificate::ref getPeerCertificate() const { + return Certificate::ref(new SimpleCertificate()); + } + + virtual std::vector<Certificate::ref> getPeerCertificateChain() const { + return std::vector<Certificate::ref>(); + } + + virtual boost::shared_ptr<CertificateVerificationError> getPeerCertificateVerificationError() const { + return boost::shared_ptr<CertificateVerificationError>(); + } + + virtual bool supportsZLibCompression() { + return true; + } + + virtual void addZLibCompression() { + compressed = true; + } + + virtual void setWhitespacePingEnabled(bool enabled) { + whitespacePingEnabled = enabled; + } + + virtual void resetXMPPParser() { + resetCount++; + } + + void breakConnection() { + onClosed(boost::make_shared<SessionStream::SessionStreamError>(SessionStream::SessionStreamError::ConnectionReadError)); + } + + void breakTLS() { + onClosed(boost::make_shared<SessionStream::SessionStreamError>(SessionStream::SessionStreamError::TLSError)); + } + + + void sendStreamStart() { + ProtocolHeader header; + header.setTo("foo.com"); + return onStreamStartReceived(header); + } + + void sendStreamFeaturesWithStartTLS() { + boost::shared_ptr<StreamFeatures> streamFeatures(new StreamFeatures()); + streamFeatures->setHasStartTLS(); + onElementReceived(streamFeatures); + } + + void sendChallenge() { + onElementReceived(boost::make_shared<AuthChallenge>()); + } + + void sendStreamError() { + onElementReceived(boost::make_shared<StreamError>()); + } + + void sendTLSProceed() { + onElementReceived(boost::make_shared<TLSProceed>()); + } + + void sendTLSFailure() { + onElementReceived(boost::make_shared<StartTLSFailure>()); + } + + void sendStreamFeaturesWithMultipleAuthentication() { + boost::shared_ptr<StreamFeatures> streamFeatures(new StreamFeatures()); + streamFeatures->addAuthenticationMechanism("PLAIN"); + streamFeatures->addAuthenticationMechanism("DIGEST-MD5"); + streamFeatures->addAuthenticationMechanism("SCRAM-SHA1"); + onElementReceived(streamFeatures); + } + + void sendStreamFeaturesWithPLAINAuthentication() { + boost::shared_ptr<StreamFeatures> streamFeatures(new StreamFeatures()); + streamFeatures->addAuthenticationMechanism("PLAIN"); + onElementReceived(streamFeatures); + } + + void sendStreamFeaturesWithEXTERNALAuthentication() { + boost::shared_ptr<StreamFeatures> streamFeatures(new StreamFeatures()); + streamFeatures->addAuthenticationMechanism("EXTERNAL"); + onElementReceived(streamFeatures); + } + + void sendStreamFeaturesWithUnknownAuthentication() { + boost::shared_ptr<StreamFeatures> streamFeatures(new StreamFeatures()); + streamFeatures->addAuthenticationMechanism("UNKNOWN"); + onElementReceived(streamFeatures); + } + + void sendStreamFeaturesWithBindAndStreamManagement() { + boost::shared_ptr<StreamFeatures> streamFeatures(new StreamFeatures()); + streamFeatures->setHasResourceBind(); + streamFeatures->setHasStreamManagement(); + onElementReceived(streamFeatures); + } + + void sendEmptyStreamFeatures() { + onElementReceived(boost::make_shared<StreamFeatures>()); + } + + void sendAuthSuccess() { + onElementReceived(boost::make_shared<AuthSuccess>()); + } + + void sendAuthFailure() { + onElementReceived(boost::make_shared<AuthFailure>()); + } + + void sendStreamManagementEnabled() { + onElementReceived(boost::make_shared<StreamManagementEnabled>()); + } + + void sendStreamManagementFailed() { + onElementReceived(boost::make_shared<StreamManagementFailed>()); + } + + void sendBindResult() { + boost::shared_ptr<ResourceBind> resourceBind(new ResourceBind()); + resourceBind->setJID(JID("foo@bar.com/bla")); + boost::shared_ptr<IQ> iq = IQ::createResult(JID("foo@bar.com"), bindID, resourceBind); + onElementReceived(iq); + } + + void sendMessage() { + boost::shared_ptr<Message> message = boost::make_shared<Message>(); + message->setTo(JID("foo@bar.com/bla")); + onElementReceived(message); + } + + void receiveStreamStart() { + Event event = popEvent(); + CPPUNIT_ASSERT(event.header); + } + + void receiveStartTLS() { + Event event = popEvent(); + CPPUNIT_ASSERT(event.element); + CPPUNIT_ASSERT(boost::dynamic_pointer_cast<StartTLSRequest>(event.element)); + } + + void receiveAuthRequest(const std::string& mech) { + Event event = popEvent(); + CPPUNIT_ASSERT(event.element); + boost::shared_ptr<AuthRequest> request(boost::dynamic_pointer_cast<AuthRequest>(event.element)); + CPPUNIT_ASSERT(request); + CPPUNIT_ASSERT_EQUAL(mech, request->getMechanism()); + } + + void receiveStreamManagementEnable() { + Event event = popEvent(); + CPPUNIT_ASSERT(event.element); + CPPUNIT_ASSERT(boost::dynamic_pointer_cast<EnableStreamManagement>(event.element)); + } + + void receiveBind() { + Event event = popEvent(); + CPPUNIT_ASSERT(event.element); + boost::shared_ptr<IQ> iq = boost::dynamic_pointer_cast<IQ>(event.element); + CPPUNIT_ASSERT(iq); + CPPUNIT_ASSERT(iq->getPayload<ResourceBind>()); + bindID = iq->getID(); + } + + void receiveAck(unsigned int n) { + Event event = popEvent(); + CPPUNIT_ASSERT(event.element); + boost::shared_ptr<StanzaAck> ack = boost::dynamic_pointer_cast<StanzaAck>(event.element); + CPPUNIT_ASSERT(ack); + CPPUNIT_ASSERT_EQUAL(n, ack->getHandledStanzasCount()); + } + + Event popEvent() { + CPPUNIT_ASSERT(!receivedEvents.empty()); + Event event = receivedEvents.front(); + receivedEvents.pop_front(); + return event; + } + + bool available; + bool canTLSEncrypt; + bool tlsEncrypted; + bool compressed; + bool whitespacePingEnabled; + std::string bindID; + int resetCount; + std::deque<Event> receivedEvents; + }; + + boost::shared_ptr<IDNConverter> idnConverter; + boost::shared_ptr<MockSessionStream> server; + bool sessionFinishedReceived; + bool needCredentials; + boost::shared_ptr<Error> sessionFinishedError; + BlindCertificateTrustChecker* blindCertificateTrustChecker; + boost::shared_ptr<CryptoProvider> crypto; }; CPPUNIT_TEST_SUITE_REGISTRATION(ClientSessionTest); #if 0 - void testAuthenticate() { - boost::shared_ptr<MockSession> session(createSession("me@foo.com/Bar")); - session->onNeedCredentials.connect(boost::bind(&ClientSessionTest::setNeedCredentials, this)); - getMockServer()->expectStreamStart(); - getMockServer()->sendStreamStart(); - getMockServer()->sendStreamFeaturesWithAuthentication(); - session->startSession(); - processEvents(); - CPPUNIT_ASSERT_EQUAL(ClientSession::WaitingForCredentials, session->getState()); - CPPUNIT_ASSERT(needCredentials_); - - getMockServer()->expectAuth("me", "mypass"); - getMockServer()->sendAuthSuccess(); - getMockServer()->expectStreamStart(); - getMockServer()->sendStreamStart(); - session->sendCredentials("mypass"); - CPPUNIT_ASSERT_EQUAL(ClientSession::Authenticating, session->getState()); - processEvents(); - CPPUNIT_ASSERT_EQUAL(ClientSession::Negotiating, session->getState()); - } - - void testAuthenticate_Unauthorized() { - boost::shared_ptr<MockSession> session(createSession("me@foo.com/Bar")); - getMockServer()->expectStreamStart(); - getMockServer()->sendStreamStart(); - getMockServer()->sendStreamFeaturesWithAuthentication(); - session->startSession(); - processEvents(); - - getMockServer()->expectAuth("me", "mypass"); - getMockServer()->sendAuthFailure(); - session->sendCredentials("mypass"); - processEvents(); - - CPPUNIT_ASSERT_EQUAL(ClientSession::Error, session->getState()); - CPPUNIT_ASSERT_EQUAL(ClientSession::AuthenticationFailedError, *session->getError()); - } - - void testAuthenticate_NoValidAuthMechanisms() { - boost::shared_ptr<MockSession> session(createSession("me@foo.com/Bar")); - getMockServer()->expectStreamStart(); - getMockServer()->sendStreamStart(); - getMockServer()->sendStreamFeaturesWithUnsupportedAuthentication(); - session->startSession(); - processEvents(); - - CPPUNIT_ASSERT_EQUAL(ClientSession::Error, session->getState()); - CPPUNIT_ASSERT_EQUAL(ClientSession::NoSupportedAuthMechanismsError, *session->getError()); - } - - void testResourceBind() { - boost::shared_ptr<MockSession> session(createSession("me@foo.com/Bar")); - getMockServer()->expectStreamStart(); - getMockServer()->sendStreamStart(); - getMockServer()->sendStreamFeaturesWithResourceBind(); - getMockServer()->expectResourceBind("Bar", "session-bind"); - // FIXME: Check CPPUNIT_ASSERT_EQUAL(ClientSession::BindingResource, session->getState()); - getMockServer()->sendResourceBindResponse("me@foo.com/Bar", "session-bind"); - session->startSession(); - - processEvents(); - - CPPUNIT_ASSERT_EQUAL(ClientSession::SessionStarted, session->getState()); - CPPUNIT_ASSERT_EQUAL(JID("me@foo.com/Bar"), session->getLocalJID()); - } - - void testResourceBind_ChangeResource() { - boost::shared_ptr<MockSession> session(createSession("me@foo.com/Bar")); - getMockServer()->expectStreamStart(); - getMockServer()->sendStreamStart(); - getMockServer()->sendStreamFeaturesWithResourceBind(); - getMockServer()->expectResourceBind("Bar", "session-bind"); - getMockServer()->sendResourceBindResponse("me@foo.com/Bar123", "session-bind"); - session->startSession(); - processEvents(); - - CPPUNIT_ASSERT_EQUAL(ClientSession::SessionStarted, session->getState()); - CPPUNIT_ASSERT_EQUAL(JID("me@foo.com/Bar123"), session->getLocalJID()); - } - - void testResourceBind_EmptyResource() { - boost::shared_ptr<MockSession> session(createSession("me@foo.com")); - getMockServer()->expectStreamStart(); - getMockServer()->sendStreamStart(); - getMockServer()->sendStreamFeaturesWithResourceBind(); - getMockServer()->expectResourceBind("", "session-bind"); - getMockServer()->sendResourceBindResponse("me@foo.com/NewResource", "session-bind"); - session->startSession(); - processEvents(); - - CPPUNIT_ASSERT_EQUAL(ClientSession::SessionStarted, session->getState()); - CPPUNIT_ASSERT_EQUAL(JID("me@foo.com/NewResource"), session->getLocalJID()); - } - - void testResourceBind_Error() { - boost::shared_ptr<MockSession> session(createSession("me@foo.com")); - getMockServer()->expectStreamStart(); - getMockServer()->sendStreamStart(); - getMockServer()->sendStreamFeaturesWithResourceBind(); - getMockServer()->expectResourceBind("", "session-bind"); - getMockServer()->sendError("session-bind"); - session->startSession(); - processEvents(); - - CPPUNIT_ASSERT_EQUAL(ClientSession::Error, session->getState()); - CPPUNIT_ASSERT_EQUAL(ClientSession::ResourceBindError, *session->getError()); - } - - void testSessionStart() { - boost::shared_ptr<MockSession> session(createSession("me@foo.com/Bar")); - session->onSessionStarted.connect(boost::bind(&ClientSessionTest::setSessionStarted, this)); - getMockServer()->expectStreamStart(); - getMockServer()->sendStreamStart(); - getMockServer()->sendStreamFeaturesWithSession(); - getMockServer()->expectSessionStart("session-start"); - // FIXME: Check CPPUNIT_ASSERT_EQUAL(ClientSession::StartingSession, session->getState()); - getMockServer()->sendSessionStartResponse("session-start"); - session->startSession(); - processEvents(); - - CPPUNIT_ASSERT_EQUAL(ClientSession::SessionStarted, session->getState()); - CPPUNIT_ASSERT(sessionStarted_); - } - - void testSessionStart_Error() { - boost::shared_ptr<MockSession> session(createSession("me@foo.com/Bar")); - getMockServer()->expectStreamStart(); - getMockServer()->sendStreamStart(); - getMockServer()->sendStreamFeaturesWithSession(); - getMockServer()->expectSessionStart("session-start"); - getMockServer()->sendError("session-start"); - session->startSession(); - processEvents(); - - CPPUNIT_ASSERT_EQUAL(ClientSession::Error, session->getState()); - CPPUNIT_ASSERT_EQUAL(ClientSession::SessionStartError, *session->getError()); - } - - void testSessionStart_AfterResourceBind() { - boost::shared_ptr<MockSession> session(createSession("me@foo.com/Bar")); - session->onSessionStarted.connect(boost::bind(&ClientSessionTest::setSessionStarted, this)); - getMockServer()->expectStreamStart(); - getMockServer()->sendStreamStart(); - getMockServer()->sendStreamFeaturesWithResourceBindAndSession(); - getMockServer()->expectResourceBind("Bar", "session-bind"); - getMockServer()->sendResourceBindResponse("me@foo.com/Bar", "session-bind"); - getMockServer()->expectSessionStart("session-start"); - getMockServer()->sendSessionStartResponse("session-start"); - session->startSession(); - processEvents(); - - CPPUNIT_ASSERT_EQUAL(ClientSession::SessionStarted, session->getState()); - CPPUNIT_ASSERT(sessionStarted_); - } - - void testWhitespacePing() { - boost::shared_ptr<MockSession> session(createSession("me@foo.com/Bar")); - getMockServer()->expectStreamStart(); - getMockServer()->sendStreamStart(); - getMockServer()->sendStreamFeatures(); - session->startSession(); - processEvents(); - CPPUNIT_ASSERT(session->getWhitespacePingLayer()); - } - - void testReceiveElementAfterSessionStarted() { - boost::shared_ptr<MockSession> session(createSession("me@foo.com/Bar")); - getMockServer()->expectStreamStart(); - getMockServer()->sendStreamStart(); - getMockServer()->sendStreamFeatures(); - session->startSession(); - processEvents(); - - getMockServer()->expectMessage(); - session->sendElement(boost::make_shared<Message>())); - } - - void testSendElement() { - boost::shared_ptr<MockSession> session(createSession("me@foo.com/Bar")); - session->onElementReceived.connect(boost::bind(&ClientSessionTest::addReceivedElement, this, _1)); - getMockServer()->expectStreamStart(); - getMockServer()->sendStreamStart(); - getMockServer()->sendStreamFeatures(); - getMockServer()->sendMessage(); - session->startSession(); - processEvents(); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(receivedElements_.size())); - CPPUNIT_ASSERT(boost::dynamic_pointer_cast<Message>(receivedElements_[0])); - } + void testAuthenticate() { + boost::shared_ptr<MockSession> session(createSession("me@foo.com/Bar")); + session->onNeedCredentials.connect(boost::bind(&ClientSessionTest::setNeedCredentials, this)); + getMockServer()->expectStreamStart(); + getMockServer()->sendStreamStart(); + getMockServer()->sendStreamFeaturesWithAuthentication(); + session->startSession(); + processEvents(); + CPPUNIT_ASSERT_EQUAL(ClientSession::WaitingForCredentials, session->getState()); + CPPUNIT_ASSERT(needCredentials_); + + getMockServer()->expectAuth("me", "mypass"); + getMockServer()->sendAuthSuccess(); + getMockServer()->expectStreamStart(); + getMockServer()->sendStreamStart(); + session->sendCredentials("mypass"); + CPPUNIT_ASSERT_EQUAL(ClientSession::Authenticating, session->getState()); + processEvents(); + CPPUNIT_ASSERT_EQUAL(ClientSession::Negotiating, session->getState()); + } + + void testAuthenticate_Unauthorized() { + boost::shared_ptr<MockSession> session(createSession("me@foo.com/Bar")); + getMockServer()->expectStreamStart(); + getMockServer()->sendStreamStart(); + getMockServer()->sendStreamFeaturesWithAuthentication(); + session->startSession(); + processEvents(); + + getMockServer()->expectAuth("me", "mypass"); + getMockServer()->sendAuthFailure(); + session->sendCredentials("mypass"); + processEvents(); + + CPPUNIT_ASSERT_EQUAL(ClientSession::Error, session->getState()); + CPPUNIT_ASSERT_EQUAL(ClientSession::AuthenticationFailedError, *session->getError()); + } + + void testAuthenticate_NoValidAuthMechanisms() { + boost::shared_ptr<MockSession> session(createSession("me@foo.com/Bar")); + getMockServer()->expectStreamStart(); + getMockServer()->sendStreamStart(); + getMockServer()->sendStreamFeaturesWithUnsupportedAuthentication(); + session->startSession(); + processEvents(); + + CPPUNIT_ASSERT_EQUAL(ClientSession::Error, session->getState()); + CPPUNIT_ASSERT_EQUAL(ClientSession::NoSupportedAuthMechanismsError, *session->getError()); + } + + void testResourceBind() { + boost::shared_ptr<MockSession> session(createSession("me@foo.com/Bar")); + getMockServer()->expectStreamStart(); + getMockServer()->sendStreamStart(); + getMockServer()->sendStreamFeaturesWithResourceBind(); + getMockServer()->expectResourceBind("Bar", "session-bind"); + // FIXME: Check CPPUNIT_ASSERT_EQUAL(ClientSession::BindingResource, session->getState()); + getMockServer()->sendResourceBindResponse("me@foo.com/Bar", "session-bind"); + session->startSession(); + + processEvents(); + + CPPUNIT_ASSERT_EQUAL(ClientSession::SessionStarted, session->getState()); + CPPUNIT_ASSERT_EQUAL(JID("me@foo.com/Bar"), session->getLocalJID()); + } + + void testResourceBind_ChangeResource() { + boost::shared_ptr<MockSession> session(createSession("me@foo.com/Bar")); + getMockServer()->expectStreamStart(); + getMockServer()->sendStreamStart(); + getMockServer()->sendStreamFeaturesWithResourceBind(); + getMockServer()->expectResourceBind("Bar", "session-bind"); + getMockServer()->sendResourceBindResponse("me@foo.com/Bar123", "session-bind"); + session->startSession(); + processEvents(); + + CPPUNIT_ASSERT_EQUAL(ClientSession::SessionStarted, session->getState()); + CPPUNIT_ASSERT_EQUAL(JID("me@foo.com/Bar123"), session->getLocalJID()); + } + + void testResourceBind_EmptyResource() { + boost::shared_ptr<MockSession> session(createSession("me@foo.com")); + getMockServer()->expectStreamStart(); + getMockServer()->sendStreamStart(); + getMockServer()->sendStreamFeaturesWithResourceBind(); + getMockServer()->expectResourceBind("", "session-bind"); + getMockServer()->sendResourceBindResponse("me@foo.com/NewResource", "session-bind"); + session->startSession(); + processEvents(); + + CPPUNIT_ASSERT_EQUAL(ClientSession::SessionStarted, session->getState()); + CPPUNIT_ASSERT_EQUAL(JID("me@foo.com/NewResource"), session->getLocalJID()); + } + + void testResourceBind_Error() { + boost::shared_ptr<MockSession> session(createSession("me@foo.com")); + getMockServer()->expectStreamStart(); + getMockServer()->sendStreamStart(); + getMockServer()->sendStreamFeaturesWithResourceBind(); + getMockServer()->expectResourceBind("", "session-bind"); + getMockServer()->sendError("session-bind"); + session->startSession(); + processEvents(); + + CPPUNIT_ASSERT_EQUAL(ClientSession::Error, session->getState()); + CPPUNIT_ASSERT_EQUAL(ClientSession::ResourceBindError, *session->getError()); + } + + void testSessionStart() { + boost::shared_ptr<MockSession> session(createSession("me@foo.com/Bar")); + session->onSessionStarted.connect(boost::bind(&ClientSessionTest::setSessionStarted, this)); + getMockServer()->expectStreamStart(); + getMockServer()->sendStreamStart(); + getMockServer()->sendStreamFeaturesWithSession(); + getMockServer()->expectSessionStart("session-start"); + // FIXME: Check CPPUNIT_ASSERT_EQUAL(ClientSession::StartingSession, session->getState()); + getMockServer()->sendSessionStartResponse("session-start"); + session->startSession(); + processEvents(); + + CPPUNIT_ASSERT_EQUAL(ClientSession::SessionStarted, session->getState()); + CPPUNIT_ASSERT(sessionStarted_); + } + + void testSessionStart_Error() { + boost::shared_ptr<MockSession> session(createSession("me@foo.com/Bar")); + getMockServer()->expectStreamStart(); + getMockServer()->sendStreamStart(); + getMockServer()->sendStreamFeaturesWithSession(); + getMockServer()->expectSessionStart("session-start"); + getMockServer()->sendError("session-start"); + session->startSession(); + processEvents(); + + CPPUNIT_ASSERT_EQUAL(ClientSession::Error, session->getState()); + CPPUNIT_ASSERT_EQUAL(ClientSession::SessionStartError, *session->getError()); + } + + void testSessionStart_AfterResourceBind() { + boost::shared_ptr<MockSession> session(createSession("me@foo.com/Bar")); + session->onSessionStarted.connect(boost::bind(&ClientSessionTest::setSessionStarted, this)); + getMockServer()->expectStreamStart(); + getMockServer()->sendStreamStart(); + getMockServer()->sendStreamFeaturesWithResourceBindAndSession(); + getMockServer()->expectResourceBind("Bar", "session-bind"); + getMockServer()->sendResourceBindResponse("me@foo.com/Bar", "session-bind"); + getMockServer()->expectSessionStart("session-start"); + getMockServer()->sendSessionStartResponse("session-start"); + session->startSession(); + processEvents(); + + CPPUNIT_ASSERT_EQUAL(ClientSession::SessionStarted, session->getState()); + CPPUNIT_ASSERT(sessionStarted_); + } + + void testWhitespacePing() { + boost::shared_ptr<MockSession> session(createSession("me@foo.com/Bar")); + getMockServer()->expectStreamStart(); + getMockServer()->sendStreamStart(); + getMockServer()->sendStreamFeatures(); + session->startSession(); + processEvents(); + CPPUNIT_ASSERT(session->getWhitespacePingLayer()); + } + + void testReceiveElementAfterSessionStarted() { + boost::shared_ptr<MockSession> session(createSession("me@foo.com/Bar")); + getMockServer()->expectStreamStart(); + getMockServer()->sendStreamStart(); + getMockServer()->sendStreamFeatures(); + session->startSession(); + processEvents(); + + getMockServer()->expectMessage(); + session->sendElement(boost::make_shared<Message>())); + } + + void testSendElement() { + boost::shared_ptr<MockSession> session(createSession("me@foo.com/Bar")); + session->onElementReceived.connect(boost::bind(&ClientSessionTest::addReceivedElement, this, _1)); + getMockServer()->expectStreamStart(); + getMockServer()->sendStreamStart(); + getMockServer()->sendStreamFeatures(); + getMockServer()->sendMessage(); + session->startSession(); + processEvents(); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(receivedElements_.size())); + CPPUNIT_ASSERT(boost::dynamic_pointer_cast<Message>(receivedElements_[0])); + } #endif diff --git a/Swiften/Client/UnitTest/NickResolverTest.cpp b/Swiften/Client/UnitTest/NickResolverTest.cpp index c7d7a3a..855b15a 100644 --- a/Swiften/Client/UnitTest/NickResolverTest.cpp +++ b/Swiften/Client/UnitTest/NickResolverTest.cpp @@ -20,134 +20,134 @@ using namespace Swift; class NickResolverTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(NickResolverTest); - CPPUNIT_TEST(testNoMatch); - CPPUNIT_TEST(testZeroLengthMatch); - CPPUNIT_TEST(testMatch); - CPPUNIT_TEST(testOverwrittenMatch); - CPPUNIT_TEST(testRemovedMatch); - CPPUNIT_TEST(testMUCNick); - CPPUNIT_TEST(testMUCNoNick); - CPPUNIT_TEST(testRemovedMatch); - CPPUNIT_TEST(testOwnNickFullOnly); - CPPUNIT_TEST(testOwnNickGivenAndFull); - CPPUNIT_TEST(testOwnNickNickEtAl); - CPPUNIT_TEST_SUITE_END(); - - public: - void setUp() { - crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); - ownJID_ = JID("kev@wonderland.lit"); - xmppRoster_ = new XMPPRosterImpl(); - stanzaChannel_ = new DummyStanzaChannel(); - iqRouter_ = new IQRouter(stanzaChannel_); - vCardStorage_ = new VCardMemoryStorage(crypto.get()); - vCardManager_ = new VCardManager(ownJID_, iqRouter_, vCardStorage_); - registry_ = new MUCRegistry(); - resolver_ = new NickResolver(ownJID_, xmppRoster_, vCardManager_, registry_); - } - - void tearDown() { - delete resolver_; - delete registry_; - delete vCardManager_; - delete iqRouter_; - delete stanzaChannel_; - delete vCardStorage_; - delete xmppRoster_; - } - - void testMUCNick() { - registry_->addMUC(JID("foo@bar")); - JID testJID("foo@bar/baz"); - - CPPUNIT_ASSERT_EQUAL(std::string("baz"), resolver_->jidToNick(testJID)); - } - - void testMUCNoNick() { - registry_->addMUC(JID("foo@bar")); - JID testJID("foo@bar"); - - CPPUNIT_ASSERT_EQUAL(std::string("foo@bar"), resolver_->jidToNick(testJID)); - } - - - void testNoMatch() { - JID testJID("foo@bar/baz"); - - CPPUNIT_ASSERT_EQUAL(std::string("foo@bar"), resolver_->jidToNick(testJID)); - } - - void testZeroLengthMatch() { - JID testJID("foo@bar/baz"); - xmppRoster_->addContact(testJID, "", groups_, RosterItemPayload::Both); - CPPUNIT_ASSERT_EQUAL(std::string("foo@bar"), resolver_->jidToNick(testJID)); - } - - void testMatch() { - JID testJID("foo@bar/baz"); - xmppRoster_->addContact(testJID, "Test", groups_, RosterItemPayload::Both); - - CPPUNIT_ASSERT_EQUAL(std::string("Test"), resolver_->jidToNick(testJID)); - } - - void testOverwrittenMatch() { - JID testJID("foo@bar/baz"); - xmppRoster_->addContact(testJID, "FailTest", groups_, RosterItemPayload::Both); - xmppRoster_->addContact(testJID, "Test", groups_, RosterItemPayload::Both); - - CPPUNIT_ASSERT_EQUAL(std::string("Test"), resolver_->jidToNick(testJID)); - } - - void testRemovedMatch() { - JID testJID("foo@bar/baz"); - xmppRoster_->addContact(testJID, "FailTest", groups_, RosterItemPayload::Both); - xmppRoster_->removeContact(testJID); - CPPUNIT_ASSERT_EQUAL(std::string("foo@bar"), resolver_->jidToNick(testJID)); - } - - void testOwnNickFullOnly() { - populateOwnVCard("", "", "Kevin Smith"); - CPPUNIT_ASSERT_EQUAL(std::string("Kevin Smith"), resolver_->jidToNick(ownJID_)); - } - - void testOwnNickGivenAndFull() { - populateOwnVCard("", "Kevin", "Kevin Smith"); - CPPUNIT_ASSERT_EQUAL(std::string("Kevin"), resolver_->jidToNick(ownJID_)); - } - - void testOwnNickNickEtAl() { - populateOwnVCard("Kev", "Kevin", "Kevin Smith"); - CPPUNIT_ASSERT_EQUAL(std::string("Kev"), resolver_->jidToNick(ownJID_)); - } - - void populateOwnVCard(const std::string& nick, const std::string& given, const std::string& full) { - VCard::ref vcard(new VCard()); - if (!nick.empty()) { - vcard->setNickname(nick); - } - if (!given.empty()) { - vcard->setGivenName(given); - } - if (!full.empty()) { - vcard->setFullName(full); - } - vCardManager_->requestVCard(ownJID_); - IQ::ref result(IQ::createResult(JID(), stanzaChannel_->sentStanzas[0]->getID(), vcard)); - stanzaChannel_->onIQReceived(result); - } - - private: - std::vector<std::string> groups_; - XMPPRosterImpl* xmppRoster_; - VCardStorage* vCardStorage_; - IQRouter* iqRouter_; - DummyStanzaChannel* stanzaChannel_; - VCardManager* vCardManager_; - MUCRegistry* registry_; - NickResolver* resolver_; - JID ownJID_; - boost::shared_ptr<CryptoProvider> crypto; + CPPUNIT_TEST_SUITE(NickResolverTest); + CPPUNIT_TEST(testNoMatch); + CPPUNIT_TEST(testZeroLengthMatch); + CPPUNIT_TEST(testMatch); + CPPUNIT_TEST(testOverwrittenMatch); + CPPUNIT_TEST(testRemovedMatch); + CPPUNIT_TEST(testMUCNick); + CPPUNIT_TEST(testMUCNoNick); + CPPUNIT_TEST(testRemovedMatch); + CPPUNIT_TEST(testOwnNickFullOnly); + CPPUNIT_TEST(testOwnNickGivenAndFull); + CPPUNIT_TEST(testOwnNickNickEtAl); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); + ownJID_ = JID("kev@wonderland.lit"); + xmppRoster_ = new XMPPRosterImpl(); + stanzaChannel_ = new DummyStanzaChannel(); + iqRouter_ = new IQRouter(stanzaChannel_); + vCardStorage_ = new VCardMemoryStorage(crypto.get()); + vCardManager_ = new VCardManager(ownJID_, iqRouter_, vCardStorage_); + registry_ = new MUCRegistry(); + resolver_ = new NickResolver(ownJID_, xmppRoster_, vCardManager_, registry_); + } + + void tearDown() { + delete resolver_; + delete registry_; + delete vCardManager_; + delete iqRouter_; + delete stanzaChannel_; + delete vCardStorage_; + delete xmppRoster_; + } + + void testMUCNick() { + registry_->addMUC(JID("foo@bar")); + JID testJID("foo@bar/baz"); + + CPPUNIT_ASSERT_EQUAL(std::string("baz"), resolver_->jidToNick(testJID)); + } + + void testMUCNoNick() { + registry_->addMUC(JID("foo@bar")); + JID testJID("foo@bar"); + + CPPUNIT_ASSERT_EQUAL(std::string("foo@bar"), resolver_->jidToNick(testJID)); + } + + + void testNoMatch() { + JID testJID("foo@bar/baz"); + + CPPUNIT_ASSERT_EQUAL(std::string("foo@bar"), resolver_->jidToNick(testJID)); + } + + void testZeroLengthMatch() { + JID testJID("foo@bar/baz"); + xmppRoster_->addContact(testJID, "", groups_, RosterItemPayload::Both); + CPPUNIT_ASSERT_EQUAL(std::string("foo@bar"), resolver_->jidToNick(testJID)); + } + + void testMatch() { + JID testJID("foo@bar/baz"); + xmppRoster_->addContact(testJID, "Test", groups_, RosterItemPayload::Both); + + CPPUNIT_ASSERT_EQUAL(std::string("Test"), resolver_->jidToNick(testJID)); + } + + void testOverwrittenMatch() { + JID testJID("foo@bar/baz"); + xmppRoster_->addContact(testJID, "FailTest", groups_, RosterItemPayload::Both); + xmppRoster_->addContact(testJID, "Test", groups_, RosterItemPayload::Both); + + CPPUNIT_ASSERT_EQUAL(std::string("Test"), resolver_->jidToNick(testJID)); + } + + void testRemovedMatch() { + JID testJID("foo@bar/baz"); + xmppRoster_->addContact(testJID, "FailTest", groups_, RosterItemPayload::Both); + xmppRoster_->removeContact(testJID); + CPPUNIT_ASSERT_EQUAL(std::string("foo@bar"), resolver_->jidToNick(testJID)); + } + + void testOwnNickFullOnly() { + populateOwnVCard("", "", "Kevin Smith"); + CPPUNIT_ASSERT_EQUAL(std::string("Kevin Smith"), resolver_->jidToNick(ownJID_)); + } + + void testOwnNickGivenAndFull() { + populateOwnVCard("", "Kevin", "Kevin Smith"); + CPPUNIT_ASSERT_EQUAL(std::string("Kevin"), resolver_->jidToNick(ownJID_)); + } + + void testOwnNickNickEtAl() { + populateOwnVCard("Kev", "Kevin", "Kevin Smith"); + CPPUNIT_ASSERT_EQUAL(std::string("Kev"), resolver_->jidToNick(ownJID_)); + } + + void populateOwnVCard(const std::string& nick, const std::string& given, const std::string& full) { + VCard::ref vcard(new VCard()); + if (!nick.empty()) { + vcard->setNickname(nick); + } + if (!given.empty()) { + vcard->setGivenName(given); + } + if (!full.empty()) { + vcard->setFullName(full); + } + vCardManager_->requestVCard(ownJID_); + IQ::ref result(IQ::createResult(JID(), stanzaChannel_->sentStanzas[0]->getID(), vcard)); + stanzaChannel_->onIQReceived(result); + } + + private: + std::vector<std::string> groups_; + XMPPRosterImpl* xmppRoster_; + VCardStorage* vCardStorage_; + IQRouter* iqRouter_; + DummyStanzaChannel* stanzaChannel_; + VCardManager* vCardManager_; + MUCRegistry* registry_; + NickResolver* resolver_; + JID ownJID_; + boost::shared_ptr<CryptoProvider> crypto; }; CPPUNIT_TEST_SUITE_REGISTRATION(NickResolverTest); diff --git a/Swiften/Client/XMLBeautifier.cpp b/Swiften/Client/XMLBeautifier.cpp index 78a10ec..f084bb3 100644 --- a/Swiften/Client/XMLBeautifier.cpp +++ b/Swiften/Client/XMLBeautifier.cpp @@ -22,26 +22,26 @@ namespace Swift { XMLBeautifier::XMLBeautifier(bool indention, bool coloring) : doIndention(indention), doColoring(coloring), intLevel(0), parser(NULL), lastWasStepDown(false) { - factory = new PlatformXMLParserFactory(); + factory = new PlatformXMLParserFactory(); } XMLBeautifier::~XMLBeautifier() { - delete factory; + delete factory; } std::string XMLBeautifier::beautify(const std::string &text) { - parser = factory->createXMLParser(this); - intLevel = 0; - buffer.str(std::string()); - parser->parse(text); - delete parser; - return buffer.str(); + parser = factory->createXMLParser(this); + intLevel = 0; + buffer.str(std::string()); + parser->parse(text); + delete parser; + return buffer.str(); } void XMLBeautifier::indent() { - for (int i = 0; i < intLevel; ++i) { - buffer << " "; - } + for (int i = 0; i < intLevel; ++i) { + buffer << " "; + } } // all bold but reset @@ -56,78 +56,78 @@ static const char colorYellow[] = "\x1b[01;33m"; std::string XMLBeautifier::styleTag(const std::string& text) const { - std::string result; - result += colorYellow; - result += text; - result += colorReset; - return result; + std::string result; + result += colorYellow; + result += text; + result += colorReset; + return result; } std::string XMLBeautifier::styleNamespace(const std::string& text) const { - std::string result; - result += colorRed; - result += text; - result += colorReset; - return result; + std::string result; + result += colorRed; + result += text; + result += colorReset; + return result; } std::string XMLBeautifier::styleAttribute(const std::string& text) const { - std::string result; - result += colorGreen; - result += text; - result += colorReset; - return result; + std::string result; + result += colorGreen; + result += text; + result += colorReset; + return result; } std::string XMLBeautifier::styleValue(const std::string& text) const { - std::string result; - result += colorCyan; - result += text; - result += colorReset; - return result; + std::string result; + result += colorCyan; + result += text; + result += colorReset; + return result; } void XMLBeautifier::handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes) { - if (doIndention) { - if (intLevel) buffer << std::endl; - } - indent(); - buffer << "<" << (doColoring ? styleTag(element) : element); - if (!ns.empty() && (!parentNSs.empty() && parentNSs.top() != ns)) { - buffer << " "; - buffer << (doColoring ? styleAttribute("xmlns") : "xmlns"); - buffer << "="; - buffer << "\"" << (doColoring ? styleNamespace(ns) : ns) << "\""; - } - if (!attributes.getEntries().empty()) { - foreach(AttributeMap::Entry entry, attributes.getEntries()) { - buffer << " "; - buffer << (doColoring ? styleAttribute(entry.getAttribute().getName()) : entry.getAttribute().getName()); - buffer << "="; - buffer << "\"" << (doColoring ? styleValue(entry.getValue()) : entry.getValue()) << "\""; - } - } - buffer << ">"; - ++intLevel; - lastWasStepDown = false; - parentNSs.push(ns); + if (doIndention) { + if (intLevel) buffer << std::endl; + } + indent(); + buffer << "<" << (doColoring ? styleTag(element) : element); + if (!ns.empty() && (!parentNSs.empty() && parentNSs.top() != ns)) { + buffer << " "; + buffer << (doColoring ? styleAttribute("xmlns") : "xmlns"); + buffer << "="; + buffer << "\"" << (doColoring ? styleNamespace(ns) : ns) << "\""; + } + if (!attributes.getEntries().empty()) { + foreach(AttributeMap::Entry entry, attributes.getEntries()) { + buffer << " "; + buffer << (doColoring ? styleAttribute(entry.getAttribute().getName()) : entry.getAttribute().getName()); + buffer << "="; + buffer << "\"" << (doColoring ? styleValue(entry.getValue()) : entry.getValue()) << "\""; + } + } + buffer << ">"; + ++intLevel; + lastWasStepDown = false; + parentNSs.push(ns); } void XMLBeautifier::handleEndElement(const std::string& element, const std::string& /* ns */) { - --intLevel; - parentNSs.pop(); - if (/*hadCDATA.top() ||*/ lastWasStepDown) { - if (doIndention) { - buffer << std::endl; - } - indent(); - } - buffer << "</" << (doColoring ? styleTag(element) : element) << ">"; - lastWasStepDown = true; + --intLevel; + parentNSs.pop(); + if (/*hadCDATA.top() ||*/ lastWasStepDown) { + if (doIndention) { + buffer << std::endl; + } + indent(); + } + buffer << "</" << (doColoring ? styleTag(element) : element) << ">"; + lastWasStepDown = true; } void XMLBeautifier::handleCharacterData(const std::string& data) { - buffer << data; - lastWasStepDown = false; + buffer << data; + lastWasStepDown = false; } } diff --git a/Swiften/Client/XMLBeautifier.h b/Swiften/Client/XMLBeautifier.h index 233c68e..a765bc5 100644 --- a/Swiften/Client/XMLBeautifier.h +++ b/Swiften/Client/XMLBeautifier.h @@ -26,36 +26,36 @@ namespace Swift { class SWIFTEN_API XMLBeautifier : public XMLParserClient { public: - XMLBeautifier(bool indention, bool coloring); - virtual ~XMLBeautifier(); + XMLBeautifier(bool indention, bool coloring); + virtual ~XMLBeautifier(); - std::string beautify(const std::string&); + std::string beautify(const std::string&); private: - void handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes); - void handleEndElement(const std::string& element, const std::string& ns); - void handleCharacterData(const std::string& data); + void handleStartElement(const std::string& element, const std::string& ns, const AttributeMap& attributes); + void handleEndElement(const std::string& element, const std::string& ns); + void handleCharacterData(const std::string& data); private: - void indent(); + void indent(); private: - std::string styleTag(const std::string& text) const; - std::string styleNamespace(const std::string& text) const; - std::string styleAttribute(const std::string& text) const; - std::string styleValue(const std::string& text) const; + std::string styleTag(const std::string& text) const; + std::string styleNamespace(const std::string& text) const; + std::string styleAttribute(const std::string& text) const; + std::string styleValue(const std::string& text) const; private: - bool doIndention; - bool doColoring; + bool doIndention; + bool doColoring; - int intLevel; - std::string inputBuffer; - std::stringstream buffer; - XMLParserFactory* factory; - XMLParser* parser; + int intLevel; + std::string inputBuffer; + std::stringstream buffer; + XMLParserFactory* factory; + XMLParser* parser; - bool lastWasStepDown; - std::stack<std::string> parentNSs; + bool lastWasStepDown; + std::stack<std::string> parentNSs; }; } |