From 74e666956ab3b0150ae63885cdf56efae6ca05b3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Sun, 19 Jul 2009 17:25:29 +0200
Subject: Factored out common link local session code.


diff --git a/Nim/main.cpp b/Nim/main.cpp
index 127878c..2fd5b21 100644
--- a/Nim/main.cpp
+++ b/Nim/main.cpp
@@ -16,9 +16,9 @@
 #include "Swiften/EventLoop/SimpleEventLoop.h"
 #include "Swiften/EventLoop/EventOwner.h"
 #include "Swiften/Elements/Element.h"
+#include "Swiften/LinkLocal/LinkLocalConnector.h"
 #include "Swiften/LinkLocal/LinkLocalServiceInfo.h"
 #include "Swiften/LinkLocal/LinkLocalRoster.h"
-#include "Swiften/LinkLocal/LinkLocalSession.h"
 #include "Swiften/LinkLocal/OutgoingLinkLocalSession.h"
 #include "Swiften/LinkLocal/IncomingLinkLocalSession.h"
 #include "Swiften/LinkLocal/DNSSDService.h"
@@ -46,20 +46,35 @@ class DummyUserRegistry : public UserRegistry {
 
 class Server {
 	public:
-		Server(int clientConnectionPort, int linkLocalConnectionPort) : boostConnectionFactory_(&boostIOServiceThread_.getIOService()), dnsSDServiceRegistered_(false), rosterRequested_(false), clientConnectionPort_(clientConnectionPort), linkLocalConnectionPort_(linkLocalConnectionPort) {
-			serverFromClientConnectionServer_ = boost::shared_ptr<BoostConnectionServer>(new BoostConnectionServer(clientConnectionPort, &boostIOServiceThread_.getIOService()));
-			serverFromClientConnectionServer_->onNewConnection.connect(boost::bind(&Server::handleNewClientConnection, this, _1));
+		Server(int clientConnectionPort, int linkLocalConnectionPort) : 
+				dnsSDServiceRegistered_(false), 
+				rosterRequested_(false), 
+				clientConnectionPort_(clientConnectionPort), 
+				linkLocalConnectionPort_(linkLocalConnectionPort) {
+			serverFromClientConnectionServer_ = 
+					boost::shared_ptr<BoostConnectionServer>(new BoostConnectionServer(
+							clientConnectionPort, &boostIOServiceThread_.getIOService()));
+			serverFromClientConnectionServer_->onNewConnection.connect(
+					boost::bind(&Server::handleNewClientConnection, this, _1));
 			serverFromClientConnectionServer_->start();
 
-			serverFromNetworkConnectionServer_ = boost::shared_ptr<BoostConnectionServer>(new BoostConnectionServer(linkLocalConnectionPort, &boostIOServiceThread_.getIOService()));
-			serverFromNetworkConnectionServer_->onNewConnection.connect(boost::bind(&Server::handleNewLinkLocalConnection, this, _1));
+			serverFromNetworkConnectionServer_ = 
+				boost::shared_ptr<BoostConnectionServer>(new BoostConnectionServer(
+					linkLocalConnectionPort, &boostIOServiceThread_.getIOService()));
+			serverFromNetworkConnectionServer_->onNewConnection.connect(
+					boost::bind(&Server::handleNewLinkLocalConnection, this, _1));
 			serverFromNetworkConnectionServer_->start();
 
-			dnsSDService_ = boost::shared_ptr<AppleDNSSDService>(new AppleDNSSDService());
-			dnsSDService_->onServiceRegistered.connect(boost::bind(&Server::handleServiceRegistered, this, _1));
-			linkLocalRoster_ = boost::shared_ptr<LinkLocalRoster>(new LinkLocalRoster(dnsSDService_));
-			linkLocalRoster_->onRosterChanged.connect(boost::bind(&Server::handleRosterChanged, this, _1));
-			linkLocalRoster_->onPresenceChanged.connect(boost::bind(&Server::handlePresenceChanged, this, _1));
+			dnsSDService_ = boost::shared_ptr<AppleDNSSDService>(
+					new AppleDNSSDService());
+			dnsSDService_->onServiceRegistered.connect
+					(boost::bind(&Server::handleServiceRegistered, this, _1));
+			linkLocalRoster_ = boost::shared_ptr<LinkLocalRoster>(
+					new LinkLocalRoster(dnsSDService_));
+			linkLocalRoster_->onRosterChanged.connect(
+					boost::bind(&Server::handleRosterChanged, this, _1));
+			linkLocalRoster_->onPresenceChanged.connect(
+					boost::bind(&Server::handlePresenceChanged, this, _1));
 			dnsSDService_->start();
 		}
 
@@ -94,12 +109,12 @@ class Server {
 			rosterRequested_ = false;
 		}
 
-		void handleLinkLocalSessionFinished(boost::shared_ptr<LinkLocalSession> session) {
+		void handleLinkLocalSessionFinished(boost::shared_ptr<Session> session) {
 			std::cout << "Link local session from " << session->getRemoteJID() << " ended" << std::endl;
 			linkLocalSessions_.erase(std::remove(linkLocalSessions_.begin(), linkLocalSessions_.end(), session), linkLocalSessions_.end());
 		}
 
-		void handleLinkLocalElementReceived(boost::shared_ptr<Element> element, boost::shared_ptr<LinkLocalSession> session) {
+		void handleLinkLocalElementReceived(boost::shared_ptr<Element> element, boost::shared_ptr<Session> session) {
 			if (boost::shared_ptr<Stanza> stanza = boost::dynamic_pointer_cast<Stanza>(element)) {
 				JID fromJID = session->getRemoteJID();
 				if (!linkLocalRoster_->hasItem(fromJID)) {
@@ -123,16 +138,16 @@ class Server {
 				return;
 			}
 
-			stanza->setFrom(session->getJID());
+			stanza->setFrom(session->getRemoteJID());
 			if (!stanza->getTo().isValid()) {
-				stanza->setTo(JID(session->getDomain()));
+				stanza->setTo(session->getLocalJID());
 			}
 
 			if (boost::shared_ptr<Presence> presence = boost::dynamic_pointer_cast<Presence>(stanza)) {
 				if (presence->getType() == Presence::Available) {
 					if (!dnsSDServiceRegistered_) {
 						dnsSDServiceRegistered_ = true;
-						dnsSDService_->registerService(session->getJID().toBare().toString(), linkLocalConnectionPort_, getLinkLocalServiceInfo(presence));
+						dnsSDService_->registerService(session->getRemoteJID().toBare().toString(), linkLocalConnectionPort_, getLinkLocalServiceInfo(presence));
 					}
 					else {
 						dnsSDService_->updateService(getLinkLocalServiceInfo(presence));
@@ -142,7 +157,7 @@ class Server {
 					unregisterService();
 				}
 			}
-			else if (!stanza->getTo().isValid() || stanza->getTo() == session->getDomain() || stanza->getTo() == session->getJID().toBare()) {
+			else if (!stanza->getTo().isValid() || stanza->getTo() == session->getLocalJID() || stanza->getTo() == session->getRemoteJID().toBare()) {
 				if (boost::shared_ptr<IQ> iq = boost::dynamic_pointer_cast<IQ>(stanza)) {
 					if (iq->getPayload<RosterPayload>()) {
 						if (iq->getType() == IQ::Get) {
@@ -173,23 +188,28 @@ class Server {
 			}
 			else {
 				JID toJID = stanza->getTo();
-				boost::shared_ptr<LinkLocalSession> outgoingSession = 
+				boost::shared_ptr<Session> outgoingSession = 
 						getLinkLocalSessionForJID(toJID);
 				if (outgoingSession) {
 					outgoingSession->sendElement(stanza);
 				}
 				else {
 					if (linkLocalRoster_->hasItem(toJID)) {
-						boost::shared_ptr<OutgoingLinkLocalSession> outgoingSession(
-								new OutgoingLinkLocalSession(
-									selfJID_, toJID, 
-									linkLocalRoster_->getHostname(toJID),
-									linkLocalRoster_->getPort(toJID),
-									dnsSDService_, 
-									&payloadParserFactories_, &payloadSerializers_,
-									&boostConnectionFactory_));
-						registerLinkLocalSession(outgoingSession);
-						outgoingSession->sendElement(stanza);
+						boost::shared_ptr<LinkLocalConnector> connector =
+							getLinkLocalConnectorForJID(toJID);
+						if (!connector) {
+							boost::shared_ptr<LinkLocalConnector> connector(
+									new LinkLocalConnector(
+										toJID, 
+										linkLocalRoster_->getHostname(toJID), 
+										linkLocalRoster_->getPort(toJID), 
+										dnsSDService_,
+										boost::shared_ptr<BoostConnection>(new BoostConnection(&boostIOServiceThread_.getIOService()))));
+							connector->onConnectFinished.connect(
+									boost::bind(&Server::handleConnectFinished, this, connector, _1));
+							connectors_.push_back(connector);
+						}
+						connector->queueElement(element);
 					}
 					else {
 						session->sendElement(IQ::createError(
@@ -200,26 +220,54 @@ class Server {
 			}
 		}
 
-		void registerLinkLocalSession(boost::shared_ptr<LinkLocalSession> session) {
+		void handleConnectFinished(boost::shared_ptr<LinkLocalConnector> connector, bool error) {
+			if (error) {
+				std::cerr << "Error connecting" << std::endl;
+				// TODO: Send back queued stanzas
+			}
+			else {
+				boost::shared_ptr<OutgoingLinkLocalSession> outgoingSession(
+						new OutgoingLinkLocalSession(
+							selfJID_, connector->getRemoteJID(), connector->getConnection(),
+							&payloadParserFactories_, &payloadSerializers_));
+				registerLinkLocalSession(outgoingSession);
+				foreach(const boost::shared_ptr<Element> element, connector->getQueuedElements()) {
+					outgoingSession->queueElement(element);
+				}
+			}
+			connectors_.erase(std::remove(connectors_.begin(), connectors_.end(), connector), connectors_.end());
+		}
+
+
+		void registerLinkLocalSession(boost::shared_ptr<Session> session) {
 			session->onSessionFinished.connect(boost::bind(&Server::handleLinkLocalSessionFinished, this, session));
 			session->onElementReceived.connect(boost::bind(&Server::handleLinkLocalElementReceived, this, _1, session));
 			linkLocalSessions_.push_back(session);
-			session->start();
+			session->startSession();
 		}
 
-		boost::shared_ptr<LinkLocalSession> getLinkLocalSessionForJID(const JID& jid) {
-			foreach(const boost::shared_ptr<LinkLocalSession> session, linkLocalSessions_) {
+		boost::shared_ptr<Session> getLinkLocalSessionForJID(const JID& jid) {
+			foreach(const boost::shared_ptr<Session> session, linkLocalSessions_) {
 				if (session->getRemoteJID() == jid) {
 					return session;
 				}
 			}
-			return boost::shared_ptr<LinkLocalSession>();
+			return boost::shared_ptr<Session>();
+		}
+
+		boost::shared_ptr<LinkLocalConnector> getLinkLocalConnectorForJID(const JID& jid) {
+			foreach(const boost::shared_ptr<LinkLocalConnector> connector, connectors_) {
+				if (connector->getRemoteJID() == jid) {
+					return connector;
+				}
+			}
+			return boost::shared_ptr<LinkLocalConnector>();
 		}
 
 		void handleRosterChanged(boost::shared_ptr<RosterPayload> roster) {
 			if (rosterRequested_) {
-				boost::shared_ptr<IQ> iq = IQ::createRequest(IQ::Set, serverFromClientSession_->getJID(), idGenerator_.generateID(), roster);
-				iq->setFrom(serverFromClientSession_->getJID().toBare());
+				boost::shared_ptr<IQ> iq = IQ::createRequest(IQ::Set, serverFromClientSession_->getRemoteJID(), idGenerator_.generateID(), roster);
+				iq->setFrom(serverFromClientSession_->getRemoteJID().toBare());
 				serverFromClientSession_->sendElement(iq);
 			}
 		}
@@ -259,14 +307,14 @@ class Server {
 	private:
 		IDGenerator idGenerator_;
 		BoostIOServiceThread boostIOServiceThread_;
-		BoostConnectionFactory boostConnectionFactory_;
 		DummyUserRegistry userRegistry_;
 		boost::shared_ptr<AppleDNSSDService> dnsSDService_;
 		boost::shared_ptr<LinkLocalRoster> linkLocalRoster_;
 		boost::shared_ptr<BoostConnectionServer> serverFromClientConnectionServer_;
 		boost::shared_ptr<ServerFromClientSession> serverFromClientSession_;
 		boost::shared_ptr<BoostConnectionServer> serverFromNetworkConnectionServer_;
-		std::vector< boost::shared_ptr<LinkLocalSession> > linkLocalSessions_;
+		std::vector< boost::shared_ptr<Session> > linkLocalSessions_;
+		std::vector< boost::shared_ptr<LinkLocalConnector> > connectors_;
 		FullPayloadParserFactoryCollection payloadParserFactories_;
 		FullPayloadSerializerCollection payloadSerializers_;
 		bool dnsSDServiceRegistered_;
diff --git a/Swiften/LinkLocal/IncomingLinkLocalSession.cpp b/Swiften/LinkLocal/IncomingLinkLocalSession.cpp
index b73e979..a1fb901 100644
--- a/Swiften/LinkLocal/IncomingLinkLocalSession.cpp
+++ b/Swiften/LinkLocal/IncomingLinkLocalSession.cpp
@@ -18,23 +18,17 @@ IncomingLinkLocalSession::IncomingLinkLocalSession(
 		boost::shared_ptr<Connection> connection, 
 		PayloadParserFactoryCollection* payloadParserFactories, 
 		PayloadSerializerCollection* payloadSerializers) :
-			LinkLocalSession(
-				localJID, 
-				connection, 
-				payloadParserFactories, 
-				payloadSerializers) {
-}
-
-void IncomingLinkLocalSession::start() {
-	initializeStreamStack();
+			Session(connection, payloadParserFactories, payloadSerializers) {
+	setLocalJID(localJID);
 }
 
 void IncomingLinkLocalSession::handleStreamStart(const ProtocolHeader& incomingHeader) {
-	remoteJID_ = JID(incomingHeader.getFrom());
-	if (!remoteJID_.isValid()) {
+	setRemoteJID(JID(incomingHeader.getFrom()));
+	if (!getRemoteJID().isValid()) {
 		finishSession();
 		return;
 	}
+
 	ProtocolHeader header;
 	header.setFrom(getLocalJID());
 	getXMPPLayer()->writeHeader(header);
@@ -55,14 +49,7 @@ void IncomingLinkLocalSession::handleElement(boost::shared_ptr<Element> element)
 		setInitialized();
 	}
 	
-	if (isInitialized()) {
-		if (stanza) {
-			onElementReceived(stanza);
-		}
-		else {
-			std::cerr << "Received unexpected element" << std::endl;
-		}
-	}
+	onElementReceived(element);
 }
 
 
diff --git a/Swiften/LinkLocal/IncomingLinkLocalSession.h b/Swiften/LinkLocal/IncomingLinkLocalSession.h
index d4fa91a..2f1a45b 100644
--- a/Swiften/LinkLocal/IncomingLinkLocalSession.h
+++ b/Swiften/LinkLocal/IncomingLinkLocalSession.h
@@ -3,7 +3,7 @@
 #include <boost/shared_ptr.hpp>
 #include <boost/signal.hpp>
 
-#include "Swiften/LinkLocal/LinkLocalSession.h"
+#include "Swiften/Session/Session.h"
 #include "Swiften/JID/JID.h"
 #include "Swiften/Network/Connection.h"
 
@@ -14,7 +14,7 @@ namespace Swift {
 	class PayloadParserFactoryCollection;
 	class PayloadSerializerCollection;
 
-	class IncomingLinkLocalSession : public LinkLocalSession {
+	class IncomingLinkLocalSession : public Session {
 		public:
 			IncomingLinkLocalSession(
 					const JID& localJID,
@@ -22,18 +22,8 @@ namespace Swift {
 					PayloadParserFactoryCollection* payloadParserFactories, 
 					PayloadSerializerCollection* payloadSerializers);
 
-			const JID& getRemoteJID() const {
-				return remoteJID_;
-			}
-
-			void start();
-
 		private:
 			void handleElement(boost::shared_ptr<Element>);
 			void handleStreamStart(const ProtocolHeader&);
-
-		private:
-			bool initialized_;
-			JID remoteJID_;
 	};
 }
diff --git a/Swiften/LinkLocal/LinkLocalConnector.cpp b/Swiften/LinkLocal/LinkLocalConnector.cpp
new file mode 100644
index 0000000..af521b0
--- /dev/null
+++ b/Swiften/LinkLocal/LinkLocalConnector.cpp
@@ -0,0 +1,57 @@
+#include "Swiften/LinkLocal/LinkLocalConnector.h"
+
+#include <boost/bind.hpp>
+
+#include "Swiften/Network/Connection.h"
+#include "Swiften/Network/ConnectionFactory.h"
+#include "Swiften/Network/HostAddress.h"
+#include "Swiften/Network/HostAddressPort.h"
+#include "Swiften/LinkLocal/DNSSDService.h"
+
+namespace Swift {
+
+LinkLocalConnector::LinkLocalConnector(
+		const JID& remoteJID,
+		const String& hostname,
+		int port,
+		boost::shared_ptr<DNSSDService> resolver,
+		boost::shared_ptr<Connection> connection) : 
+			remoteJID_(remoteJID),
+			hostname_(hostname),
+			port_(port),
+			resolver_(resolver),
+			connection_(connection),
+			resolving_(false) {
+}
+
+void LinkLocalConnector::connect() {
+	resolving_ = true;
+	resolver_->onHostnameResolved.connect(boost::bind(&LinkLocalConnector::handleHostnameResolved, boost::dynamic_pointer_cast<LinkLocalConnector>(shared_from_this()), _1, _2));
+	resolver_->resolveHostname(hostname_);
+}
+
+void LinkLocalConnector::handleHostnameResolved(const String& hostname, const boost::optional<HostAddress>& address) {
+	if (resolving_) {
+		if (hostname == hostname_) {
+			resolving_ = false;
+			if (address) {
+				connection_->onConnectFinished.connect(boost::bind(boost::ref(onConnectFinished), _1));
+				connection_->connect(HostAddressPort(*address, port_));
+			}
+			else {
+				onConnectFinished(false);
+			}
+		}
+	}
+}
+
+void LinkLocalConnector::handleConnected(bool error) {
+	onConnectFinished(error);
+}
+
+void LinkLocalConnector::queueElement(boost::shared_ptr<Element> element) {
+	queuedElements_.push_back(element);
+}
+
+
+}
diff --git a/Swiften/LinkLocal/LinkLocalConnector.h b/Swiften/LinkLocal/LinkLocalConnector.h
new file mode 100644
index 0000000..d296804
--- /dev/null
+++ b/Swiften/LinkLocal/LinkLocalConnector.h
@@ -0,0 +1,59 @@
+#pragma once
+
+#include <boost/shared_ptr.hpp>
+#include <boost/signal.hpp>
+#include <boost/enable_shared_from_this.hpp>
+#include <vector>
+
+#include "Swiften/JID/JID.h"
+#include "Swiften/Network/Connection.h"
+
+namespace Swift {
+	class ConnectionFactory;
+	class HostAddress;
+	class String;
+	class Element;
+	class PayloadParserFactoryCollection;
+	class PayloadSerializerCollection;
+	class DNSSDService;
+
+	class LinkLocalConnector : public boost::enable_shared_from_this<LinkLocalConnector> {
+		public:
+			LinkLocalConnector(
+					const JID& remoteJID,
+					const String& hostname,
+					int port,
+					boost::shared_ptr<DNSSDService> resolver,
+					boost::shared_ptr<Connection> connection);
+
+			const JID& getRemoteJID() const {
+				return remoteJID_;
+			}
+
+			void connect();
+			void queueElement(boost::shared_ptr<Element> element);
+
+			const std::vector<boost::shared_ptr<Element> >& getQueuedElements() const {
+				return queuedElements_;
+			}
+
+			boost::shared_ptr<Connection> getConnection() const {
+				return connection_;
+			}
+
+			boost::signal<void (bool)> onConnectFinished;
+
+		private:
+			void handleHostnameResolved(const String& hostname, const boost::optional<HostAddress>& address);
+			void handleConnected(bool error);
+
+		private:
+			JID remoteJID_;
+			String hostname_;
+			int port_;
+			boost::shared_ptr<DNSSDService> resolver_;
+			boost::shared_ptr<Connection> connection_;
+			bool resolving_;
+			std::vector<boost::shared_ptr<Element> > queuedElements_;
+	};
+}
diff --git a/Swiften/LinkLocal/LinkLocalSession.cpp b/Swiften/LinkLocal/LinkLocalSession.cpp
deleted file mode 100644
index 60227a7..0000000
--- a/Swiften/LinkLocal/LinkLocalSession.cpp
+++ /dev/null
@@ -1,64 +0,0 @@
-#include "Swiften/LinkLocal/LinkLocalSession.h"
-
-#include <boost/bind.hpp>
-
-#include "Swiften/StreamStack/XMPPLayer.h"
-#include "Swiften/StreamStack/StreamStack.h"
-
-namespace Swift {
-
-LinkLocalSession::LinkLocalSession(
-		const JID& localJID,
-		boost::shared_ptr<Connection> connection,
-		PayloadParserFactoryCollection* payloadParserFactories, 
-		PayloadSerializerCollection* payloadSerializers) : 
-			localJID(localJID),
-			payloadParserFactories(payloadParserFactories),
-			payloadSerializers(payloadSerializers),
-			connection(connection),
-			initialized(false) {
-}
-
-LinkLocalSession::~LinkLocalSession() {
-	delete streamStack;
-}
-
-void LinkLocalSession::initializeStreamStack() {
-	assert(connection);
-	xmppLayer = boost::shared_ptr<XMPPLayer>(
-			new XMPPLayer(payloadParserFactories, payloadSerializers));
-	xmppLayer->onStreamStart.connect(
-			boost::bind(&LinkLocalSession::handleStreamStart, this, _1));
-	xmppLayer->onElement.connect(
-			boost::bind(&LinkLocalSession::handleElement, this, _1));
-	//xmppLayer->onError.connect(
-	//		boost::bind(&LinkLocalSession::setError, this, XMLError));
-	connection->onDisconnected.connect(
-			boost::bind(&LinkLocalSession::handleDisconnected, shared_from_this(), _1));
-	connectionLayer = boost::shared_ptr<ConnectionLayer>(new ConnectionLayer(connection));
-	streamStack = new StreamStack(xmppLayer, connectionLayer);
-}
-
-void LinkLocalSession::finishSession() {
-	connection->disconnect();
-}
-
-void LinkLocalSession::sendElement(boost::shared_ptr<Element> stanza) {
-	xmppLayer->writeElement(stanza);
-}
-
-void LinkLocalSession::handleDisconnected(const boost::optional<Connection::Error>& connectionError) {
-	if (connectionError) {
-		onSessionFinished(boost::optional<Error>(ConnectionError));
-	}
-	else {
-		onSessionFinished(boost::optional<Error>());
-	}
-}
-
-void LinkLocalSession::setInitialized() {
-	initialized = true;
-	onSessionStarted();
-}
-
-}
diff --git a/Swiften/LinkLocal/LinkLocalSession.h b/Swiften/LinkLocal/LinkLocalSession.h
deleted file mode 100644
index 4bec14d..0000000
--- a/Swiften/LinkLocal/LinkLocalSession.h
+++ /dev/null
@@ -1,85 +0,0 @@
-#pragma once
-
-#include <boost/shared_ptr.hpp>
-#include <boost/signal.hpp>
-#include <boost/optional.hpp>
-#include <boost/enable_shared_from_this.hpp>
-
-#include "Swiften/JID/JID.h"
-#include "Swiften/Elements/Element.h"
-#include "Swiften/Network/Connection.h"
-#include "Swiften/StreamStack/ConnectionLayer.h"
-
-namespace Swift {
-	class ProtocolHeader;
-	class StreamStack;
-	class JID;
-	class Stanza;
-	class ByteArray;
-	class PayloadParserFactoryCollection;
-	class PayloadSerializerCollection;
-	class XMPPLayer;
-
-	class LinkLocalSession : 
-			public boost::enable_shared_from_this<LinkLocalSession> {
-		public:
-			enum Error { ConnectionError, UnknownError };
-
-			LinkLocalSession(
-					const JID& localJID,
-					boost::shared_ptr<Connection> connection,
-					PayloadParserFactoryCollection* payloadParserFactories, 
-					PayloadSerializerCollection* payloadSerializers);
-			virtual ~LinkLocalSession();
-
-			void finishSession();
-
-			// TODO: Make non-virtual when OutgoingSession is fixed
-			virtual void sendElement(boost::shared_ptr<Element>);
-
-			virtual const JID& getRemoteJID() const = 0;
-
-			virtual void start() = 0;
-
-			boost::signal<void (boost::shared_ptr<Element>)> onElementReceived;
-			boost::signal<void (boost::optional<Error>)> onSessionFinished;
-			boost::signal<void ()> onSessionStarted;
-			boost::signal<void (const ByteArray&)> onDataWritten;
-			boost::signal<void (const ByteArray&)> onDataRead;
-
-		protected:
-			void initializeStreamStack();
-
-			const JID& getLocalJID() const {
-				return localJID;
-			}
-
-			boost::shared_ptr<XMPPLayer> getXMPPLayer() const {
-				return xmppLayer;
-			}
-
-			// TODO: Remove later
-			void setConnection(boost::shared_ptr<Connection> c) {
-				connection = c;
-			}
-
-			virtual void handleElement(boost::shared_ptr<Element>) = 0;
-			virtual void handleStreamStart(const ProtocolHeader&) = 0;
-
-			void setInitialized();
-			bool isInitialized() const { return initialized; }
-
-		private:
-			void handleDisconnected(const boost::optional<Connection::Error>& error);
-
-		private:
-			JID localJID;
-			PayloadParserFactoryCollection* payloadParserFactories;
-			PayloadSerializerCollection* payloadSerializers;
-			boost::shared_ptr<Connection> connection;
-			boost::shared_ptr<XMPPLayer> xmppLayer;
-			boost::shared_ptr<ConnectionLayer> connectionLayer;
-			StreamStack* streamStack;
-			bool initialized;
-	};
-}
diff --git a/Swiften/LinkLocal/Makefile.inc b/Swiften/LinkLocal/Makefile.inc
index 1d29844..c24f2b8 100644
--- a/Swiften/LinkLocal/Makefile.inc
+++ b/Swiften/LinkLocal/Makefile.inc
@@ -4,8 +4,7 @@ SWIFTEN_SOURCES += \
 	Swiften/LinkLocal/LinkLocalServiceInfo.cpp \
 	Swiften/LinkLocal/IncomingLinkLocalSession.cpp \
 	Swiften/LinkLocal/OutgoingLinkLocalSession.cpp \
-	Swiften/LinkLocal/LinkLocalSession.cpp
-
+	Swiften/LinkLocal/LinkLocalConnector.cpp
 
 ifeq ($(MACOSX),1)
 SWIFTEN_SOURCES += \
diff --git a/Swiften/LinkLocal/OutgoingLinkLocalSession.cpp b/Swiften/LinkLocal/OutgoingLinkLocalSession.cpp
index 7415174..4118e34 100644
--- a/Swiften/LinkLocal/OutgoingLinkLocalSession.cpp
+++ b/Swiften/LinkLocal/OutgoingLinkLocalSession.cpp
@@ -1,105 +1,38 @@
-// TODO: Send back errors if we can't make a connection
-
 #include "Swiften/LinkLocal/OutgoingLinkLocalSession.h"
 
 #include <boost/bind.hpp>
 
 #include "Swiften/Elements/ProtocolHeader.h"
-#include "Swiften/Network/Connection.h"
-#include "Swiften/Network/ConnectionFactory.h"
-#include "Swiften/Network/HostAddress.h"
-#include "Swiften/Network/HostAddressPort.h"
-#include "Swiften/StreamStack/StreamStack.h"
-#include "Swiften/LinkLocal/DNSSDService.h"
-#include "Swiften/StreamStack/ConnectionLayer.h"
-#include "Swiften/StreamStack/XMPPLayer.h"
 #include "Swiften/Elements/StreamFeatures.h"
 #include "Swiften/Elements/IQ.h"
-#include "Swiften/SASL/PLAINMessage.h"
 
 namespace Swift {
 
 OutgoingLinkLocalSession::OutgoingLinkLocalSession(
 		const JID& localJID,
 		const JID& remoteJID,
-		const String& hostname,
-		int port,
-		boost::shared_ptr<DNSSDService> resolver,
+		boost::shared_ptr<Connection> connection,
 		PayloadParserFactoryCollection* payloadParserFactories, 
-		PayloadSerializerCollection* payloadSerializers,
-		ConnectionFactory* connectionFactory) :
-			LinkLocalSession(
-				localJID, 
-				boost::shared_ptr<Connection>(), 
-				payloadParserFactories, 
-				payloadSerializers),
-			resolving_(false),
-			remoteJID_(remoteJID),
-			hostname_(hostname),
-			port_(port),
-			resolver_(resolver),
-			connectionFactory_(connectionFactory) {
-}
-
-void OutgoingLinkLocalSession::start() {
-	resolving_ = true;
-	resolver_->onHostnameResolved.connect(boost::bind(&OutgoingLinkLocalSession::handleHostnameResolved, boost::dynamic_pointer_cast<OutgoingLinkLocalSession>(shared_from_this()), _1, _2));
-	resolver_->resolveHostname(hostname_);
-}
-
-void OutgoingLinkLocalSession::handleHostnameResolved(const String& hostname, const boost::optional<HostAddress>& address) {
-	if (resolving_) {
-		if (hostname == hostname_) {
-			resolving_ = false;
-			if (address) {
-				boost::shared_ptr<Connection> connection = connectionFactory_->createConnection();
-				setConnection(connection);
-				initializeStreamStack();
-				connection->onConnectFinished.connect(boost::bind(&OutgoingLinkLocalSession::handleConnected, boost::dynamic_pointer_cast<OutgoingLinkLocalSession>(shared_from_this()), _1));
-				connection->connect(HostAddressPort(*address, port_));
-			}
-			else {
-				onSessionFinished(boost::optional<Error>(UnknownError));
-			}
-		}
-	}
-}
-
-void OutgoingLinkLocalSession::handleConnected(bool error) {
-	if (!error) {
-		ProtocolHeader header;
-		header.setFrom(getLocalJID());
-		getXMPPLayer()->writeHeader(header);
-	}
-	else {
-		// TODO: Error
-	}
+		PayloadSerializerCollection* payloadSerializers) :
+			Session(connection, payloadParserFactories, payloadSerializers) {
+	setLocalJID(localJID);
+	setRemoteJID(remoteJID);
 }
 
 void OutgoingLinkLocalSession::handleStreamStart(const ProtocolHeader&) {
 	foreach(const boost::shared_ptr<Element>& stanza, queuedElements_) {
-		LinkLocalSession::sendElement(stanza);
+		sendElement(stanza);
 	}
 	queuedElements_.clear();
 	setInitialized();
 }
 
 void OutgoingLinkLocalSession::handleElement(boost::shared_ptr<Element> element) {
-	if (isInitialized()) {
-		boost::shared_ptr<Element> stanza = boost::dynamic_pointer_cast<Element>(element);
-		if (stanza) {
-			onElementReceived(stanza);
-		}
-	}
+	onElementReceived(element);
 }
 
-void OutgoingLinkLocalSession::sendElement(boost::shared_ptr<Element> stanza) {
-	if (isInitialized()) {
-		LinkLocalSession::sendElement(stanza);
-	}
-	else {
-		queuedElements_.push_back(stanza);
-	}
+void OutgoingLinkLocalSession::queueElement(boost::shared_ptr<Element> element) {
+	queuedElements_.push_back(element);
 }
 
 
diff --git a/Swiften/LinkLocal/OutgoingLinkLocalSession.h b/Swiften/LinkLocal/OutgoingLinkLocalSession.h
index d3fed0b..904a9d3 100644
--- a/Swiften/LinkLocal/OutgoingLinkLocalSession.h
+++ b/Swiften/LinkLocal/OutgoingLinkLocalSession.h
@@ -5,51 +5,32 @@
 #include <boost/enable_shared_from_this.hpp>
 #include <vector>
 
-#include "Swiften/LinkLocal/LinkLocalSession.h"
+#include "Swiften/Session/Session.h"
 #include "Swiften/JID/JID.h"
 
 namespace Swift {
 	class ConnectionFactory;
-	class HostAddress;
 	class String;
 	class Element;
 	class PayloadParserFactoryCollection;
 	class PayloadSerializerCollection;
-	class DNSSDService;
 
-	class OutgoingLinkLocalSession : public LinkLocalSession {
+	class OutgoingLinkLocalSession : public Session {
 		public:
 			OutgoingLinkLocalSession(
 					const JID& localJID,
 					const JID& remoteJID,
-					const String& hostname,
-					int port,
-					boost::shared_ptr<DNSSDService> resolver,
+					boost::shared_ptr<Connection> connection,
 					PayloadParserFactoryCollection* payloadParserFactories, 
-					PayloadSerializerCollection* payloadSerializers,
-					ConnectionFactory* connectionFactory);
+					PayloadSerializerCollection* payloadSerializers);
 
-			const JID& getRemoteJID() const {
-				return remoteJID_;
-			}
-
-			void start();
-
-			void sendElement(boost::shared_ptr<Element> stanza);
+			void queueElement(boost::shared_ptr<Element> element);
 
 		private:
 			void handleElement(boost::shared_ptr<Element>);
 			void handleStreamStart(const ProtocolHeader&);
-			void handleHostnameResolved(const String& hostname, const boost::optional<HostAddress>& address);
-			void handleConnected(bool error);
 
 		private:
-			bool resolving_;
-			JID remoteJID_;
-			String hostname_;
-			int port_;
-			boost::shared_ptr<DNSSDService> resolver_;
 			std::vector<boost::shared_ptr<Element> > queuedElements_;
-			ConnectionFactory* connectionFactory_;
 	};
 }
-- 
cgit v0.10.2-6-g49f6