From 2ef4bb560dad95555a5ae94d0bd5bff49d50d3d3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Mon, 27 Dec 2010 16:10:27 +0100
Subject: Avoid leaking connection on exit.


diff --git a/QA/valgrind.supp b/QA/valgrind.supp
index 8601b60..fe09cef 100644
--- a/QA/valgrind.supp
+++ b/QA/valgrind.supp
@@ -90,3 +90,10 @@
    Memcheck:Cond
    fun:*mersenne_twister*
 }
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   fun:malloc
+   fun:__cxa_get_globals
+}
diff --git a/Swiften/Chat/UnitTest/ChatStateNotifierTest.cpp b/Swiften/Chat/UnitTest/ChatStateNotifierTest.cpp
index 00fc11d..5d7961b 100644
--- a/Swiften/Chat/UnitTest/ChatStateNotifierTest.cpp
+++ b/Swiften/Chat/UnitTest/ChatStateNotifierTest.cpp
@@ -38,6 +38,7 @@ public:
 	
 	void tearDown() {
 		delete notifier_;
+		delete entityCapsProvider;
 		delete stanzaChannel;
 	}
 	
diff --git a/Swiften/Client/ClientSession.h b/Swiften/Client/ClientSession.h
index 170491f..b779735 100644
--- a/Swiften/Client/ClientSession.h
+++ b/Swiften/Client/ClientSession.h
@@ -81,6 +81,10 @@ namespace Swift {
 			void start();
 			void finish();
 
+			bool isFinished() const {
+				return getState() == Finished;
+			}
+
 			void sendCredentials(const String& password);
 			void sendStanza(boost::shared_ptr<Stanza>);
 
diff --git a/Swiften/Client/CoreClient.cpp b/Swiften/Client/CoreClient.cpp
index 7b1f3fd..46b4cbb 100644
--- a/Swiften/Client/CoreClient.cpp
+++ b/Swiften/Client/CoreClient.cpp
@@ -34,7 +34,7 @@ CoreClient::CoreClient(EventLoop* eventLoop, NetworkFactories* networkFactories,
 }
 
 CoreClient::~CoreClient() {
-	if (session_ || connection_) {
+	if ((session_ && !session_->isFinished()) || connection_) {
 		std::cerr << "Warning: Client not disconnected properly" << std::endl;
 	}
 	delete tlsFactories;
@@ -79,7 +79,6 @@ void CoreClient::handleConnectorFinished(boost::shared_ptr<Connection> connectio
 		}
 		sessionStream_->onDataRead.connect(boost::bind(&CoreClient::handleDataRead, this, _1));
 		sessionStream_->onDataWritten.connect(boost::bind(&CoreClient::handleDataWritten, this, _1));
-		sessionStream_->initialize();
 
 		session_ = ClientSession::create(jid_, sessionStream_);
 		session_->setCertificateTrustChecker(certificateTrustChecker);
@@ -94,7 +93,7 @@ void CoreClient::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_) {
+	if (!session_->isFinished()) {
 		session_->finish();
 	}
 	else if (connector_) {
@@ -109,7 +108,6 @@ void CoreClient::setCertificate(const String& certificate) {
 void CoreClient::handleSessionFinished(boost::shared_ptr<Error> error) {
 	session_->onFinished.disconnect(boost::bind(&CoreClient::handleSessionFinished, this, _1));
 	session_->onNeedCredentials.disconnect(boost::bind(&CoreClient::handleNeedCredentials, this));
-	session_.reset();
 
 	sessionStream_->onDataRead.disconnect(boost::bind(&CoreClient::handleDataRead, this, _1));
 	sessionStream_->onDataWritten.disconnect(boost::bind(&CoreClient::handleDataWritten, this, _1));
@@ -244,7 +242,7 @@ void CoreClient::sendPresence(boost::shared_ptr<Presence> presence) {
 }
 
 bool CoreClient::isActive() const {
-	return session_ || connector_;
+	return (session_ && !session_->isFinished()) || connector_;
 }
 
 void CoreClient::setCertificateTrustChecker(CertificateTrustChecker* checker) {
diff --git a/Swiften/Component/CoreComponent.cpp b/Swiften/Component/CoreComponent.cpp
index c3451de..eabe62d 100644
--- a/Swiften/Component/CoreComponent.cpp
+++ b/Swiften/Component/CoreComponent.cpp
@@ -65,7 +65,6 @@ void CoreComponent::handleConnectorFinished(boost::shared_ptr<Connection> connec
 		sessionStream_ = boost::shared_ptr<BasicSessionStream>(new BasicSessionStream(ComponentStreamType, connection_, getPayloadParserFactories(), getPayloadSerializers(), NULL, networkFactories->getTimerFactory()));
 		sessionStream_->onDataRead.connect(boost::bind(&CoreComponent::handleDataRead, this, _1));
 		sessionStream_->onDataWritten.connect(boost::bind(&CoreComponent::handleDataWritten, this, _1));
-		sessionStream_->initialize();
 
 		session_ = ComponentSession::create(jid_, secret_, sessionStream_);
 		stanzaChannel_->setSession(session_);
diff --git a/Swiften/Session/BasicSessionStream.cpp b/Swiften/Session/BasicSessionStream.cpp
index c4d1b6d..3f06315 100644
--- a/Swiften/Session/BasicSessionStream.cpp
+++ b/Swiften/Session/BasicSessionStream.cpp
@@ -33,23 +33,17 @@ BasicSessionStream::BasicSessionStream(
 			tlsContextFactory(tlsContextFactory), 
 			timerFactory(timerFactory), 
 			streamType(streamType),
-			xmppLayer(NULL),
-			connectionLayer(NULL),
 			compressionLayer(NULL),
 			tlsLayer(NULL),
 			whitespacePingLayer(NULL) {
-}
-
-void BasicSessionStream::initialize() {
 	xmppLayer = new XMPPLayer(payloadParserFactories, payloadSerializers, streamType);
-	xmppLayer->onStreamStart.connect(boost::bind(&BasicSessionStream::handleStreamStartReceived, shared_from_this(), _1));
-	xmppLayer->onElement.connect(boost::bind(&BasicSessionStream::handleElementReceived, shared_from_this(), _1));
-	xmppLayer->onError.connect(boost::bind(
-			&BasicSessionStream::handleXMPPError, shared_from_this()));
-	xmppLayer->onDataRead.connect(boost::bind(&BasicSessionStream::handleDataRead, shared_from_this(), _1));
-	xmppLayer->onWriteData.connect(boost::bind(&BasicSessionStream::handleDataWritten, shared_from_this(), _1));
-
-	connection->onDisconnected.connect(boost::bind(&BasicSessionStream::handleConnectionError, shared_from_this(), _1));
+	xmppLayer->onStreamStart.connect(boost::bind(&BasicSessionStream::handleStreamStartReceived, this, _1));
+	xmppLayer->onElement.connect(boost::bind(&BasicSessionStream::handleElementReceived, this, _1));
+	xmppLayer->onError.connect(boost::bind(&BasicSessionStream::handleXMPPError, this));
+	xmppLayer->onDataRead.connect(boost::bind(&BasicSessionStream::handleDataRead, this, _1));
+	xmppLayer->onWriteData.connect(boost::bind(&BasicSessionStream::handleDataWritten, this, _1));
+
+	connection->onDisconnected.connect(boost::bind(&BasicSessionStream::handleConnectionError, this, _1));
 	connectionLayer = new ConnectionLayer(connection);
 
 	streamStack = new StreamStack(xmppLayer, connectionLayer);
@@ -59,10 +53,23 @@ void BasicSessionStream::initialize() {
 
 BasicSessionStream::~BasicSessionStream() {
 	delete compressionLayer;
-	delete tlsLayer;
+
+	if (tlsLayer) {
+		tlsLayer->onError.disconnect(boost::bind(&BasicSessionStream::handleTLSError, this));
+		tlsLayer->onConnected.disconnect(boost::bind(&BasicSessionStream::handleTLSConnected, this));
+		delete tlsLayer;
+	}
 	delete whitespacePingLayer;
 	delete streamStack;
+
+	connection->onDisconnected.disconnect(boost::bind(&BasicSessionStream::handleConnectionError, this, _1));
 	delete connectionLayer;
+
+	xmppLayer->onStreamStart.disconnect(boost::bind(&BasicSessionStream::handleStreamStartReceived, this, _1));
+	xmppLayer->onElement.disconnect(boost::bind(&BasicSessionStream::handleElementReceived, this, _1));
+	xmppLayer->onError.disconnect(boost::bind(&BasicSessionStream::handleXMPPError, this));
+	xmppLayer->onDataRead.disconnect(boost::bind(&BasicSessionStream::handleDataRead, this, _1));
+	xmppLayer->onWriteData.disconnect(boost::bind(&BasicSessionStream::handleDataWritten, this, _1));
 	delete xmppLayer;
 }
 
@@ -97,8 +104,8 @@ void BasicSessionStream::addTLSEncryption() {
 	}
 	else {
 		streamStack->addLayer(tlsLayer);
-		tlsLayer->onError.connect(boost::bind(&BasicSessionStream::handleTLSError, shared_from_this()));
-		tlsLayer->onConnected.connect(boost::bind(&BasicSessionStream::handleTLSConnected, shared_from_this()));
+		tlsLayer->onError.connect(boost::bind(&BasicSessionStream::handleTLSError, this));
+		tlsLayer->onConnected.connect(boost::bind(&BasicSessionStream::handleTLSConnected, this));
 		tlsLayer->connect();
 	}
 }
diff --git a/Swiften/Session/BasicSessionStream.h b/Swiften/Session/BasicSessionStream.h
index c601792..35b5481 100644
--- a/Swiften/Session/BasicSessionStream.h
+++ b/Swiften/Session/BasicSessionStream.h
@@ -7,7 +7,6 @@
 #pragma once
 
 #include <boost/shared_ptr.hpp>
-#include <boost/enable_shared_from_this.hpp>
 
 #include "Swiften/Network/Connection.h"
 #include "Swiften/Session/SessionStream.h"
@@ -25,9 +24,7 @@ namespace Swift {
 	class ConnectionLayer;
 	class CompressionLayer;
 
-	class BasicSessionStream : 
-			public SessionStream, 
-			public boost::enable_shared_from_this<BasicSessionStream> {
+	class BasicSessionStream : public SessionStream {
 		public:
 			BasicSessionStream(
 				StreamType streamType,
@@ -39,8 +36,6 @@ namespace Swift {
 			);
 			~BasicSessionStream();
 
-			void initialize();
-
 			virtual bool isAvailable();
 
 			virtual void writeHeader(const ProtocolHeader& header);
diff --git a/Swiften/StreamStack/ConnectionLayer.h b/Swiften/StreamStack/ConnectionLayer.h
index fab014e..0da0900 100644
--- a/Swiften/StreamStack/ConnectionLayer.h
+++ b/Swiften/StreamStack/ConnectionLayer.h
@@ -20,6 +20,10 @@ namespace Swift {
 				connection->onDataRead.connect(boost::bind(&ConnectionLayer::writeDataToParentLayer, this, _1));
 			}
 
+			~ConnectionLayer() {
+				connection->onDataRead.disconnect(boost::bind(&ConnectionLayer::writeDataToParentLayer, this, _1));
+			}
+
 			void writeData(const ByteArray& data) {
 				connection->write(data);
 			}
-- 
cgit v0.10.2-6-g49f6