diff options
Diffstat (limited to 'Swiften/Component')
19 files changed, 1017 insertions, 1013 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 9d8b5d3..a7ef621 100644 --- a/Swiften/Component/Component.h +++ b/Swiften/Component/Component.h @@ -6,32 +6,31 @@ #pragma once -#include <Swiften/Component/CoreComponent.h> - #include <Swiften/Base/API.h> +#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 072fd73..a7375a7 100644 --- a/Swiften/Component/ComponentConnector.cpp +++ b/Swiften/Component/ComponentConnector.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ @@ -7,11 +7,10 @@ #include <Swiften/Component/ComponentConnector.h> #include <boost/bind.hpp> -#include <iostream> #include <Swiften/Network/ConnectionFactory.h> -#include <Swiften/Network/DomainNameResolver.h> #include <Swiften/Network/DomainNameAddressQuery.h> +#include <Swiften/Network/DomainNameResolver.h> #include <Swiften/Network/TimerFactory.h> namespace Swift { @@ -20,88 +19,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(std::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(std::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(std::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); +void ComponentConnector::finish(std::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); } void ComponentConnector::handleTimeout() { - finish(boost::shared_ptr<Connection>()); + finish(std::shared_ptr<Connection>()); } } diff --git a/Swiften/Component/ComponentConnector.h b/Swiften/Component/ComponentConnector.h index e5acdb0..ab36901 100644 --- a/Swiften/Component/ComponentConnector.h +++ b/Swiften/Component/ComponentConnector.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ @@ -7,59 +7,60 @@ #pragma once #include <deque> -#include <Swiften/Base/boost_bsignals.h> -#include <boost/shared_ptr.hpp> +#include <memory> +#include <string> + +#include <boost/signals2.hpp> #include <Swiften/Base/API.h> #include <Swiften/Network/Connection.h> -#include <Swiften/Network/Timer.h> -#include <Swiften/Network/HostAddressPort.h> -#include <string> #include <Swiften/Network/DomainNameResolveError.h> +#include <Swiften/Network/HostAddressPort.h> +#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::signals2::trackable, public std::enable_shared_from_this<ComponentConnector> { + public: + typedef std::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::signals2::signal<void (std::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(std::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; + std::shared_ptr<Timer> timer; + std::shared_ptr<DomainNameAddressQuery> addressQuery; + std::deque<HostAddress> addressQueryResults; + std::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 8914686..647b3da 100644 --- a/Swiften/Component/ComponentHandshakeGenerator.cpp +++ b/Swiften/Component/ComponentHandshakeGenerator.cpp @@ -1,24 +1,25 @@ /* - * Copyright (c) 2010 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #include <Swiften/Component/ComponentHandshakeGenerator.h> -#include <Swiften/StringCodecs/Hexify.h> + #include <Swiften/Base/String.h> #include <Swiften/Crypto/CryptoProvider.h> +#include <Swiften/StringCodecs/Hexify.h> 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 d69790f..0805ac1 100644 --- a/Swiften/Component/ComponentSession.cpp +++ b/Swiften/Component/ComponentSession.cpp @@ -1,122 +1,123 @@ /* - * Copyright (c) 2010-2014 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #include <Swiften/Component/ComponentSession.h> +#include <memory> + #include <boost/bind.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <Swiften/Component/ComponentHandshakeGenerator.h> +#include <Swiften/Elements/ComponentHandshake.h> #include <Swiften/Elements/ProtocolHeader.h> #include <Swiften/Elements/StreamFeatures.h> -#include <Swiften/Elements/ComponentHandshake.h> #include <Swiften/Session/SessionStream.h> -#include <Swiften/Component/ComponentHandshakeGenerator.h> namespace Swift { -ComponentSession::ComponentSession(const JID& jid, const std::string& secret, boost::shared_ptr<SessionStream> stream, CryptoProvider* crypto) : jid(jid), secret(secret), stream(stream), crypto(crypto), state(Initial) { +ComponentSession::ComponentSession(const JID& jid, const std::string& secret, std::shared_ptr<SessionStream> stream, CryptoProvider* crypto) : jid(jid), secret(secret), stream(stream), crypto(crypto), state(Initial) { } 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); +void ComponentSession::sendStanza(std::shared_ptr<Stanza> 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); - } +void ComponentSession::handleElement(std::shared_ptr<ToplevelElement> element) { + if (std::shared_ptr<Stanza> stanza = std::dynamic_pointer_cast<Stanza>(element)) { + if (getState() == Initialized) { + onStanzaReceived(stanza); + } + else { + finishSession(Error::UnexpectedElementError); + } + } + else if (std::dynamic_pointer_cast<ComponentHandshake>(element)) { + if (!checkState(Authenticating)) { + return; + } + stream->setWhitespacePingEnabled(true); + state = Initialized; + onInitialized(); + } + else if (getState() == Authenticating) { + if (std::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); - } +void ComponentSession::handleStreamClosed(std::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); + } } void ComponentSession::finish() { - finishSession(boost::shared_ptr<Error>()); + finishSession(std::shared_ptr<Error>()); } void ComponentSession::finishSession(Error::Type error) { - finishSession(boost::make_shared<Swift::ComponentSession::Error>(error)); + finishSession(std::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(); +void ComponentSession::finishSession(std::shared_ptr<Swift::Error> finishError) { + state = Finishing; + error = finishError; + assert(stream->isOpen()); + stream->writeFooter(); + stream->close(); } } diff --git a/Swiften/Component/ComponentSession.h b/Swiften/Component/ComponentSession.h index 0b8c55c..9d963a1 100644 --- a/Swiften/Component/ComponentSession.h +++ b/Swiften/Component/ComponentSession.h @@ -1,86 +1,86 @@ /* - * Copyright (c) 2010-2014 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> -#include <boost/enable_shared_from_this.hpp> +#include <memory> +#include <string> + +#include <boost/signals2.hpp> #include <Swiften/Base/API.h> -#include <Swiften/JID/JID.h> -#include <Swiften/Base/boost_bsignals.h> #include <Swiften/Base/Error.h> -#include <string> -#include <Swiften/Elements/ToplevelElement.h> #include <Swiften/Elements/Stanza.h> +#include <Swiften/Elements/ToplevelElement.h> +#include <Swiften/JID/JID.h> #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 std::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 std::shared_ptr<ComponentSession> create(const JID& jid, const std::string& secret, std::shared_ptr<SessionStream> stream, CryptoProvider* crypto) { + return std::shared_ptr<ComponentSession>(new ComponentSession(jid, secret, stream, crypto)); + } + + State getState() const { + return state; + } + + void start(); + void finish(); + + void sendStanza(std::shared_ptr<Stanza>); + + public: + boost::signals2::signal<void ()> onInitialized; + boost::signals2::signal<void (std::shared_ptr<Swift::Error>)> onFinished; + boost::signals2::signal<void (std::shared_ptr<Stanza>)> onStanzaReceived; + + private: + ComponentSession(const JID& jid, const std::string& secret, std::shared_ptr<SessionStream>, CryptoProvider*); + + void finishSession(Error::Type error); + void finishSession(std::shared_ptr<Swift::Error> error); + + void sendStreamHeader(); + + void handleElement(std::shared_ptr<ToplevelElement>); + void handleStreamStart(const ProtocolHeader&); + void handleStreamClosed(std::shared_ptr<Swift::Error>); + + bool checkState(State); + + private: + JID jid; + std::string secret; + std::shared_ptr<SessionStream> stream; + CryptoProvider* crypto; + std::shared_ptr<Swift::Error> error; + State state; + }; } diff --git a/Swiften/Component/ComponentSessionStanzaChannel.cpp b/Swiften/Component/ComponentSessionStanzaChannel.cpp index fa58d4b..fd61594 100644 --- a/Swiften/Component/ComponentSessionStanzaChannel.cpp +++ b/Swiften/Component/ComponentSessionStanzaChannel.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ @@ -7,73 +7,74 @@ #include <Swiften/Component/ComponentSessionStanzaChannel.h> #include <boost/bind.hpp> -#include <iostream> + +#include <Swiften/Base/Log.h> 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)); +void ComponentSessionStanzaChannel::setSession(std::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)); } -void ComponentSessionStanzaChannel::sendIQ(boost::shared_ptr<IQ> iq) { - send(iq); +void ComponentSessionStanzaChannel::sendIQ(std::shared_ptr<IQ> iq) { + send(iq); } -void ComponentSessionStanzaChannel::sendMessage(boost::shared_ptr<Message> message) { - send(message); +void ComponentSessionStanzaChannel::sendMessage(std::shared_ptr<Message> message) { + send(message); } -void ComponentSessionStanzaChannel::sendPresence(boost::shared_ptr<Presence> presence) { - send(presence); +void ComponentSessionStanzaChannel::sendPresence(std::shared_ptr<Presence> 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); +void ComponentSessionStanzaChannel::send(std::shared_ptr<Stanza> stanza) { + if (!isAvailable()) { + SWIFT_LOG(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(); +void ComponentSessionStanzaChannel::handleSessionFinished(std::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(); - 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; - } +void ComponentSessionStanzaChannel::handleStanza(std::shared_ptr<Stanza> stanza) { + std::shared_ptr<Message> message = std::dynamic_pointer_cast<Message>(stanza); + if (message) { + onMessageReceived(message); + return; + } + + std::shared_ptr<Presence> presence = std::dynamic_pointer_cast<Presence>(stanza); + if (presence) { + onPresenceReceived(presence); + return; + } + + std::shared_ptr<IQ> iq = std::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 f0f4abd..ad38edc 100644 --- a/Swiften/Component/ComponentSessionStanzaChannel.h +++ b/Swiften/Component/ComponentSessionStanzaChannel.h @@ -1,56 +1,56 @@ /* - * Copyright (c) 2010-2015 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> #include <Swiften/Base/API.h> #include <Swiften/Base/IDGenerator.h> -#include <Swiften/Component/ComponentSession.h> #include <Swiften/Client/StanzaChannel.h> -#include <Swiften/Elements/Message.h> +#include <Swiften/Component/ComponentSession.h> #include <Swiften/Elements/IQ.h> +#include <Swiften/Elements/Message.h> #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(std::shared_ptr<ComponentSession> session); + + void sendIQ(std::shared_ptr<IQ> iq); + void sendMessage(std::shared_ptr<Message> message); + void sendPresence(std::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(std::shared_ptr<Stanza> stanza); + void handleSessionFinished(std::shared_ptr<Error> error); + void handleStanza(std::shared_ptr<Stanza> stanza); + void handleSessionInitialized(); + + private: + IDGenerator idGenerator; + std::shared_ptr<ComponentSession> session; + }; } diff --git a/Swiften/Component/ComponentXMLTracer.cpp b/Swiften/Component/ComponentXMLTracer.cpp index 8efc774..94d4ec2 100644 --- a/Swiften/Component/ComponentXMLTracer.cpp +++ b/Swiften/Component/ComponentXMLTracer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ @@ -7,25 +7,26 @@ #include <Swiften/Component/ComponentXMLTracer.h> #include <iostream> + #include <boost/bind.hpp> 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 358b0c6..3896bdd 100644 --- a/Swiften/Component/CoreComponent.cpp +++ b/Swiften/Component/CoreComponent.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2015 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ @@ -7,9 +7,9 @@ #include <Swiften/Component/CoreComponent.h> #include <boost/bind.hpp> -#include <iostream> #include <Swiften/Base/IDGenerator.h> +#include <Swiften/Base/Log.h> #include <Swiften/Component/ComponentSession.h> #include <Swiften/Component/ComponentSessionStanzaChannel.h> #include <Swiften/Network/Connector.h> @@ -19,152 +19,151 @@ #include <Swiften/TLS/PKCS12Certificate.h> #include <Swiften/TLS/TLSOptions.h> - 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_) { + SWIFT_LOG(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(); - } +void CoreComponent::handleConnectorFinished(std::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_ = std::make_shared<BasicSessionStream>(ComponentStreamType, connection_, getPayloadParserFactories(), getPayloadSerializers(), nullptr, 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); - } +void CoreComponent::handleSessionFinished(std::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 (std::shared_ptr<ComponentSession::Error> actualError = std::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 (std::shared_ptr<SessionStream::SessionStreamError> actualError = std::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); +void CoreComponent::sendMessage(std::shared_ptr<Message> message) { + stanzaChannel_->sendMessage(message); } -void CoreComponent::sendPresence(boost::shared_ptr<Presence> presence) { - stanzaChannel_->sendPresence(presence); +void CoreComponent::sendPresence(std::shared_ptr<Presence> 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..669be97 100644 --- a/Swiften/Component/CoreComponent.h +++ b/Swiften/Component/CoreComponent.h @@ -6,14 +6,14 @@ #pragma once +#include <memory> #include <string> -#include <boost/shared_ptr.hpp> +#include <boost/signals2.hpp> #include <Swiften/Base/API.h> #include <Swiften/Base/Error.h> #include <Swiften/Base/SafeByteArray.h> -#include <Swiften/Base/boost_bsignals.h> #include <Swiften/Component/ComponentConnector.h> #include <Swiften/Component/ComponentError.h> #include <Swiften/Component/ComponentSession.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(std::shared_ptr<Message>); + void sendPresence(std::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::signals2::signal<void (const ComponentError&)> onError; + boost::signals2::signal<void ()> onConnected; + boost::signals2::signal<void (const SafeByteArray&)> onDataRead; + boost::signals2::signal<void (const SafeByteArray&)> onDataWritten; + + boost::signals2::signal<void (std::shared_ptr<Message>)> onMessageReceived; + boost::signals2::signal<void (std::shared_ptr<Presence>) > onPresenceReceived; + + private: + void handleConnectorFinished(std::shared_ptr<Connection>); + void handleStanzaChannelAvailableChanged(bool available); + void handleSessionFinished(std::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_; + std::shared_ptr<Connection> connection_; + std::shared_ptr<BasicSessionStream> sessionStream_; + std::shared_ptr<ComponentSession> session_; + bool disconnectRequested_; + }; } diff --git a/Swiften/Component/SConscript b/Swiften/Component/SConscript index ef5700c..2553ac6 100644 --- a/Swiften/Component/SConscript +++ b/Swiften/Component/SConscript @@ -1,13 +1,13 @@ Import("swiften_env") sources = [ - "ComponentHandshakeGenerator.cpp", - "ComponentConnector.cpp", - "ComponentSession.cpp", - "ComponentSessionStanzaChannel.cpp", - "CoreComponent.cpp", - "Component.cpp", - "ComponentXMLTracer.cpp", - ] + "ComponentHandshakeGenerator.cpp", + "ComponentConnector.cpp", + "ComponentSession.cpp", + "ComponentSessionStanzaChannel.cpp", + "CoreComponent.cpp", + "Component.cpp", + "ComponentXMLTracer.cpp", + ] swiften_env.Append(SWIFTEN_OBJECTS = swiften_env.SwiftenObject(sources)) diff --git a/Swiften/Component/UnitTest/ComponentConnectorTest.cpp b/Swiften/Component/UnitTest/ComponentConnectorTest.cpp index 3968c2c..3b4fa83 100644 --- a/Swiften/Component/UnitTest/ComponentConnectorTest.cpp +++ b/Swiften/Component/UnitTest/ComponentConnectorTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2015 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ @@ -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::fromString("1.1.1.1").get(); + host2 = HostAddress::fromString("2.2.2.2").get(); + 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(std::shared_ptr<Connection> connection) { + std::shared_ptr<MockConnection> c(std::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) { + } + + std::shared_ptr<Connection> createConnection() { + return std::make_shared<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< std::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..ce8eaa4 100644 --- a/Swiften/Component/UnitTest/ComponentHandshakeGeneratorTest.cpp +++ b/Swiften/Component/UnitTest/ComponentHandshakeGeneratorTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2013 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ @@ -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 = std::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: + std::shared_ptr<CryptoProvider> crypto; }; CPPUNIT_TEST_SUITE_REGISTRATION(ComponentHandshakeGeneratorTest); diff --git a/Swiften/Component/UnitTest/ComponentSessionTest.cpp b/Swiften/Component/UnitTest/ComponentSessionTest.cpp index 8d5d700..48c6d8d 100644 --- a/Swiften/Component/UnitTest/ComponentSessionTest.cpp +++ b/Swiften/Component/UnitTest/ComponentSessionTest.cpp @@ -1,220 +1,222 @@ /* - * Copyright (c) 2010-2014 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ -#include <cppunit/extensions/HelperMacros.h> -#include <cppunit/extensions/TestFactoryRegistry.h> #include <deque> + #include <boost/bind.hpp> #include <boost/optional.hpp> -#include <Swiften/Session/SessionStream.h> +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + #include <Swiften/Component/ComponentSession.h> -#include <Swiften/Elements/ComponentHandshake.h> -#include <Swiften/Elements/AuthFailure.h> #include <Swiften/Crypto/CryptoProvider.h> #include <Swiften/Crypto/PlatformCryptoProvider.h> +#include <Swiften/Elements/AuthFailure.h> +#include <Swiften/Elements/ComponentHandshake.h> +#include <Swiften/Session/SessionStream.h> 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 = std::make_shared<MockSessionStream>(); + sessionFinishedReceived = false; + crypto = std::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); + } + + void testStart() { + std::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() { + std::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() { + std::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: + std::shared_ptr<ComponentSession> createSession() { + std::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(std::shared_ptr<Error> error) { + sessionFinishedReceived = true; + sessionFinishedError = error; + } + + class MockSessionStream : public SessionStream { + public: + struct Event { + Event(std::shared_ptr<ToplevelElement> element) : element(element), footer(false) {} + Event(const ProtocolHeader& header) : header(header), footer(false) {} + Event() : footer(true) {} + + std::shared_ptr<ToplevelElement> element; + boost::optional<ProtocolHeader> header; + bool footer; + }; + + MockSessionStream() : available(true), whitespacePingEnabled(false), resetCount(0) { + } + + virtual void close() { + onClosed(std::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(std::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 std::shared_ptr<CertificateVerificationError> getPeerCertificateVerificationError() const { + return std::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(std::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(std::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; + }; + + std::shared_ptr<MockSessionStream> server; + bool sessionFinishedReceived = false; + std::shared_ptr<Error> sessionFinishedError; + std::shared_ptr<CryptoProvider> crypto; }; CPPUNIT_TEST_SUITE_REGISTRATION(ComponentSessionTest); |