From 6c181e11f30cfb58688f327326a03f268ee3790a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Mon, 20 Jul 2009 12:02:41 +0200
Subject: Move Slimber server out of main.


diff --git a/Slimber/.gitignore b/Slimber/.gitignore
index 6bb3f86..f7293e8 100644
--- a/Slimber/.gitignore
+++ b/Slimber/.gitignore
@@ -1 +1 @@
-nim
+slimber
diff --git a/Slimber/Makefile.inc b/Slimber/Makefile.inc
index 904bc83..86692b3 100644
--- a/Slimber/Makefile.inc
+++ b/Slimber/Makefile.inc
@@ -1,5 +1,6 @@
 SLIMBER_TARGET = Slimber/slimber
 SLIMBER_SOURCES = \
+	Slimber/Server.cpp \
 	Slimber/main.cpp
 SLIMBER_OBJECTS = \
 	$(SLIMBER_SOURCES:.cpp=.o)
diff --git a/Slimber/Server.cpp b/Slimber/Server.cpp
new file mode 100644
index 0000000..e84659a
--- /dev/null
+++ b/Slimber/Server.cpp
@@ -0,0 +1,279 @@
+#include "Slimber/Server.h"
+
+#include <string>
+#include <boost/bind.hpp>
+
+#include "Swiften/Session/SessionTracer.h"
+#include "Swiften/Elements/IQ.h"
+#include "Swiften/Elements/VCard.h"
+#include "Swiften/Server/UserRegistry.h"
+#include "Swiften/Base/String.h"
+#include "Swiften/LinkLocal/LinkLocalServiceInfo.h"
+#include "Swiften/LinkLocal/LinkLocalRoster.h"
+#include "Swiften/LinkLocal/OutgoingLinkLocalSession.h"
+#include "Swiften/LinkLocal/IncomingLinkLocalSession.h"
+#include "Swiften/Network/ConnectionServer.h"
+#include "Swiften/Server/ServerFromClientSession.h"
+
+namespace Swift {
+
+Server::Server(int clientConnectionPort, int linkLocalConnectionPort, boost::shared_ptr<DNSSDService> dnsSDService) : 
+		dnsSDServiceRegistered_(false), 
+		rosterRequested_(false), 
+		clientConnectionPort_(clientConnectionPort), 
+		linkLocalConnectionPort_(linkLocalConnectionPort),
+		dnsSDService_(dnsSDService) {
+	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_->start();
+
+	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();
+}
+
+void Server::handleNewClientConnection(boost::shared_ptr<Connection> c) {
+	if (serverFromClientSession_) {
+		c->disconnect();
+	}
+	serverFromClientSession_ = boost::shared_ptr<ServerFromClientSession>(new ServerFromClientSession(idGenerator_.generateID(), c, &payloadParserFactories_, &payloadSerializers_, &userRegistry_));
+	serverFromClientSession_->onElementReceived.connect(boost::bind(&Server::handleElementReceived, this, _1, serverFromClientSession_));
+	serverFromClientSession_->onSessionFinished.connect(boost::bind(&Server::handleSessionFinished, this, serverFromClientSession_));
+	tracers_.push_back(boost::shared_ptr<SessionTracer>(new SessionTracer(serverFromClientSession_)));
+	serverFromClientSession_->startSession();
+}
+
+void Server::handleNewLinkLocalConnection(boost::shared_ptr<Connection> connection) {
+	boost::shared_ptr<IncomingLinkLocalSession> session(
+			new IncomingLinkLocalSession(
+				selfJID_, connection, 
+				&payloadParserFactories_, &payloadSerializers_));
+	registerLinkLocalSession(session);
+}
+
+void Server::handleServiceRegistered(const DNSSDService::Service& service) {
+	std::cout << "Service registered " << service.name << " " << service.type << " " << service.domain << std::endl;
+	selfJID_ = JID(service.name);
+}
+
+void Server::handleSessionFinished(boost::shared_ptr<ServerFromClientSession>) {
+	serverFromClientSession_.reset();
+	unregisterService();
+	selfJID_ = JID();
+	rosterRequested_ = false;
+}
+
+void Server::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 Server::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)) {
+			return; // TODO: Queue
+		}
+		stanza->setFrom(fromJID);
+		serverFromClientSession_->sendElement(stanza);
+	}
+}
+
+void Server::unregisterService() {
+	if (dnsSDServiceRegistered_) {
+		dnsSDServiceRegistered_ = false;
+		dnsSDService_->unregisterService();
+	}
+}
+
+void Server::handleElementReceived(boost::shared_ptr<Element> element, boost::shared_ptr<ServerFromClientSession> session) {
+	boost::shared_ptr<Stanza> stanza = boost::dynamic_pointer_cast<Stanza>(element);
+	if (!stanza) {
+		return;
+	}
+
+	stanza->setFrom(session->getRemoteJID());
+	if (!stanza->getTo().isValid()) {
+		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->getRemoteJID().toBare().toString(), linkLocalConnectionPort_, getLinkLocalServiceInfo(presence));
+			}
+			else {
+				dnsSDService_->updateService(getLinkLocalServiceInfo(presence));
+			}
+		}
+		else {
+			unregisterService();
+		}
+	}
+	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) {
+					session->sendElement(IQ::createResult(iq->getFrom(), iq->getID(), linkLocalRoster_->getRoster()));
+					rosterRequested_ = true;
+					foreach(const boost::shared_ptr<Presence> presence, linkLocalRoster_->getAllPresence()) {
+						session->sendElement(presence);
+					}
+				}
+				else {
+					session->sendElement(IQ::createError(iq->getFrom(), iq->getID(), Error::Forbidden, Error::Cancel));
+				}
+			}
+			if (iq->getPayload<VCard>()) {
+				if (iq->getType() == IQ::Get) {
+					boost::shared_ptr<VCard> vcard(new VCard());
+					vcard->setNickname(iq->getFrom().getNode());
+					session->sendElement(IQ::createResult(iq->getFrom(), iq->getID(), vcard));
+				}
+				else {
+					session->sendElement(IQ::createError(iq->getFrom(), iq->getID(), Error::Forbidden, Error::Cancel));
+				}
+			}
+			else {
+				session->sendElement(IQ::createError(iq->getFrom(), iq->getID(), Error::FeatureNotImplemented, Error::Cancel));
+			}
+		}
+	}
+	else {
+		JID toJID = stanza->getTo();
+		boost::shared_ptr<Session> outgoingSession = 
+				getLinkLocalSessionForJID(toJID);
+		if (outgoingSession) {
+			outgoingSession->sendElement(stanza);
+		}
+		else {
+			if (linkLocalRoster_->hasItem(toJID)) {
+				boost::shared_ptr<LinkLocalConnector> connector =
+					getLinkLocalConnectorForJID(toJID);
+				if (!connector) {
+					connector = boost::shared_ptr<LinkLocalConnector>(
+							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->connect();
+				}
+				connector->queueElement(element);
+			}
+			else {
+				session->sendElement(IQ::createError(
+						stanza->getFrom(), stanza->getID(), 
+						Error::RecipientUnavailable, Error::Wait));
+			}
+		}
+	}
+}
+
+void Server::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_));
+		foreach(const boost::shared_ptr<Element> element, connector->getQueuedElements()) {
+			outgoingSession->queueElement(element);
+		}
+		registerLinkLocalSession(outgoingSession);
+	}
+	connectors_.erase(std::remove(connectors_.begin(), connectors_.end(), connector), connectors_.end());
+}
+
+
+void Server::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);
+	tracers_.push_back(boost::shared_ptr<SessionTracer>(new SessionTracer(session)));
+	session->startSession();
+}
+
+boost::shared_ptr<Session> Server::getLinkLocalSessionForJID(const JID& jid) {
+	foreach(const boost::shared_ptr<Session> session, linkLocalSessions_) {
+		if (session->getRemoteJID() == jid) {
+			return session;
+		}
+	}
+	return boost::shared_ptr<Session>();
+}
+
+boost::shared_ptr<LinkLocalConnector> Server::getLinkLocalConnectorForJID(const JID& jid) {
+	foreach(const boost::shared_ptr<LinkLocalConnector> connector, connectors_) {
+		if (connector->getRemoteJID() == jid) {
+			return connector;
+		}
+	}
+	return boost::shared_ptr<LinkLocalConnector>();
+}
+
+void Server::handleRosterChanged(boost::shared_ptr<RosterPayload> roster) {
+	if (rosterRequested_) {
+		boost::shared_ptr<IQ> iq = IQ::createRequest(IQ::Set, serverFromClientSession_->getRemoteJID(), idGenerator_.generateID(), roster);
+		iq->setFrom(serverFromClientSession_->getRemoteJID().toBare());
+		serverFromClientSession_->sendElement(iq);
+	}
+}
+
+void Server::handlePresenceChanged(boost::shared_ptr<Presence> presence) {
+	if (rosterRequested_) {
+		serverFromClientSession_->sendElement(presence);
+	}
+}
+
+LinkLocalServiceInfo Server::getLinkLocalServiceInfo(boost::shared_ptr<Presence> presence) {
+	LinkLocalServiceInfo info;
+	info.setFirstName("Remko");
+	info.setLastName("Tron\xc3\xa7on");
+	info.setEMail("email@example.com");
+	info.setJID(JID("jid@example.com"));
+	info.setMessage(presence->getStatus());
+	info.setNick("Remko");
+	switch (presence->getShow()) {
+		case StatusShow::Online: 
+		case StatusShow::None: 
+		case StatusShow::FFC: 
+			info.setStatus(LinkLocalServiceInfo::Available);
+			break;
+		case StatusShow::Away: 
+		case StatusShow::XA: 
+			info.setStatus(LinkLocalServiceInfo::Away);
+			break;
+		case StatusShow::DND: 
+			info.setStatus(LinkLocalServiceInfo::DND);
+			break;
+	}
+	info.setPort(linkLocalConnectionPort_);
+	return info;
+}
+
+}
diff --git a/Slimber/Server.h b/Slimber/Server.h
new file mode 100644
index 0000000..573e3d9
--- /dev/null
+++ b/Slimber/Server.h
@@ -0,0 +1,76 @@
+#pragma once
+
+#include <boost/shared_ptr.hpp>
+#include <vector>
+
+#include "Swiften/Network/BoostConnection.h"
+#include "Swiften/Network/BoostIOServiceThread.h"
+#include "Swiften/Network/BoostConnectionServer.h"
+#include "Swiften/Server/UserRegistry.h"
+#include "Swiften/Base/IDGenerator.h"
+#include "Swiften/Network/Connection.h"
+#include "Swiften/LinkLocal/DNSSDService.h"
+#include "Swiften/LinkLocal/LinkLocalRoster.h"
+#include "Swiften/Session/SessionTracer.h"
+#include "Swiften/Server/ServerFromClientSession.h"
+#include "Swiften/Elements/Element.h"
+#include "Swiften/LinkLocal/LinkLocalConnector.h"
+#include "Swiften/JID/JID.h"
+#include "Swiften/Elements/Presence.h"
+#include "Swiften/Elements/RosterPayload.h"
+#include "Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.h"
+#include "Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h"
+
+namespace Swift {
+	class Server {
+		public:
+			Server(int clientConnectionPort, int linkLocalConnectionPort, boost::shared_ptr<DNSSDService> dnsSDService);
+
+		private:
+			void handleNewClientConnection(boost::shared_ptr<Connection> c);
+			void handleNewLinkLocalConnection(boost::shared_ptr<Connection> connection);
+			void handleServiceRegistered(const DNSSDService::Service& service);
+			void handleSessionFinished(boost::shared_ptr<ServerFromClientSession>);
+			void handleLinkLocalSessionFinished(boost::shared_ptr<Session> session);
+			void handleLinkLocalElementReceived(boost::shared_ptr<Element> element, boost::shared_ptr<Session> session);
+			void unregisterService();
+			void handleElementReceived(boost::shared_ptr<Element> element, boost::shared_ptr<ServerFromClientSession> session);
+			void handleConnectFinished(boost::shared_ptr<LinkLocalConnector> connector, bool error);
+			void registerLinkLocalSession(boost::shared_ptr<Session> session);
+			boost::shared_ptr<Session> getLinkLocalSessionForJID(const JID& jid);
+			boost::shared_ptr<LinkLocalConnector> getLinkLocalConnectorForJID(const JID& jid);
+			void handleRosterChanged(boost::shared_ptr<RosterPayload> roster);
+			void handlePresenceChanged(boost::shared_ptr<Presence> presence);
+			LinkLocalServiceInfo getLinkLocalServiceInfo(boost::shared_ptr<Presence> presence);
+
+		private:
+			class DummyUserRegistry : public UserRegistry {
+				public:
+					DummyUserRegistry() {}
+
+					virtual bool isValidUserPassword(const JID&, const String&) const {
+						return true;
+					}
+			};
+
+		private:
+			IDGenerator idGenerator_;
+			BoostIOServiceThread boostIOServiceThread_;
+			DummyUserRegistry userRegistry_;
+			bool dnsSDServiceRegistered_;
+			bool rosterRequested_;
+			int clientConnectionPort_;
+			int linkLocalConnectionPort_;
+			boost::shared_ptr<DNSSDService> 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<SessionTracer> > tracers_;
+			std::vector< boost::shared_ptr<Session> > linkLocalSessions_;
+			std::vector< boost::shared_ptr<LinkLocalConnector> > connectors_;
+			FullPayloadParserFactoryCollection payloadParserFactories_;
+			FullPayloadSerializerCollection payloadSerializers_;
+			JID selfJID_;
+	};
+}
diff --git a/Slimber/main.cpp b/Slimber/main.cpp
index a048312..31ae15a 100644
--- a/Slimber/main.cpp
+++ b/Slimber/main.cpp
@@ -1,348 +1,30 @@
 #include <string>
 #include <boost/bind.hpp>
-#include <boost/shared_ptr.hpp>
 
 #include "Swiften/Base/Platform.h"
-#include "Swiften/Session/SessionTracer.h"
-#include "Swiften/Network/BoostConnectionFactory.h"
-#include "Swiften/Elements/IQ.h"
-#include "Swiften/Elements/Presence.h"
-#include "Swiften/Elements/RosterPayload.h"
-#include "Swiften/Elements/VCard.h"
-#include "Swiften/Server/UserRegistry.h"
-#include "Swiften/JID/JID.h"
-#include "Swiften/Base/String.h"
-#include "Swiften/Server/UserRegistry.h"
-#include "Swiften/Base/IDGenerator.h"
-#include "Swiften/EventLoop/MainEventLoop.h"
-#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/OutgoingLinkLocalSession.h"
-#include "Swiften/LinkLocal/IncomingLinkLocalSession.h"
-#include "Swiften/LinkLocal/DNSSDService.h"
-#include "Swiften/Network/ConnectionServer.h"
-#include "Swiften/Network/BoostConnection.h"
-#include "Swiften/Network/BoostIOServiceThread.h"
-#include "Swiften/Network/BoostConnectionServer.h"
-#include "Swiften/Server/ServerFromClientSession.h"
-#include "Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.h"
-#include "Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h"
-
 #if defined(SWIFTEN_PLATFORM_MACOSX) || defined(SWIFTEN_PLATFORM_WINDOWS)
 #include "Swiften/LinkLocal/AppleDNSSDService.h"
 #else
 #include "Swiften/LinkLocal/AvahiDNSSDService.h"
 #endif
+#include "Slimber/Server.h"
+#include "Swiften/EventLoop/SimpleEventLoop.h"
 
 using namespace Swift;
 
+int main() {
+	SimpleEventLoop eventLoop;
 
-class DummyUserRegistry : public UserRegistry {
-	public:
-		DummyUserRegistry() {
-		}
-
-		virtual bool isValidUserPassword(const JID&, const String&) const {
-			return true;
-		}
-};
-
-class Server {
-	public:
-		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_->start();
-
+	boost::shared_ptr<DNSSDService> dnsSDService;
 #if defined(SWIFTEN_PLATFORM_MACOSX) || defined(SWIFTEN_PLATFORM_WINDOWS)
-			dnsSDService_ = boost::shared_ptr<AppleDNSSDService>(
-					new AppleDNSSDService());
+	dnsSDService = boost::shared_ptr<AppleDNSSDService>(
+			new AppleDNSSDService());
 #else
-			dnsSDService_ = boost::shared_ptr<AvahiDNSSDService>(
-					new AvahiDNSSDService());
+	dnsSDService = boost::shared_ptr<AvahiDNSSDService>(
+			new AvahiDNSSDService());
 #endif
-			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();
-		}
-
-	private:
-		void handleNewClientConnection(boost::shared_ptr<Connection> c) {
-			if (serverFromClientSession_) {
-				c->disconnect();
-			}
-			serverFromClientSession_ = boost::shared_ptr<ServerFromClientSession>(new ServerFromClientSession(idGenerator_.generateID(), c, &payloadParserFactories_, &payloadSerializers_, &userRegistry_));
-			serverFromClientSession_->onElementReceived.connect(boost::bind(&Server::handleElementReceived, this, _1, serverFromClientSession_));
-			serverFromClientSession_->onSessionFinished.connect(boost::bind(&Server::handleSessionFinished, this, serverFromClientSession_));
-			tracers_.push_back(boost::shared_ptr<SessionTracer>(new SessionTracer(serverFromClientSession_)));
-			serverFromClientSession_->startSession();
-		}
-
-		void handleNewLinkLocalConnection(boost::shared_ptr<Connection> connection) {
-			boost::shared_ptr<IncomingLinkLocalSession> session(
-					new IncomingLinkLocalSession(
-						selfJID_, connection, 
-						&payloadParserFactories_, &payloadSerializers_));
-			registerLinkLocalSession(session);
-		}
-		
-		void handleServiceRegistered(const DNSSDService::Service& service) {
-			std::cout << "Service registered " << service.name << " " << service.type << " " << service.domain << std::endl;
-			selfJID_ = JID(service.name);
-		}
-
-		void handleSessionFinished(boost::shared_ptr<ServerFromClientSession>) {
-			serverFromClientSession_.reset();
-			unregisterService();
-			selfJID_ = JID();
-			rosterRequested_ = false;
-		}
-
-		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<Session> session) {
-			if (boost::shared_ptr<Stanza> stanza = boost::dynamic_pointer_cast<Stanza>(element)) {
-				JID fromJID = session->getRemoteJID();
-				if (!linkLocalRoster_->hasItem(fromJID)) {
-					return; // TODO: Queue
-				}
-				stanza->setFrom(fromJID);
-				serverFromClientSession_->sendElement(stanza);
-			}
-		}
-
-		void unregisterService() {
-			if (dnsSDServiceRegistered_) {
-				dnsSDServiceRegistered_ = false;
-				dnsSDService_->unregisterService();
-			}
-		}
 
-		void handleElementReceived(boost::shared_ptr<Element> element, boost::shared_ptr<ServerFromClientSession> session) {
-			boost::shared_ptr<Stanza> stanza = boost::dynamic_pointer_cast<Stanza>(element);
-			if (!stanza) {
-				return;
-			}
-
-			stanza->setFrom(session->getRemoteJID());
-			if (!stanza->getTo().isValid()) {
-				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->getRemoteJID().toBare().toString(), linkLocalConnectionPort_, getLinkLocalServiceInfo(presence));
-					}
-					else {
-						dnsSDService_->updateService(getLinkLocalServiceInfo(presence));
-					}
-				}
-				else {
-					unregisterService();
-				}
-			}
-			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) {
-							session->sendElement(IQ::createResult(iq->getFrom(), iq->getID(), linkLocalRoster_->getRoster()));
-							rosterRequested_ = true;
-							foreach(const boost::shared_ptr<Presence> presence, linkLocalRoster_->getAllPresence()) {
-								session->sendElement(presence);
-							}
-						}
-						else {
-							session->sendElement(IQ::createError(iq->getFrom(), iq->getID(), Error::Forbidden, Error::Cancel));
-						}
-					}
-					if (iq->getPayload<VCard>()) {
-						if (iq->getType() == IQ::Get) {
-							boost::shared_ptr<VCard> vcard(new VCard());
-							vcard->setNickname(iq->getFrom().getNode());
-							session->sendElement(IQ::createResult(iq->getFrom(), iq->getID(), vcard));
-						}
-						else {
-							session->sendElement(IQ::createError(iq->getFrom(), iq->getID(), Error::Forbidden, Error::Cancel));
-						}
-					}
-					else {
-						session->sendElement(IQ::createError(iq->getFrom(), iq->getID(), Error::FeatureNotImplemented, Error::Cancel));
-					}
-				}
-			}
-			else {
-				JID toJID = stanza->getTo();
-				boost::shared_ptr<Session> outgoingSession = 
-						getLinkLocalSessionForJID(toJID);
-				if (outgoingSession) {
-					outgoingSession->sendElement(stanza);
-				}
-				else {
-					if (linkLocalRoster_->hasItem(toJID)) {
-						boost::shared_ptr<LinkLocalConnector> connector =
-							getLinkLocalConnectorForJID(toJID);
-						if (!connector) {
-							connector = boost::shared_ptr<LinkLocalConnector>(
-									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->connect();
-						}
-						connector->queueElement(element);
-					}
-					else {
-						session->sendElement(IQ::createError(
-								stanza->getFrom(), stanza->getID(), 
-								Error::RecipientUnavailable, Error::Wait));
-					}
-				}
-			}
-		}
-
-		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_));
-				foreach(const boost::shared_ptr<Element> element, connector->getQueuedElements()) {
-					outgoingSession->queueElement(element);
-				}
-				registerLinkLocalSession(outgoingSession);
-			}
-			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);
-			tracers_.push_back(boost::shared_ptr<SessionTracer>(new SessionTracer(session)));
-			session->startSession();
-		}
-
-		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<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_->getRemoteJID(), idGenerator_.generateID(), roster);
-				iq->setFrom(serverFromClientSession_->getRemoteJID().toBare());
-				serverFromClientSession_->sendElement(iq);
-			}
-		}
-
-		void handlePresenceChanged(boost::shared_ptr<Presence> presence) {
-			if (rosterRequested_) {
-				serverFromClientSession_->sendElement(presence);
-			}
-		}
-
-		LinkLocalServiceInfo getLinkLocalServiceInfo(boost::shared_ptr<Presence> presence) {
-			LinkLocalServiceInfo info;
-			info.setFirstName("Remko");
-			info.setLastName("Tron\xc3\xa7on");
-			info.setEMail("email@example.com");
-			info.setJID(JID("jid@example.com"));
-			info.setMessage(presence->getStatus());
-			info.setNick("Remko");
-			switch (presence->getShow()) {
-				case StatusShow::Online: 
-				case StatusShow::None: 
-				case StatusShow::FFC: 
-					info.setStatus(LinkLocalServiceInfo::Available);
-					break;
-				case StatusShow::Away: 
-				case StatusShow::XA: 
-					info.setStatus(LinkLocalServiceInfo::Away);
-					break;
-				case StatusShow::DND: 
-					info.setStatus(LinkLocalServiceInfo::DND);
-					break;
-			}
-			info.setPort(linkLocalConnectionPort_);
-			return info;
-		}
-
-	private:
-		IDGenerator idGenerator_;
-		BoostIOServiceThread boostIOServiceThread_;
-		DummyUserRegistry userRegistry_;
-		boost::shared_ptr<DNSSDService> 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<SessionTracer> > tracers_;
-		std::vector< boost::shared_ptr<Session> > linkLocalSessions_;
-		std::vector< boost::shared_ptr<LinkLocalConnector> > connectors_;
-		FullPayloadParserFactoryCollection payloadParserFactories_;
-		FullPayloadSerializerCollection payloadSerializers_;
-		bool dnsSDServiceRegistered_;
-		bool rosterRequested_;
-		int clientConnectionPort_;
-		int linkLocalConnectionPort_;
-		JID selfJID_;
-};
-
-int main() {
-	SimpleEventLoop eventLoop;
-	Server server(5222, 5562);
+	Server server(5222, 5562, dnsSDService);
 	eventLoop.run();
 	return 0;
 }
-- 
cgit v0.10.2-6-g49f6