From 1a3208aff3349cdecec30f12dacfd10ecb5901eb 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:53:34 +0200
Subject: Separate CoreClient out of Client.


diff --git a/Swiften/Client/Client.cpp b/Swiften/Client/Client.cpp
index 120a8fb..44804be 100644
--- a/Swiften/Client/Client.cpp
+++ b/Swiften/Client/Client.cpp
@@ -6,212 +6,9 @@
 
 #include "Swiften/Client/Client.h"
 
-#include <boost/bind.hpp>
-
-#include "Swiften/Network/MainBoostIOServiceThread.h"
-#include "Swiften/Network/BoostIOServiceThread.h"
-#include "Swiften/Client/ClientSession.h"
-#include "Swiften/StreamStack/PlatformTLSLayerFactory.h"
-#include "Swiften/Network/Connector.h"
-#include "Swiften/Network/BoostConnectionFactory.h"
-#include "Swiften/Network/BoostTimerFactory.h"
-#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) {
-	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();
-}
-
-Client::~Client() {
-	if (session_ || connection_) {
-		std::cerr << "Warning: Client not disconnected properly" << std::endl;
-	}
-	delete tlsLayerFactory_;
-	delete timerFactory_;
-	delete connectionFactory_;
-	delete iqRouter_;
-
-	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() {
-	connect(jid_.getDomain());
-}
-
-void Client::connect(const JID& jid) {
-	jid_ = jid;
-	connect();
-}
-
-void Client::connect(const String& host) {
-	assert(!connector_);
-	connector_ = Connector::create(host, &resolver_, connectionFactory_, timerFactory_);
-	connector_->onConnectFinished.connect(boost::bind(&Client::handleConnectorFinished, this, _1));
-	connector_->setTimeoutMilliseconds(60*1000);
-	connector_->start();
-}
-
-void Client::handleConnectorFinished(boost::shared_ptr<Connection> connection) {
-	connector_->onConnectFinished.disconnect(boost::bind(&Client::handleConnectorFinished, this, _1));
-	connector_.reset();
-	if (!connection) {
-		if (!disconnectRequested_) {
-			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_);
-		stanzaChannel_->setSession(session_);
-		session_->onFinished.connect(boost::bind(&Client::handleSessionFinished, this, _1));
-		session_->onNeedCredentials.connect(boost::bind(&Client::handleNeedCredentials, this));
-		session_->start();
-	}
-}
-
-void Client::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_) {
-		session_->finish();
-	}
-	else if (connector_) {
-		connector_->stop();
-		assert(!session_);
-	}
-	assert(!session_);
-	assert(!sessionStream_);
-	assert(!connector_);
-	disconnectRequested_ = false;
-}
-
-void Client::setCertificate(const String& certificate) {
-	certificate_ = certificate;
-}
-
-void Client::handleSessionFinished(boost::shared_ptr<Error> error) {
-	session_->onFinished.disconnect(boost::bind(&Client::handleSessionFinished, this, _1));
-	session_->onNeedCredentials.disconnect(boost::bind(&Client::handleNeedCredentials, this));
-	session_.reset();
-
-	sessionStream_->onDataRead.disconnect(boost::bind(&Client::handleDataRead, this, _1));
-	sessionStream_->onDataWritten.disconnect(boost::bind(&Client::handleDataWritten, this, _1));
-	sessionStream_.reset();
-
-	connection_->disconnect();
-	connection_.reset();
-
-	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);
-	}
-}
-
-void Client::handleNeedCredentials() {
-	assert(session_);
-	session_->sendCredentials(password_);
-}
-
-void Client::handleDataRead(const String& data) {
-	onDataRead(data);
-}
-
-void Client::handleDataWritten(const String& data) {
-	onDataWritten(data);
-}
-
-void Client::handleStanzaChannelAvailableChanged(bool available) {
-	if (available) {
-		onConnected();
-	}
-}
-
-void Client::sendMessage(boost::shared_ptr<Message> message) {
-	stanzaChannel_->sendMessage(message);
-}
-
-void Client::sendPresence(boost::shared_ptr<Presence> presence) {
-	stanzaChannel_->sendPresence(presence);
+Client::Client(const JID& jid, const String& password) : CoreClient(jid, password) {
 }
 
 }
diff --git a/Swiften/Client/Client.h b/Swiften/Client/Client.h
index 4319eaa..7609eb8 100644
--- a/Swiften/Client/Client.h
+++ b/Swiften/Client/Client.h
@@ -6,106 +6,11 @@
 
 #pragma once
 
-#include "Swiften/Base/boost_bsignals.h"
-#include <boost/shared_ptr.hpp>
-
-#include "Swiften/Network/PlatformDomainNameResolver.h"
-#include "Swiften/Network/Connector.h"
-#include "Swiften/Base/Error.h"
-#include "Swiften/Client/ClientSession.h"
-#include "Swiften/Client/ClientError.h"
-#include "Swiften/Elements/Presence.h"
-#include "Swiften/Elements/Message.h"
-#include "Swiften/JID/JID.h"
-#include "Swiften/Base/String.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"
+#include "Swiften/Client/CoreClient.h"
 
 namespace Swift {
-	class IQRouter;
-	class TLSLayerFactory;
-	class ConnectionFactory;
-	class TimerFactory;
-	class ClientSession;
-	class BasicSessionStream;
-
-	class Client  {
+	class Client : public CoreClient {
 		public:
 			Client(const JID& jid, const String& password);
-			~Client();
-
-			void setCertificate(const String& certificate);
-
-			void connect();
-			void connect(const JID& jid);
-			void connect(const String& host);
-			void disconnect();
-			
-			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 {
-				if (session_) {
-					return session_->getLocalJID();
-				}
-				else {
-					return jid_;
-				}
-			}
-
-		public:
-			boost::signal<void (const ClientError&)> onError;
-			boost::signal<void ()> onConnected;
-			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 handleStanzaChannelAvailableChanged(bool available);
-			void handleSessionFinished(boost::shared_ptr<Error>);
-			void handleNeedCredentials();
-			void handleDataRead(const String&);
-			void handleDataWritten(const String&);
-
-		private:
-			PlatformDomainNameResolver resolver_;
-			JID jid_;
-			String password_;
-			ClientSessionStanzaChannel* stanzaChannel_;
-			IQRouter* iqRouter_;
-			Connector::ref connector_;
-			ConnectionFactory* connectionFactory_;
-			TimerFactory* timerFactory_;
-			TLSLayerFactory* tlsLayerFactory_;
-			FullPayloadParserFactoryCollection payloadParserFactories_;
-			FullPayloadSerializerCollection payloadSerializers_;
-			boost::shared_ptr<Connection> connection_;
-			boost::shared_ptr<BasicSessionStream> sessionStream_;
-			boost::shared_ptr<ClientSession> session_;
-			String certificate_;
-			bool disconnectRequested_;
 	};
 }
diff --git a/Swiften/Client/CoreClient.cpp b/Swiften/Client/CoreClient.cpp
new file mode 100644
index 0000000..c80acb5
--- /dev/null
+++ b/Swiften/Client/CoreClient.cpp
@@ -0,0 +1,217 @@
+/*
+ * 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/CoreClient.h"
+
+#include <boost/bind.hpp>
+
+#include "Swiften/Network/MainBoostIOServiceThread.h"
+#include "Swiften/Network/BoostIOServiceThread.h"
+#include "Swiften/Client/ClientSession.h"
+#include "Swiften/StreamStack/PlatformTLSLayerFactory.h"
+#include "Swiften/Network/Connector.h"
+#include "Swiften/Network/BoostConnectionFactory.h"
+#include "Swiften/Network/BoostTimerFactory.h"
+#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 {
+
+CoreClient::CoreClient(const JID& jid, const String& password) : jid_(jid), password_(password), disconnectRequested_(false) {
+	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(&CoreClient::handleStanzaChannelAvailableChanged, this, _1));
+
+	iqRouter_ = new IQRouter(stanzaChannel_);
+	connectionFactory_ = new BoostConnectionFactory(&MainBoostIOServiceThread::getInstance().getIOService());
+	timerFactory_ = new BoostTimerFactory(&MainBoostIOServiceThread::getInstance().getIOService());
+	tlsLayerFactory_ = new PlatformTLSLayerFactory();
+}
+
+CoreClient::~CoreClient() {
+	if (session_ || connection_) {
+		std::cerr << "Warning: Client not disconnected properly" << std::endl;
+	}
+	delete tlsLayerFactory_;
+	delete timerFactory_;
+	delete connectionFactory_;
+	delete iqRouter_;
+
+	stanzaChannel_->onAvailableChanged.disconnect(boost::bind(&CoreClient::handleStanzaChannelAvailableChanged, this, _1));
+	stanzaChannel_->onMessageReceived.disconnect(boost::ref(onMessageReceived));
+	stanzaChannel_->onPresenceReceived.disconnect(boost::ref(onPresenceReceived));
+	stanzaChannel_->onStanzaAcked.disconnect(boost::ref(onStanzaAcked));
+	delete stanzaChannel_;
+}
+
+void CoreClient::connect() {
+	connect(jid_.getDomain());
+}
+
+void CoreClient::connect(const JID& jid) {
+	jid_ = jid;
+	connect();
+}
+
+void CoreClient::connect(const String& host) {
+	assert(!connector_);
+	connector_ = Connector::create(host, &resolver_, connectionFactory_, timerFactory_);
+	connector_->onConnectFinished.connect(boost::bind(&CoreClient::handleConnectorFinished, this, _1));
+	connector_->setTimeoutMilliseconds(60*1000);
+	connector_->start();
+}
+
+void CoreClient::handleConnectorFinished(boost::shared_ptr<Connection> connection) {
+	connector_->onConnectFinished.disconnect(boost::bind(&CoreClient::handleConnectorFinished, this, _1));
+	connector_.reset();
+	if (!connection) {
+		if (!disconnectRequested_) {
+			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(&CoreClient::handleDataRead, this, _1));
+		sessionStream_->onDataWritten.connect(boost::bind(&CoreClient::handleDataWritten, this, _1));
+		sessionStream_->initialize();
+
+		session_ = ClientSession::create(jid_, sessionStream_);
+		stanzaChannel_->setSession(session_);
+		session_->onFinished.connect(boost::bind(&CoreClient::handleSessionFinished, this, _1));
+		session_->onNeedCredentials.connect(boost::bind(&CoreClient::handleNeedCredentials, this));
+		session_->start();
+	}
+}
+
+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_) {
+		session_->finish();
+	}
+	else if (connector_) {
+		connector_->stop();
+		assert(!session_);
+	}
+	assert(!session_);
+	assert(!sessionStream_);
+	assert(!connector_);
+	disconnectRequested_ = false;
+}
+
+void CoreClient::setCertificate(const String& certificate) {
+	certificate_ = 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));
+	sessionStream_.reset();
+
+	connection_->disconnect();
+	connection_.reset();
+
+	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);
+	}
+}
+
+void CoreClient::handleNeedCredentials() {
+	assert(session_);
+	session_->sendCredentials(password_);
+}
+
+void CoreClient::handleDataRead(const String& data) {
+	onDataRead(data);
+}
+
+void CoreClient::handleDataWritten(const String& data) {
+	onDataWritten(data);
+}
+
+void CoreClient::handleStanzaChannelAvailableChanged(bool available) {
+	if (available) {
+		onConnected();
+	}
+}
+
+void CoreClient::sendMessage(boost::shared_ptr<Message> message) {
+	stanzaChannel_->sendMessage(message);
+}
+
+void CoreClient::sendPresence(boost::shared_ptr<Presence> presence) {
+	stanzaChannel_->sendPresence(presence);
+}
+
+}
diff --git a/Swiften/Client/CoreClient.h b/Swiften/Client/CoreClient.h
new file mode 100644
index 0000000..704cf3b
--- /dev/null
+++ b/Swiften/Client/CoreClient.h
@@ -0,0 +1,111 @@
+/*
+ * 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 <boost/shared_ptr.hpp>
+
+#include "Swiften/Network/PlatformDomainNameResolver.h"
+#include "Swiften/Network/Connector.h"
+#include "Swiften/Base/Error.h"
+#include "Swiften/Client/ClientSession.h"
+#include "Swiften/Client/ClientError.h"
+#include "Swiften/Elements/Presence.h"
+#include "Swiften/Elements/Message.h"
+#include "Swiften/JID/JID.h"
+#include "Swiften/Base/String.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;
+	class TLSLayerFactory;
+	class ConnectionFactory;
+	class TimerFactory;
+	class ClientSession;
+	class BasicSessionStream;
+
+	class CoreClient  {
+		public:
+			CoreClient(const JID& jid, const String& password);
+			~CoreClient();
+
+			void setCertificate(const String& certificate);
+
+			void connect();
+			void connect(const JID& jid);
+			void connect(const String& host);
+			void disconnect();
+			
+			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 {
+				if (session_) {
+					return session_->getLocalJID();
+				}
+				else {
+					return jid_;
+				}
+			}
+
+		public:
+			boost::signal<void (const ClientError&)> onError;
+			boost::signal<void ()> onConnected;
+			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 handleStanzaChannelAvailableChanged(bool available);
+			void handleSessionFinished(boost::shared_ptr<Error>);
+			void handleNeedCredentials();
+			void handleDataRead(const String&);
+			void handleDataWritten(const String&);
+
+		private:
+			PlatformDomainNameResolver resolver_;
+			JID jid_;
+			String password_;
+			ClientSessionStanzaChannel* stanzaChannel_;
+			IQRouter* iqRouter_;
+			Connector::ref connector_;
+			ConnectionFactory* connectionFactory_;
+			TimerFactory* timerFactory_;
+			TLSLayerFactory* tlsLayerFactory_;
+			FullPayloadParserFactoryCollection payloadParserFactories_;
+			FullPayloadSerializerCollection payloadSerializers_;
+			boost::shared_ptr<Connection> connection_;
+			boost::shared_ptr<BasicSessionStream> sessionStream_;
+			boost::shared_ptr<ClientSession> session_;
+			String certificate_;
+			bool disconnectRequested_;
+	};
+}
diff --git a/Swiften/SConscript b/Swiften/SConscript
index 981b714..9ffc3de 100644
--- a/Swiften/SConscript
+++ b/Swiften/SConscript
@@ -30,6 +30,7 @@ if env["SCONS_STAGE"] == "build" :
 			"Chat/ChatStateNotifier.cpp",
 			"Chat/ChatStateMessageSender.cpp",
 			"Client/ClientSessionStanzaChannel.cpp",
+			"Client/CoreClient.cpp",
 			"Client/Client.cpp",
 			"Client/ClientSession.cpp",
 			"Compress/ZLibCodecompressor.cpp",
-- 
cgit v0.10.2-6-g49f6