diff options
author | Remko Tronçon <git@el-tramo.be> | 2009-12-07 18:23:22 (GMT) |
---|---|---|
committer | Remko Tronçon <git@el-tramo.be> | 2009-12-07 18:23:22 (GMT) |
commit | e32059da8bffc67806862bf78f762d67fb3e4848 (patch) | |
tree | 529f5481dc8b832090c778874a0255cbc1c73524 | |
parent | 2e1bed9790ce11d856006aaa8692fed225cc10d3 (diff) | |
download | swift-e32059da8bffc67806862bf78f762d67fb3e4848.zip swift-e32059da8bffc67806862bf78f762d67fb3e4848.tar.bz2 |
Fixed segfault on disconnect.
-rw-r--r-- | Swiften/Client/Client.cpp | 7 | ||||
-rw-r--r-- | Swiften/Client/ClientSession.cpp | 3 | ||||
-rw-r--r-- | Swiften/Client/ClientSession.h | 1 |
3 files changed, 8 insertions, 3 deletions
diff --git a/Swiften/Client/Client.cpp b/Swiften/Client/Client.cpp index e9de19a..27f3d9c 100644 --- a/Swiften/Client/Client.cpp +++ b/Swiften/Client/Client.cpp @@ -27,184 +27,185 @@ Client::~Client() { } delete tlsLayerFactory_; delete timerFactory_; delete connectionFactory_; } bool Client::isAvailable() { return session_; } void Client::connect() { assert(!connector_); connector_ = boost::shared_ptr<Connector>(new Connector(jid_.getDomain(), &resolver_, connectionFactory_)); connector_->onConnectFinished.connect(boost::bind(&Client::handleConnectorFinished, this, _1)); connector_->start(); } void Client::handleConnectorFinished(boost::shared_ptr<Connection> connection) { // TODO: Add domain name resolver error connector_.reset(); if (!connection) { onError(ClientError::ConnectionError); } else { assert(!connection_); connection_ = connection; assert(!sessionStream_); sessionStream_ = boost::shared_ptr<BasicSessionStream>(new BasicSessionStream(connection_, &payloadParserFactories_, &payloadSerializers_, tlsLayerFactory_, timerFactory_)); if (!certificate_.isEmpty()) { sessionStream_->setTLSCertificate(PKCS12Certificate(certificate_, password_)); } sessionStream_->onDataRead.connect(boost::bind(&Client::handleDataRead, this, _1)); sessionStream_->onDataWritten.connect(boost::bind(&Client::handleDataWritten, this, _1)); sessionStream_->initialize(); session_ = ClientSession::create(jid_, sessionStream_); session_->onInitialized.connect(boost::bind(boost::ref(onConnected))); session_->onFinished.connect(boost::bind(&Client::handleSessionFinished, this, _1)); session_->onNeedCredentials.connect(boost::bind(&Client::handleNeedCredentials, this)); session_->onElementReceived.connect(boost::bind(&Client::handleElement, this, _1)); session_->start(); } } void Client::disconnect() { if (session_) { session_->finish(); - session_.reset(); } - closeConnection(); + else { + closeConnection(); + } } void Client::closeConnection() { if (sessionStream_) { sessionStream_.reset(); } if (connection_) { connection_->disconnect(); connection_.reset(); } } void Client::send(boost::shared_ptr<Stanza> stanza) { if (!isAvailable()) { std::cerr << "Warning: Client: Trying to send a stanza while disconnected." << std::endl; return; } session_->sendElement(stanza); } void Client::sendIQ(boost::shared_ptr<IQ> iq) { send(iq); } void Client::sendMessage(boost::shared_ptr<Message> message) { send(message); } void Client::sendPresence(boost::shared_ptr<Presence> presence) { send(presence); } String Client::getNewIQID() { return idGenerator_.generateID(); } void Client::handleElement(boost::shared_ptr<Element> element) { boost::shared_ptr<Message> message = boost::dynamic_pointer_cast<Message>(element); if (message) { onMessageReceived(message); return; } boost::shared_ptr<Presence> presence = boost::dynamic_pointer_cast<Presence>(element); if (presence) { onPresenceReceived(presence); return; } boost::shared_ptr<IQ> iq = boost::dynamic_pointer_cast<IQ>(element); if (iq) { onIQReceived(iq); return; } } void Client::setCertificate(const String& certificate) { certificate_ = certificate; } void Client::handleSessionFinished(boost::shared_ptr<Error> error) { + session_.reset(); closeConnection(); if (error) { ClientError clientError; if (boost::shared_ptr<ClientSession::Error> actualError = boost::dynamic_pointer_cast<ClientSession::Error>(error)) { switch(actualError->type) { case ClientSession::Error::AuthenticationFailedError: clientError = ClientError(ClientError::AuthenticationFailedError); break; case ClientSession::Error::CompressionFailedError: clientError = ClientError(ClientError::CompressionFailedError); break; case ClientSession::Error::ServerVerificationFailedError: clientError = ClientError(ClientError::ServerVerificationFailedError); break; case ClientSession::Error::NoSupportedAuthMechanismsError: clientError = ClientError(ClientError::NoSupportedAuthMechanismsError); break; case ClientSession::Error::UnexpectedElementError: clientError = ClientError(ClientError::UnexpectedElementError); break; case ClientSession::Error::ResourceBindError: clientError = ClientError(ClientError::ResourceBindError); break; case ClientSession::Error::SessionStartError: clientError = ClientError(ClientError::SessionStartError); break; case ClientSession::Error::TLSError: clientError = ClientError(ClientError::TLSError); break; case ClientSession::Error::TLSClientCertificateError: clientError = ClientError(ClientError::ClientCertificateError); break; } } else if (boost::shared_ptr<SessionStream::Error> actualError = boost::dynamic_pointer_cast<SessionStream::Error>(error)) { switch(actualError->type) { case SessionStream::Error::ParseError: clientError = ClientError(ClientError::XMLError); break; case SessionStream::Error::TLSError: clientError = ClientError(ClientError::TLSError); break; case SessionStream::Error::InvalidTLSCertificateError: clientError = ClientError(ClientError::ClientCertificateLoadError); break; case SessionStream::Error::ConnectionReadError: clientError = ClientError(ClientError::ConnectionReadError); break; case SessionStream::Error::ConnectionWriteError: clientError = ClientError(ClientError::ConnectionWriteError); break; } } onError(clientError); } - session_.reset(); } void Client::handleNeedCredentials() { assert(session_); session_->sendCredentials(password_); } void Client::handleDataRead(const String& data) { onDataRead(data); } void Client::handleDataWritten(const String& data) { onDataWritten(data); } } diff --git a/Swiften/Client/ClientSession.cpp b/Swiften/Client/ClientSession.cpp index 8427d27..16bda40 100644 --- a/Swiften/Client/ClientSession.cpp +++ b/Swiften/Client/ClientSession.cpp @@ -1,84 +1,87 @@ #include "Swiften/Client/ClientSession.h" #include <boost/bind.hpp> #include "Swiften/Elements/ProtocolHeader.h" #include "Swiften/Elements/StreamFeatures.h" #include "Swiften/Elements/StartTLSRequest.h" #include "Swiften/Elements/StartTLSFailure.h" #include "Swiften/Elements/TLSProceed.h" #include "Swiften/Elements/AuthRequest.h" #include "Swiften/Elements/AuthSuccess.h" #include "Swiften/Elements/AuthFailure.h" #include "Swiften/Elements/AuthChallenge.h" #include "Swiften/Elements/AuthResponse.h" #include "Swiften/Elements/Compressed.h" #include "Swiften/Elements/CompressFailure.h" #include "Swiften/Elements/CompressRequest.h" #include "Swiften/Elements/StartSession.h" #include "Swiften/Elements/IQ.h" #include "Swiften/Elements/ResourceBind.h" #include "Swiften/SASL/PLAINClientAuthenticator.h" #include "Swiften/SASL/SCRAMSHA1ClientAuthenticator.h" #include "Swiften/Session/SessionStream.h" namespace Swift { ClientSession::ClientSession( const JID& jid, boost::shared_ptr<SessionStream> stream) : localJID(jid), state(Initial), stream(stream), needSessionStart(false), authenticator(NULL) { } +ClientSession::~ClientSession() { +} + void ClientSession::start() { stream->onStreamStartReceived.connect(boost::bind(&ClientSession::handleStreamStart, shared_from_this(), _1)); stream->onElementReceived.connect(boost::bind(&ClientSession::handleElement, shared_from_this(), _1)); stream->onError.connect(boost::bind(&ClientSession::handleStreamError, shared_from_this(), _1)); stream->onTLSEncrypted.connect(boost::bind(&ClientSession::handleTLSEncrypted, shared_from_this())); assert(state == Initial); state = WaitingForStreamStart; sendStreamHeader(); } void ClientSession::sendStreamHeader() { ProtocolHeader header; header.setTo(getRemoteJID()); stream->writeHeader(header); } void ClientSession::sendElement(boost::shared_ptr<Element> element) { stream->writeElement(element); } void ClientSession::handleStreamStart(const ProtocolHeader&) { checkState(WaitingForStreamStart); state = Negotiating; } void ClientSession::handleElement(boost::shared_ptr<Element> element) { if (getState() == Initialized) { onElementReceived(element); } else if (StreamFeatures* streamFeatures = dynamic_cast<StreamFeatures*>(element.get())) { if (!checkState(Negotiating)) { return; } if (streamFeatures->hasStartTLS() && stream->supportsTLSEncryption()) { state = WaitingForEncrypt; stream->writeElement(boost::shared_ptr<StartTLSRequest>(new StartTLSRequest())); } else if (streamFeatures->hasCompressionMethod("zlib")) { state = Compressing; stream->writeElement(boost::shared_ptr<CompressRequest>(new CompressRequest("zlib"))); } else if (streamFeatures->hasAuthenticationMechanisms()) { if (stream->hasTLSCertificate()) { if (streamFeatures->hasAuthenticationMechanism("EXTERNAL")) { state = Authenticating; stream->writeElement(boost::shared_ptr<Element>(new AuthRequest("EXTERNAL", ""))); diff --git a/Swiften/Client/ClientSession.h b/Swiften/Client/ClientSession.h index ef4d747..685672e 100644 --- a/Swiften/Client/ClientSession.h +++ b/Swiften/Client/ClientSession.h @@ -1,96 +1,97 @@ #pragma once #include <boost/signal.hpp> #include <boost/shared_ptr.hpp> #include <boost/enable_shared_from_this.hpp> #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" namespace Swift { class ClientAuthenticator; class ClientSession : public boost::enable_shared_from_this<ClientSession> { public: enum State { Initial, WaitingForStreamStart, Negotiating, Compressing, WaitingForEncrypt, Encrypting, WaitingForCredentials, Authenticating, BindingResource, StartingSession, Initialized, Finished }; struct Error : public Swift::Error { enum Type { AuthenticationFailedError, CompressionFailedError, ServerVerificationFailedError, NoSupportedAuthMechanismsError, UnexpectedElementError, ResourceBindError, SessionStartError, TLSClientCertificateError, TLSError, } type; Error(Type type) : type(type) {} }; + ~ClientSession(); static boost::shared_ptr<ClientSession> create(const JID& jid, boost::shared_ptr<SessionStream> stream) { return boost::shared_ptr<ClientSession>(new ClientSession(jid, stream)); } State getState() const { return state; } void start(); void finish(); void sendCredentials(const String& password); void sendElement(boost::shared_ptr<Element> element); public: boost::signal<void ()> onNeedCredentials; boost::signal<void ()> onInitialized; boost::signal<void (boost::shared_ptr<Swift::Error>)> onFinished; boost::signal<void (boost::shared_ptr<Element>)> onElementReceived; private: ClientSession( const JID& jid, boost::shared_ptr<SessionStream>); void finishSession(Error::Type error); void finishSession(boost::shared_ptr<Swift::Error> error); JID getRemoteJID() const { return JID("", localJID.getDomain()); } void sendStreamHeader(); void sendSessionStart(); void handleElement(boost::shared_ptr<Element>); void handleStreamStart(const ProtocolHeader&); void handleStreamError(boost::shared_ptr<Swift::Error>); void handleTLSEncrypted(); bool checkState(State); private: JID localJID; State state; boost::shared_ptr<SessionStream> stream; bool needSessionStart; |