From 3760140b77f1cf568a7cdf824502ff6568e62fc1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Sun, 10 Oct 2010 18:07:31 +0200
Subject: Client refactoring.

Removing inheritance from StanzaChannel to trim down the public API.

diff --git a/Swift/Controllers/MainController.cpp b/Swift/Controllers/MainController.cpp
index 53b9ab0..c219ae9 100644
--- a/Swift/Controllers/MainController.cpp
+++ b/Swift/Controllers/MainController.cpp
@@ -285,7 +285,7 @@ void MainController::handleConnected() {
 		rosterController_->onChangeStatusRequest.connect(boost::bind(&MainController::handleChangeStatusRequest, this, _1, _2));
 		rosterController_->onSignOutRequest.connect(boost::bind(&MainController::signOut, this));
 
-		chatsManager_ = new ChatsManager(jid_, client_, client_->getIQRouter(), eventController_, chatWindowFactory_, nickResolver_, presenceOracle_, serverDiscoInfo_, presenceSender_, uiEventStream_, chatListWindowFactory_, useDelayForLatency_, &timerFactory_, mucRegistry_, entityCapsManager_);
+		chatsManager_ = new ChatsManager(jid_, client_->getStanzaChannel(), client_->getIQRouter(), eventController_, chatWindowFactory_, nickResolver_, presenceOracle_, serverDiscoInfo_, presenceSender_, uiEventStream_, chatListWindowFactory_, useDelayForLatency_, &timerFactory_, mucRegistry_, entityCapsManager_);
 		client_->onMessageReceived.connect(boost::bind(&ChatsManager::handleIncomingMessage, chatsManager_, _1));
 		chatsManager_->setAvatarManager(avatarManager_);
 
@@ -420,17 +420,17 @@ void MainController::performLoginFromCachedCredentials() {
 	}
 	if (!client_) {
 		client_ = new Swift::Client(jid_, password_);
-		presenceSender_ = new PresenceSender(client_);
-		presenceOracle_ = new PresenceOracle(client_);
+		presenceSender_ = new PresenceSender(client_->getStanzaChannel());
+		presenceOracle_ = new PresenceOracle(client_->getStanzaChannel());
 		mucRegistry_ = new MUCRegistry();
 		xmppRoster_ = new XMPPRoster();
 		vcardManager_ = new VCardManager(jid_, client_->getIQRouter(), getVCardStorageForProfile(jid_));
 		vcardManager_->onVCardChanged.connect(boost::bind(&MainController::handleVCardReceived, this, _1, _2));
 		nickResolver_ = new NickResolver(this->jid_.toBare(), xmppRoster_, vcardManager_, mucRegistry_);
-		avatarManager_ = new AvatarManagerImpl(vcardManager_, client_, avatarStorage_, mucRegistry_);
-		capsManager_ = new CapsManager(capsStorage_, client_, client_->getIQRouter());
-		entityCapsManager_ = new EntityCapsManager(capsManager_, client_);
-		presenceNotifier_ = new PresenceNotifier(client_, notifier_, mucRegistry_, avatarManager_, nickResolver_, presenceOracle_, &timerFactory_);
+		avatarManager_ = new AvatarManagerImpl(vcardManager_, client_->getStanzaChannel(), avatarStorage_, mucRegistry_);
+		capsManager_ = new CapsManager(capsStorage_, client_->getStanzaChannel(), client_->getIQRouter());
+		entityCapsManager_ = new EntityCapsManager(capsManager_, client_->getStanzaChannel());
+		presenceNotifier_ = new PresenceNotifier(client_->getStanzaChannel(), notifier_, mucRegistry_, avatarManager_, nickResolver_, presenceOracle_, &timerFactory_);
 		presenceNotifier_->onNotificationActivated.connect(boost::bind(&MainController::handleNotificationClicked, this, _1));
 		eventNotifier_ = new EventNotifier(eventController_, notifier_, avatarManager_, nickResolver_);
 		eventNotifier_->onNotificationActivated.connect(boost::bind(&MainController::handleNotificationClicked, this, _1));
diff --git a/Swiften/Client/Client.cpp b/Swiften/Client/Client.cpp
index 5b57672..120a8fb 100644
--- a/Swiften/Client/Client.cpp
+++ b/Swiften/Client/Client.cpp
@@ -18,11 +18,19 @@
 #include "Swiften/TLS/PKCS12Certificate.h"
 #include "Swiften/Session/BasicSessionStream.h"
 #include "Swiften/Queries/IQRouter.h"
+#include "Swiften/Base/IDGenerator.h"
+#include "Swiften/Client/ClientSessionStanzaChannel.h"
 
 namespace Swift {
 
 Client::Client(const JID& jid, const String& password) : jid_(jid), password_(password), disconnectRequested_(false) {
-	iqRouter_ = new IQRouter(this);
+	stanzaChannel_ = new ClientSessionStanzaChannel();
+	stanzaChannel_->onMessageReceived.connect(boost::ref(onMessageReceived));
+	stanzaChannel_->onPresenceReceived.connect(boost::ref(onPresenceReceived));
+	stanzaChannel_->onStanzaAcked.connect(boost::ref(onStanzaAcked));
+	stanzaChannel_->onAvailableChanged.connect(boost::bind(&Client::handleStanzaChannelAvailableChanged, this, _1));
+
+	iqRouter_ = new IQRouter(stanzaChannel_);
 	connectionFactory_ = new BoostConnectionFactory(&MainBoostIOServiceThread::getInstance().getIOService());
 	timerFactory_ = new BoostTimerFactory(&MainBoostIOServiceThread::getInstance().getIOService());
 	tlsLayerFactory_ = new PlatformTLSLayerFactory();
@@ -36,10 +44,12 @@ Client::~Client() {
 	delete timerFactory_;
 	delete connectionFactory_;
 	delete iqRouter_;
-}
 
-bool Client::isAvailable() {
-	return session_ && session_->getState() == ClientSession::Initialized;
+	stanzaChannel_->onAvailableChanged.disconnect(boost::bind(&Client::handleStanzaChannelAvailableChanged, this, _1));
+	stanzaChannel_->onMessageReceived.disconnect(boost::ref(onMessageReceived));
+	stanzaChannel_->onPresenceReceived.disconnect(boost::ref(onPresenceReceived));
+	stanzaChannel_->onStanzaAcked.disconnect(boost::ref(onStanzaAcked));
+	delete stanzaChannel_;
 }
 
 void Client::connect() {
@@ -81,11 +91,9 @@ void Client::handleConnectorFinished(boost::shared_ptr<Connection> connection) {
 		sessionStream_->initialize();
 
 		session_ = ClientSession::create(jid_, sessionStream_);
-		session_->onInitialized.connect(boost::bind(&Client::handleSessionInitialized, this));
-		session_->onStanzaAcked.connect(boost::bind(&Client::handleStanzaAcked, this, _1));
+		stanzaChannel_->setSession(session_);
 		session_->onFinished.connect(boost::bind(&Client::handleSessionFinished, this, _1));
 		session_->onNeedCredentials.connect(boost::bind(&Client::handleNeedCredentials, this));
-		session_->onStanzaReceived.connect(boost::bind(&Client::handleStanza, this, _1));
 		session_->start();
 	}
 }
@@ -107,60 +115,13 @@ void Client::disconnect() {
 	disconnectRequested_ = false;
 }
 
-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_->sendStanza(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::handleStanza(boost::shared_ptr<Stanza> stanza) {
-	boost::shared_ptr<Message> message = boost::dynamic_pointer_cast<Message>(stanza);
-	if (message) {
-		onMessageReceived(message);
-		return;
-	}
-
-	boost::shared_ptr<Presence> presence = boost::dynamic_pointer_cast<Presence>(stanza);
-	if (presence) {
-		onPresenceReceived(presence);
-		return;
-	}
-
-	boost::shared_ptr<IQ> iq = boost::dynamic_pointer_cast<IQ>(stanza);
-	if (iq) {
-		onIQReceived(iq);
-		return;
-	}
-}
-
 void Client::setCertificate(const String& certificate) {
 	certificate_ = certificate;
 }
 
 void Client::handleSessionFinished(boost::shared_ptr<Error> error) {
-	session_->onInitialized.disconnect(boost::bind(&Client::handleSessionInitialized, this));
-	session_->onStanzaAcked.disconnect(boost::bind(&Client::handleStanzaAcked, this, _1));
 	session_->onFinished.disconnect(boost::bind(&Client::handleSessionFinished, this, _1));
 	session_->onNeedCredentials.disconnect(boost::bind(&Client::handleNeedCredentials, this));
-	session_->onStanzaReceived.disconnect(boost::bind(&Client::handleStanza, this, _1));
 	session_.reset();
 
 	sessionStream_->onDataRead.disconnect(boost::bind(&Client::handleDataRead, this, _1));
@@ -170,8 +131,6 @@ void Client::handleSessionFinished(boost::shared_ptr<Error> error) {
 	connection_->disconnect();
 	connection_.reset();
 
-	onAvailableChanged(false);
-
 	if (error) {
 		ClientError clientError;
 		if (boost::shared_ptr<ClientSession::Error> actualError = boost::dynamic_pointer_cast<ClientSession::Error>(error)) {
@@ -233,13 +192,6 @@ void Client::handleNeedCredentials() {
 	session_->sendCredentials(password_);
 }
 
-bool Client::getStreamManagementEnabled() const {
-	if (session_) {
-		return session_->getStreamManagementEnabled();
-	}
-	return false;
-}
-
 void Client::handleDataRead(const String& data) {
 	onDataRead(data);
 }
@@ -248,14 +200,18 @@ void Client::handleDataWritten(const String& data) {
 	onDataWritten(data);
 }
 
-void Client::handleStanzaAcked(boost::shared_ptr<Stanza> stanza) {
-	onStanzaAcked(stanza);
+void Client::handleStanzaChannelAvailableChanged(bool available) {
+	if (available) {
+		onConnected();
+	}
+}
+
+void Client::sendMessage(boost::shared_ptr<Message> message) {
+	stanzaChannel_->sendMessage(message);
 }
 
-void Client::handleSessionInitialized() {
-	jid_ = session_->getLocalJID();
-	onConnected();
-	onAvailableChanged(true);
+void Client::sendPresence(boost::shared_ptr<Presence> presence) {
+	stanzaChannel_->sendPresence(presence);
 }
 
 }
diff --git a/Swiften/Client/Client.h b/Swiften/Client/Client.h
index 5432920..4319eaa 100644
--- a/Swiften/Client/Client.h
+++ b/Swiften/Client/Client.h
@@ -18,11 +18,11 @@
 #include "Swiften/Elements/Message.h"
 #include "Swiften/JID/JID.h"
 #include "Swiften/Base/String.h"
-#include "Swiften/Base/IDGenerator.h"
 #include "Swiften/Client/StanzaChannel.h"
 #include "Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.h"
 #include "Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h"
 #include "Swiften/Base/Shared.h"
+#include "Swiften/Client/ClientSessionStanzaChannel.h"
 
 namespace Swift {
 	class IQRouter;
@@ -32,7 +32,7 @@ namespace Swift {
 	class ClientSession;
 	class BasicSessionStream;
 
-	class Client : public StanzaChannel, public boost::bsignals::trackable {
+	class Client  {
 		public:
 			Client(const JID& jid, const String& password);
 			~Client();
@@ -44,24 +44,32 @@ namespace Swift {
 			void connect(const String& host);
 			void disconnect();
 			
-			bool isAvailable();
-
-			bool getStreamManagementEnabled() const;
-
-			virtual void sendIQ(boost::shared_ptr<IQ>);
-			virtual void sendMessage(boost::shared_ptr<Message>);
-			virtual void sendPresence(boost::shared_ptr<Presence>);
+			void sendMessage(boost::shared_ptr<Message>);
+			void sendPresence(boost::shared_ptr<Presence>);
 
 			IQRouter* getIQRouter() const {
 				return iqRouter_;
 			}
 
+			StanzaChannel* getStanzaChannel() const {
+				return stanzaChannel_;
+			}
+
+			bool isAvailable() const {
+				return stanzaChannel_->isAvailable();
+			}
+
 			/**
 			 * Returns the JID of the client. 
 			 * After the session was initialized, this returns the bound JID.
 			 */
 			const JID& getJID() const {
-				return jid_;
+				if (session_) {
+					return session_->getLocalJID();
+				}
+				else {
+					return jid_;
+				}
 			}
 
 		public:
@@ -70,23 +78,23 @@ namespace Swift {
 			boost::signal<void (const String&)> onDataRead;
 			boost::signal<void (const String&)> onDataWritten;
 
+			boost::signal<void (boost::shared_ptr<Message>)> onMessageReceived;
+			boost::signal<void (boost::shared_ptr<Presence>) > onPresenceReceived;
+			boost::signal<void (boost::shared_ptr<Stanza>)> onStanzaAcked;
+
 		private:
 			void handleConnectorFinished(boost::shared_ptr<Connection>);
-			void handleSessionInitialized();
-			void send(boost::shared_ptr<Stanza>);
-			virtual String getNewIQID();
-			void handleStanza(boost::shared_ptr<Stanza>);
+			void handleStanzaChannelAvailableChanged(bool available);
 			void handleSessionFinished(boost::shared_ptr<Error>);
 			void handleNeedCredentials();
 			void handleDataRead(const String&);
 			void handleDataWritten(const String&);
-			void handleStanzaAcked(boost::shared_ptr<Stanza>);
 
 		private:
 			PlatformDomainNameResolver resolver_;
 			JID jid_;
 			String password_;
-			IDGenerator idGenerator_;
+			ClientSessionStanzaChannel* stanzaChannel_;
 			IQRouter* iqRouter_;
 			Connector::ref connector_;
 			ConnectionFactory* connectionFactory_;
diff --git a/Swiften/Client/ClientSessionStanzaChannel.cpp b/Swiften/Client/ClientSessionStanzaChannel.cpp
new file mode 100644
index 0000000..7656d06
--- /dev/null
+++ b/Swiften/Client/ClientSessionStanzaChannel.cpp
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include "Swiften/Client/ClientSessionStanzaChannel.h"
+
+#include <boost/bind.hpp>
+
+namespace Swift {
+
+void ClientSessionStanzaChannel::setSession(boost::shared_ptr<ClientSession> session) {
+	assert(!this->session);
+	this->session = session;
+	session->onInitialized.connect(boost::bind(&ClientSessionStanzaChannel::handleSessionInitialized, this));
+	session->onFinished.connect(boost::bind(&ClientSessionStanzaChannel::handleSessionFinished, this, _1));
+	session->onStanzaReceived.connect(boost::bind(&ClientSessionStanzaChannel::handleStanza, this, _1));
+	session->onStanzaAcked.connect(boost::bind(&ClientSessionStanzaChannel::handleStanzaAcked, this, _1));
+}
+
+void ClientSessionStanzaChannel::sendIQ(boost::shared_ptr<IQ> iq) {
+	send(iq);
+}
+
+void ClientSessionStanzaChannel::sendMessage(boost::shared_ptr<Message> message) {
+	send(message);
+}
+
+void ClientSessionStanzaChannel::sendPresence(boost::shared_ptr<Presence> presence) {
+	send(presence);
+}
+
+String ClientSessionStanzaChannel::getNewIQID() {
+	return idGenerator.generateID();
+}
+
+void ClientSessionStanzaChannel::send(boost::shared_ptr<Stanza> stanza) {
+	if (!isAvailable()) {
+		std::cerr << "Warning: Client: Trying to send a stanza while disconnected." << std::endl;
+		return;
+	}
+	session->sendStanza(stanza);
+}
+
+void ClientSessionStanzaChannel::handleSessionFinished(boost::shared_ptr<Error> error) {
+	session->onFinished.disconnect(boost::bind(&ClientSessionStanzaChannel::handleSessionFinished, this, _1));
+	session->onStanzaReceived.disconnect(boost::bind(&ClientSessionStanzaChannel::handleStanza, this, _1));
+	session->onStanzaAcked.disconnect(boost::bind(&ClientSessionStanzaChannel::handleStanzaAcked, this, _1));
+	session->onInitialized.disconnect(boost::bind(&ClientSessionStanzaChannel::handleSessionInitialized, this));
+	session.reset();
+
+	onAvailableChanged(false);
+}
+
+void ClientSessionStanzaChannel::handleStanza(boost::shared_ptr<Stanza> stanza) {
+	boost::shared_ptr<Message> message = boost::dynamic_pointer_cast<Message>(stanza);
+	if (message) {
+		onMessageReceived(message);
+		return;
+	}
+
+	boost::shared_ptr<Presence> presence = boost::dynamic_pointer_cast<Presence>(stanza);
+	if (presence) {
+		onPresenceReceived(presence);
+		return;
+	}
+
+	boost::shared_ptr<IQ> iq = boost::dynamic_pointer_cast<IQ>(stanza);
+	if (iq) {
+		onIQReceived(iq);
+		return;
+	}
+}
+
+
+bool ClientSessionStanzaChannel::getStreamManagementEnabled() const {
+	if (session) {
+		return session->getStreamManagementEnabled();
+	}
+	return false;
+}
+
+void ClientSessionStanzaChannel::handleStanzaAcked(boost::shared_ptr<Stanza> stanza) {
+	onStanzaAcked(stanza);
+}
+
+
+void ClientSessionStanzaChannel::handleSessionInitialized() {
+	onAvailableChanged(true);
+}
+
+}
diff --git a/Swiften/Client/ClientSessionStanzaChannel.h b/Swiften/Client/ClientSessionStanzaChannel.h
new file mode 100644
index 0000000..d3fd093
--- /dev/null
+++ b/Swiften/Client/ClientSessionStanzaChannel.h
@@ -0,0 +1,48 @@
+/*
+ * 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 <boost/shared_ptr.hpp>
+
+#include "Swiften/Base/IDGenerator.h"
+#include "Swiften/Client/ClientSession.h"
+#include "Swiften/Client/StanzaChannel.h"
+#include "Swiften/Elements/Message.h"
+#include "Swiften/Elements/IQ.h"
+#include "Swiften/Elements/Presence.h"
+
+namespace Swift {
+	/**
+	 * StanzaChannel implementation around a ClientSession.
+	 */
+	class ClientSessionStanzaChannel : public StanzaChannel {
+		public:
+			void setSession(boost::shared_ptr<ClientSession> session);
+
+			void sendIQ(boost::shared_ptr<IQ> iq);
+			void sendMessage(boost::shared_ptr<Message> message);
+			void sendPresence(boost::shared_ptr<Presence> presence);
+			bool getStreamManagementEnabled() const;
+
+			bool isAvailable() const {
+				return session && session->getState() == ClientSession::Initialized;
+			}
+
+		private:
+			String getNewIQID();
+			void send(boost::shared_ptr<Stanza> stanza);
+			void handleSessionFinished(boost::shared_ptr<Error> error);
+			void handleStanza(boost::shared_ptr<Stanza> stanza);
+			void handleStanzaAcked(boost::shared_ptr<Stanza> stanza);
+			void handleSessionInitialized();
+
+		private:
+			IDGenerator idGenerator;
+			boost::shared_ptr<ClientSession> session;
+	};
+
+}
diff --git a/Swiften/Client/DummyStanzaChannel.h b/Swiften/Client/DummyStanzaChannel.h
index f13e587..b8ae545 100644
--- a/Swiften/Client/DummyStanzaChannel.h
+++ b/Swiften/Client/DummyStanzaChannel.h
@@ -40,7 +40,7 @@ namespace Swift {
 				return "test-id";
 			}
 			
-			virtual bool isAvailable() {
+			virtual bool isAvailable() const {
 				return available_;
 			}
 
diff --git a/Swiften/Client/StanzaChannel.h b/Swiften/Client/StanzaChannel.h
index f7bb26a..4d6392c 100644
--- a/Swiften/Client/StanzaChannel.h
+++ b/Swiften/Client/StanzaChannel.h
@@ -18,7 +18,7 @@ namespace Swift {
 		public:
 			virtual void sendMessage(boost::shared_ptr<Message>) = 0;
 			virtual void sendPresence(boost::shared_ptr<Presence>) = 0;
-			virtual bool isAvailable() = 0;
+			virtual bool isAvailable() const = 0;
 			virtual bool getStreamManagementEnabled() const = 0;
 
 			boost::signal<void (bool /* isAvailable */)> onAvailableChanged;
diff --git a/Swiften/Queries/DummyIQChannel.h b/Swiften/Queries/DummyIQChannel.h
index e327beb..92b7f2b 100644
--- a/Swiften/Queries/DummyIQChannel.h
+++ b/Swiften/Queries/DummyIQChannel.h
@@ -4,8 +4,7 @@
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
 
-#ifndef SWIFTEN_DummyIQChannel_H
-#define SWIFTEN_DummyIQChannel_H
+#pragma once
 
 #include <vector>
 
@@ -24,12 +23,10 @@ namespace Swift {
 				return "test-id";
 			}
 
-			virtual bool isAvailable() {
+			virtual bool isAvailable() const {
 				return true;
 			}
 
 			std::vector<boost::shared_ptr<IQ> > iqs_;
 	};
 }
-
-#endif
diff --git a/Swiften/Queries/IQChannel.h b/Swiften/Queries/IQChannel.h
index 2f18111..e700b51 100644
--- a/Swiften/Queries/IQChannel.h
+++ b/Swiften/Queries/IQChannel.h
@@ -21,7 +21,7 @@ namespace Swift {
 			virtual void sendIQ(boost::shared_ptr<IQ>) = 0;
 			virtual String getNewIQID() = 0;
 			
-			virtual bool isAvailable() = 0;
+			virtual bool isAvailable() const = 0;
 
 			boost::signal<void (boost::shared_ptr<IQ>)> onIQReceived;
 	};
diff --git a/Swiften/SConscript b/Swiften/SConscript
index ace9ab7..981b714 100644
--- a/Swiften/SConscript
+++ b/Swiften/SConscript
@@ -29,6 +29,7 @@ if env["SCONS_STAGE"] == "build" :
 			"Chat/ChatStateTracker.cpp",
 			"Chat/ChatStateNotifier.cpp",
 			"Chat/ChatStateMessageSender.cpp",
+			"Client/ClientSessionStanzaChannel.cpp",
 			"Client/Client.cpp",
 			"Client/ClientSession.cpp",
 			"Compress/ZLibCodecompressor.cpp",
-- 
cgit v0.10.2-6-g49f6