From 150542a5c60fe49f4e164ffdaa51236795426214 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Mon, 10 Oct 2011 09:37:12 +0200
Subject: Force disconnect signals when calling connect() shortly after
 disconnect().


diff --git a/Swiften/Client/CoreClient.cpp b/Swiften/Client/CoreClient.cpp
index dbc6de2..22e3612 100644
--- a/Swiften/Client/CoreClient.cpp
+++ b/Swiften/Client/CoreClient.cpp
@@ -41,9 +41,7 @@ CoreClient::CoreClient(const JID& jid, const SafeByteArray& password, NetworkFac
 }
 
 CoreClient::~CoreClient() {
-	if ((session_ && !session_->isFinished()) || connection_) {
-		std::cerr << "Warning: Client not disconnected properly" << std::endl;
-	}
+	forceReset();
 	delete tlsFactories;
 	delete iqRouter_;
 
@@ -61,10 +59,11 @@ void CoreClient::connect(const ClientOptions& o) {
 }
 
 void CoreClient::connect(const std::string& host) {
+	forceReset();
+
 	SWIFT_LOG(debug) << "Connecting to host " << host << std::endl;
 	disconnectRequested_ = false;
 	assert(!connector_);
-
 	assert(proxyConnectionFactories.empty());
 	PlatformProxyProvider proxyProvider;
 	if(proxyProvider.getSOCKS5Proxy().isValid()) {
@@ -83,13 +82,7 @@ void CoreClient::connect(const std::string& host) {
 }
 
 void CoreClient::handleConnectorFinished(boost::shared_ptr<Connection> connection) {
-	connector_->onConnectFinished.disconnect(boost::bind(&CoreClient::handleConnectorFinished, this, _1));
-	connector_.reset();
-	foreach(ConnectionFactory* f, proxyConnectionFactories) {
-		delete f;
-	}
-	proxyConnectionFactories.clear();
-
+	resetConnector();
 	if (!connection) {
 		if (options.forgetPassword) {
 			purgePassword();
@@ -151,15 +144,7 @@ void CoreClient::handleSessionFinished(boost::shared_ptr<Error> error) {
 	if (options.forgetPassword) {
 		purgePassword();
 	}
-	session_->onFinished.disconnect(boost::bind(&CoreClient::handleSessionFinished, this, _1));
-	session_->onNeedCredentials.disconnect(boost::bind(&CoreClient::handleNeedCredentials, this));
-
-	sessionStream_->onDataRead.disconnect(boost::bind(&CoreClient::handleDataRead, this, _1));
-	sessionStream_->onDataWritten.disconnect(boost::bind(&CoreClient::handleDataWritten, this, _1));
-	sessionStream_.reset();
-
-	connection_->disconnect();
-	connection_.reset();
+	resetSession();
 
 	boost::optional<ClientError> actualError;
 	if (error) {
@@ -341,4 +326,36 @@ void CoreClient::purgePassword() {
 	safeClear(password_);
 }
 
+void CoreClient::resetConnector() {
+	connector_->onConnectFinished.disconnect(boost::bind(&CoreClient::handleConnectorFinished, this, _1));
+	connector_.reset();
+	foreach(ConnectionFactory* f, proxyConnectionFactories) {
+		delete f;
+	}
+	proxyConnectionFactories.clear();
+}
+
+void CoreClient::resetSession() {
+	session_->onFinished.disconnect(boost::bind(&CoreClient::handleSessionFinished, this, _1));
+	session_->onNeedCredentials.disconnect(boost::bind(&CoreClient::handleNeedCredentials, this));
+
+	sessionStream_->onDataRead.disconnect(boost::bind(&CoreClient::handleDataRead, this, _1));
+	sessionStream_->onDataWritten.disconnect(boost::bind(&CoreClient::handleDataWritten, this, _1));
+	sessionStream_.reset();
+
+	connection_->disconnect();
+	connection_.reset();
+}
+
+void CoreClient::forceReset() {
+	if (connector_) {
+		std::cerr << "Warning: Client not disconnected properly: Connector still active" << std::endl;
+		resetConnector();
+	}
+	if (sessionStream_ || connection_) {
+		std::cerr << "Warning: Client not disconnected properly: Session still active" << std::endl;
+		resetSession();
+	}
+}
+
 }
diff --git a/Swiften/Client/CoreClient.h b/Swiften/Client/CoreClient.h
index 3472e76..ad31e72 100644
--- a/Swiften/Client/CoreClient.h
+++ b/Swiften/Client/CoreClient.h
@@ -209,6 +209,10 @@ namespace Swift {
 			void handleStanzaAcked(boost::shared_ptr<Stanza>);
 			void purgePassword();
 
+			void resetConnector();
+			void resetSession();
+			void forceReset();
+
 		private:
 			JID jid_;
 			SafeByteArray password_;
diff --git a/Swiften/QA/ClientTest/ClientTest.cpp b/Swiften/QA/ClientTest/ClientTest.cpp
index 584f644..4515893 100644
--- a/Swiften/QA/ClientTest/ClientTest.cpp
+++ b/Swiften/QA/ClientTest/ClientTest.cpp
@@ -22,27 +22,33 @@ SimpleEventLoop eventLoop;
 BoostNetworkFactories networkFactories(&eventLoop);
 
 Client* client = 0;
-bool reconnected = false;
 bool rosterReceived = false;
+enum TestStage {
+	FirstConnect,
+	Reconnect
+};
+TestStage stage;
 
-void handleDisconnected(boost::optional<ClientError>) {
-	eventLoop.stop();
-}
-
-void handleRosterReceived(boost::shared_ptr<Payload>) {
-	if (reconnected) {
-		rosterReceived = true;
-		client->onDisconnected.connect(boost::bind(&handleDisconnected, _1));
-		client->disconnect();
+void handleDisconnected(boost::optional<ClientError> e) {
+	std::cout << "Disconnected: " << e << std::endl;
+	if (stage == FirstConnect) {
+		stage = Reconnect;
+		client->connect();
 	}
 	else {
-		reconnected = true;
-		client->disconnect();
-		client->connect();
+		eventLoop.stop();
 	}
 }
 
+void handleRosterReceived(boost::shared_ptr<Payload>) {
+	rosterReceived = true;
+	std::cout << "Disconnecting" << std::endl;
+	client->disconnect();
+}
+
 void handleConnected() {
+	std::cout << "Connected" << std::endl;
+	rosterReceived = false;
 	GetRosterRequest::ref rosterRequest = GetRosterRequest::create(client->getIQRouter());
 	rosterRequest->onResponse.connect(boost::bind(&handleRosterReceived, _1));
 	rosterRequest->send();
@@ -63,7 +69,9 @@ int main(int, char**) {
 	client = new Swift::Client(JID(jid), std::string(pass), &networkFactories);
 	ClientXMLTracer* tracer = new ClientXMLTracer(client);
 	client->onConnected.connect(&handleConnected);
+	client->onDisconnected.connect(boost::bind(&handleDisconnected, _1));
 	client->setAlwaysTrustCertificates();
+	stage = FirstConnect;
 	client->connect();
 
 	{
-- 
cgit v0.10.2-6-g49f6