diff options
author | Tobias Markmann <tm@ayena.de> | 2016-03-31 14:57:35 (GMT) |
---|---|---|
committer | Tobias Markmann <tm@ayena.de> | 2016-03-31 14:57:35 (GMT) |
commit | cfbdb43d2cadd40aa87338d41548e4bf89e146e6 (patch) | |
tree | 18d94153a302445196fc0c18586abf44a1ce4a38 /Swiften/Component | |
parent | 1d545a4a7fb877f021508094b88c1f17b30d8b4e (diff) | |
download | swift-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/Component')
-rw-r--r-- | Swiften/Component/Component.cpp | 10 | ||||
-rw-r--r-- | Swiften/Component/Component.h | 40 | ||||
-rw-r--r-- | Swiften/Component/ComponentConnector.cpp | 114 | ||||
-rw-r--r-- | Swiften/Component/ComponentConnector.h | 68 | ||||
-rw-r--r-- | Swiften/Component/ComponentError.h | 32 | ||||
-rw-r--r-- | Swiften/Component/ComponentHandshakeGenerator.cpp | 14 | ||||
-rw-r--r-- | Swiften/Component/ComponentHandshakeGenerator.h | 10 | ||||
-rw-r--r-- | Swiften/Component/ComponentSession.cpp | 130 | ||||
-rw-r--r-- | Swiften/Component/ComponentSession.h | 128 | ||||
-rw-r--r-- | Swiften/Component/ComponentSessionStanzaChannel.cpp | 74 | ||||
-rw-r--r-- | Swiften/Component/ComponentSessionStanzaChannel.h | 70 | ||||
-rw-r--r-- | Swiften/Component/ComponentXMLTracer.cpp | 16 | ||||
-rw-r--r-- | Swiften/Component/ComponentXMLTracer.h | 14 | ||||
-rw-r--r-- | Swiften/Component/CoreComponent.cpp | 216 | ||||
-rw-r--r-- | Swiften/Component/CoreComponent.h | 150 | ||||
-rw-r--r-- | Swiften/Component/UnitTest/ComponentConnectorTest.cpp | 368 | ||||
-rw-r--r-- | Swiften/Component/UnitTest/ComponentHandshakeGeneratorTest.cpp | 44 | ||||
-rw-r--r-- | Swiften/Component/UnitTest/ComponentSessionTest.cpp | 390 |
18 files changed, 944 insertions, 944 deletions
diff --git a/Swiften/Component/Component.cpp b/Swiften/Component/Component.cpp index 1340de2..e6835bd 100644 --- a/Swiften/Component/Component.cpp +++ b/Swiften/Component/Component.cpp @@ -11,17 +11,17 @@ namespace Swift { Component::Component(const JID& jid, const std::string& secret, NetworkFactories* networkFactories) : CoreComponent(jid, secret, networkFactories) { - softwareVersionResponder = new SoftwareVersionResponder(getIQRouter()); - softwareVersionResponder->start(); + softwareVersionResponder = new SoftwareVersionResponder(getIQRouter()); + softwareVersionResponder->start(); } Component::~Component() { - softwareVersionResponder->stop(); - delete softwareVersionResponder; + softwareVersionResponder->stop(); + delete softwareVersionResponder; } void Component::setSoftwareVersion(const std::string& name, const std::string& version) { - softwareVersionResponder->setVersion(name, version); + softwareVersionResponder->setVersion(name, version); } } diff --git a/Swiften/Component/Component.h b/Swiften/Component/Component.h index 63aa9f7..a7ef621 100644 --- a/Swiften/Component/Component.h +++ b/Swiften/Component/Component.h @@ -10,27 +10,27 @@ #include <Swiften/Component/CoreComponent.h> namespace Swift { - class SoftwareVersionResponder; + class SoftwareVersionResponder; - /** - * Provides the core functionality for writing XMPP component software. - * - * Besides connecting to an XMPP server, this class also provides interfaces for - * performing most component tasks on the XMPP network. - */ - class SWIFTEN_API Component : public CoreComponent { - public: - Component(const JID& jid, const std::string& secret, NetworkFactories* networkFactories); - virtual ~Component(); + /** + * Provides the core functionality for writing XMPP component software. + * + * Besides connecting to an XMPP server, this class also provides interfaces for + * performing most component tasks on the XMPP network. + */ + class SWIFTEN_API Component : public CoreComponent { + public: + Component(const JID& jid, const std::string& secret, NetworkFactories* networkFactories); + virtual ~Component(); - /** - * 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); + /** + * 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); - private: - SoftwareVersionResponder* softwareVersionResponder; - }; + private: + SoftwareVersionResponder* softwareVersionResponder; + }; } diff --git a/Swiften/Component/ComponentConnector.cpp b/Swiften/Component/ComponentConnector.cpp index 7a2121a..410c19e 100644 --- a/Swiften/Component/ComponentConnector.cpp +++ b/Swiften/Component/ComponentConnector.cpp @@ -21,88 +21,88 @@ ComponentConnector::ComponentConnector(const std::string& hostname, int port, Do } void ComponentConnector::setTimeoutMilliseconds(int milliseconds) { - timeoutMilliseconds = milliseconds; + timeoutMilliseconds = milliseconds; } void ComponentConnector::start() { - assert(!currentConnection); - assert(!timer); - assert(!addressQuery); - addressQuery = resolver->createAddressQuery(hostname); - addressQuery->onResult.connect(boost::bind(&ComponentConnector::handleAddressQueryResult, shared_from_this(), _1, _2)); - if (timeoutMilliseconds > 0) { - timer = timerFactory->createTimer(timeoutMilliseconds); - timer->onTick.connect(boost::bind(&ComponentConnector::handleTimeout, shared_from_this())); - timer->start(); - } - addressQuery->run(); + assert(!currentConnection); + assert(!timer); + assert(!addressQuery); + addressQuery = resolver->createAddressQuery(hostname); + addressQuery->onResult.connect(boost::bind(&ComponentConnector::handleAddressQueryResult, shared_from_this(), _1, _2)); + if (timeoutMilliseconds > 0) { + timer = timerFactory->createTimer(timeoutMilliseconds); + timer->onTick.connect(boost::bind(&ComponentConnector::handleTimeout, shared_from_this())); + timer->start(); + } + addressQuery->run(); } void ComponentConnector::stop() { - finish(boost::shared_ptr<Connection>()); + finish(boost::shared_ptr<Connection>()); } void ComponentConnector::handleAddressQueryResult(const std::vector<HostAddress>& addresses, boost::optional<DomainNameResolveError> error) { - addressQuery.reset(); - if (error || addresses.empty()) { - finish(boost::shared_ptr<Connection>()); - } - else { - addressQueryResults = std::deque<HostAddress>(addresses.begin(), addresses.end()); - tryNextAddress(); - } + addressQuery.reset(); + if (error || addresses.empty()) { + finish(boost::shared_ptr<Connection>()); + } + else { + addressQueryResults = std::deque<HostAddress>(addresses.begin(), addresses.end()); + tryNextAddress(); + } } void ComponentConnector::tryNextAddress() { - assert(!addressQueryResults.empty()); - HostAddress address = addressQueryResults.front(); - addressQueryResults.pop_front(); - tryConnect(HostAddressPort(address, port)); + assert(!addressQueryResults.empty()); + HostAddress address = addressQueryResults.front(); + addressQueryResults.pop_front(); + tryConnect(HostAddressPort(address, port)); } void ComponentConnector::tryConnect(const HostAddressPort& target) { - assert(!currentConnection); - currentConnection = connectionFactory->createConnection(); - currentConnection->onConnectFinished.connect(boost::bind(&ComponentConnector::handleConnectionConnectFinished, shared_from_this(), _1)); - currentConnection->connect(target); + assert(!currentConnection); + currentConnection = connectionFactory->createConnection(); + currentConnection->onConnectFinished.connect(boost::bind(&ComponentConnector::handleConnectionConnectFinished, shared_from_this(), _1)); + currentConnection->connect(target); } void ComponentConnector::handleConnectionConnectFinished(bool error) { - currentConnection->onConnectFinished.disconnect(boost::bind(&ComponentConnector::handleConnectionConnectFinished, shared_from_this(), _1)); - if (error) { - currentConnection.reset(); - if (!addressQueryResults.empty()) { - tryNextAddress(); - } - else { - finish(boost::shared_ptr<Connection>()); - } - } - else { - finish(currentConnection); - } + currentConnection->onConnectFinished.disconnect(boost::bind(&ComponentConnector::handleConnectionConnectFinished, shared_from_this(), _1)); + if (error) { + currentConnection.reset(); + if (!addressQueryResults.empty()) { + tryNextAddress(); + } + else { + finish(boost::shared_ptr<Connection>()); + } + } + else { + finish(currentConnection); + } } void ComponentConnector::finish(boost::shared_ptr<Connection> connection) { - if (timer) { - timer->stop(); - timer->onTick.disconnect(boost::bind(&ComponentConnector::handleTimeout, shared_from_this())); - timer.reset(); - } - if (addressQuery) { - addressQuery->onResult.disconnect(boost::bind(&ComponentConnector::handleAddressQueryResult, shared_from_this(), _1, _2)); - addressQuery.reset(); - } - if (currentConnection) { - currentConnection->onConnectFinished.disconnect(boost::bind(&ComponentConnector::handleConnectionConnectFinished, shared_from_this(), _1)); - currentConnection.reset(); - } - onConnectFinished(connection); + if (timer) { + timer->stop(); + timer->onTick.disconnect(boost::bind(&ComponentConnector::handleTimeout, shared_from_this())); + timer.reset(); + } + if (addressQuery) { + addressQuery->onResult.disconnect(boost::bind(&ComponentConnector::handleAddressQueryResult, shared_from_this(), _1, _2)); + addressQuery.reset(); + } + if (currentConnection) { + currentConnection->onConnectFinished.disconnect(boost::bind(&ComponentConnector::handleConnectionConnectFinished, shared_from_this(), _1)); + currentConnection.reset(); + } + onConnectFinished(connection); } void ComponentConnector::handleTimeout() { - finish(boost::shared_ptr<Connection>()); + finish(boost::shared_ptr<Connection>()); } } diff --git a/Swiften/Component/ComponentConnector.h b/Swiften/Component/ComponentConnector.h index 008236b..68cb0d7 100644 --- a/Swiften/Component/ComponentConnector.h +++ b/Swiften/Component/ComponentConnector.h @@ -19,48 +19,48 @@ #include <Swiften/Network/Timer.h> namespace Swift { - class DomainNameAddressQuery; - class DomainNameResolver; - class ConnectionFactory; - class TimerFactory; + class DomainNameAddressQuery; + class DomainNameResolver; + class ConnectionFactory; + class TimerFactory; - class SWIFTEN_API ComponentConnector : public boost::bsignals::trackable, public boost::enable_shared_from_this<ComponentConnector> { - public: - typedef boost::shared_ptr<ComponentConnector> ref; + class SWIFTEN_API ComponentConnector : public boost::bsignals::trackable, public boost::enable_shared_from_this<ComponentConnector> { + public: + typedef boost::shared_ptr<ComponentConnector> ref; - static ComponentConnector::ref create(const std::string& hostname, int port, DomainNameResolver* resolver, ConnectionFactory* connectionFactory, TimerFactory* timerFactory) { - return ref(new ComponentConnector(hostname, port, resolver, connectionFactory, timerFactory)); - } + static ComponentConnector::ref create(const std::string& hostname, int port, DomainNameResolver* resolver, ConnectionFactory* connectionFactory, TimerFactory* timerFactory) { + return ref(new ComponentConnector(hostname, port, resolver, connectionFactory, timerFactory)); + } - void setTimeoutMilliseconds(int milliseconds); + void setTimeoutMilliseconds(int milliseconds); - void start(); - void stop(); + void start(); + void stop(); - boost::signal<void (boost::shared_ptr<Connection>)> onConnectFinished; + boost::signal<void (boost::shared_ptr<Connection>)> onConnectFinished; - private: - ComponentConnector(const std::string& hostname, int port, DomainNameResolver*, ConnectionFactory*, TimerFactory*); + private: + ComponentConnector(const std::string& hostname, int port, DomainNameResolver*, ConnectionFactory*, TimerFactory*); - void handleAddressQueryResult(const std::vector<HostAddress>& address, boost::optional<DomainNameResolveError> error); - void tryNextAddress(); - void tryConnect(const HostAddressPort& target); + void handleAddressQueryResult(const std::vector<HostAddress>& address, boost::optional<DomainNameResolveError> error); + void tryNextAddress(); + void tryConnect(const HostAddressPort& target); - void handleConnectionConnectFinished(bool error); - void finish(boost::shared_ptr<Connection>); - void handleTimeout(); + void handleConnectionConnectFinished(bool error); + void finish(boost::shared_ptr<Connection>); + void handleTimeout(); - private: - std::string hostname; - int port; - DomainNameResolver* resolver; - ConnectionFactory* connectionFactory; - TimerFactory* timerFactory; - int timeoutMilliseconds; - boost::shared_ptr<Timer> timer; - boost::shared_ptr<DomainNameAddressQuery> addressQuery; - std::deque<HostAddress> addressQueryResults; - boost::shared_ptr<Connection> currentConnection; - }; + private: + std::string hostname; + int port; + DomainNameResolver* resolver; + ConnectionFactory* connectionFactory; + TimerFactory* timerFactory; + int timeoutMilliseconds; + boost::shared_ptr<Timer> timer; + boost::shared_ptr<DomainNameAddressQuery> addressQuery; + std::deque<HostAddress> addressQueryResults; + boost::shared_ptr<Connection> currentConnection; + }; } diff --git a/Swiften/Component/ComponentError.h b/Swiften/Component/ComponentError.h index 7609b9a..dca8c99 100644 --- a/Swiften/Component/ComponentError.h +++ b/Swiften/Component/ComponentError.h @@ -9,23 +9,23 @@ #include <Swiften/Base/API.h> namespace Swift { - class SWIFTEN_API ComponentError { - public: - enum Type { - UnknownError, - ConnectionError, - ConnectionReadError, - ConnectionWriteError, - XMLError, - AuthenticationFailedError, - UnexpectedElementError - }; + class SWIFTEN_API ComponentError { + public: + enum Type { + UnknownError, + ConnectionError, + ConnectionReadError, + ConnectionWriteError, + XMLError, + AuthenticationFailedError, + UnexpectedElementError + }; - ComponentError(Type type = UnknownError) : type_(type) {} + ComponentError(Type type = UnknownError) : type_(type) {} - Type getType() const { return type_; } + Type getType() const { return type_; } - private: - Type type_; - }; + private: + Type type_; + }; } diff --git a/Swiften/Component/ComponentHandshakeGenerator.cpp b/Swiften/Component/ComponentHandshakeGenerator.cpp index a0eacab..647b3da 100644 --- a/Swiften/Component/ComponentHandshakeGenerator.cpp +++ b/Swiften/Component/ComponentHandshakeGenerator.cpp @@ -13,13 +13,13 @@ namespace Swift { std::string ComponentHandshakeGenerator::getHandshake(const std::string& streamID, const std::string& secret, CryptoProvider* crypto) { - std::string concatenatedString = streamID + secret; - String::replaceAll(concatenatedString, '&', "&"); - String::replaceAll(concatenatedString, '<', "<"); - String::replaceAll(concatenatedString, '>', ">"); - String::replaceAll(concatenatedString, '\'', "'"); - String::replaceAll(concatenatedString, '"', """); - return Hexify::hexify(crypto->getSHA1Hash(createByteArray(concatenatedString))); + std::string concatenatedString = streamID + secret; + String::replaceAll(concatenatedString, '&', "&"); + String::replaceAll(concatenatedString, '<', "<"); + String::replaceAll(concatenatedString, '>', ">"); + String::replaceAll(concatenatedString, '\'', "'"); + String::replaceAll(concatenatedString, '"', """); + return Hexify::hexify(crypto->getSHA1Hash(createByteArray(concatenatedString))); } } diff --git a/Swiften/Component/ComponentHandshakeGenerator.h b/Swiften/Component/ComponentHandshakeGenerator.h index 7d9f60c..0aafb83 100644 --- a/Swiften/Component/ComponentHandshakeGenerator.h +++ b/Swiften/Component/ComponentHandshakeGenerator.h @@ -11,11 +11,11 @@ #include <Swiften/Base/API.h> namespace Swift { - class CryptoProvider; + class CryptoProvider; - class SWIFTEN_API ComponentHandshakeGenerator { - public: - static std::string getHandshake(const std::string& streamID, const std::string& secret, CryptoProvider* crypto); - }; + class SWIFTEN_API ComponentHandshakeGenerator { + public: + static std::string getHandshake(const std::string& streamID, const std::string& secret, CryptoProvider* crypto); + }; } diff --git a/Swiften/Component/ComponentSession.cpp b/Swiften/Component/ComponentSession.cpp index 79660de..46c88db 100644 --- a/Swiften/Component/ComponentSession.cpp +++ b/Swiften/Component/ComponentSession.cpp @@ -24,99 +24,99 @@ ComponentSession::~ComponentSession() { } void ComponentSession::start() { - stream->onStreamStartReceived.connect(boost::bind(&ComponentSession::handleStreamStart, shared_from_this(), _1)); - stream->onElementReceived.connect(boost::bind(&ComponentSession::handleElement, shared_from_this(), _1)); - stream->onClosed.connect(boost::bind(&ComponentSession::handleStreamClosed, shared_from_this(), _1)); + stream->onStreamStartReceived.connect(boost::bind(&ComponentSession::handleStreamStart, shared_from_this(), _1)); + stream->onElementReceived.connect(boost::bind(&ComponentSession::handleElement, shared_from_this(), _1)); + stream->onClosed.connect(boost::bind(&ComponentSession::handleStreamClosed, shared_from_this(), _1)); - assert(state == Initial); - state = WaitingForStreamStart; - sendStreamHeader(); + assert(state == Initial); + state = WaitingForStreamStart; + sendStreamHeader(); } void ComponentSession::sendStreamHeader() { - ProtocolHeader header; - header.setTo(jid); - stream->writeHeader(header); + ProtocolHeader header; + header.setTo(jid); + stream->writeHeader(header); } void ComponentSession::sendStanza(boost::shared_ptr<Stanza> stanza) { - stream->writeElement(stanza); + stream->writeElement(stanza); } void ComponentSession::handleStreamStart(const ProtocolHeader& header) { - checkState(WaitingForStreamStart); - state = Authenticating; - stream->writeElement(ComponentHandshake::ref(new ComponentHandshake(ComponentHandshakeGenerator::getHandshake(header.getID(), secret, crypto)))); + checkState(WaitingForStreamStart); + state = Authenticating; + stream->writeElement(ComponentHandshake::ref(new ComponentHandshake(ComponentHandshakeGenerator::getHandshake(header.getID(), secret, crypto)))); } void ComponentSession::handleElement(boost::shared_ptr<ToplevelElement> element) { - if (boost::shared_ptr<Stanza> stanza = boost::dynamic_pointer_cast<Stanza>(element)) { - if (getState() == Initialized) { - onStanzaReceived(stanza); - } - else { - finishSession(Error::UnexpectedElementError); - } - } - else if (boost::dynamic_pointer_cast<ComponentHandshake>(element)) { - if (!checkState(Authenticating)) { - return; - } - stream->setWhitespacePingEnabled(true); - state = Initialized; - onInitialized(); - } - else if (getState() == Authenticating) { - if (boost::dynamic_pointer_cast<StreamFeatures>(element)) { - // M-Link sends stream features, so swallow that. - } - else { - // FIXME: We should actually check the element received - finishSession(Error::AuthenticationFailedError); - } - } - else { - finishSession(Error::UnexpectedElementError); - } + if (boost::shared_ptr<Stanza> stanza = boost::dynamic_pointer_cast<Stanza>(element)) { + if (getState() == Initialized) { + onStanzaReceived(stanza); + } + else { + finishSession(Error::UnexpectedElementError); + } + } + else if (boost::dynamic_pointer_cast<ComponentHandshake>(element)) { + if (!checkState(Authenticating)) { + return; + } + stream->setWhitespacePingEnabled(true); + state = Initialized; + onInitialized(); + } + else if (getState() == Authenticating) { + if (boost::dynamic_pointer_cast<StreamFeatures>(element)) { + // M-Link sends stream features, so swallow that. + } + else { + // FIXME: We should actually check the element received + finishSession(Error::AuthenticationFailedError); + } + } + else { + finishSession(Error::UnexpectedElementError); + } } bool ComponentSession::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 ComponentSession::handleStreamClosed(boost::shared_ptr<Swift::Error> streamError) { - State oldState = state; - state = Finished; - stream->setWhitespacePingEnabled(false); - stream->onStreamStartReceived.disconnect(boost::bind(&ComponentSession::handleStreamStart, shared_from_this(), _1)); - stream->onElementReceived.disconnect(boost::bind(&ComponentSession::handleElement, shared_from_this(), _1)); - stream->onClosed.disconnect(boost::bind(&ComponentSession::handleStreamClosed, shared_from_this(), _1)); - if (oldState == Finishing) { - onFinished(error); - } - else { - onFinished(streamError); - } + State oldState = state; + state = Finished; + stream->setWhitespacePingEnabled(false); + stream->onStreamStartReceived.disconnect(boost::bind(&ComponentSession::handleStreamStart, shared_from_this(), _1)); + stream->onElementReceived.disconnect(boost::bind(&ComponentSession::handleElement, shared_from_this(), _1)); + stream->onClosed.disconnect(boost::bind(&ComponentSession::handleStreamClosed, shared_from_this(), _1)); + if (oldState == Finishing) { + onFinished(error); + } + else { + onFinished(streamError); + } } void ComponentSession::finish() { - finishSession(boost::shared_ptr<Error>()); + finishSession(boost::shared_ptr<Error>()); } void ComponentSession::finishSession(Error::Type error) { - finishSession(boost::make_shared<Swift::ComponentSession::Error>(error)); + finishSession(boost::make_shared<Swift::ComponentSession::Error>(error)); } void ComponentSession::finishSession(boost::shared_ptr<Swift::Error> finishError) { - state = Finishing; - error = finishError; - assert(stream->isOpen()); - stream->writeFooter(); - stream->close(); + state = Finishing; + error = finishError; + assert(stream->isOpen()); + stream->writeFooter(); + stream->close(); } } diff --git a/Swiften/Component/ComponentSession.h b/Swiften/Component/ComponentSession.h index 3a750cc..608bb79 100644 --- a/Swiften/Component/ComponentSession.h +++ b/Swiften/Component/ComponentSession.h @@ -20,68 +20,68 @@ #include <Swiften/Session/SessionStream.h> namespace Swift { - class ComponentAuthenticator; - class CryptoProvider; - - class SWIFTEN_API ComponentSession : public boost::enable_shared_from_this<ComponentSession> { - public: - enum State { - Initial, - WaitingForStreamStart, - Authenticating, - Initialized, - Finishing, - Finished - }; - - struct Error : public Swift::Error { - enum Type { - AuthenticationFailedError, - UnexpectedElementError - } type; - Error(Type type) : type(type) {} - }; - - ~ComponentSession(); - - static boost::shared_ptr<ComponentSession> create(const JID& jid, const std::string& secret, boost::shared_ptr<SessionStream> stream, CryptoProvider* crypto) { - return boost::shared_ptr<ComponentSession>(new ComponentSession(jid, secret, stream, crypto)); - } - - State getState() const { - return state; - } - - void start(); - void finish(); - - void sendStanza(boost::shared_ptr<Stanza>); - - public: - boost::signal<void ()> onInitialized; - boost::signal<void (boost::shared_ptr<Swift::Error>)> onFinished; - boost::signal<void (boost::shared_ptr<Stanza>)> onStanzaReceived; - - private: - ComponentSession(const JID& jid, const std::string& secret, boost::shared_ptr<SessionStream>, CryptoProvider*); - - void finishSession(Error::Type error); - void finishSession(boost::shared_ptr<Swift::Error> error); - - void sendStreamHeader(); - - void handleElement(boost::shared_ptr<ToplevelElement>); - void handleStreamStart(const ProtocolHeader&); - void handleStreamClosed(boost::shared_ptr<Swift::Error>); - - bool checkState(State); - - private: - JID jid; - std::string secret; - boost::shared_ptr<SessionStream> stream; - CryptoProvider* crypto; - boost::shared_ptr<Swift::Error> error; - State state; - }; + class ComponentAuthenticator; + class CryptoProvider; + + class SWIFTEN_API ComponentSession : public boost::enable_shared_from_this<ComponentSession> { + public: + enum State { + Initial, + WaitingForStreamStart, + Authenticating, + Initialized, + Finishing, + Finished + }; + + struct Error : public Swift::Error { + enum Type { + AuthenticationFailedError, + UnexpectedElementError + } type; + Error(Type type) : type(type) {} + }; + + ~ComponentSession(); + + static boost::shared_ptr<ComponentSession> create(const JID& jid, const std::string& secret, boost::shared_ptr<SessionStream> stream, CryptoProvider* crypto) { + return boost::shared_ptr<ComponentSession>(new ComponentSession(jid, secret, stream, crypto)); + } + + State getState() const { + return state; + } + + void start(); + void finish(); + + void sendStanza(boost::shared_ptr<Stanza>); + + public: + boost::signal<void ()> onInitialized; + boost::signal<void (boost::shared_ptr<Swift::Error>)> onFinished; + boost::signal<void (boost::shared_ptr<Stanza>)> onStanzaReceived; + + private: + ComponentSession(const JID& jid, const std::string& secret, boost::shared_ptr<SessionStream>, CryptoProvider*); + + void finishSession(Error::Type error); + void finishSession(boost::shared_ptr<Swift::Error> error); + + void sendStreamHeader(); + + void handleElement(boost::shared_ptr<ToplevelElement>); + void handleStreamStart(const ProtocolHeader&); + void handleStreamClosed(boost::shared_ptr<Swift::Error>); + + bool checkState(State); + + private: + JID jid; + std::string secret; + boost::shared_ptr<SessionStream> stream; + CryptoProvider* crypto; + boost::shared_ptr<Swift::Error> error; + State state; + }; } diff --git a/Swiften/Component/ComponentSessionStanzaChannel.cpp b/Swiften/Component/ComponentSessionStanzaChannel.cpp index 7ff374f..ffb1f13 100644 --- a/Swiften/Component/ComponentSessionStanzaChannel.cpp +++ b/Swiften/Component/ComponentSessionStanzaChannel.cpp @@ -13,68 +13,68 @@ namespace Swift { void ComponentSessionStanzaChannel::setSession(boost::shared_ptr<ComponentSession> session) { - assert(!this->session); - this->session = session; - session->onInitialized.connect(boost::bind(&ComponentSessionStanzaChannel::handleSessionInitialized, this)); - session->onFinished.connect(boost::bind(&ComponentSessionStanzaChannel::handleSessionFinished, this, _1)); - session->onStanzaReceived.connect(boost::bind(&ComponentSessionStanzaChannel::handleStanza, this, _1)); + assert(!this->session); + this->session = session; + session->onInitialized.connect(boost::bind(&ComponentSessionStanzaChannel::handleSessionInitialized, this)); + session->onFinished.connect(boost::bind(&ComponentSessionStanzaChannel::handleSessionFinished, this, _1)); + session->onStanzaReceived.connect(boost::bind(&ComponentSessionStanzaChannel::handleStanza, this, _1)); } void ComponentSessionStanzaChannel::sendIQ(boost::shared_ptr<IQ> iq) { - send(iq); + send(iq); } void ComponentSessionStanzaChannel::sendMessage(boost::shared_ptr<Message> message) { - send(message); + send(message); } void ComponentSessionStanzaChannel::sendPresence(boost::shared_ptr<Presence> presence) { - send(presence); + send(presence); } std::string ComponentSessionStanzaChannel::getNewIQID() { - return idGenerator.generateID(); + return idGenerator.generateID(); } void ComponentSessionStanzaChannel::send(boost::shared_ptr<Stanza> stanza) { - if (!isAvailable()) { - std::cerr << "Warning: Component: Trying to send a stanza while disconnected." << std::endl; - return; - } - session->sendStanza(stanza); + if (!isAvailable()) { + std::cerr << "Warning: Component: Trying to send a stanza while disconnected." << std::endl; + return; + } + session->sendStanza(stanza); } void ComponentSessionStanzaChannel::handleSessionFinished(boost::shared_ptr<Error>) { - session->onFinished.disconnect(boost::bind(&ComponentSessionStanzaChannel::handleSessionFinished, this, _1)); - session->onStanzaReceived.disconnect(boost::bind(&ComponentSessionStanzaChannel::handleStanza, this, _1)); - session->onInitialized.disconnect(boost::bind(&ComponentSessionStanzaChannel::handleSessionInitialized, this)); - session.reset(); + session->onFinished.disconnect(boost::bind(&ComponentSessionStanzaChannel::handleSessionFinished, this, _1)); + session->onStanzaReceived.disconnect(boost::bind(&ComponentSessionStanzaChannel::handleStanza, this, _1)); + session->onInitialized.disconnect(boost::bind(&ComponentSessionStanzaChannel::handleSessionInitialized, this)); + session.reset(); - onAvailableChanged(false); + onAvailableChanged(false); } void ComponentSessionStanzaChannel::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; + } } void ComponentSessionStanzaChannel::handleSessionInitialized() { - onAvailableChanged(true); + onAvailableChanged(true); } } diff --git a/Swiften/Component/ComponentSessionStanzaChannel.h b/Swiften/Component/ComponentSessionStanzaChannel.h index a507904..31931ea 100644 --- a/Swiften/Component/ComponentSessionStanzaChannel.h +++ b/Swiften/Component/ComponentSessionStanzaChannel.h @@ -17,40 +17,40 @@ #include <Swiften/Elements/Presence.h> namespace Swift { - /** - * StanzaChannel implementation around a ComponentSession. - */ - class SWIFTEN_API ComponentSessionStanzaChannel : public StanzaChannel { - public: - void setSession(boost::shared_ptr<ComponentSession> 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 { - return false; - } - - std::vector<Certificate::ref> getPeerCertificateChain() const { - // TODO: actually implement this method - return std::vector<Certificate::ref>(); - } - - bool isAvailable() const { - return session && session->getState() == ComponentSession::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 handleSessionInitialized(); - - private: - IDGenerator idGenerator; - boost::shared_ptr<ComponentSession> session; - }; + /** + * StanzaChannel implementation around a ComponentSession. + */ + class SWIFTEN_API ComponentSessionStanzaChannel : public StanzaChannel { + public: + void setSession(boost::shared_ptr<ComponentSession> 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 { + return false; + } + + std::vector<Certificate::ref> getPeerCertificateChain() const { + // TODO: actually implement this method + return std::vector<Certificate::ref>(); + } + + bool isAvailable() const { + return session && session->getState() == ComponentSession::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 handleSessionInitialized(); + + private: + IDGenerator idGenerator; + boost::shared_ptr<ComponentSession> session; + }; } diff --git a/Swiften/Component/ComponentXMLTracer.cpp b/Swiften/Component/ComponentXMLTracer.cpp index 49d948b..94d4ec2 100644 --- a/Swiften/Component/ComponentXMLTracer.cpp +++ b/Swiften/Component/ComponentXMLTracer.cpp @@ -13,20 +13,20 @@ namespace Swift { ComponentXMLTracer::ComponentXMLTracer(CoreComponent* client) { - client->onDataRead.connect(boost::bind(&ComponentXMLTracer::printData, '<', _1)); - client->onDataWritten.connect(boost::bind(&ComponentXMLTracer::printData, '>', _1)); + client->onDataRead.connect(boost::bind(&ComponentXMLTracer::printData, '<', _1)); + client->onDataWritten.connect(boost::bind(&ComponentXMLTracer::printData, '>', _1)); } void ComponentXMLTracer::printData(char direction, const SafeByteArray& data) { - printLine(direction); - std::cerr << byteArrayToString(ByteArray(data.begin(), data.end())) << std::endl; + printLine(direction); + std::cerr << byteArrayToString(ByteArray(data.begin(), data.end())) << std::endl; } void ComponentXMLTracer::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/Component/ComponentXMLTracer.h b/Swiften/Component/ComponentXMLTracer.h index 2c07305..d34930b 100644 --- a/Swiften/Component/ComponentXMLTracer.h +++ b/Swiften/Component/ComponentXMLTracer.h @@ -10,12 +10,12 @@ #include <Swiften/Component/Component.h> namespace Swift { - class SWIFTEN_API ComponentXMLTracer { - public: - ComponentXMLTracer(CoreComponent* component); + class SWIFTEN_API ComponentXMLTracer { + public: + ComponentXMLTracer(CoreComponent* component); - private: - static void printData(char direction, const SafeByteArray& data); - static void printLine(char c); - }; + private: + static void printData(char direction, const SafeByteArray& data); + static void printLine(char c); + }; } diff --git a/Swiften/Component/CoreComponent.cpp b/Swiften/Component/CoreComponent.cpp index fbf59f3..0b8e01c 100644 --- a/Swiften/Component/CoreComponent.cpp +++ b/Swiften/Component/CoreComponent.cpp @@ -23,148 +23,148 @@ namespace Swift { CoreComponent::CoreComponent(const JID& jid, const std::string& secret, NetworkFactories* networkFactories) : networkFactories(networkFactories), jid_(jid), secret_(secret), disconnectRequested_(false) { - stanzaChannel_ = new ComponentSessionStanzaChannel(); - stanzaChannel_->onMessageReceived.connect(boost::ref(onMessageReceived)); - stanzaChannel_->onPresenceReceived.connect(boost::ref(onPresenceReceived)); - stanzaChannel_->onAvailableChanged.connect(boost::bind(&CoreComponent::handleStanzaChannelAvailableChanged, this, _1)); + stanzaChannel_ = new ComponentSessionStanzaChannel(); + stanzaChannel_->onMessageReceived.connect(boost::ref(onMessageReceived)); + stanzaChannel_->onPresenceReceived.connect(boost::ref(onPresenceReceived)); + stanzaChannel_->onAvailableChanged.connect(boost::bind(&CoreComponent::handleStanzaChannelAvailableChanged, this, _1)); - iqRouter_ = new IQRouter(stanzaChannel_); - iqRouter_->setFrom(jid); + iqRouter_ = new IQRouter(stanzaChannel_); + iqRouter_->setFrom(jid); } CoreComponent::~CoreComponent() { - if (session_ || connection_) { - std::cerr << "Warning: Component not disconnected properly" << std::endl; - } - delete iqRouter_; - - stanzaChannel_->onAvailableChanged.disconnect(boost::bind(&CoreComponent::handleStanzaChannelAvailableChanged, this, _1)); - stanzaChannel_->onMessageReceived.disconnect(boost::ref(onMessageReceived)); - stanzaChannel_->onPresenceReceived.disconnect(boost::ref(onPresenceReceived)); - delete stanzaChannel_; + if (session_ || connection_) { + std::cerr << "Warning: Component not disconnected properly" << std::endl; + } + delete iqRouter_; + + stanzaChannel_->onAvailableChanged.disconnect(boost::bind(&CoreComponent::handleStanzaChannelAvailableChanged, this, _1)); + stanzaChannel_->onMessageReceived.disconnect(boost::ref(onMessageReceived)); + stanzaChannel_->onPresenceReceived.disconnect(boost::ref(onPresenceReceived)); + delete stanzaChannel_; } void CoreComponent::connect(const std::string& host, int port) { - assert(!connector_); - connector_ = ComponentConnector::create(host, port, networkFactories->getDomainNameResolver(), networkFactories->getConnectionFactory(), networkFactories->getTimerFactory()); - connector_->onConnectFinished.connect(boost::bind(&CoreComponent::handleConnectorFinished, this, _1)); - connector_->setTimeoutMilliseconds(60*1000); - connector_->start(); + assert(!connector_); + connector_ = ComponentConnector::create(host, port, networkFactories->getDomainNameResolver(), networkFactories->getConnectionFactory(), networkFactories->getTimerFactory()); + connector_->onConnectFinished.connect(boost::bind(&CoreComponent::handleConnectorFinished, this, _1)); + connector_->setTimeoutMilliseconds(60*1000); + connector_->start(); } void CoreComponent::handleConnectorFinished(boost::shared_ptr<Connection> connection) { - connector_->onConnectFinished.disconnect(boost::bind(&CoreComponent::handleConnectorFinished, this, _1)); - connector_.reset(); - if (!connection) { - if (!disconnectRequested_) { - onError(ComponentError::ConnectionError); - } - } - else { - assert(!connection_); - connection_ = connection; - - assert(!sessionStream_); - sessionStream_ = boost::shared_ptr<BasicSessionStream>(new BasicSessionStream(ComponentStreamType, connection_, getPayloadParserFactories(), getPayloadSerializers(), NULL, networkFactories->getTimerFactory(), networkFactories->getXMLParserFactory(), TLSOptions())); - sessionStream_->onDataRead.connect(boost::bind(&CoreComponent::handleDataRead, this, _1)); - sessionStream_->onDataWritten.connect(boost::bind(&CoreComponent::handleDataWritten, this, _1)); - - session_ = ComponentSession::create(jid_, secret_, sessionStream_, networkFactories->getCryptoProvider()); - stanzaChannel_->setSession(session_); - session_->onFinished.connect(boost::bind(&CoreComponent::handleSessionFinished, this, _1)); - session_->start(); - } + connector_->onConnectFinished.disconnect(boost::bind(&CoreComponent::handleConnectorFinished, this, _1)); + connector_.reset(); + if (!connection) { + if (!disconnectRequested_) { + onError(ComponentError::ConnectionError); + } + } + else { + assert(!connection_); + connection_ = connection; + + assert(!sessionStream_); + sessionStream_ = boost::shared_ptr<BasicSessionStream>(new BasicSessionStream(ComponentStreamType, connection_, getPayloadParserFactories(), getPayloadSerializers(), NULL, networkFactories->getTimerFactory(), networkFactories->getXMLParserFactory(), TLSOptions())); + sessionStream_->onDataRead.connect(boost::bind(&CoreComponent::handleDataRead, this, _1)); + sessionStream_->onDataWritten.connect(boost::bind(&CoreComponent::handleDataWritten, this, _1)); + + session_ = ComponentSession::create(jid_, secret_, sessionStream_, networkFactories->getCryptoProvider()); + stanzaChannel_->setSession(session_); + session_->onFinished.connect(boost::bind(&CoreComponent::handleSessionFinished, this, _1)); + session_->start(); + } } void CoreComponent::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_->finish(); - } - else if (connector_) { - connector_->stop(); - assert(!session_); - } - //assert(!session_); /* commenting out until we have time to refactor to be like CoreClient */ - //assert(!sessionStream_); - //assert(!connector_); - disconnectRequested_ = false; + // 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_->finish(); + } + else if (connector_) { + connector_->stop(); + assert(!session_); + } + //assert(!session_); /* commenting out until we have time to refactor to be like CoreClient */ + //assert(!sessionStream_); + //assert(!connector_); + disconnectRequested_ = false; } void CoreComponent::handleSessionFinished(boost::shared_ptr<Error> error) { - session_->onFinished.disconnect(boost::bind(&CoreComponent::handleSessionFinished, this, _1)); - session_.reset(); - - sessionStream_->onDataRead.disconnect(boost::bind(&CoreComponent::handleDataRead, this, _1)); - sessionStream_->onDataWritten.disconnect(boost::bind(&CoreComponent::handleDataWritten, this, _1)); - sessionStream_.reset(); - - connection_->disconnect(); - connection_.reset(); - - if (error) { - ComponentError componentError; - if (boost::shared_ptr<ComponentSession::Error> actualError = boost::dynamic_pointer_cast<ComponentSession::Error>(error)) { - switch(actualError->type) { - case ComponentSession::Error::AuthenticationFailedError: - componentError = ComponentError(ComponentError::AuthenticationFailedError); - break; - case ComponentSession::Error::UnexpectedElementError: - componentError = ComponentError(ComponentError::UnexpectedElementError); - break; - } - } - else if (boost::shared_ptr<SessionStream::SessionStreamError> actualError = boost::dynamic_pointer_cast<SessionStream::SessionStreamError>(error)) { - switch(actualError->type) { - case SessionStream::SessionStreamError::ParseError: - componentError = ComponentError(ComponentError::XMLError); - break; - case SessionStream::SessionStreamError::TLSError: - assert(false); - componentError = ComponentError(ComponentError::UnknownError); - break; - case SessionStream::SessionStreamError::InvalidTLSCertificateError: - assert(false); - componentError = ComponentError(ComponentError::UnknownError); - break; - case SessionStream::SessionStreamError::ConnectionReadError: - componentError = ComponentError(ComponentError::ConnectionReadError); - break; - case SessionStream::SessionStreamError::ConnectionWriteError: - componentError = ComponentError(ComponentError::ConnectionWriteError); - break; - } - } - onError(componentError); - } + session_->onFinished.disconnect(boost::bind(&CoreComponent::handleSessionFinished, this, _1)); + session_.reset(); + + sessionStream_->onDataRead.disconnect(boost::bind(&CoreComponent::handleDataRead, this, _1)); + sessionStream_->onDataWritten.disconnect(boost::bind(&CoreComponent::handleDataWritten, this, _1)); + sessionStream_.reset(); + + connection_->disconnect(); + connection_.reset(); + + if (error) { + ComponentError componentError; + if (boost::shared_ptr<ComponentSession::Error> actualError = boost::dynamic_pointer_cast<ComponentSession::Error>(error)) { + switch(actualError->type) { + case ComponentSession::Error::AuthenticationFailedError: + componentError = ComponentError(ComponentError::AuthenticationFailedError); + break; + case ComponentSession::Error::UnexpectedElementError: + componentError = ComponentError(ComponentError::UnexpectedElementError); + break; + } + } + else if (boost::shared_ptr<SessionStream::SessionStreamError> actualError = boost::dynamic_pointer_cast<SessionStream::SessionStreamError>(error)) { + switch(actualError->type) { + case SessionStream::SessionStreamError::ParseError: + componentError = ComponentError(ComponentError::XMLError); + break; + case SessionStream::SessionStreamError::TLSError: + assert(false); + componentError = ComponentError(ComponentError::UnknownError); + break; + case SessionStream::SessionStreamError::InvalidTLSCertificateError: + assert(false); + componentError = ComponentError(ComponentError::UnknownError); + break; + case SessionStream::SessionStreamError::ConnectionReadError: + componentError = ComponentError(ComponentError::ConnectionReadError); + break; + case SessionStream::SessionStreamError::ConnectionWriteError: + componentError = ComponentError(ComponentError::ConnectionWriteError); + break; + } + } + onError(componentError); + } } void CoreComponent::handleDataRead(const SafeByteArray& data) { - onDataRead(data); + onDataRead(data); } void CoreComponent::handleDataWritten(const SafeByteArray& data) { - onDataWritten(data); + onDataWritten(data); } void CoreComponent::handleStanzaChannelAvailableChanged(bool available) { - if (available) { - onConnected(); - } + if (available) { + onConnected(); + } } void CoreComponent::sendMessage(boost::shared_ptr<Message> message) { - stanzaChannel_->sendMessage(message); + stanzaChannel_->sendMessage(message); } void CoreComponent::sendPresence(boost::shared_ptr<Presence> presence) { - stanzaChannel_->sendPresence(presence); + stanzaChannel_->sendPresence(presence); } void CoreComponent::sendData(const std::string& data) { - sessionStream_->writeData(data); + sessionStream_->writeData(data); } } diff --git a/Swiften/Component/CoreComponent.h b/Swiften/Component/CoreComponent.h index 12b38eb..ff88173 100644 --- a/Swiften/Component/CoreComponent.h +++ b/Swiften/Component/CoreComponent.h @@ -26,79 +26,79 @@ #include <Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h> namespace Swift { - class EventLoop; - class IQRouter; - class NetworkFactories; - class ComponentSession; - class BasicSessionStream; - - /** - * The central class for communicating with an XMPP server as a component. - * - * This class is responsible for setting up the connection with the XMPP - * server and authenticating the component. - * - * This class can be used directly in your application, although the Component - * subclass provides more functionality and interfaces, and is better suited - * for most needs. - */ - class SWIFTEN_API CoreComponent : public Entity { - public: - CoreComponent(const JID& jid, const std::string& secret, NetworkFactories* networkFactories); - virtual ~CoreComponent(); - - void connect(const std::string& host, int port); - void disconnect(); - - void sendMessage(boost::shared_ptr<Message>); - void sendPresence(boost::shared_ptr<Presence>); - void sendData(const std::string& data); - - IQRouter* getIQRouter() const { - return iqRouter_; - } - - StanzaChannel* getStanzaChannel() const { - return stanzaChannel_; - } - - bool isAvailable() const { - return stanzaChannel_->isAvailable(); - } - - /** - * Returns the JID of the component - */ - const JID& getJID() const { - return jid_; - } - - public: - boost::signal<void (const ComponentError&)> onError; - boost::signal<void ()> onConnected; - boost::signal<void (const SafeByteArray&)> onDataRead; - boost::signal<void (const SafeByteArray&)> onDataWritten; - - boost::signal<void (boost::shared_ptr<Message>)> onMessageReceived; - boost::signal<void (boost::shared_ptr<Presence>) > onPresenceReceived; - - private: - void handleConnectorFinished(boost::shared_ptr<Connection>); - void handleStanzaChannelAvailableChanged(bool available); - void handleSessionFinished(boost::shared_ptr<Error>); - void handleDataRead(const SafeByteArray&); - void handleDataWritten(const SafeByteArray&); - - private: - NetworkFactories* networkFactories; - JID jid_; - std::string secret_; - ComponentSessionStanzaChannel* stanzaChannel_; - IQRouter* iqRouter_; - ComponentConnector::ref connector_; - boost::shared_ptr<Connection> connection_; - boost::shared_ptr<BasicSessionStream> sessionStream_; - boost::shared_ptr<ComponentSession> session_; - bool disconnectRequested_; - }; + class EventLoop; + class IQRouter; + class NetworkFactories; + class ComponentSession; + class BasicSessionStream; + + /** + * The central class for communicating with an XMPP server as a component. + * + * This class is responsible for setting up the connection with the XMPP + * server and authenticating the component. + * + * This class can be used directly in your application, although the Component + * subclass provides more functionality and interfaces, and is better suited + * for most needs. + */ + class SWIFTEN_API CoreComponent : public Entity { + public: + CoreComponent(const JID& jid, const std::string& secret, NetworkFactories* networkFactories); + virtual ~CoreComponent(); + + void connect(const std::string& host, int port); + void disconnect(); + + void sendMessage(boost::shared_ptr<Message>); + void sendPresence(boost::shared_ptr<Presence>); + void sendData(const std::string& data); + + IQRouter* getIQRouter() const { + return iqRouter_; + } + + StanzaChannel* getStanzaChannel() const { + return stanzaChannel_; + } + + bool isAvailable() const { + return stanzaChannel_->isAvailable(); + } + + /** + * Returns the JID of the component + */ + const JID& getJID() const { + return jid_; + } + + public: + boost::signal<void (const ComponentError&)> onError; + boost::signal<void ()> onConnected; + boost::signal<void (const SafeByteArray&)> onDataRead; + boost::signal<void (const SafeByteArray&)> onDataWritten; + + boost::signal<void (boost::shared_ptr<Message>)> onMessageReceived; + boost::signal<void (boost::shared_ptr<Presence>) > onPresenceReceived; + + private: + void handleConnectorFinished(boost::shared_ptr<Connection>); + void handleStanzaChannelAvailableChanged(bool available); + void handleSessionFinished(boost::shared_ptr<Error>); + void handleDataRead(const SafeByteArray&); + void handleDataWritten(const SafeByteArray&); + + private: + NetworkFactories* networkFactories; + JID jid_; + std::string secret_; + ComponentSessionStanzaChannel* stanzaChannel_; + IQRouter* iqRouter_; + ComponentConnector::ref connector_; + boost::shared_ptr<Connection> connection_; + boost::shared_ptr<BasicSessionStream> sessionStream_; + boost::shared_ptr<ComponentSession> session_; + bool disconnectRequested_; + }; } diff --git a/Swiften/Component/UnitTest/ComponentConnectorTest.cpp b/Swiften/Component/UnitTest/ComponentConnectorTest.cpp index 3968c2c..04a6a9e 100644 --- a/Swiften/Component/UnitTest/ComponentConnectorTest.cpp +++ b/Swiften/Component/UnitTest/ComponentConnectorTest.cpp @@ -21,190 +21,190 @@ using namespace Swift; class ComponentConnectorTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(ComponentConnectorTest); - CPPUNIT_TEST(testConnect); - CPPUNIT_TEST(testConnect_FirstAddressHostFails); - CPPUNIT_TEST(testConnect_NoHosts); - CPPUNIT_TEST(testConnect_TimeoutDuringResolve); - CPPUNIT_TEST(testConnect_TimeoutDuringConnect); - CPPUNIT_TEST(testConnect_NoTimeout); - CPPUNIT_TEST(testStop_Timeout); - CPPUNIT_TEST_SUITE_END(); - - public: - void setUp() { - host1 = HostAddress("1.1.1.1"); - host2 = HostAddress("2.2.2.2"); - eventLoop = new DummyEventLoop(); - resolver = new StaticDomainNameResolver(eventLoop); - connectionFactory = new MockConnectionFactory(eventLoop); - timerFactory = new DummyTimerFactory(); - } - - void tearDown() { - delete timerFactory; - delete connectionFactory; - delete resolver; - delete eventLoop; - } - - void testConnect() { - ComponentConnector::ref testling(createConnector("foo.com", 1234)); - resolver->addAddress("foo.com", host1); - - testling->start(); - eventLoop->processEvents(); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); - CPPUNIT_ASSERT(connections[0]); - CPPUNIT_ASSERT(HostAddressPort(host1, 1234) == *(connections[0]->hostAddressPort)); - } - - void testConnect_FirstAddressHostFails() { - ComponentConnector::ref testling(createConnector("foo.com", 1234)); - resolver->addAddress("foo.com", host1); - resolver->addAddress("foo.com", host2); - connectionFactory->failingPorts.push_back(HostAddressPort(host1, 1234)); - - testling->start(); - eventLoop->processEvents(); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); - CPPUNIT_ASSERT(connections[0]); - CPPUNIT_ASSERT(HostAddressPort(host2, 1234) == *(connections[0]->hostAddressPort)); - } - - void testConnect_NoHosts() { - ComponentConnector::ref testling(createConnector("foo.com", 1234)); - - testling->start(); - eventLoop->processEvents(); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); - CPPUNIT_ASSERT(!connections[0]); - } - - - void testConnect_TimeoutDuringResolve() { - ComponentConnector::ref testling(createConnector("foo.com", 1234)); - - testling->setTimeoutMilliseconds(10); - resolver->setIsResponsive(false); - - testling->start(); - eventLoop->processEvents(); - timerFactory->setTime(10); - eventLoop->processEvents(); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); - CPPUNIT_ASSERT(!connections[0]); - } - - void testConnect_TimeoutDuringConnect() { - ComponentConnector::ref testling(createConnector("foo.com", 1234)); - testling->setTimeoutMilliseconds(10); - resolver->addAddress("foo.com", host1); - connectionFactory->isResponsive = false; - - testling->start(); - eventLoop->processEvents(); - timerFactory->setTime(10); - eventLoop->processEvents(); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); - CPPUNIT_ASSERT(!connections[0]); - } - - void testConnect_NoTimeout() { - ComponentConnector::ref testling(createConnector("foo.com", 1234)); - testling->setTimeoutMilliseconds(10); - resolver->addAddress("foo.com", host1); - - testling->start(); - eventLoop->processEvents(); - timerFactory->setTime(10); - eventLoop->processEvents(); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); - CPPUNIT_ASSERT(connections[0]); - } - - void testStop_Timeout() { - ComponentConnector::ref testling(createConnector("foo.com", 1234)); - testling->setTimeoutMilliseconds(10); - resolver->addAddress("foo.com", host1); - - testling->start(); - testling->stop(); - - eventLoop->processEvents(); - timerFactory->setTime(10); - eventLoop->processEvents(); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); - CPPUNIT_ASSERT(!connections[0]); - } - - private: - ComponentConnector::ref createConnector(const std::string& hostname, int port) { - ComponentConnector::ref connector = ComponentConnector::create(hostname, port, resolver, connectionFactory, timerFactory); - connector->onConnectFinished.connect(boost::bind(&ComponentConnectorTest::handleConnectorFinished, this, _1)); - return connector; - } - - void handleConnectorFinished(boost::shared_ptr<Connection> connection) { - boost::shared_ptr<MockConnection> c(boost::dynamic_pointer_cast<MockConnection>(connection)); - if (connection) { - assert(c); - } - connections.push_back(c); - } - - struct MockConnection : public Connection { - public: - MockConnection(const std::vector<HostAddressPort>& failingPorts, bool isResponsive, EventLoop* eventLoop) : eventLoop(eventLoop), failingPorts(failingPorts), isResponsive(isResponsive) {} - - void listen() { assert(false); } - void connect(const HostAddressPort& address) { - hostAddressPort = address; - if (isResponsive) { - bool fail = std::find(failingPorts.begin(), failingPorts.end(), address) != failingPorts.end(); - eventLoop->postEvent(boost::bind(boost::ref(onConnectFinished), fail)); - } - } - - void disconnect() { assert(false); } - void write(const SafeByteArray&) { assert(false); } - HostAddressPort getLocalAddress() const { return HostAddressPort(); } - HostAddressPort getRemoteAddress() const { return HostAddressPort(); } - - EventLoop* eventLoop; - boost::optional<HostAddressPort> hostAddressPort; - std::vector<HostAddressPort> failingPorts; - bool isResponsive; - }; - - struct MockConnectionFactory : public ConnectionFactory { - MockConnectionFactory(EventLoop* eventLoop) : eventLoop(eventLoop), isResponsive(true) { - } - - boost::shared_ptr<Connection> createConnection() { - return boost::shared_ptr<Connection>(new MockConnection(failingPorts, isResponsive, eventLoop)); - } - - EventLoop* eventLoop; - bool isResponsive; - std::vector<HostAddressPort> failingPorts; - }; - - private: - HostAddress host1; - HostAddress host2; - DummyEventLoop* eventLoop; - StaticDomainNameResolver* resolver; - MockConnectionFactory* connectionFactory; - DummyTimerFactory* timerFactory; - std::vector< boost::shared_ptr<MockConnection> > connections; + CPPUNIT_TEST_SUITE(ComponentConnectorTest); + CPPUNIT_TEST(testConnect); + CPPUNIT_TEST(testConnect_FirstAddressHostFails); + CPPUNIT_TEST(testConnect_NoHosts); + CPPUNIT_TEST(testConnect_TimeoutDuringResolve); + CPPUNIT_TEST(testConnect_TimeoutDuringConnect); + CPPUNIT_TEST(testConnect_NoTimeout); + CPPUNIT_TEST(testStop_Timeout); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + host1 = HostAddress("1.1.1.1"); + host2 = HostAddress("2.2.2.2"); + eventLoop = new DummyEventLoop(); + resolver = new StaticDomainNameResolver(eventLoop); + connectionFactory = new MockConnectionFactory(eventLoop); + timerFactory = new DummyTimerFactory(); + } + + void tearDown() { + delete timerFactory; + delete connectionFactory; + delete resolver; + delete eventLoop; + } + + void testConnect() { + ComponentConnector::ref testling(createConnector("foo.com", 1234)); + resolver->addAddress("foo.com", host1); + + testling->start(); + eventLoop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); + CPPUNIT_ASSERT(connections[0]); + CPPUNIT_ASSERT(HostAddressPort(host1, 1234) == *(connections[0]->hostAddressPort)); + } + + void testConnect_FirstAddressHostFails() { + ComponentConnector::ref testling(createConnector("foo.com", 1234)); + resolver->addAddress("foo.com", host1); + resolver->addAddress("foo.com", host2); + connectionFactory->failingPorts.push_back(HostAddressPort(host1, 1234)); + + testling->start(); + eventLoop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); + CPPUNIT_ASSERT(connections[0]); + CPPUNIT_ASSERT(HostAddressPort(host2, 1234) == *(connections[0]->hostAddressPort)); + } + + void testConnect_NoHosts() { + ComponentConnector::ref testling(createConnector("foo.com", 1234)); + + testling->start(); + eventLoop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); + CPPUNIT_ASSERT(!connections[0]); + } + + + void testConnect_TimeoutDuringResolve() { + ComponentConnector::ref testling(createConnector("foo.com", 1234)); + + testling->setTimeoutMilliseconds(10); + resolver->setIsResponsive(false); + + testling->start(); + eventLoop->processEvents(); + timerFactory->setTime(10); + eventLoop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); + CPPUNIT_ASSERT(!connections[0]); + } + + void testConnect_TimeoutDuringConnect() { + ComponentConnector::ref testling(createConnector("foo.com", 1234)); + testling->setTimeoutMilliseconds(10); + resolver->addAddress("foo.com", host1); + connectionFactory->isResponsive = false; + + testling->start(); + eventLoop->processEvents(); + timerFactory->setTime(10); + eventLoop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); + CPPUNIT_ASSERT(!connections[0]); + } + + void testConnect_NoTimeout() { + ComponentConnector::ref testling(createConnector("foo.com", 1234)); + testling->setTimeoutMilliseconds(10); + resolver->addAddress("foo.com", host1); + + testling->start(); + eventLoop->processEvents(); + timerFactory->setTime(10); + eventLoop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); + CPPUNIT_ASSERT(connections[0]); + } + + void testStop_Timeout() { + ComponentConnector::ref testling(createConnector("foo.com", 1234)); + testling->setTimeoutMilliseconds(10); + resolver->addAddress("foo.com", host1); + + testling->start(); + testling->stop(); + + eventLoop->processEvents(); + timerFactory->setTime(10); + eventLoop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(connections.size())); + CPPUNIT_ASSERT(!connections[0]); + } + + private: + ComponentConnector::ref createConnector(const std::string& hostname, int port) { + ComponentConnector::ref connector = ComponentConnector::create(hostname, port, resolver, connectionFactory, timerFactory); + connector->onConnectFinished.connect(boost::bind(&ComponentConnectorTest::handleConnectorFinished, this, _1)); + return connector; + } + + void handleConnectorFinished(boost::shared_ptr<Connection> connection) { + boost::shared_ptr<MockConnection> c(boost::dynamic_pointer_cast<MockConnection>(connection)); + if (connection) { + assert(c); + } + connections.push_back(c); + } + + struct MockConnection : public Connection { + public: + MockConnection(const std::vector<HostAddressPort>& failingPorts, bool isResponsive, EventLoop* eventLoop) : eventLoop(eventLoop), failingPorts(failingPorts), isResponsive(isResponsive) {} + + void listen() { assert(false); } + void connect(const HostAddressPort& address) { + hostAddressPort = address; + if (isResponsive) { + bool fail = std::find(failingPorts.begin(), failingPorts.end(), address) != failingPorts.end(); + eventLoop->postEvent(boost::bind(boost::ref(onConnectFinished), fail)); + } + } + + void disconnect() { assert(false); } + void write(const SafeByteArray&) { assert(false); } + HostAddressPort getLocalAddress() const { return HostAddressPort(); } + HostAddressPort getRemoteAddress() const { return HostAddressPort(); } + + EventLoop* eventLoop; + boost::optional<HostAddressPort> hostAddressPort; + std::vector<HostAddressPort> failingPorts; + bool isResponsive; + }; + + struct MockConnectionFactory : public ConnectionFactory { + MockConnectionFactory(EventLoop* eventLoop) : eventLoop(eventLoop), isResponsive(true) { + } + + boost::shared_ptr<Connection> createConnection() { + return boost::shared_ptr<Connection>(new MockConnection(failingPorts, isResponsive, eventLoop)); + } + + EventLoop* eventLoop; + bool isResponsive; + std::vector<HostAddressPort> failingPorts; + }; + + private: + HostAddress host1; + HostAddress host2; + DummyEventLoop* eventLoop; + StaticDomainNameResolver* resolver; + MockConnectionFactory* connectionFactory; + DummyTimerFactory* timerFactory; + std::vector< boost::shared_ptr<MockConnection> > connections; }; CPPUNIT_TEST_SUITE_REGISTRATION(ComponentConnectorTest); diff --git a/Swiften/Component/UnitTest/ComponentHandshakeGeneratorTest.cpp b/Swiften/Component/UnitTest/ComponentHandshakeGeneratorTest.cpp index 570ccf1..82f43f6 100644 --- a/Swiften/Component/UnitTest/ComponentHandshakeGeneratorTest.cpp +++ b/Swiften/Component/UnitTest/ComponentHandshakeGeneratorTest.cpp @@ -14,28 +14,28 @@ using namespace Swift; class ComponentHandshakeGeneratorTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(ComponentHandshakeGeneratorTest); - CPPUNIT_TEST(testGetHandshake); - CPPUNIT_TEST(testGetHandshake_SpecialChars); - CPPUNIT_TEST_SUITE_END(); - - public: - void setUp() { - crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); - } - - void testGetHandshake() { - std::string result = ComponentHandshakeGenerator::getHandshake("myid", "mysecret", crypto.get()); - CPPUNIT_ASSERT_EQUAL(std::string("4011cd31f9b99ac089a0cd7ce297da7323fa2525"), result); - } - - void testGetHandshake_SpecialChars() { - std::string result = ComponentHandshakeGenerator::getHandshake("&<", ">'\"", crypto.get()); - CPPUNIT_ASSERT_EQUAL(std::string("33631b3e0aaeb2a11c4994c917919324028873fe"), result); - } - - private: - boost::shared_ptr<CryptoProvider> crypto; + CPPUNIT_TEST_SUITE(ComponentHandshakeGeneratorTest); + CPPUNIT_TEST(testGetHandshake); + CPPUNIT_TEST(testGetHandshake_SpecialChars); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); + } + + void testGetHandshake() { + std::string result = ComponentHandshakeGenerator::getHandshake("myid", "mysecret", crypto.get()); + CPPUNIT_ASSERT_EQUAL(std::string("4011cd31f9b99ac089a0cd7ce297da7323fa2525"), result); + } + + void testGetHandshake_SpecialChars() { + std::string result = ComponentHandshakeGenerator::getHandshake("&<", ">'\"", crypto.get()); + CPPUNIT_ASSERT_EQUAL(std::string("33631b3e0aaeb2a11c4994c917919324028873fe"), result); + } + + private: + boost::shared_ptr<CryptoProvider> crypto; }; CPPUNIT_TEST_SUITE_REGISTRATION(ComponentHandshakeGeneratorTest); diff --git a/Swiften/Component/UnitTest/ComponentSessionTest.cpp b/Swiften/Component/UnitTest/ComponentSessionTest.cpp index 61c8ce9..1726794 100644 --- a/Swiften/Component/UnitTest/ComponentSessionTest.cpp +++ b/Swiften/Component/UnitTest/ComponentSessionTest.cpp @@ -22,201 +22,201 @@ using namespace Swift; class ComponentSessionTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(ComponentSessionTest); - CPPUNIT_TEST(testStart); - CPPUNIT_TEST(testStart_Error); - CPPUNIT_TEST(testStart_Unauthorized); - CPPUNIT_TEST_SUITE_END(); - - public: - void setUp() { - server = boost::make_shared<MockSessionStream>(); - sessionFinishedReceived = false; - crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); - } - - void testStart() { - boost::shared_ptr<ComponentSession> session(createSession()); - session->start(); - server->receiveStreamStart(); - server->sendStreamStart(); - server->receiveHandshake(); - server->sendHandshakeResponse(); - - CPPUNIT_ASSERT(server->whitespacePingEnabled); - - session->finish(); - CPPUNIT_ASSERT(!server->whitespacePingEnabled); - - } - - void testStart_Error() { - boost::shared_ptr<ComponentSession> session(createSession()); - session->start(); - server->breakConnection(); - - CPPUNIT_ASSERT_EQUAL(ComponentSession::Finished, session->getState()); - CPPUNIT_ASSERT(sessionFinishedReceived); - CPPUNIT_ASSERT(sessionFinishedError); - } - - void testStart_Unauthorized() { - boost::shared_ptr<ComponentSession> session(createSession()); - session->start(); - server->receiveStreamStart(); - server->sendStreamStart(); - server->receiveHandshake(); - server->sendHandshakeError(); - - CPPUNIT_ASSERT_EQUAL(ComponentSession::Finished, session->getState()); - CPPUNIT_ASSERT(sessionFinishedReceived); - CPPUNIT_ASSERT(sessionFinishedError); - } - - private: - boost::shared_ptr<ComponentSession> createSession() { - boost::shared_ptr<ComponentSession> session = ComponentSession::create(JID("service.foo.com"), "servicesecret", server, crypto.get()); - session->onFinished.connect(boost::bind(&ComponentSessionTest::handleSessionFinished, this, _1)); - return session; - } - - void handleSessionFinished(boost::shared_ptr<Error> error) { - sessionFinishedReceived = true; - sessionFinishedError = error; - } - - 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), 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 false; - } - - virtual void addTLSEncryption() { - assert(false); - } - - virtual bool isTLSEncrypted() { - return false; - } - - virtual ByteArray getTLSFinishMessage() const { - return ByteArray(); - } - - virtual Certificate::ref getPeerCertificate() const { - return Certificate::ref(); - } - - 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() { - assert(false); - } - - virtual void setWhitespacePingEnabled(bool enabled) { - whitespacePingEnabled = enabled; - } - - virtual void resetXMPPParser() { - resetCount++; - } - - void breakConnection() { - onClosed(boost::make_shared<SessionStream::SessionStreamError>(SessionStream::SessionStreamError::ConnectionReadError)); - } - - void sendStreamStart() { - ProtocolHeader header; - header.setFrom("service.foo.com"); - return onStreamStartReceived(header); - } - - void sendHandshakeResponse() { - onElementReceived(ComponentHandshake::ref(new ComponentHandshake())); - } - - void sendHandshakeError() { - // FIXME: This isn't the correct element - onElementReceived(AuthFailure::ref(new AuthFailure())); - } - - void receiveStreamStart() { - Event event = popEvent(); - CPPUNIT_ASSERT(event.header); - } - - void receiveHandshake() { - Event event = popEvent(); - CPPUNIT_ASSERT(event.element); - ComponentHandshake::ref handshake(boost::dynamic_pointer_cast<ComponentHandshake>(event.element)); - CPPUNIT_ASSERT(handshake); - CPPUNIT_ASSERT_EQUAL(std::string("4c4f8a41141722c8bbfbdd92d827f7b2fc0a542b"), handshake->getData()); - } - - Event popEvent() { - CPPUNIT_ASSERT(!receivedEvents.empty()); - Event event = receivedEvents.front(); - receivedEvents.pop_front(); - return event; - } - - bool available; - bool whitespacePingEnabled; - std::string bindID; - int resetCount; - std::deque<Event> receivedEvents; - }; - - boost::shared_ptr<MockSessionStream> server; - bool sessionFinishedReceived; - boost::shared_ptr<Error> sessionFinishedError; - boost::shared_ptr<CryptoProvider> crypto; + CPPUNIT_TEST_SUITE(ComponentSessionTest); + CPPUNIT_TEST(testStart); + CPPUNIT_TEST(testStart_Error); + CPPUNIT_TEST(testStart_Unauthorized); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + server = boost::make_shared<MockSessionStream>(); + sessionFinishedReceived = false; + crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); + } + + void testStart() { + boost::shared_ptr<ComponentSession> session(createSession()); + session->start(); + server->receiveStreamStart(); + server->sendStreamStart(); + server->receiveHandshake(); + server->sendHandshakeResponse(); + + CPPUNIT_ASSERT(server->whitespacePingEnabled); + + session->finish(); + CPPUNIT_ASSERT(!server->whitespacePingEnabled); + + } + + void testStart_Error() { + boost::shared_ptr<ComponentSession> session(createSession()); + session->start(); + server->breakConnection(); + + CPPUNIT_ASSERT_EQUAL(ComponentSession::Finished, session->getState()); + CPPUNIT_ASSERT(sessionFinishedReceived); + CPPUNIT_ASSERT(sessionFinishedError); + } + + void testStart_Unauthorized() { + boost::shared_ptr<ComponentSession> session(createSession()); + session->start(); + server->receiveStreamStart(); + server->sendStreamStart(); + server->receiveHandshake(); + server->sendHandshakeError(); + + CPPUNIT_ASSERT_EQUAL(ComponentSession::Finished, session->getState()); + CPPUNIT_ASSERT(sessionFinishedReceived); + CPPUNIT_ASSERT(sessionFinishedError); + } + + private: + boost::shared_ptr<ComponentSession> createSession() { + boost::shared_ptr<ComponentSession> session = ComponentSession::create(JID("service.foo.com"), "servicesecret", server, crypto.get()); + session->onFinished.connect(boost::bind(&ComponentSessionTest::handleSessionFinished, this, _1)); + return session; + } + + void handleSessionFinished(boost::shared_ptr<Error> error) { + sessionFinishedReceived = true; + sessionFinishedError = error; + } + + 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), 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 false; + } + + virtual void addTLSEncryption() { + assert(false); + } + + virtual bool isTLSEncrypted() { + return false; + } + + virtual ByteArray getTLSFinishMessage() const { + return ByteArray(); + } + + virtual Certificate::ref getPeerCertificate() const { + return Certificate::ref(); + } + + 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() { + assert(false); + } + + virtual void setWhitespacePingEnabled(bool enabled) { + whitespacePingEnabled = enabled; + } + + virtual void resetXMPPParser() { + resetCount++; + } + + void breakConnection() { + onClosed(boost::make_shared<SessionStream::SessionStreamError>(SessionStream::SessionStreamError::ConnectionReadError)); + } + + void sendStreamStart() { + ProtocolHeader header; + header.setFrom("service.foo.com"); + return onStreamStartReceived(header); + } + + void sendHandshakeResponse() { + onElementReceived(ComponentHandshake::ref(new ComponentHandshake())); + } + + void sendHandshakeError() { + // FIXME: This isn't the correct element + onElementReceived(AuthFailure::ref(new AuthFailure())); + } + + void receiveStreamStart() { + Event event = popEvent(); + CPPUNIT_ASSERT(event.header); + } + + void receiveHandshake() { + Event event = popEvent(); + CPPUNIT_ASSERT(event.element); + ComponentHandshake::ref handshake(boost::dynamic_pointer_cast<ComponentHandshake>(event.element)); + CPPUNIT_ASSERT(handshake); + CPPUNIT_ASSERT_EQUAL(std::string("4c4f8a41141722c8bbfbdd92d827f7b2fc0a542b"), handshake->getData()); + } + + Event popEvent() { + CPPUNIT_ASSERT(!receivedEvents.empty()); + Event event = receivedEvents.front(); + receivedEvents.pop_front(); + return event; + } + + bool available; + bool whitespacePingEnabled; + std::string bindID; + int resetCount; + std::deque<Event> receivedEvents; + }; + + boost::shared_ptr<MockSessionStream> server; + bool sessionFinishedReceived; + boost::shared_ptr<Error> sessionFinishedError; + boost::shared_ptr<CryptoProvider> crypto; }; CPPUNIT_TEST_SUITE_REGISTRATION(ComponentSessionTest); |