summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTobias Markmann <tm@ayena.de>2016-03-31 14:57:35 (GMT)
committerTobias Markmann <tm@ayena.de>2016-03-31 14:57:35 (GMT)
commitcfbdb43d2cadd40aa87338d41548e4bf89e146e6 (patch)
tree18d94153a302445196fc0c18586abf44a1ce4a38 /Swiften/Client
parent1d545a4a7fb877f021508094b88c1f17b30d8b4e (diff)
downloadswift-cfbdb43d2cadd40aa87338d41548e4bf89e146e6.zip
swift-cfbdb43d2cadd40aa87338d41548e4bf89e146e6.tar.bz2
Convert tabs to 4 spaces for all source files
Removed trailing spaces and whitespace on empty lines in the process. Changed CheckTabs.py tool to disallow hard tabs in source files. Test-Information: Manually checked 30 random files that the conversion worked as expected. Change-Id: I874f99d617bd3d2bb55f02d58f22f58f9b094480
Diffstat (limited to 'Swiften/Client')
-rw-r--r--Swiften/Client/BlockList.cpp8
-rw-r--r--Swiften/Client/BlockList.h42
-rw-r--r--Swiften/Client/BlockListImpl.cpp68
-rw-r--r--Swiften/Client/BlockListImpl.h50
-rw-r--r--Swiften/Client/Client.cpp172
-rw-r--r--Swiften/Client/Client.h384
-rw-r--r--Swiften/Client/ClientBlockListManager.cpp174
-rw-r--r--Swiften/Client/ClientBlockListManager.h66
-rw-r--r--Swiften/Client/ClientError.h90
-rw-r--r--Swiften/Client/ClientOptions.h290
-rw-r--r--Swiften/Client/ClientSession.cpp776
-rw-r--r--Swiften/Client/ClientSession.h356
-rw-r--r--Swiften/Client/ClientSessionStanzaChannel.cpp110
-rw-r--r--Swiften/Client/ClientSessionStanzaChannel.h62
-rw-r--r--Swiften/Client/ClientXMLTracer.cpp46
-rw-r--r--Swiften/Client/ClientXMLTracer.h26
-rw-r--r--Swiften/Client/CoreClient.cpp706
-rw-r--r--Swiften/Client/CoreClient.h438
-rw-r--r--Swiften/Client/DummyNickManager.h18
-rw-r--r--Swiften/Client/DummyStanzaChannel.h150
-rw-r--r--Swiften/Client/MemoryStorages.cpp34
-rw-r--r--Swiften/Client/MemoryStorages.h44
-rw-r--r--Swiften/Client/NickManager.h14
-rw-r--r--Swiften/Client/NickManagerImpl.cpp32
-rw-r--r--Swiften/Client/NickManagerImpl.h30
-rw-r--r--Swiften/Client/NickResolver.cpp76
-rw-r--r--Swiften/Client/NickResolver.h48
-rw-r--r--Swiften/Client/StanzaChannel.h24
-rw-r--r--Swiften/Client/Storages.h36
-rw-r--r--Swiften/Client/UnitTest/BlockListImplTest.cpp138
-rw-r--r--Swiften/Client/UnitTest/ClientBlockListManagerTest.cpp328
-rw-r--r--Swiften/Client/UnitTest/ClientSessionTest.cpp1560
-rw-r--r--Swiften/Client/UnitTest/NickResolverTest.cpp256
-rw-r--r--Swiften/Client/XMLBeautifier.cpp132
-rw-r--r--Swiften/Client/XMLBeautifier.h40
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;
};
}