/* * Copyright (c) 2010 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ #pragma once #include "Swiften/Base/boost_bsignals.h" #include #include #include "Swiften/Base/Error.h" #include "Swiften/Session/SessionStream.h" #include #include "Swiften/JID/JID.h" #include "Swiften/Elements/Element.h" #include "Swiften/StreamManagement/StanzaAckRequester.h" #include "Swiften/StreamManagement/StanzaAckResponder.h" namespace Swift { class ClientAuthenticator; class CertificateTrustChecker; class ClientSession : public boost::enable_shared_from_this { public: enum State { Initial, WaitingForStreamStart, Negotiating, Compressing, WaitingForEncrypt, Encrypting, WaitingForCredentials, Authenticating, EnablingSessionManagement, BindingResource, StartingSession, Initialized, Finishing, Finished }; struct Error : public Swift::Error { enum Type { AuthenticationFailedError, CompressionFailedError, ServerVerificationFailedError, NoSupportedAuthMechanismsError, UnexpectedElementError, ResourceBindError, SessionStartError, TLSClientCertificateError, TLSError, StreamError, } type; Error(Type type) : type(type) {} }; enum UseTLS { NeverUseTLS, UseTLSWhenAvailable }; ~ClientSession(); static boost::shared_ptr create(const JID& jid, boost::shared_ptr stream) { return boost::shared_ptr(new ClientSession(jid, stream)); } State getState() const { return state; } void setAllowPLAINOverNonTLS(bool b) { allowPLAINOverNonTLS = b; } void setUseStreamCompression(bool b) { useStreamCompression = b; } void setUseTLS(UseTLS b) { useTLS = b; } bool getStreamManagementEnabled() const { return stanzaAckRequester_; } const JID& getLocalJID() const { return localJID; } void start(); void finish(); bool isFinished() const { return getState() == Finished; } void sendCredentials(const std::string& password); void sendStanza(boost::shared_ptr); void setCertificateTrustChecker(CertificateTrustChecker* checker) { certificateTrustChecker = checker; } public: boost::signal onNeedCredentials; boost::signal onInitialized; boost::signal)> onFinished; boost::signal)> onStanzaReceived; boost::signal)> onStanzaAcked; private: ClientSession( const JID& jid, boost::shared_ptr); void finishSession(Error::Type error); void finishSession(boost::shared_ptr error); JID getRemoteJID() const { return JID("", localJID.getDomain()); } void sendStreamHeader(); void handleElement(boost::shared_ptr); void handleStreamStart(const ProtocolHeader&); void handleStreamClosed(boost::shared_ptr); void handleTLSEncrypted(); bool checkState(State); void continueSessionInitialization(); void requestAck(); void handleStanzaAcked(boost::shared_ptr stanza); void ack(unsigned int handledStanzasCount); void continueAfterTLSEncrypted(); void checkTrustOrFinish(Certificate::ref certificate, boost::shared_ptr error); private: JID localJID; State state; boost::shared_ptr stream; bool allowPLAINOverNonTLS; bool useStreamCompression; UseTLS useTLS; bool needSessionStart; bool needResourceBind; bool needAcking; ClientAuthenticator* authenticator; boost::shared_ptr stanzaAckRequester_; boost::shared_ptr stanzaAckResponder_; boost::shared_ptr error_; CertificateTrustChecker* certificateTrustChecker; }; }