diff options
author | Remko Tronçon <git@el-tramo.be> | 2009-11-09 20:34:44 (GMT) |
---|---|---|
committer | Remko Tronçon <git@el-tramo.be> | 2009-11-09 22:12:10 (GMT) |
commit | c682941cd230ad8caed3f3d457de3dc0cd7172d4 (patch) | |
tree | e4d4382a8627409d81bb7c79a62f1bc55f45b410 /Swiften/Client | |
parent | f1d74218cb432513c376b46aa115acb3e107ed3a (diff) | |
download | swift-contrib-c682941cd230ad8caed3f3d457de3dc0cd7172d4.zip swift-contrib-c682941cd230ad8caed3f3d457de3dc0cd7172d4.tar.bz2 |
Refactoring Client.
Diffstat (limited to 'Swiften/Client')
-rw-r--r-- | Swiften/Client/Client.cpp | 31 | ||||
-rw-r--r-- | Swiften/Client/Client.h | 8 | ||||
-rw-r--r-- | Swiften/Client/ClientSession.cpp | 196 | ||||
-rw-r--r-- | Swiften/Client/ClientSession.h | 79 |
4 files changed, 150 insertions, 164 deletions
diff --git a/Swiften/Client/Client.cpp b/Swiften/Client/Client.cpp index b3bea0d..adda6af 100644 --- a/Swiften/Client/Client.cpp +++ b/Swiften/Client/Client.cpp @@ -50,25 +50,26 @@ void Client::handleConnectionConnectFinished(bool error) { assert(!sessionStream_); sessionStream_ = boost::shared_ptr<BasicSessionStream>(new BasicSessionStream(connection_, &payloadParserFactories_, &payloadSerializers_, tlsLayerFactory_)); sessionStream_->initialize(); - - session_ = boost::shared_ptr<ClientSession>(new ClientSession(jid_, connection_, tlsLayerFactory_, &payloadParserFactories_, &payloadSerializers_)); if (!certificate_.isEmpty()) { - session_->setCertificate(PKCS12Certificate(certificate_, password_)); + sessionStream_->setTLSCertificate(PKCS12Certificate(certificate_, password_)); } - session_->onSessionStarted.connect(boost::bind(boost::ref(onConnected))); - session_->onSessionFinished.connect(boost::bind(&Client::handleSessionFinished, this, _1)); - session_->onNeedCredentials.connect(boost::bind(&Client::handleNeedCredentials, this)); - session_->onDataRead.connect(boost::bind(&Client::handleDataRead, this, _1)); - session_->onDataWritten.connect(boost::bind(&Client::handleDataWritten, this, _1)); - session_->onElementReceived.connect(boost::bind(&Client::handleElement, this, _1)); - session_->startSession(); + //sessionStream_->onDataRead.connect(boost::bind(&Client::handleDataRead, this, _1)); + //sessionStream_->onDataWritten.connect(boost::bind(&Client::handleDataWritten, this, _1)); + + session_ = boost::shared_ptr<ClientSession>(new ClientSession(jid_, sessionStream_)); + session_->onInitialized.connect(boost::bind(boost::ref(onConnected))); + session_->onFinished.connect(boost::bind(&Client::handleSessionFinished, shared_from_this(), _1)); + session_->onNeedCredentials.connect(boost::bind(&Client::handleNeedCredentials, shared_from_this())); + session_->onElementReceived.connect(boost::bind(&Client::handleElement, shared_from_this(), _1)); + session_->start(); } } void Client::disconnect() { - if (session_) { - session_->finishSession(); - } + // TODO + //if (session_) { + // session_->finishSession(); + //} } void Client::send(boost::shared_ptr<Stanza> stanza) { @@ -115,9 +116,10 @@ void Client::setCertificate(const String& certificate) { certificate_ = certificate; } -void Client::handleSessionFinished(const boost::optional<Session::SessionError>& error) { +void Client::handleSessionFinished(boost::shared_ptr<Error> error) { if (error) { ClientError clientError; + /* switch (*error) { case Session::ConnectionReadError: clientError = ClientError(ClientError::ConnectionReadError); @@ -153,6 +155,7 @@ void Client::handleSessionFinished(const boost::optional<Session::SessionError>& clientError = ClientError(ClientError::ClientCertificateError); break; } + */ onError(clientError); } } diff --git a/Swiften/Client/Client.h b/Swiften/Client/Client.h index 0e68f55..27c2458 100644 --- a/Swiften/Client/Client.h +++ b/Swiften/Client/Client.h @@ -3,7 +3,9 @@ #include <boost/signals.hpp> #include <boost/shared_ptr.hpp> +#include <boost/enable_shared_from_this.hpp> +#include "Swiften/Base/Error.h" #include "Swiften/Client/ClientSession.h" #include "Swiften/Client/ClientError.h" #include "Swiften/Elements/Presence.h" @@ -22,7 +24,7 @@ namespace Swift { class ClientSession; class BasicSessionStream; - class Client : public StanzaChannel, public IQRouter, public boost::bsignals::trackable { + class Client : public StanzaChannel, public IQRouter, public boost::enable_shared_from_this<Client> { public: Client(const JID& jid, const String& password); ~Client(); @@ -39,7 +41,7 @@ namespace Swift { virtual void sendPresence(boost::shared_ptr<Presence>); public: - boost::signal<void (ClientError)> onError; + boost::signal<void (const ClientError&)> onError; boost::signal<void ()> onConnected; boost::signal<void (const String&)> onDataRead; boost::signal<void (const String&)> onDataWritten; @@ -49,7 +51,7 @@ namespace Swift { void send(boost::shared_ptr<Stanza>); virtual String getNewIQID(); void handleElement(boost::shared_ptr<Element>); - void handleSessionFinished(const boost::optional<Session::SessionError>& error); + void handleSessionFinished(boost::shared_ptr<Error>); void handleNeedCredentials(); void handleDataRead(const ByteArray&); void handleDataWritten(const ByteArray&); diff --git a/Swiften/Client/ClientSession.cpp b/Swiften/Client/ClientSession.cpp index a0e1289..ed5d27d 100644 --- a/Swiften/Client/ClientSession.cpp +++ b/Swiften/Client/ClientSession.cpp @@ -2,13 +2,7 @@ #include <boost/bind.hpp> -#include "Swiften/Network/ConnectionFactory.h" #include "Swiften/Elements/ProtocolHeader.h" -#include "Swiften/StreamStack/StreamStack.h" -#include "Swiften/StreamStack/ConnectionLayer.h" -#include "Swiften/StreamStack/XMPPLayer.h" -#include "Swiften/StreamStack/TLSLayer.h" -#include "Swiften/StreamStack/TLSLayerFactory.h" #include "Swiften/Elements/StreamFeatures.h" #include "Swiften/Elements/StartTLSRequest.h" #include "Swiften/Elements/StartTLSFailure.h" @@ -20,47 +14,46 @@ #include "Swiften/Elements/IQ.h" #include "Swiften/Elements/ResourceBind.h" #include "Swiften/SASL/PLAINMessage.h" -#include "Swiften/StreamStack/WhitespacePingLayer.h" +#include "Swiften/Session/SessionStream.h" namespace Swift { ClientSession::ClientSession( const JID& jid, - boost::shared_ptr<Connection> connection, - TLSLayerFactory* tlsLayerFactory, - PayloadParserFactoryCollection* payloadParserFactories, - PayloadSerializerCollection* payloadSerializers) : - Session(connection, payloadParserFactories, payloadSerializers), - tlsLayerFactory_(tlsLayerFactory), - state_(Initial), - needSessionStart_(false) { - setLocalJID(jid); - setRemoteJID(JID("", jid.getDomain())); + boost::shared_ptr<SessionStream> stream) : + localJID(jid), + state(Initial), + stream(stream), + needSessionStart(false) { + stream->onStreamStartReceived.connect(boost::bind(&ClientSession::handleStreamStart, shared_from_this(), _1)); + stream->onElementReceived.connect(boost::bind(&ClientSession::handleElement, shared_from_this(), _1)); + stream->onError.connect(boost::bind(&ClientSession::handleStreamError, shared_from_this(), _1)); + stream->onTLSEncrypted.connect(boost::bind(&ClientSession::handleTLSEncrypted, shared_from_this())); } -void ClientSession::handleSessionStarted() { - assert(state_ == Initial); - state_ = WaitingForStreamStart; +void ClientSession::start() { + assert(state == Initial); + state = WaitingForStreamStart; sendStreamHeader(); } void ClientSession::sendStreamHeader() { ProtocolHeader header; header.setTo(getRemoteJID()); - getXMPPLayer()->writeHeader(header); + stream->writeHeader(header); } -void ClientSession::setCertificate(const PKCS12Certificate& certificate) { - certificate_ = certificate; +void ClientSession::sendElement(boost::shared_ptr<Element> element) { + stream->writeElement(element); } void ClientSession::handleStreamStart(const ProtocolHeader&) { checkState(WaitingForStreamStart); - state_ = Negotiating; + state = Negotiating; } void ClientSession::handleElement(boost::shared_ptr<Element> element) { - if (getState() == SessionStarted) { + if (getState() == Initialized) { onElementReceived(element); } else if (StreamFeatures* streamFeatures = dynamic_cast<StreamFeatures*>(element.get())) { @@ -68,152 +61,121 @@ void ClientSession::handleElement(boost::shared_ptr<Element> element) { return; } - if (streamFeatures->hasStartTLS() && tlsLayerFactory_->canCreate()) { - state_ = Encrypting; - getXMPPLayer()->writeElement(boost::shared_ptr<StartTLSRequest>(new StartTLSRequest())); + if (streamFeatures->hasStartTLS() && stream->supportsTLSEncryption()) { + state = WaitingForEncrypt; + stream->writeElement(boost::shared_ptr<StartTLSRequest>(new StartTLSRequest())); } else if (streamFeatures->hasAuthenticationMechanisms()) { - if (!certificate_.isNull()) { - if (streamFeatures->hasAuthenticationMechanism("EXTERNAL")) { - state_ = Authenticating; - getXMPPLayer()->writeElement(boost::shared_ptr<Element>(new AuthRequest("EXTERNAL", ""))); - } - else { - finishSession(ClientCertificateError); - } + if (stream->hasTLSCertificate() && streamFeatures->hasAuthenticationMechanism("EXTERNAL")) { + state = Authenticating; + stream->writeElement(boost::shared_ptr<Element>(new AuthRequest("EXTERNAL", ""))); } else if (streamFeatures->hasAuthenticationMechanism("PLAIN")) { - state_ = WaitingForCredentials; + state = WaitingForCredentials; onNeedCredentials(); } else { - finishSession(NoSupportedAuthMechanismsError); + finishSession(Error::NoSupportedAuthMechanismsError); } } else { // Start the session - - // Add a whitespace ping layer - whitespacePingLayer_ = boost::shared_ptr<WhitespacePingLayer>(new WhitespacePingLayer()); - getStreamStack()->addLayer(whitespacePingLayer_); - whitespacePingLayer_->setActive(); + stream->setWhitespacePingEnabled(true); if (streamFeatures->hasSession()) { - needSessionStart_ = true; + needSessionStart = true; } if (streamFeatures->hasResourceBind()) { - state_ = BindingResource; + state = BindingResource; boost::shared_ptr<ResourceBind> resourceBind(new ResourceBind()); - if (!getLocalJID().getResource().isEmpty()) { - resourceBind->setResource(getLocalJID().getResource()); + if (!localJID.getResource().isEmpty()) { + resourceBind->setResource(localJID.getResource()); } - getXMPPLayer()->writeElement(IQ::createRequest(IQ::Set, JID(), "session-bind", resourceBind)); + stream->writeElement(IQ::createRequest(IQ::Set, JID(), "session-bind", resourceBind)); } - else if (needSessionStart_) { + else if (needSessionStart) { sendSessionStart(); } else { - state_ = SessionStarted; - onSessionStarted(); + state = Initialized; + onInitialized(); } } } else if (dynamic_cast<AuthSuccess*>(element.get())) { checkState(Authenticating); - state_ = WaitingForStreamStart; - getXMPPLayer()->resetParser(); + state = WaitingForStreamStart; + stream->resetXMPPParser(); sendStreamHeader(); } else if (dynamic_cast<AuthFailure*>(element.get())) { - finishSession(AuthenticationFailedError); + finishSession(Error::AuthenticationFailedError); } else if (dynamic_cast<TLSProceed*>(element.get())) { - tlsLayer_ = tlsLayerFactory_->createTLSLayer(); - getStreamStack()->addLayer(tlsLayer_); - if (!certificate_.isNull() && !tlsLayer_->setClientCertificate(certificate_)) { - finishSession(ClientCertificateLoadError); - } - else { - tlsLayer_->onConnected.connect(boost::bind(&ClientSession::handleTLSConnected, this)); - tlsLayer_->onError.connect(boost::bind(&ClientSession::handleTLSError, this)); - tlsLayer_->connect(); - } + checkState(WaitingForEncrypt); + state = Encrypting; + stream->addTLSEncryption(); } else if (dynamic_cast<StartTLSFailure*>(element.get())) { - finishSession(TLSError); + finishSession(Error::TLSError); } else if (IQ* iq = dynamic_cast<IQ*>(element.get())) { - if (state_ == BindingResource) { + if (state == BindingResource) { boost::shared_ptr<ResourceBind> resourceBind(iq->getPayload<ResourceBind>()); if (iq->getType() == IQ::Error && iq->getID() == "session-bind") { - finishSession(ResourceBindError); + finishSession(Error::ResourceBindError); } else if (!resourceBind) { - finishSession(UnexpectedElementError); + finishSession(Error::UnexpectedElementError); } else if (iq->getType() == IQ::Result) { - setLocalJID(resourceBind->getJID()); - if (!getLocalJID().isValid()) { - finishSession(ResourceBindError); + localJID = resourceBind->getJID(); + if (!localJID.isValid()) { + finishSession(Error::ResourceBindError); } - if (needSessionStart_) { + if (needSessionStart) { sendSessionStart(); } else { - state_ = SessionStarted; + state = Initialized; } } else { - finishSession(UnexpectedElementError); + finishSession(Error::UnexpectedElementError); } } - else if (state_ == StartingSession) { + else if (state == StartingSession) { if (iq->getType() == IQ::Result) { - state_ = SessionStarted; - onSessionStarted(); + state = Initialized; + onInitialized(); } else if (iq->getType() == IQ::Error) { - finishSession(SessionStartError); + finishSession(Error::SessionStartError); } else { - finishSession(UnexpectedElementError); + finishSession(Error::UnexpectedElementError); } } else { - finishSession(UnexpectedElementError); + finishSession(Error::UnexpectedElementError); } } else { // FIXME Not correct? - state_ = SessionStarted; - onSessionStarted(); + state = Initialized; + onInitialized(); } } void ClientSession::sendSessionStart() { - state_ = StartingSession; - getXMPPLayer()->writeElement(IQ::createRequest(IQ::Set, JID(), "session-start", boost::shared_ptr<StartSession>(new StartSession()))); -} - -void ClientSession::handleSessionFinished(const boost::optional<SessionError>& error) { - if (whitespacePingLayer_) { - whitespacePingLayer_->setInactive(); - } - - if (error) { - //assert(!error_); - state_ = Error; - error_ = error; - } - else { - state_ = Finished; - } + state = StartingSession; + stream->writeElement(IQ::createRequest(IQ::Set, JID(), "session-start", boost::shared_ptr<StartSession>(new StartSession()))); } bool ClientSession::checkState(State state) { - if (state_ != state) { - finishSession(UnexpectedElementError); + if (state != state) { + finishSession(Error::UnexpectedElementError); return false; } return true; @@ -221,18 +183,36 @@ bool ClientSession::checkState(State state) { void ClientSession::sendCredentials(const String& password) { assert(WaitingForCredentials); - state_ = Authenticating; - getXMPPLayer()->writeElement(boost::shared_ptr<Element>(new AuthRequest("PLAIN", PLAINMessage(getLocalJID().getNode(), password).getValue()))); + state = Authenticating; + stream->writeElement(boost::shared_ptr<Element>(new AuthRequest("PLAIN", PLAINMessage(localJID.getNode(), password).getValue()))); } -void ClientSession::handleTLSConnected() { - state_ = WaitingForStreamStart; - getXMPPLayer()->resetParser(); +void ClientSession::handleTLSEncrypted() { + checkState(WaitingForEncrypt); + state = WaitingForStreamStart; + stream->resetXMPPParser(); sendStreamHeader(); } -void ClientSession::handleTLSError() { - finishSession(TLSError); +void ClientSession::handleStreamError(boost::shared_ptr<Swift::Error> error) { + finishSession(error); +} + +void ClientSession::finish() { + if (stream->isAvailable()) { + stream->writeFooter(); + } + finishSession(boost::shared_ptr<Error>()); +} + +void ClientSession::finishSession(Error::Type error) { + finishSession(boost::shared_ptr<Swift::ClientSession::Error>(new Swift::ClientSession::Error(error))); } +void ClientSession::finishSession(boost::shared_ptr<Swift::Error> error) { + stream->setWhitespacePingEnabled(false); + onFinished(error); +} + + } diff --git a/Swiften/Client/ClientSession.h b/Swiften/Client/ClientSession.h index fead182..1b01a66 100644 --- a/Swiften/Client/ClientSession.h +++ b/Swiften/Client/ClientSession.h @@ -2,87 +2,88 @@ #include <boost/signal.hpp> #include <boost/shared_ptr.hpp> +#include <boost/enable_shared_from_this.hpp> -#include "Swiften/Session/Session.h" +#include "Swiften/Base/Error.h" +#include "Swiften/Session/SessionStream.h" +#include "Swiften/Session/BasicSessionStream.h" #include "Swiften/Base/String.h" #include "Swiften/JID/JID.h" #include "Swiften/Elements/Element.h" -#include "Swiften/Network/Connection.h" -#include "Swiften/TLS/PKCS12Certificate.h" namespace Swift { - class PayloadParserFactoryCollection; - class PayloadSerializerCollection; - class ConnectionFactory; - class Connection; - class StreamStack; - class XMPPLayer; - class ConnectionLayer; - class TLSLayerFactory; - class TLSLayer; - class WhitespacePingLayer; - - class ClientSession : public Session { + class ClientSession : public boost::enable_shared_from_this<ClientSession> { public: enum State { Initial, WaitingForStreamStart, Negotiating, Compressing, + WaitingForEncrypt, Encrypting, WaitingForCredentials, Authenticating, BindingResource, StartingSession, - SessionStarted, - Error, + Initialized, Finished }; + struct Error : public Swift::Error { + enum Type { + AuthenticationFailedError, + NoSupportedAuthMechanismsError, + UnexpectedElementError, + ResourceBindError, + SessionStartError, + TLSError, + } type; + Error(Type type) : type(type) {} + }; + ClientSession( const JID& jid, - boost::shared_ptr<Connection>, - TLSLayerFactory*, - PayloadParserFactoryCollection*, - PayloadSerializerCollection*); + boost::shared_ptr<SessionStream>); State getState() const { - return state_; + return state; } - boost::optional<SessionError> getError() const { - return error_; - } + void start(); + void finish(); void sendCredentials(const String& password); - void setCertificate(const PKCS12Certificate& certificate); + void sendElement(boost::shared_ptr<Element> element); private: + void finishSession(Error::Type error); + void finishSession(boost::shared_ptr<Swift::Error> error); + + JID getRemoteJID() const { + return JID("", localJID.getDomain()); + } + void sendStreamHeader(); void sendSessionStart(); - virtual void handleSessionStarted(); - virtual void handleSessionFinished(const boost::optional<SessionError>& error); virtual void handleElement(boost::shared_ptr<Element>); virtual void handleStreamStart(const ProtocolHeader&); + virtual void handleStreamError(boost::shared_ptr<Swift::Error>); - void handleTLSConnected(); - void handleTLSError(); + void handleTLSEncrypted(); - void setError(SessionError); bool checkState(State); public: boost::signal<void ()> onNeedCredentials; - boost::signal<void ()> onSessionStarted; + boost::signal<void ()> onInitialized; + boost::signal<void (boost::shared_ptr<Swift::Error>)> onFinished; + boost::signal<void (boost::shared_ptr<Element>)> onElementReceived; private: - TLSLayerFactory* tlsLayerFactory_; - State state_; - boost::optional<SessionError> error_; - boost::shared_ptr<TLSLayer> tlsLayer_; - boost::shared_ptr<WhitespacePingLayer> whitespacePingLayer_; - bool needSessionStart_; - PKCS12Certificate certificate_; + JID localJID; + State state; + boost::shared_ptr<SessionStream> stream; + bool needSessionStart; }; } |