From c8634883470be42eaa674aab05db61c46b005608 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Thu, 30 Jul 2009 21:15:34 +0200
Subject: Make Slimber use the new LinkLocal framework.

XMPP Server is temporarily out of order.

diff --git a/Slimber/CLI/main.cpp b/Slimber/CLI/main.cpp
index 7ebdb0f..b82ffcd 100644
--- a/Slimber/CLI/main.cpp
+++ b/Slimber/CLI/main.cpp
@@ -2,14 +2,8 @@
 #include <boost/bind.hpp>
 
 #include "Swiften/Base/Platform.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 "Slimber/FileVCardCollection.h"
-#include "Swiften/LinkLocal/LinkLocalRoster.h"
 #include "Swiften/LinkLocal/LinkLocalServiceBrowser.h"
 #include "Swiften/LinkLocal/DNSSD/DNSSDBrowseQuery.h"
 #include "Swiften/LinkLocal/DNSSD/DNSSDRegisterQuery.h"
@@ -27,19 +21,7 @@ int main() {
 	browser.start();
 
 /*
-	boost::shared_ptr<DNSSDService> dnsSDService;
-#if defined(SWIFTEN_PLATFORM_MACOSX) || defined(SWIFTEN_PLATFORM_WINDOWS)
-	dnsSDService = boost::shared_ptr<AppleDNSSDService>(
-			new AppleDNSSDService());
-#else
-	dnsSDService = boost::shared_ptr<AvahiDNSSDService>(
-			new AvahiDNSSDService());
-#endif
-
-	boost::shared_ptr<LinkLocalRoster> linkLocalRoster = boost::shared_ptr<LinkLocalRoster>(new LinkLocalRoster(dnsSDService));
-
 	FileVCardCollection vCardCollection(PlatformApplication("Slimber").getSettingsDir());
-
 	Server server(5222, 5562, linkLocalRoster, dnsSDService, &vCardCollection);
 	*/
 	
diff --git a/Slimber/Cocoa/Makefile.inc b/Slimber/Cocoa/Makefile.inc
index 8068350..8cd72cd 100644
--- a/Slimber/Cocoa/Makefile.inc
+++ b/Slimber/Cocoa/Makefile.inc
@@ -2,9 +2,6 @@ SLIMBER_COCOA_TARGET = Slimber/Cocoa/Slimber.app
 SLIMBER_COCOA_BINARY = \
 	Slimber/Cocoa/Slimber
 SLIMBER_COCOA_SOURCES = \
-	Slimber/Server.cpp \
-	Slimber/VCardCollection.cpp \
-	Slimber/FileVCardCollection.cpp \
 	Slimber/Cocoa/MainController.mm \
 	Slimber/Cocoa/Slimber.mm \
 	Slimber/Cocoa/main.mm \
@@ -45,5 +42,5 @@ $(SLIMBER_COCOA_TARGET): $(SLIMBER_COCOA_BINARY) $(SLIMBER_COCOA_NIBS) Slimber/C
 	cp $(SLIMBER_COCOA_NIBS) $(SLIMBER_COCOA_TARGET)/Contents/Resources
 	cp $(SLIMBER_COCOA_RESOURCES) $(SLIMBER_COCOA_TARGET)/Contents/Resources
 
-$(SLIMBER_COCOA_BINARY): $(SLIMBER_COCOA_OBJECTS) $(SWIFTEN_TARGET)
-	$(QUIET_LINK)$(CXX) -o $@ $(SLIMBER_COCOA_OBJECTS) $(LDFLAGS) $(SWIFTEN_TARGET) $(LIBS) -framework Cocoa
+$(SLIMBER_COCOA_BINARY): $(SLIMBER_COCOA_OBJECTS) $(SWIFTEN_TARGET) $(SLIMBER_TRGET)
+	$(QUIET_LINK)$(CXX) -o $@ $(SLIMBER_COCOA_OBJECTS) $(LDFLAGS) $(SLIMBER_TARGET) $(SWIFTEN_TARGET) $(LIBS) -framework Cocoa
diff --git a/Slimber/Cocoa/Menulet.m b/Slimber/Cocoa/Menulet.m
index 4fa7fed..1cc1f1f 100644
--- a/Slimber/Cocoa/Menulet.m
+++ b/Slimber/Cocoa/Menulet.m
@@ -49,8 +49,10 @@
 		[statusMenu addItem: [[NSMenuItem alloc] initWithTitle: @"Online users:" action: NULL keyEquivalent: @""]];
 		int i;
 		for (i = 0; i < [userNames count]; ++i) {
-			NSMenuItem* userItem = [[NSMenuItem alloc] initWithTitle: [@"  " stringByAppendingString: [userNames objectAtIndex: i]] action: NULL keyEquivalent: @""];
+			NSString* text = [NSString stringWithFormat: @"  %@", [userNames objectAtIndex: i]]; 
+			NSMenuItem* userItem = [[NSMenuItem alloc] initWithTitle: text action: NULL keyEquivalent: @""];
 			[statusMenu addItem: userItem];
+			[userItem release];
 		}
 	}
 	else {
diff --git a/Slimber/Cocoa/Slimber.h b/Slimber/Cocoa/Slimber.h
index c2c0e2d..b62f9e5 100644
--- a/Slimber/Cocoa/Slimber.h
+++ b/Slimber/Cocoa/Slimber.h
@@ -1,16 +1,13 @@
 #pragma once
 
-#include <string>
-#include <boost/bind.hpp>
 #include <boost/shared_ptr.hpp>
 
-#include "Swiften/LinkLocal/DNSSDService.h"
-#include "Swiften/LinkLocal/LinkLocalRoster.h"
-
 @class Menulet;
 namespace Swift {
 	class Server;
 	class VCardCollection;
+	class LinkLocalServiceBrowser;
+	class BonjourQuerier;
 }
 
 class Slimber {
@@ -20,11 +17,11 @@ class Slimber {
 
 	private:
 		void handleSelfConnected(bool b);
-		void handleRosterChanged();
+		void handleServicesChanged();
 
 	private:
-		boost::shared_ptr<Swift::DNSSDService> dnsSDService;
-		boost::shared_ptr<Swift::LinkLocalRoster>linkLocalRoster;
+		boost::shared_ptr<Swift::BonjourQuerier> dnsSDQuerier;
+		Swift::LinkLocalServiceBrowser* linkLocalServiceBrowser;
 		Swift::VCardCollection* vCardCollection;
 		Swift::Server* server;
 		Menulet* menulet;
diff --git a/Slimber/Cocoa/Slimber.mm b/Slimber/Cocoa/Slimber.mm
index ae1d9fd..d4851c8 100644
--- a/Slimber/Cocoa/Slimber.mm
+++ b/Slimber/Cocoa/Slimber.mm
@@ -1,9 +1,12 @@
 #include "Slimber/Cocoa/Slimber.h"
 
+#include <boost/bind.hpp>
+
 #include "Swiften/Base/foreach.h"
-#include "Swiften/Elements/RosterPayload.h"
-#include "Swiften/LinkLocal/AppleDNSSDService.h"
 #include "Swiften/Application/Platform/PlatformApplication.h"
+#include "Swiften/LinkLocal/LinkLocalService.h"
+#include "Swiften/LinkLocal/LinkLocalServiceBrowser.h"
+#include "Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuerier.h"
 #include "Slimber/Cocoa/Menulet.h"
 #include "Slimber/Server.h"
 #include "Slimber/FileVCardCollection.h"
@@ -11,37 +14,46 @@
 using namespace Swift;
 
 Slimber::Slimber() {
-	dnsSDService = boost::shared_ptr<AppleDNSSDService>(new AppleDNSSDService());
+	dnsSDQuerier = boost::shared_ptr<BonjourQuerier>(new BonjourQuerier());
+	dnsSDQuerier->start();
 
-	linkLocalRoster = boost::shared_ptr<LinkLocalRoster>(new LinkLocalRoster(dnsSDService));
-	linkLocalRoster->onRosterChanged.connect(boost::bind(&Slimber::handleRosterChanged, this));
+	linkLocalServiceBrowser = new LinkLocalServiceBrowser(dnsSDQuerier);
+	linkLocalServiceBrowser->onServiceAdded.connect(
+			boost::bind(&Slimber::handleServicesChanged, this));
+	linkLocalServiceBrowser->onServiceRemoved.connect(
+			boost::bind(&Slimber::handleServicesChanged, this));
+	linkLocalServiceBrowser->onServiceChanged.connect(
+			boost::bind(&Slimber::handleServicesChanged, this));
+	linkLocalServiceBrowser->start();
 
-	vCardCollection = new FileVCardCollection(PlatformApplication("Slimber").getSettingsDir());
+	vCardCollection = new FileVCardCollection(
+			PlatformApplication("Slimber").getSettingsDir());
 
-	server = new Server(5222, 5562, linkLocalRoster, dnsSDService, vCardCollection);
-	server->onSelfConnected.connect(boost::bind(&Slimber::handleSelfConnected, this, _1));
+	server = new Server(5222, 5562, linkLocalServiceBrowser, vCardCollection);
+	server->onSelfConnected.connect(
+			boost::bind(&Slimber::handleSelfConnected, this, _1));
 
 	menulet = [[Menulet alloc] init];
-	handleRosterChanged();
+	handleServicesChanged();
 }
 
 Slimber::~Slimber() {
 	[menulet release];
 	delete server;
 	delete vCardCollection;
+	linkLocalServiceBrowser->stop();
+	delete linkLocalServiceBrowser;
+	dnsSDQuerier->stop();
 }
 
 void Slimber::handleSelfConnected(bool b) {
 	[menulet setSelfConnected: b];
 }
 
-void Slimber::handleRosterChanged() {
+void Slimber::handleServicesChanged() {
 	NSMutableArray* names = [[NSMutableArray alloc] init];
-	boost::shared_ptr<RosterPayload> roster = linkLocalRoster->getRoster();
-	foreach(const RosterItemPayload& item, roster->getItems()) {
-		NSString* name = [NSString stringWithUTF8String: item.getName().getUTF8Data()];
-		[names addObject: name];
-		[name release];
+	foreach(const LinkLocalService& service, linkLocalServiceBrowser->getServices()) {
+		[names addObject: [NSString stringWithUTF8String: service.getDescription().getUTF8Data()]];
 	}
 
 	[menulet setUserNames: names];
diff --git a/Slimber/Server.cpp b/Slimber/Server.cpp
index 39f4233..a63201b 100644
--- a/Slimber/Server.cpp
+++ b/Slimber/Server.cpp
@@ -3,75 +3,89 @@
 #include <string>
 #include <boost/bind.hpp>
 
+#include "Swiften/LinkLocal/LinkLocalConnector.h"
+#include "Swiften/Network/Connection.h"
+#include "Swiften/Session/SessionTracer.h"
+#include "Swiften/Elements/Element.h"
+#include "Swiften/Elements/Presence.h"
+#include "Swiften/Elements/RosterPayload.h"
+#include "Swiften/Network/BoostConnection.h"
+#include "Swiften/Network/BoostConnectionServer.h"
 #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/LinkLocal/LinkLocalServiceBrowser.h"
 #include "Swiften/Network/ConnectionServer.h"
 #include "Slimber/VCardCollection.h"
+#include "Slimber/LinkLocalPresenceManager.h"
 #include "Swiften/Server/ServerFromClientSession.h"
 
 namespace Swift {
 
-Server::Server(int clientConnectionPort, int linkLocalConnectionPort, boost::shared_ptr<LinkLocalRoster> linkLocalRoster, boost::shared_ptr<DNSSDService> dnsSDService, VCardCollection* vCardCollection) : 
-		dnsSDServiceRegistered_(false), 
-		rosterRequested_(false), 
-		clientConnectionPort_(clientConnectionPort), 
-		linkLocalConnectionPort_(linkLocalConnectionPort),
-		linkLocalRoster_(linkLocalRoster),
-		dnsSDService_(dnsSDService),
-		vCardCollection_(vCardCollection) {
-	serverFromClientConnectionServer_ = 
+Server::Server(
+		int clientConnectionPort, 
+		int linkLocalConnectionPort, 
+		LinkLocalServiceBrowser* linkLocalServiceBrowser,
+		VCardCollection* vCardCollection) : 
+			linkLocalServiceRegistered(false), 
+			rosterRequested(false), 
+			clientConnectionPort(clientConnectionPort), 
+			linkLocalConnectionPort(linkLocalConnectionPort),
+			linkLocalServiceBrowser(linkLocalServiceBrowser),
+			vCardCollection(vCardCollection) {
+	serverFromClientConnectionServer = 
 			boost::shared_ptr<BoostConnectionServer>(new BoostConnectionServer(
-					clientConnectionPort, &boostIOServiceThread_.getIOService()));
-	serverFromClientConnectionServer_->onNewConnection.connect(
+					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();
+	serverFromClientConnectionServer->start();
 
-	dnsSDService_->onServiceRegistered.connect
-			(boost::bind(&Server::handleServiceRegistered, this, _1));
-	linkLocalRoster_->onRosterChanged.connect(
+	presenceManager = new LinkLocalPresenceManager(linkLocalServiceBrowser);
+	presenceManager->onRosterChanged.connect(
 			boost::bind(&Server::handleRosterChanged, this, _1));
-	linkLocalRoster_->onPresenceChanged.connect(
+	presenceManager->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_->onSessionStarted.connect(boost::bind(&Server::handleSessionStarted, this));
-	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();
+	linkLocalServiceBrowser->onServiceRegistered.connect(
+			boost::bind(&Server::handleServiceRegistered, this, _1));
+
+	/*
+	serverFromNetworkConnectionServer = 
+		boost::shared_ptr<BoostConnectionServer>(new BoostConnectionServer(
+			linkLocalConnectionPort, &boostIOServiceThread.getIOService()));
+	serverFromNetworkConnectionServer->onNewConnection.connect(
+			boost::bind(&Server::handleNewLinkLocalConnection, this, _1));
+	serverFromNetworkConnectionServer->start();
+	*/
 }
 
-void Server::handleNewLinkLocalConnection(boost::shared_ptr<Connection> connection) {
-	boost::shared_ptr<IncomingLinkLocalSession> session(
-			new IncomingLinkLocalSession(
-				selfJID_, connection, 
-				&payloadParserFactories_, &payloadSerializers_));
-	registerLinkLocalSession(session);
+Server::~Server() {
+	delete presenceManager;
 }
 
-void Server::handleServiceRegistered(const DNSSDServiceID& service) {
-	std::cout << "Service registered " << service.getName() << " " << service.getType() << " " << service.getDomain() << std::endl;
-	selfJID_ = JID(service.getName());
+void Server::handleNewClientConnection(boost::shared_ptr<Connection> connection) {
+	if (serverFromClientSession) {
+		connection->disconnect();
+	}
+	serverFromClientSession = boost::shared_ptr<ServerFromClientSession>(
+			new ServerFromClientSession(idGenerator.generateID(), connection, 
+					&payloadParserFactories, &payloadSerializers, &userRegistry));
+	serverFromClientSession->onSessionStarted.connect(
+			boost::bind(&Server::handleSessionStarted, this));
+	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::handleSessionStarted() {
@@ -79,34 +93,18 @@ void Server::handleSessionStarted() {
 }
 
 void Server::handleSessionFinished(boost::shared_ptr<ServerFromClientSession>) {
-	serverFromClientSession_.reset();
+	serverFromClientSession.reset();
 	unregisterService();
-	selfJID_ = JID();
-	rosterRequested_ = false;
+	selfJID = JID();
+	rosterRequested = false;
 	onSelfConnected(false);
-	lastPresence_.reset();
-}
-
-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);
-	}
+	lastPresence.reset();
 }
 
 void Server::unregisterService() {
-	if (dnsSDServiceRegistered_) {
-		dnsSDServiceRegistered_ = false;
-		dnsSDService_->unregisterService();
+	if (linkLocalServiceRegistered) {
+		linkLocalServiceRegistered = false;
+		linkLocalServiceBrowser->unregisterService();
 	}
 }
 
@@ -123,14 +121,17 @@ void Server::handleElementReceived(boost::shared_ptr<Element> element, boost::sh
 
 	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));
+			if (!linkLocalServiceRegistered) {
+				linkLocalServiceRegistered = true;
+				linkLocalServiceBrowser->registerService(
+						session->getRemoteJID().toBare().toString(), 
+						linkLocalConnectionPort, getLinkLocalServiceInfo(presence));
 			}
 			else {
-				dnsSDService_->updateService(getLinkLocalServiceInfo(presence));
+				linkLocalServiceBrowser->updateService(
+						getLinkLocalServiceInfo(presence));
 			}
-			lastPresence_ = presence;
+			lastPresence = presence;
 		}
 		else {
 			unregisterService();
@@ -140,9 +141,9 @@ void Server::handleElementReceived(boost::shared_ptr<Element> element, boost::sh
 		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(IQ::createResult(iq->getFrom(), iq->getID(), presenceManager->getRoster()));
+					rosterRequested = true;
+					foreach(const boost::shared_ptr<Presence> presence, presenceManager->getAllPresence()) {
 						session->sendElement(presence);
 					}
 				}
@@ -152,13 +153,13 @@ void Server::handleElementReceived(boost::shared_ptr<Element> element, boost::sh
 			}
 			if (boost::shared_ptr<VCard> vcard = iq->getPayload<VCard>()) {
 				if (iq->getType() == IQ::Get) {
-					session->sendElement(IQ::createResult(iq->getFrom(), iq->getID(), vCardCollection_->getOwnVCard()));
+					session->sendElement(IQ::createResult(iq->getFrom(), iq->getID(), vCardCollection->getOwnVCard()));
 				}
 				else {
-					vCardCollection_->setOwnVCard(vcard);
+					vCardCollection->setOwnVCard(vcard);
 					session->sendElement(IQ::createResult(iq->getFrom(), iq->getID()));
-					if (lastPresence_) {
-						dnsSDService_->updateService(getLinkLocalServiceInfo(lastPresence_));
+					if (lastPresence) {
+						linkLocalServiceBrowser->updateService(getLinkLocalServiceInfo(lastPresence));
 					}
 				}
 			}
@@ -167,6 +168,7 @@ void Server::handleElementReceived(boost::shared_ptr<Element> element, boost::sh
 			}
 		}
 	}
+	/*
 	else {
 		JID toJID = stanza->getTo();
 		boost::shared_ptr<Session> outgoingSession = 
@@ -175,17 +177,17 @@ void Server::handleElementReceived(boost::shared_ptr<Element> element, boost::sh
 			outgoingSession->sendElement(stanza);
 		}
 		else {
-			if (linkLocalRoster_->hasItem(toJID)) {
+			if (linkLocalServiceBrowser->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()))));
+								linkLocalServiceBrowser->getHostname(toJID), 
+								linkLocalServiceBrowser->getPort(toJID), 
+								linkLocalServiceBrowser,
+								boost::shared_ptr<BoostConnection>(new BoostConnection(&boostIOServiceThread.getIOService()))));
 					connector->onConnectFinished.connect(
 							boost::bind(&Server::handleConnectFinished, this, connector, _1));
 					connectors_.push_back(connector);
@@ -200,6 +202,32 @@ void Server::handleElementReceived(boost::shared_ptr<Element> element, boost::sh
 			}
 		}
 	}
+	*/
+}
+
+/*
+void Server::handleNewLinkLocalConnection(boost::shared_ptr<Connection> connection) {
+	boost::shared_ptr<IncomingLinkLocalSession> session(
+			new IncomingLinkLocalSession(
+				selfJID, connection, 
+				&payloadParserFactories, &payloadSerializers));
+	registerLinkLocalSession(session);
+}
+
+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 (!linkLocalServiceBrowser->hasItem(fromJID)) {
+			return; // TODO: Queue
+		}
+		stanza->setFrom(fromJID);
+		serverFromClientSession->sendElement(stanza);
+	}
 }
 
 void Server::handleConnectFinished(boost::shared_ptr<LinkLocalConnector> connector, bool error) {
@@ -210,8 +238,8 @@ void Server::handleConnectFinished(boost::shared_ptr<LinkLocalConnector> connect
 	else {
 		boost::shared_ptr<OutgoingLinkLocalSession> outgoingSession(
 				new OutgoingLinkLocalSession(
-					selfJID_, connector->getRemoteJID(), connector->getConnection(),
-					&payloadParserFactories_, &payloadSerializers_));
+					selfJID, connector->getRemoteJID(), connector->getConnection(),
+					&payloadParserFactories, &payloadSerializers));
 		foreach(const boost::shared_ptr<Element> element, connector->getQueuedElements()) {
 			outgoingSession->queueElement(element);
 		}
@@ -225,7 +253,7 @@ 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)));
+	//tracers.push_back(boost::shared_ptr<SessionTracer>(new SessionTracer(session)));
 	session->startSession();
 }
 
@@ -246,24 +274,32 @@ boost::shared_ptr<LinkLocalConnector> Server::getLinkLocalConnectorForJID(const
 	}
 	return boost::shared_ptr<LinkLocalConnector>();
 }
+*/
+
+void Server::handleServiceRegistered(const DNSSDServiceID& service) {
+	selfJID = JID(service.getName());
+}
 
 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);
+	if (rosterRequested) {
+		assert(serverFromClientSession);
+		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);
+	if (rosterRequested) {
+		serverFromClientSession->sendElement(presence);
 	}
 }
 
 LinkLocalServiceInfo Server::getLinkLocalServiceInfo(boost::shared_ptr<Presence> presence) {
 	LinkLocalServiceInfo info;
-	boost::shared_ptr<VCard> vcard = vCardCollection_->getOwnVCard();
+	boost::shared_ptr<VCard> vcard = vCardCollection->getOwnVCard();
 	if (!vcard->getFamilyName().isEmpty() || !vcard->getGivenName().isEmpty()) {
 		info.setFirstName(vcard->getGivenName());
 		info.setLastName(vcard->getFamilyName());
@@ -294,7 +330,7 @@ LinkLocalServiceInfo Server::getLinkLocalServiceInfo(boost::shared_ptr<Presence>
 			info.setStatus(LinkLocalServiceInfo::DND);
 			break;
 	}
-	info.setPort(linkLocalConnectionPort_);
+	info.setPort(linkLocalConnectionPort);
 	return info;
 }
 
diff --git a/Slimber/Server.h b/Slimber/Server.h
index 9167106..3ed0a58 100644
--- a/Slimber/Server.h
+++ b/Slimber/Server.h
@@ -3,49 +3,56 @@
 #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"
+#include "Swiften/LinkLocal/LinkLocalServiceInfo.h"
 
 namespace Swift {
+	class DNSSDServiceID;
+	class String;
 	class VCardCollection;
+	class LinkLocalServiceBrowser;
+	class LinkLocalPresenceManager;
+	class BoostConnectionServer;
+	class SessionTracer;
+	class RosterPayload;
+	class Presence;
 
 	class Server {
 		public:
-			Server(int clientConnectionPort, int linkLocalConnectionPort, boost::shared_ptr<LinkLocalRoster>, boost::shared_ptr<DNSSDService> dnsSDService, VCardCollection* vCardCollection);
+			Server(
+					int clientConnectionPort, 
+					int linkLocalConnectionPort, 
+					LinkLocalServiceBrowser* browser, 
+					VCardCollection* vCardCollection);
+			~Server();
 
 			boost::signal<void (bool)> onSelfConnected;
 
 		private:
 			void handleNewClientConnection(boost::shared_ptr<Connection> c);
-			void handleNewLinkLocalConnection(boost::shared_ptr<Connection> connection);
-			void handleServiceRegistered(const DNSSDServiceID& service);
 			void handleSessionStarted();
 			void handleSessionFinished(boost::shared_ptr<ServerFromClientSession>);
+			void handleElementReceived(boost::shared_ptr<Element> element, boost::shared_ptr<ServerFromClientSession> session);
+			void handleRosterChanged(boost::shared_ptr<RosterPayload> roster);
+			void handlePresenceChanged(boost::shared_ptr<Presence> presence);
+			void handleServiceRegistered(const DNSSDServiceID& service);
+/*
+			void handleNewLinkLocalConnection(boost::shared_ptr<Connection> connection);
 			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);
+			*/
+
+			void unregisterService();
 			LinkLocalServiceInfo getLinkLocalServiceInfo(boost::shared_ptr<Presence> presence);
 
 		private:
@@ -59,25 +66,27 @@ namespace Swift {
 			};
 
 		private:
-			IDGenerator idGenerator_;
-			BoostIOServiceThread boostIOServiceThread_;
-			DummyUserRegistry userRegistry_;
-			bool dnsSDServiceRegistered_;
-			bool rosterRequested_;
-			int clientConnectionPort_;
-			int linkLocalConnectionPort_;
-			boost::shared_ptr<LinkLocalRoster> linkLocalRoster_;
-			boost::shared_ptr<DNSSDService> dnsSDService_;
-			VCardCollection* vCardCollection_;
-			boost::shared_ptr<Presence> lastPresence_;
-			boost::shared_ptr<BoostConnectionServer> serverFromClientConnectionServer_;
-			boost::shared_ptr<ServerFromClientSession> serverFromClientSession_;
+			IDGenerator idGenerator;
+			FullPayloadParserFactoryCollection payloadParserFactories;
+			FullPayloadSerializerCollection payloadSerializers;
+			BoostIOServiceThread boostIOServiceThread;
+			DummyUserRegistry userRegistry;
+			bool linkLocalServiceRegistered;
+			bool rosterRequested;
+			int clientConnectionPort;
+			int linkLocalConnectionPort;
+			LinkLocalServiceBrowser* linkLocalServiceBrowser;
+			VCardCollection* vCardCollection;
+			LinkLocalPresenceManager* presenceManager;
+			boost::shared_ptr<BoostConnectionServer> serverFromClientConnectionServer;
+			boost::shared_ptr<ServerFromClientSession> serverFromClientSession;
+			boost::shared_ptr<Presence> lastPresence;
+			JID selfJID;
+			/*
 			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_;
+*/
+			std::vector< boost::shared_ptr<SessionTracer> > tracers;
 	};
 }
diff --git a/Slimber/UnitTest/LinkLocalPresenceManagerTest.cpp b/Slimber/UnitTest/LinkLocalPresenceManagerTest.cpp
index a1ecdf8..f15daf4 100644
--- a/Slimber/UnitTest/LinkLocalPresenceManagerTest.cpp
+++ b/Slimber/UnitTest/LinkLocalPresenceManagerTest.cpp
@@ -18,6 +18,7 @@ using namespace Swift;
 
 class LinkLocalPresenceManagerTest : public CppUnit::TestFixture {
 		CPPUNIT_TEST_SUITE(LinkLocalPresenceManagerTest);
+		CPPUNIT_TEST(testConstructor);
 		CPPUNIT_TEST(testServiceAdded);
 		CPPUNIT_TEST(testServiceRemoved);
 		CPPUNIT_TEST(testServiceChanged);
@@ -31,8 +32,6 @@ class LinkLocalPresenceManagerTest : public CppUnit::TestFixture {
 		CPPUNIT_TEST_SUITE_END();
 
 	public:
-		LinkLocalPresenceManagerTest() {}
-
 		void setUp() {
 			eventLoop = new DummyEventLoop();
 			querier = boost::shared_ptr<FakeDNSSDQuerier>(new FakeDNSSDQuerier("wonderland.lit"));
@@ -46,6 +45,15 @@ class LinkLocalPresenceManagerTest : public CppUnit::TestFixture {
 			delete eventLoop;
 		}
 
+		void testConstructor() {
+			addService("alice@wonderland");
+			addService("rabbit@teaparty");
+			std::auto_ptr<LinkLocalPresenceManager> testling(createTestling());
+
+			CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(testling->getRoster()->getItems().size()));
+			CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(testling->getAllPresence().size()));
+		}
+
 		void testServiceAdded() {
 			std::auto_ptr<LinkLocalPresenceManager> testling(createTestling());
 
diff --git a/Swiften/LinkLocal/AppleDNSSDService.cpp b/Swiften/LinkLocal/AppleDNSSDService.cpp
deleted file mode 100644
index a052eb1..0000000
--- a/Swiften/LinkLocal/AppleDNSSDService.cpp
+++ /dev/null
@@ -1,299 +0,0 @@
-#include "Swiften/LinkLocal/AppleDNSSDService.h"
-
-#include <algorithm>
-#include <unistd.h>
-#include <iostream>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <fcntl.h>
-
-#include "Swiften/EventLoop/MainEventLoop.h"
-#include "Swiften/LinkLocal/LinkLocalServiceInfo.h"
-#include "Swiften/Network/HostAddress.h"
-
-namespace Swift {
-
-AppleDNSSDService::AppleDNSSDService() : thread(0), stopRequested(false), haveError(false), browseSDRef(0), registerSDRef(0) {
-	int fds[2];
-	int result = pipe(fds);
-	assert(result == 0);
-	interruptSelectReadSocket = fds[0];
-	fcntl(interruptSelectReadSocket, F_SETFL, fcntl(interruptSelectReadSocket, F_GETFL)|O_NONBLOCK);
-	interruptSelectWriteSocket = fds[1];
-}
-
-AppleDNSSDService::~AppleDNSSDService() {
-	stop();
-}
-
-void AppleDNSSDService::start() {
-	stop();
-	thread = new boost::thread(boost::bind(&AppleDNSSDService::doStart, shared_from_this()));
-}
-
-void AppleDNSSDService::stop() {
-	if (thread) {
-		stopRequested = true;
-		interruptSelect();
-		thread->join();
-		delete thread;
-		stopRequested = false;
-	}
-}
-
-void AppleDNSSDService::registerService(const String& name, int port, const LinkLocalServiceInfo& info) {
-	boost::lock_guard<boost::mutex> lock(sdRefsMutex);
-
-	assert(!registerSDRef);
-	ByteArray txtRecord = info.toTXTRecord();
-	DNSServiceErrorType result = DNSServiceRegister(&registerSDRef, 0, 0, name.getUTF8Data(), "_presence._tcp", NULL, NULL, port, txtRecord.getSize(), txtRecord.getData(), &AppleDNSSDService::handleServiceRegisteredGlobal, this);
-	if (result != kDNSServiceErr_NoError) {
-		std::cerr << "Error creating service registration" << std::endl;
-		haveError = true;
-	}
-
-	interruptSelect();
-}
-
-void AppleDNSSDService::updateService(const LinkLocalServiceInfo& info) {
-	boost::lock_guard<boost::mutex> lock(sdRefsMutex);
-	assert(registerSDRef);
-	ByteArray txtRecord = info.toTXTRecord();
-	DNSServiceUpdateRecord(registerSDRef, NULL, NULL, txtRecord.getSize(), txtRecord.getData(), 0);
-}
-
-void AppleDNSSDService::unregisterService() {
-	boost::lock_guard<boost::mutex> lock(sdRefsMutex);
-
-	assert(registerSDRef);
-	DNSServiceRefDeallocate(registerSDRef); // Interrupts select()
-	registerSDRef = NULL;
-}
-
-void AppleDNSSDService::startResolvingService(const DNSSDServiceID& service) {
-	boost::lock_guard<boost::mutex> lock(sdRefsMutex);
-
-	DNSServiceRef resolveSDRef;
-	DNSServiceErrorType result = DNSServiceResolve(&resolveSDRef, 0, service.getNetworkInterfaceID(), service.getName().getUTF8Data(), service.getType().getUTF8Data(), service.getDomain().getUTF8Data(), &AppleDNSSDService::handleServiceResolvedGlobal, this);
-	if (result != kDNSServiceErr_NoError) {
-		std::cerr << "Error creating service resolve query" << std::endl;
-		haveError = true;
-	}
-	else {
-		bool isNew = resolveSDRefs.insert(std::make_pair(service, resolveSDRef)).second;
-		assert(isNew);
-	}
-
-	interruptSelect();
-}
-
-void AppleDNSSDService::stopResolvingService(const DNSSDServiceID& service) {
-	boost::lock_guard<boost::mutex> lock(sdRefsMutex);
-
-	ServiceSDRefMap::iterator i = resolveSDRefs.find(service);
-	assert(i != resolveSDRefs.end());
-	DNSServiceRefDeallocate(i->second); // Interrupts select()
-	resolveSDRefs.erase(i);
-}
-
-void AppleDNSSDService::resolveHostname(const String& hostname, int interfaceIndex) {
-	boost::lock_guard<boost::mutex> lock(sdRefsMutex);
-
-	DNSServiceRef hostnameResolveSDRef;
-	DNSServiceErrorType result = DNSServiceGetAddrInfo(&hostnameResolveSDRef, 0, interfaceIndex, kDNSServiceProtocol_IPv4, hostname.getUTF8Data(), &AppleDNSSDService::handleHostnameResolvedGlobal, this);
-	if (result != kDNSServiceErr_NoError) {
-		std::cerr << "Error creating hostname resolve query" << std::endl;
-		haveError = true;
-	}
-	else {
-		hostnameResolveSDRefs.push_back(hostnameResolveSDRef);
-	}
-
-	interruptSelect();
-}
-
-void AppleDNSSDService::doStart() {
-	haveError = false;
-	onStarted();
-
-	// Listen for new services
-	{
-		boost::lock_guard<boost::mutex> lock(sdRefsMutex);
-		assert(!browseSDRef);
-		DNSServiceErrorType result = DNSServiceBrowse(&browseSDRef, 0, 0, "_presence._tcp", 0, &AppleDNSSDService::handleServiceDiscoveredGlobal , this);
-		if (result != kDNSServiceErr_NoError) {
-			std::cerr << "Error creating browse query" << std::endl;
-			haveError = true;
-		}
-	}
-
-	// Run the main loop
-	while (!haveError && !stopRequested) {
-		fd_set fdSet;
-		FD_ZERO(&fdSet);
-		int maxSocket = interruptSelectReadSocket;
-		FD_SET(interruptSelectReadSocket, &fdSet);
-
-		{
-			boost::lock_guard<boost::mutex> lock(sdRefsMutex);
-
-			// Browsing
-			int browseSocket = DNSServiceRefSockFD(browseSDRef);
-			maxSocket = std::max(maxSocket, browseSocket);
-			FD_SET(browseSocket, &fdSet);
-
-			// Registration
-			if (registerSDRef) {
-				int registerSocket = DNSServiceRefSockFD(registerSDRef);
-				maxSocket = std::max(maxSocket, registerSocket);
-				FD_SET(registerSocket, &fdSet);
-			}
-
-			// Service resolving
-			for (ServiceSDRefMap::const_iterator i = resolveSDRefs.begin(); i != resolveSDRefs.end(); ++i) {
-				int resolveSocket = DNSServiceRefSockFD(i->second);
-				maxSocket = std::max(maxSocket, resolveSocket);
-				FD_SET(resolveSocket, &fdSet);
-			}
-
-			// Hostname resolving
-			for (HostnameSDRefs::const_iterator i = hostnameResolveSDRefs.begin(); i != hostnameResolveSDRefs.end(); ++i) {
-				int hostnameResolveSocket = DNSServiceRefSockFD(*i);
-				maxSocket = std::max(maxSocket, hostnameResolveSocket);
-				FD_SET(hostnameResolveSocket, &fdSet);
-			}
-		}
-
-		int selectResult = select(maxSocket+1, &fdSet, NULL, NULL, 0);
-
-		// Flush the interruptSelectReadSocket
-		if (FD_ISSET(interruptSelectReadSocket, &fdSet)) {
-			char dummy;
-			while (read(interruptSelectReadSocket, &dummy, 1) > 0) {}
-		}
-
-		{
-			boost::lock_guard<boost::mutex> lock(sdRefsMutex);
-			if (selectResult <= 0) {
-				continue;
-			}
-			if (FD_ISSET(DNSServiceRefSockFD(browseSDRef), &fdSet)) {
-				DNSServiceProcessResult(browseSDRef);
-			}
-			if (registerSDRef && FD_ISSET(DNSServiceRefSockFD(registerSDRef), &fdSet)) {
-				DNSServiceProcessResult(registerSDRef);
-			}
-			for (ServiceSDRefMap::const_iterator i = resolveSDRefs.begin(); i != resolveSDRefs.end(); ++i) {
-				if (FD_ISSET(DNSServiceRefSockFD(i->second), &fdSet)) {
-					DNSServiceProcessResult(i->second);
-				}
-			}
-			for (HostnameSDRefs::const_iterator i = hostnameResolveSDRefs.begin(); i != hostnameResolveSDRefs.end(); ++i) {
-				if (FD_ISSET(DNSServiceRefSockFD(*i), &fdSet)) {
-					DNSServiceProcessResult(*i);
-					hostnameResolveSDRefs.erase(std::remove(hostnameResolveSDRefs.begin(), hostnameResolveSDRefs.end(), *i), hostnameResolveSDRefs.end());
-					DNSServiceRefDeallocate(*i);
-					break; // Stop the loop, because we removed an element
-				}
-			}
-		}
-	}
-
-	{
-		boost::lock_guard<boost::mutex> lock(sdRefsMutex);
-
-		for (ServiceSDRefMap::const_iterator i = resolveSDRefs.begin(); i != resolveSDRefs.end(); ++i) {
-			DNSServiceRefDeallocate(i->second);
-		}
-		resolveSDRefs.clear();
-
-		for (HostnameSDRefs::const_iterator i = hostnameResolveSDRefs.begin(); i != hostnameResolveSDRefs.end(); ++i) {
-			DNSServiceRefDeallocate(*i);
-		}
-		hostnameResolveSDRefs.clear();
-
-		if (registerSDRef) {
-			DNSServiceRefDeallocate(registerSDRef);
-			registerSDRef = NULL;
-		}
-
-		DNSServiceRefDeallocate(browseSDRef);
-		browseSDRef = NULL;
-	}
-
-	MainEventLoop::postEvent(boost::bind(boost::ref(onStopped), haveError), shared_from_this());
-}
-
-void AppleDNSSDService::interruptSelect() {
-	char c = 0;
-	write(interruptSelectWriteSocket, &c, 1);
-}
-
-void AppleDNSSDService::handleServiceDiscoveredGlobal(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *serviceName, const char *regtype, const char *replyDomain, void *context ) {
-	static_cast<AppleDNSSDService*>(context)->handleServiceDiscovered(sdRef, flags, interfaceIndex, errorCode, serviceName, regtype, replyDomain);
-}
-
-void AppleDNSSDService::handleServiceDiscovered(DNSServiceRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *serviceName, const char *regtype, const char *replyDomain) {
-	if (errorCode != kDNSServiceErr_NoError) {
-		return;
-	}
-	else {
-		DNSSDServiceID service(serviceName, regtype, replyDomain, interfaceIndex);
-		if (flags & kDNSServiceFlagsAdd) {
-			MainEventLoop::postEvent(boost::bind(boost::ref(onServiceAdded), service), shared_from_this());
-		}
-		else {
-			MainEventLoop::postEvent(boost::bind(boost::ref(onServiceRemoved), service), shared_from_this());
-		}
-	}
-}
-
-void AppleDNSSDService::handleServiceRegisteredGlobal(DNSServiceRef sdRef, DNSServiceFlags flags, DNSServiceErrorType errorCode, const char *name, const char *regtype, const char *domain, void *context) {
-	static_cast<AppleDNSSDService*>(context)->handleServiceRegistered(sdRef, flags, errorCode, name, regtype, domain);
-}
-
-void AppleDNSSDService::handleServiceRegistered(DNSServiceRef, DNSServiceFlags, DNSServiceErrorType errorCode, const char *name, const char *regtype, const char *domain) {
-	if (errorCode != kDNSServiceErr_NoError) {
-		std::cerr << "Error registering service" << std::endl;
-		haveError = true;
-	}
-	else {
-		MainEventLoop::postEvent(boost::bind(boost::ref(onServiceRegistered), DNSSDServiceID(name, regtype, domain, 0)), shared_from_this());
-	}
-}
-
-void AppleDNSSDService::handleServiceResolvedGlobal(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *fullname, const char *hosttarget, uint16_t port, uint16_t txtLen, const unsigned char *txtRecord, void *context ) {
-	static_cast<AppleDNSSDService*>(context)->handleServiceResolved(sdRef, flags, interfaceIndex, errorCode, fullname, hosttarget, port, txtLen, txtRecord);
-}
-
-void AppleDNSSDService::handleServiceResolved(DNSServiceRef sdRef, DNSServiceFlags, uint32_t, DNSServiceErrorType errorCode, const char *, const char *hosttarget, uint16_t port, uint16_t txtLen, const unsigned char *txtRecord) {
-	if (errorCode != kDNSServiceErr_NoError) {
-		return;
-	}
-	for (ServiceSDRefMap::const_iterator i = resolveSDRefs.begin(); i != resolveSDRefs.end(); ++i) {
-		if (i->second == sdRef) {
-			MainEventLoop::postEvent(boost::bind(boost::ref(onServiceResolved), i->first, ResolveResult(hosttarget, port, LinkLocalServiceInfo::createFromTXTRecord(ByteArray(reinterpret_cast<const char*>(txtRecord), txtLen)))), shared_from_this());
-			return;
-		}
-	}
-	assert(false);
-}
-
-void AppleDNSSDService::handleHostnameResolvedGlobal(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *hostname, const struct sockaddr *address, uint32_t ttl, void *context) {
-	static_cast<AppleDNSSDService*>(context)->handleHostnameResolved(sdRef, flags, interfaceIndex, errorCode, hostname, address, ttl);
-} 
-
-void AppleDNSSDService::handleHostnameResolved(DNSServiceRef, DNSServiceFlags, uint32_t, DNSServiceErrorType errorCode, const char *hostname, const struct sockaddr *rawAddress, uint32_t) {
-	if (errorCode) {
-		std::cerr << "Error resolving hostname" << std::endl;
-		MainEventLoop::postEvent(boost::bind(boost::ref(onHostnameResolved), hostname, boost::optional<HostAddress>()), shared_from_this());
-	}
-	else {
-		assert(rawAddress->sa_family == AF_INET);
-		const sockaddr_in* sa = reinterpret_cast<const sockaddr_in*>(rawAddress);
-		uint32_t address = ntohl(sa->sin_addr.s_addr);
-		MainEventLoop::postEvent(boost::bind(boost::ref(onHostnameResolved), String(hostname), HostAddress(reinterpret_cast<unsigned char*>(&address), 4)), shared_from_this());
-	}
-}
-
-}
diff --git a/Swiften/LinkLocal/AppleDNSSDService.h b/Swiften/LinkLocal/AppleDNSSDService.h
deleted file mode 100644
index 554a154..0000000
--- a/Swiften/LinkLocal/AppleDNSSDService.h
+++ /dev/null
@@ -1,57 +0,0 @@
-#pragma once
-
-#include <boost/enable_shared_from_this.hpp>
-#include <boost/thread.hpp>
-#include <boost/thread/mutex.hpp>
-#include <dns_sd.h>
-
-#include "Swiften/LinkLocal/DNSSDService.h"
-#include "Swiften/LinkLocal/DNSSD/DNSSDServiceID.h"
-#include "Swiften/EventLoop/EventOwner.h"
-
-namespace Swift {
-	class AppleDNSSDService : public DNSSDService, public EventOwner, public boost::enable_shared_from_this<AppleDNSSDService> {
-		public:
-			AppleDNSSDService();
-			~AppleDNSSDService();
-
-			virtual void start();
-			virtual void stop();
-
-			virtual void registerService(const String& name, int port, const LinkLocalServiceInfo&);
-			virtual void updateService(const LinkLocalServiceInfo&);
-			virtual void unregisterService();
-
-			virtual void startResolvingService(const DNSSDServiceID&);
-			virtual void stopResolvingService(const DNSSDServiceID&);
-
-			virtual void resolveHostname(const String& hostname, int interfaceIndex = 0);
-
-		private:
-			void doStart();
-			void interruptSelect();
-
-			static void handleServiceDiscoveredGlobal(DNSServiceRef, DNSServiceFlags, uint32_t, DNSServiceErrorType, const char *, const char *, const char *, void*);
-			void handleServiceDiscovered(DNSServiceRef, DNSServiceFlags, uint32_t, DNSServiceErrorType, const char *, const char *, const char *);
-			static void handleServiceRegisteredGlobal(DNSServiceRef, DNSServiceFlags, DNSServiceErrorType, const char *, const char *, const char *, void *);
-			void handleServiceRegistered(DNSServiceRef, DNSServiceFlags, DNSServiceErrorType, const char *, const char *, const char *);
-			static void handleServiceResolvedGlobal(DNSServiceRef, DNSServiceFlags, uint32_t, DNSServiceErrorType, const char *, const char *, uint16_t, uint16_t, const unsigned char *, void *);
-			void handleServiceResolved(DNSServiceRef, DNSServiceFlags, uint32_t, DNSServiceErrorType, const char *, const char *, uint16_t, uint16_t, const unsigned char *);
-			static void handleHostnameResolvedGlobal(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *hostname, const struct sockaddr *address, uint32_t ttl, void *context);
-			void handleHostnameResolved(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *hostname, const struct sockaddr *address, uint32_t ttl);
-
-		private:
-			boost::thread* thread;
-			bool stopRequested;
-			bool haveError;
-			int interruptSelectReadSocket;
-			int interruptSelectWriteSocket;
-			boost::mutex sdRefsMutex;
-			DNSServiceRef browseSDRef;
-			DNSServiceRef registerSDRef;
-			typedef std::map<DNSSDServiceID, DNSServiceRef> ServiceSDRefMap;
-			ServiceSDRefMap resolveSDRefs;
-			typedef std::vector<DNSServiceRef> HostnameSDRefs;
-			HostnameSDRefs hostnameResolveSDRefs;
-	};
-}
diff --git a/Swiften/LinkLocal/AvahiDNSSDService.cpp b/Swiften/LinkLocal/AvahiDNSSDService.cpp
deleted file mode 100644
index 5f6295f..0000000
--- a/Swiften/LinkLocal/AvahiDNSSDService.cpp
+++ /dev/null
@@ -1,157 +0,0 @@
-#include "Swiften/LinkLocal/AvahiDNSSDService.h"
-
-#include <boost/bind.hpp>
-
-#include "Swiften/EventLoop/MainEventLoop.h"
-#include "Swiften/LinkLocal/LinkLocalServiceInfo.h"
-#include "Swiften/Network/HostAddress.h"
-
-namespace Swift {
-
-AvahiDNSSDService::AvahiDNSSDService() : client(NULL), threadedPoll(0), serviceBrowser(0) {
-}
-
-AvahiDNSSDService::~AvahiDNSSDService() {
-}
-
-void AvahiDNSSDService::start() {
-	threadedPoll = avahi_threaded_poll_new();
-
-	int error;
-	client = avahi_client_new(
-			avahi_threaded_poll_get(threadedPoll), 
-			static_cast<AvahiClientFlags>(0), NULL, this, &error); // TODO
-	if (!client) {
-		// TODO
-		std::cerr << "Avahi Error: " << avahi_strerror(error) << std::endl;
-		return;
-	}
-
-	serviceBrowser = avahi_service_browser_new(
-			client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 
-			"_presence._tcp", NULL, static_cast<AvahiLookupFlags>(0), 
-			handleServiceDiscoveredGlobal, this);
-	if (!serviceBrowser) {
-		// TODO
-		std::cerr << "Avahi Error: " << avahi_strerror(error) << std::endl;
-		return;
-	}
-
-	avahi_threaded_poll_start(threadedPoll);
-}
-
-void AvahiDNSSDService::stop() {
-	avahi_threaded_poll_stop(threadedPoll);
-	avahi_service_browser_free(serviceBrowser);
-	avahi_client_free(client);
-	avahi_threaded_poll_free(threadedPoll);
-}
-
-void AvahiDNSSDService::registerService(const String& name, int port, const LinkLocalServiceInfo& info) {
-	avahi_threaded_poll_lock(threadedPoll);
-	avahi_threaded_poll_unlock(threadedPoll);
-}
-
-void AvahiDNSSDService::updateService(const LinkLocalServiceInfo& info) {
-	avahi_threaded_poll_lock(threadedPoll);
-	avahi_threaded_poll_unlock(threadedPoll);
-}
-
-void AvahiDNSSDService::unregisterService() {
-	avahi_threaded_poll_lock(threadedPoll);
-	avahi_threaded_poll_unlock(threadedPoll);
-}
-
-void AvahiDNSSDService::startResolvingService(const DNSSDServiceID& service) {
-	avahi_threaded_poll_lock(threadedPoll);
-
-	AvahiServiceResolver* resolver = avahi_service_resolver_new(
-			client, 
-			service.getNetworkInterfaceID(), 
-			AVAHI_PROTO_INET,
-			service.getName().getUTF8Data(), 
-			service.getType().getUTF8Data(), 
-			service.getDomain().getUTF8Data(), 
-			AVAHI_PROTO_UNSPEC, 
-			static_cast<AvahiLookupFlags>(0), 
-			&AvahiDNSSDService::handleServiceResolvedGlobal, 
-			this);
-	assert(serviceResolvers.find(service) == serviceResolvers.end());
-	serviceResolvers[service] = resolver;
-
-	avahi_threaded_poll_unlock(threadedPoll);
-}
-
-void AvahiDNSSDService::stopResolvingService(const DNSSDServiceID& service) {
-	avahi_threaded_poll_lock(threadedPoll);
-
-	ServiceResolverMap::iterator i = serviceResolvers.find(service);
-	assert(i != serviceResolvers.end());
-	avahi_service_resolver_free(i->second);
-	serviceResolvers.erase(i);
-
-	avahi_threaded_poll_unlock(threadedPoll);
-}
-
-// TODO: Take interfaceIndex into account
-void AvahiDNSSDService::resolveHostname(const String& hostname, int) {
-	HostnameAddressMap::const_iterator i = hostnameAddresses.find(hostname);
-	if (i == hostnameAddresses.end()) {
-		MainEventLoop::postEvent(boost::bind(boost::ref(onHostnameResolved), hostname, boost::optional<HostAddress>()), shared_from_this());
-	}
-	else {
-		MainEventLoop::postEvent(boost::bind(boost::ref(onHostnameResolved), hostname, boost::optional<HostAddress>(i->second)), shared_from_this());
-	}
-}
-
-void AvahiDNSSDService::handleServiceDiscovered(AvahiServiceBrowser *, AvahiIfIndex interfaceIndex, AvahiProtocol, AvahiBrowserEvent event, const char *name, const char *type, const char *domain, AvahiLookupResultFlags) {
-	switch(event) {
-		case AVAHI_BROWSER_FAILURE:
-			std::cerr << "Browse error" << std::endl;
-			// TODO	
-			return;
-		case AVAHI_BROWSER_NEW: {
-				std::cerr << "Service added: " << name << " " << type << " " << domain << std::endl;
-				DNSSDServiceID service(name, type, domain, interfaceIndex);
-				MainEventLoop::postEvent(boost::bind(boost::ref(onServiceAdded), service), shared_from_this());
-			}
-			break;
-		case AVAHI_BROWSER_REMOVE: {
-				std::cerr << "Service removed: " << name << " " << type << " " << domain << std::endl;
-				DNSSDServiceID service(name, type, domain, interfaceIndex);
-				MainEventLoop::postEvent(boost::bind(boost::ref(onServiceRemoved), service), shared_from_this());
-			}
-			break;
-		case AVAHI_BROWSER_ALL_FOR_NOW:
-		case AVAHI_BROWSER_CACHE_EXHAUSTED:
-			break;
-	}
-}
-
-void AvahiDNSSDService::handleServiceResolved(AvahiServiceResolver *, AvahiIfIndex interfaceIndex, AvahiProtocol, AvahiResolverEvent event, const char *name, const char *type, const char *domain, const char *hostname, const AvahiAddress *address, uint16_t port, AvahiStringList *txt, AvahiLookupResultFlags) {
-	switch(event) {
-		case AVAHI_RESOLVER_FAILURE:
-			//TODO
-			std::cerr << "Resolve error" << std::endl;
-			break;
-		case AVAHI_RESOLVER_FOUND:
-			ByteArray data;
-			for(AvahiStringList* i = txt; i; i = avahi_string_list_get_next(i)) {
-				char size = i->size;
-				data += ByteArray(&size, 1);
-				data += ByteArray(reinterpret_cast<char*>(avahi_string_list_get_text(i)), avahi_string_list_get_size(i));
-			}
-			
-			assert(address->proto == AVAHI_PROTO_INET);
-			HostAddress hostAddress(reinterpret_cast<const unsigned char*>(&address->data.ipv4.address), 4);
-			hostnameAddresses[String(hostname)] = hostAddress;
-			MainEventLoop::postEvent(boost::bind(boost::ref(onServiceResolved), 
-					DNSSDServiceID(name, type, domain, interfaceIndex), 
-					ResolveResult(hostname, port, 
-						LinkLocalServiceInfo::createFromTXTRecord(data))),
-					shared_from_this());
-			break;
-	}
-}
-
-}
diff --git a/Swiften/LinkLocal/AvahiDNSSDService.h b/Swiften/LinkLocal/AvahiDNSSDService.h
deleted file mode 100644
index 7162ade..0000000
--- a/Swiften/LinkLocal/AvahiDNSSDService.h
+++ /dev/null
@@ -1,55 +0,0 @@
-#pragma once
-
-#include <map>
-#include <boost/enable_shared_from_this.hpp>
-#include <avahi-client/client.h>
-#include <avahi-client/lookup.h>
-#include <avahi-common/thread-watch.h>
-#include <avahi-common/watch.h>
-#include <avahi-common/malloc.h>
-#include <avahi-common/error.h>
-
-
-#include "Swiften/EventLoop/EventOwner.h"
-#include "Swiften/LinkLocal/DNSSDService.h"
-
-namespace Swift {
-	class AvahiDNSSDService : public DNSSDService, public EventOwner, public boost::enable_shared_from_this<AvahiDNSSDService> {
-		public:
-			AvahiDNSSDService();
-			~AvahiDNSSDService();
-
-			virtual void start();
-			virtual void stop();
-
-			virtual void registerService(const String& name, int port, const LinkLocalServiceInfo&);
-			virtual void updateService(const LinkLocalServiceInfo&);
-			virtual void unregisterService();
-
-			virtual void startResolvingService(const DNSSDServiceID&);
-			virtual void stopResolvingService(const DNSSDServiceID&);
-
-			virtual void resolveHostname(const String& hostname, int interfaceIndex = 0);
-		
-		private:
-			static void handleServiceDiscoveredGlobal(AvahiServiceBrowser *b, AvahiIfIndex networkInterface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *name, const char *type, const char *domain, AvahiLookupResultFlags flags, void* userdata) {
-				static_cast<AvahiDNSSDService*>(userdata)->handleServiceDiscovered(b, networkInterface, protocol, event, name, type, domain, flags);
-			}
-			void handleServiceDiscovered(AvahiServiceBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *name, const char *type, const char *domain, AVAHI_GCC_UNUSED AvahiLookupResultFlags flags);
-
-			static void handleServiceResolvedGlobal(AvahiServiceResolver *r, AvahiIfIndex interfaceIndex, AvahiProtocol protocol, AvahiResolverEvent event, const char *name, const char *type, const char *domain, const char *hostname, const AvahiAddress *address, uint16_t port, AvahiStringList *txt, AvahiLookupResultFlags flags, void* userdata) {
-				static_cast<AvahiDNSSDService*>(userdata)->handleServiceResolved(r, interfaceIndex, protocol, event, name, type, domain, hostname, address, port, txt, flags);
-			}
-			void handleServiceResolved(AvahiServiceResolver *r, AvahiIfIndex interface, AvahiProtocol protocol, AvahiResolverEvent event, const char *name, const char *type, const char *domain, const char *hostname, const AvahiAddress *address, uint16_t port, AvahiStringList *txt, AvahiLookupResultFlags flags);
-
-
-		private:
-			AvahiClient* client;
-			AvahiThreadedPoll* threadedPoll;
-			AvahiServiceBrowser* serviceBrowser;
-			typedef std::map<DNSSDServiceID, AvahiServiceResolver*> ServiceResolverMap;
-			ServiceResolverMap serviceResolvers;
-			typedef std::map<String, HostAddress> HostnameAddressMap;
-			HostnameAddressMap hostnameAddresses;
-	};
-}
diff --git a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourRegisterQuery.h b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourRegisterQuery.h
index 34d5742..ddc2788 100644
--- a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourRegisterQuery.h
+++ b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourRegisterQuery.h
@@ -48,7 +48,7 @@ namespace Swift {
 					MainEventLoop::postEvent(boost::bind(boost::ref(onRegisterFinished), boost::optional<DNSSDServiceID>()), shared_from_this());
 				}
 				else {
-					MainEventLoop::postEvent(boost::bind(boost::ref(onRegisterFinished), boost::optional<DNSSDServiceID>(DNSSDServiceID(name, regtype, domain, 0))), shared_from_this());
+					MainEventLoop::postEvent(boost::bind(boost::ref(onRegisterFinished), boost::optional<DNSSDServiceID>(DNSSDServiceID(name, domain, regtype, 0))), shared_from_this());
 				}
 			}
 	};
diff --git a/Swiften/LinkLocal/DNSSDService.cpp b/Swiften/LinkLocal/DNSSDService.cpp
deleted file mode 100644
index 9545981..0000000
--- a/Swiften/LinkLocal/DNSSDService.cpp
+++ /dev/null
@@ -1,8 +0,0 @@
-#include "Swiften/LinkLocal/DNSSDService.h"
-
-namespace Swift {
-
-DNSSDService::~DNSSDService() {
-}
-
-}
diff --git a/Swiften/LinkLocal/DNSSDService.h b/Swiften/LinkLocal/DNSSDService.h
deleted file mode 100644
index 0ace21b..0000000
--- a/Swiften/LinkLocal/DNSSDService.h
+++ /dev/null
@@ -1,45 +0,0 @@
-#pragma once
-
-#include <boost/signal.hpp>
-#include <map>
-
-#include "Swiften/Base/String.h"
-#include "Swiften/LinkLocal/DNSSD/DNSSDServiceID.h"
-#include "Swiften/LinkLocal/LinkLocalServiceInfo.h"
-
-namespace Swift {
-	class LinkLocalServiceInfo;
-	class HostAddress;
-
-	class DNSSDService {
-		public:
-			struct ResolveResult {
-				ResolveResult(const String& host, int port, const LinkLocalServiceInfo& info) : host(host), port(port), info(info) {}
-				String host;
-				int port;
-				LinkLocalServiceInfo info;
-			};
-
-			virtual ~DNSSDService();
-
-			virtual void start() = 0;
-			virtual void stop() = 0;
-
-			virtual void registerService(const String& name, int port, const LinkLocalServiceInfo&) = 0;
-			virtual void updateService(const LinkLocalServiceInfo&) = 0;
-			virtual void unregisterService() = 0;
-
-			virtual void startResolvingService(const DNSSDServiceID&) = 0;
-			virtual void stopResolvingService(const DNSSDServiceID&) = 0;
-			
-			virtual void resolveHostname(const String& hostname, int interfaceIndex = 0) = 0;
-
-			boost::signal<void ()> onStarted;
-			boost::signal<void (bool)> onStopped;
-			boost::signal<void (const DNSSDServiceID&)> onServiceAdded;
-			boost::signal<void (const DNSSDServiceID&)> onServiceRemoved;
-			boost::signal<void (const DNSSDServiceID&)> onServiceRegistered;
-			boost::signal<void (const DNSSDServiceID&, const ResolveResult&)> onServiceResolved;
-			boost::signal<void (const String&, const boost::optional<HostAddress>&)> onHostnameResolved;
-	};
-}
diff --git a/Swiften/LinkLocal/LinkLocalConnector.cpp b/Swiften/LinkLocal/LinkLocalConnector.cpp
index af521b0..28107ed 100644
--- a/Swiften/LinkLocal/LinkLocalConnector.cpp
+++ b/Swiften/LinkLocal/LinkLocalConnector.cpp
@@ -6,7 +6,7 @@
 #include "Swiften/Network/ConnectionFactory.h"
 #include "Swiften/Network/HostAddress.h"
 #include "Swiften/Network/HostAddressPort.h"
-#include "Swiften/LinkLocal/DNSSDService.h"
+#include "Swiften/LinkLocal/DNSSD/DNSSDQuerier.h"
 
 namespace Swift {
 
@@ -14,22 +14,23 @@ LinkLocalConnector::LinkLocalConnector(
 		const JID& remoteJID,
 		const String& hostname,
 		int port,
-		boost::shared_ptr<DNSSDService> resolver,
+		boost::shared_ptr<DNSSDQuerier> querier,
 		boost::shared_ptr<Connection> connection) : 
 			remoteJID_(remoteJID),
 			hostname_(hostname),
 			port_(port),
-			resolver_(resolver),
+			querier_(querier),
 			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_);
+	//querier_->onHostnameResolved.connect(boost::bind(&LinkLocalConnector::handleHostnameResolved, boost::dynamic_pointer_cast<LinkLocalConnector>(shared_from_this()), _1, _2));
+	//querier_->resolveHostname(hostname_);
 }
 
+/*
 void LinkLocalConnector::handleHostnameResolved(const String& hostname, const boost::optional<HostAddress>& address) {
 	if (resolving_) {
 		if (hostname == hostname_) {
@@ -44,6 +45,7 @@ void LinkLocalConnector::handleHostnameResolved(const String& hostname, const bo
 		}
 	}
 }
+*/
 
 void LinkLocalConnector::handleConnected(bool error) {
 	onConnectFinished(error);
diff --git a/Swiften/LinkLocal/LinkLocalConnector.h b/Swiften/LinkLocal/LinkLocalConnector.h
index d296804..2ddb5b8 100644
--- a/Swiften/LinkLocal/LinkLocalConnector.h
+++ b/Swiften/LinkLocal/LinkLocalConnector.h
@@ -15,7 +15,7 @@ namespace Swift {
 	class Element;
 	class PayloadParserFactoryCollection;
 	class PayloadSerializerCollection;
-	class DNSSDService;
+	class DNSSDQuerier;
 
 	class LinkLocalConnector : public boost::enable_shared_from_this<LinkLocalConnector> {
 		public:
@@ -23,7 +23,7 @@ namespace Swift {
 					const JID& remoteJID,
 					const String& hostname,
 					int port,
-					boost::shared_ptr<DNSSDService> resolver,
+					boost::shared_ptr<DNSSDQuerier> querier,
 					boost::shared_ptr<Connection> connection);
 
 			const JID& getRemoteJID() const {
@@ -44,14 +44,14 @@ namespace Swift {
 			boost::signal<void (bool)> onConnectFinished;
 
 		private:
-			void handleHostnameResolved(const String& hostname, const boost::optional<HostAddress>& address);
+			//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<DNSSDQuerier> querier_;
 			boost::shared_ptr<Connection> connection_;
 			bool resolving_;
 			std::vector<boost::shared_ptr<Element> > queuedElements_;
diff --git a/Swiften/LinkLocal/LinkLocalRoster.cpp b/Swiften/LinkLocal/LinkLocalRoster.cpp
deleted file mode 100644
index af3c1af..0000000
--- a/Swiften/LinkLocal/LinkLocalRoster.cpp
+++ /dev/null
@@ -1,142 +0,0 @@
-#include <boost/bind.hpp>
-#include <iostream>
-
-#include "Swiften/LinkLocal/LinkLocalRoster.h"
-#include "Swiften/Network/HostAddress.h"
-
-namespace Swift {
-
-LinkLocalRoster::LinkLocalRoster(boost::shared_ptr<DNSSDService> service) : dnsSDService(service) {
-	dnsSDService->onStopped.connect(boost::bind(&LinkLocalRoster::handleStopped, this, _1));
-	dnsSDService->onServiceRegistered.connect(boost::bind(&LinkLocalRoster::handleServiceRegistered, this, _1));
-	dnsSDService->onServiceAdded.connect(boost::bind(&LinkLocalRoster::handleServiceAdded, this, _1));
-	dnsSDService->onServiceRemoved.connect(boost::bind(&LinkLocalRoster::handleServiceRemoved, this, _1));
-	dnsSDService->onServiceResolved.connect(boost::bind(&LinkLocalRoster::handleServiceResolved, this, _1, _2));
-}
-
-boost::shared_ptr<RosterPayload> LinkLocalRoster::getRoster() const {
-	boost::shared_ptr<RosterPayload> roster(new RosterPayload());
-	for(ServiceMap::const_iterator i = services.begin(); i != services.end(); ++i) {
-		roster->addItem(getRosterItem(i->first, i->second));
-	}
-	return roster;
-}
-
-std::vector<boost::shared_ptr<Presence> > LinkLocalRoster::getAllPresence() const {
-	std::vector<boost::shared_ptr<Presence> > result;
-	for(ServiceMap::const_iterator i = services.begin(); i != services.end(); ++i) {
-		result.push_back(getPresence(i->first, i->second));
-	}
-	return result;
-}
-
-RosterItemPayload LinkLocalRoster::getRosterItem(const DNSSDServiceID& service, const DNSSDService::ResolveResult& resolveResult) const {
- return RosterItemPayload(getJIDForService(service), getRosterName(service, resolveResult), RosterItemPayload::Both);
-}
-
-String LinkLocalRoster::getRosterName(const DNSSDServiceID& service, const DNSSDService::ResolveResult& resolveResult) const {
-	if (!resolveResult.info.getNick().isEmpty()) {
-		return resolveResult.info.getNick();
-	}
-	else if (!resolveResult.info.getFirstName().isEmpty()) {
-		String result = resolveResult.info.getFirstName();
-		if (!resolveResult.info.getLastName().isEmpty()) {
-			result += " " + resolveResult.info.getLastName();
-		}
-		return result;
-	}
-	else if (!resolveResult.info.getLastName().isEmpty()) {
-		return resolveResult.info.getLastName();
-	}
-	return service.getName();
-}
-
-JID LinkLocalRoster::getJIDForService(const DNSSDServiceID& service) const {
-	return JID(service.getName());
-}
-
-boost::shared_ptr<Presence> LinkLocalRoster::getPresence(const DNSSDServiceID& service, const DNSSDService::ResolveResult& resolveResult) const {
-	boost::shared_ptr<Presence> presence(new Presence());
-	presence->setFrom(getJIDForService(service));
-	switch (resolveResult.info.getStatus()) {
-		case LinkLocalServiceInfo::Available:
-			presence->setShow(StatusShow::Online);
-			break;
-		case LinkLocalServiceInfo::Away:
-			presence->setShow(StatusShow::Away);
-			break;
-		case LinkLocalServiceInfo::DND:
-			presence->setShow(StatusShow::DND);
-			break;
-	}
-	presence->setStatus(resolveResult.info.getMessage());
-	return presence;
-}
-
-void LinkLocalRoster::handleServiceAdded(const DNSSDServiceID& service) {
-	if (selfService && *selfService == service) {
-		return;
-	}
-	dnsSDService->startResolvingService(service);
-}
-
-void LinkLocalRoster::handleServiceRemoved(const DNSSDServiceID& service) {
-	if (selfService && *selfService == service) {
-		return;
-	}
-	dnsSDService->stopResolvingService(service);
-	services.erase(service);
-	boost::shared_ptr<RosterPayload> roster(new RosterPayload());
-	roster->addItem(RosterItemPayload(getJIDForService(service), "", RosterItemPayload::Remove));
-	onRosterChanged(roster);
-}
-
-void LinkLocalRoster::handleServiceResolved(const DNSSDServiceID& service, const DNSSDService::ResolveResult& result) {
-	std::pair<ServiceMap::iterator, bool> r = services.insert(std::make_pair(service, result));
-	if (r.second) {
-		boost::shared_ptr<RosterPayload> roster(new RosterPayload());
-		roster->addItem(getRosterItem(service, result));
-		onRosterChanged(roster);
-	}
-	else {
-		r.first->second = result;
-	}
-	onPresenceChanged(getPresence(service, result));
-}
-
-void LinkLocalRoster::handleServiceRegistered(const DNSSDServiceID& service) {
-	selfService = service;
-}
-
-void LinkLocalRoster::handleStopped(bool error) {
-	std::cout << "DNSSDService stopped: " << error << std::endl;
-}
-
-bool LinkLocalRoster::hasItem(const JID& j) const {
-	for(ServiceMap::const_iterator i = services.begin(); i != services.end(); ++i) {
-		if (getJIDForService(i->first) == j) {
-			return true;
-		}
-	}
-	return false;
-}
-
-String LinkLocalRoster::getHostname(const JID& j) const {
-	for(ServiceMap::const_iterator i = services.begin(); i != services.end(); ++i) {
-		if (getJIDForService(i->first) == j) {
-			return i->second.host;
-		}
-	}
-	return "";
-}
-
-int LinkLocalRoster::getPort(const JID& j) const {
-	for(ServiceMap::const_iterator i = services.begin(); i != services.end(); ++i) {
-		if (getJIDForService(i->first) == j) {
-			return i->second.port;
-		}
-	}
-	return 0;
-}
-
-}
diff --git a/Swiften/LinkLocal/LinkLocalRoster.h b/Swiften/LinkLocal/LinkLocalRoster.h
deleted file mode 100644
index 03ed2d5..0000000
--- a/Swiften/LinkLocal/LinkLocalRoster.h
+++ /dev/null
@@ -1,48 +0,0 @@
-#pragma once
-
-#include <boost/shared_ptr.hpp>
-#include <boost/optional.hpp>
-#include <set>
-
-#include "Swiften/Base/String.h"
-#include "Swiften/JID/JID.h"
-#include "Swiften/LinkLocal/DNSSDService.h"
-#include "Swiften/Elements/RosterPayload.h"
-#include "Swiften/Elements/Presence.h"
-
-namespace Swift {
-	class HostAddress;
-
-	class LinkLocalRoster {
-		public:
-			LinkLocalRoster(boost::shared_ptr<DNSSDService> service);
-
-			boost::shared_ptr<RosterPayload> getRoster() const;
-			std::vector<boost::shared_ptr<Presence> > getAllPresence() const;
-
-			boost::signal<void (boost::shared_ptr<RosterPayload>)> onRosterChanged;
-			boost::signal<void (boost::shared_ptr<Presence>)> onPresenceChanged;
-
-			bool hasItem(const JID&) const;
-			String getHostname(const JID&) const;
-			int getPort(const JID&) const;
-
-		private:
-			RosterItemPayload getRosterItem(const DNSSDServiceID& service, const DNSSDService::ResolveResult& info) const;
-			String getRosterName(const DNSSDServiceID& service, const DNSSDService::ResolveResult& info) const;
-			JID getJIDForService(const DNSSDServiceID& service) const;
-			boost::shared_ptr<Presence> getPresence(const DNSSDServiceID& service, const DNSSDService::ResolveResult& info) const;
-
-			void handleStopped(bool);
-			void handleServiceRegistered(const DNSSDServiceID& service);
-			void handleServiceAdded(const DNSSDServiceID&);
-			void handleServiceRemoved(const DNSSDServiceID&);
-			void handleServiceResolved(const DNSSDServiceID& service, const DNSSDService::ResolveResult& result);
-
-		private:
-			boost::shared_ptr<DNSSDService> dnsSDService;
-			boost::optional<DNSSDServiceID> selfService;
-			typedef std::map<DNSSDServiceID, DNSSDService::ResolveResult> ServiceMap;
-			ServiceMap services;
-	};
-}
diff --git a/Swiften/LinkLocal/LinkLocalServiceBrowser.cpp b/Swiften/LinkLocal/LinkLocalServiceBrowser.cpp
index f65cd7a..b24d8f0 100644
--- a/Swiften/LinkLocal/LinkLocalServiceBrowser.cpp
+++ b/Swiften/LinkLocal/LinkLocalServiceBrowser.cpp
@@ -65,6 +65,11 @@ void LinkLocalServiceBrowser::registerService(const String& name, int port, cons
 	registerQuery->registerService();
 }
 
+void LinkLocalServiceBrowser::updateService(const LinkLocalServiceInfo& info) {
+	assert(registerQuery);
+	registerQuery->updateServiceInfo(info.toTXTRecord());
+}
+
 void LinkLocalServiceBrowser::unregisterService() {
 	assert(registerQuery);
 	registerQuery->unregisterService();
@@ -125,6 +130,7 @@ void LinkLocalServiceBrowser::handleServiceResolved(const DNSSDServiceID& servic
 void LinkLocalServiceBrowser::handleRegisterFinished(const boost::optional<DNSSDServiceID>& result) {
 	if (result) {
 		selfService = result;
+		onServiceRegistered(*result);
 	}
 	else {
 		haveError = true;
diff --git a/Swiften/LinkLocal/LinkLocalServiceBrowser.h b/Swiften/LinkLocal/LinkLocalServiceBrowser.h
index a6623b1..7ef661c 100644
--- a/Swiften/LinkLocal/LinkLocalServiceBrowser.h
+++ b/Swiften/LinkLocal/LinkLocalServiceBrowser.h
@@ -25,7 +25,12 @@ namespace Swift {
 			bool isRunning() const;
 			bool hasError() const;
 
-			void registerService(const String& name, int port, const LinkLocalServiceInfo& info = LinkLocalServiceInfo());
+			void registerService(
+					const String& name, 
+					int port, 
+					const LinkLocalServiceInfo& info = LinkLocalServiceInfo());
+			void updateService(
+					const LinkLocalServiceInfo& info = LinkLocalServiceInfo());
 			void unregisterService();
 			bool isRegistered() const;
 
@@ -34,6 +39,7 @@ namespace Swift {
 			boost::signal<void (const LinkLocalService&)> onServiceAdded;
 			boost::signal<void (const LinkLocalService&)> onServiceChanged;
 			boost::signal<void (const LinkLocalService&)> onServiceRemoved;
+			boost::signal<void (const DNSSDServiceID&)> onServiceRegistered;
 			boost::signal<void (bool)> onStopped;
 
 		private:
diff --git a/Swiften/LinkLocal/Makefile.inc b/Swiften/LinkLocal/Makefile.inc
index 3738789..715d686 100644
--- a/Swiften/LinkLocal/Makefile.inc
+++ b/Swiften/LinkLocal/Makefile.inc
@@ -1,21 +1,10 @@
 SWIFTEN_SOURCES += \
 	Swiften/LinkLocal/LinkLocalServiceBrowser.cpp \
-	Swiften/LinkLocal/DNSSDService.cpp \
 	Swiften/LinkLocal/LinkLocalService.cpp \
-	Swiften/LinkLocal/LinkLocalRoster.cpp \
 	Swiften/LinkLocal/LinkLocalServiceInfo.cpp \
 	Swiften/LinkLocal/IncomingLinkLocalSession.cpp \
 	Swiften/LinkLocal/OutgoingLinkLocalSession.cpp \
 	Swiften/LinkLocal/LinkLocalConnector.cpp
 
-ifeq ($(HAVE_BONJOUR),yes)
-SWIFTEN_SOURCES += \
-	Swiften/LinkLocal/AppleDNSSDService.cpp
-endif
-ifeq ($(HAVE_AVAHI),yes)
-SWIFTEN_SOURCES += \
-	Swiften/LinkLocal/AvahiDNSSDService.cpp
-endif
-
 include Swiften/LinkLocal/DNSSD/Makefile.inc
 include Swiften/LinkLocal/UnitTest/Makefile.inc
diff --git a/Swiften/LinkLocal/UnitTest/LinkLocalServiceBrowserTest.cpp b/Swiften/LinkLocal/UnitTest/LinkLocalServiceBrowserTest.cpp
index 6e4d3b4..76117c0 100644
--- a/Swiften/LinkLocal/UnitTest/LinkLocalServiceBrowserTest.cpp
+++ b/Swiften/LinkLocal/UnitTest/LinkLocalServiceBrowserTest.cpp
@@ -27,6 +27,7 @@ class LinkLocalServiceBrowserTest : public CppUnit::TestFixture {
 		CPPUNIT_TEST(testRegisterService);
 		CPPUNIT_TEST(testRegisterService_Error);
 		CPPUNIT_TEST(testRegisterService_Reregister);
+		CPPUNIT_TEST(testUpdateService);
 		CPPUNIT_TEST_SUITE_END();
 
 	public:
@@ -239,7 +240,8 @@ class LinkLocalServiceBrowserTest : public CppUnit::TestFixture {
 			eventLoop->processEvents();
 
 			CPPUNIT_ASSERT(querier->isServiceRegistered("foo@bar", 1234, info.toTXTRecord()));
-
+			CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(registeredServices.size()));
+			CPPUNIT_ASSERT(registeredServices[0] == DNSSDServiceID("foo@bar", "wonderland.lit"));
 			testling->stop();
 		}
 
@@ -279,6 +281,23 @@ class LinkLocalServiceBrowserTest : public CppUnit::TestFixture {
 			testling->stop();
 		}
 
+		void testUpdateService() {
+			boost::shared_ptr<LinkLocalServiceBrowser> testling = createTestling();
+			testling->start();
+			eventLoop->processEvents();
+
+			LinkLocalServiceInfo info;
+			info.setFirstName("Foo");
+			testling->registerService("foo@bar", 1234, info);
+			eventLoop->processEvents();
+			info.setFirstName("Bar");
+			testling->updateService(info);
+
+			CPPUNIT_ASSERT(querier->isServiceRegistered("foo@bar", 1234, info.toTXTRecord()));
+
+			testling->stop();
+		}
+
 	private:
 		boost::shared_ptr<LinkLocalServiceBrowser> createTestling() {
 			boost::shared_ptr<LinkLocalServiceBrowser> testling(
@@ -289,6 +308,8 @@ class LinkLocalServiceBrowserTest : public CppUnit::TestFixture {
 					&LinkLocalServiceBrowserTest::handleServiceChanged, this, _1));
 			testling->onServiceRemoved.connect(boost::bind(
 					&LinkLocalServiceBrowserTest::handleServiceRemoved, this, _1));
+			testling->onServiceRegistered.connect(boost::bind(
+					&LinkLocalServiceBrowserTest::handleServiceRegistered, this, _1));
 			testling->onStopped.connect(boost::bind(
 					&LinkLocalServiceBrowserTest::handleStopped, this, _1));
 			return testling;
@@ -306,6 +327,10 @@ class LinkLocalServiceBrowserTest : public CppUnit::TestFixture {
 			changedServices.push_back(service);
 		}
 
+		void handleServiceRegistered(const DNSSDServiceID& service) {
+			registeredServices.push_back(service);
+		}
+
 		void handleStopped(bool error) {
 			CPPUNIT_ASSERT(!errorStopReceived);
 			CPPUNIT_ASSERT(!normalStopReceived);
@@ -323,6 +348,7 @@ class LinkLocalServiceBrowserTest : public CppUnit::TestFixture {
 		std::vector<LinkLocalService> addedServices;
 		std::vector<LinkLocalService> changedServices;
 		std::vector<LinkLocalService> removedServices;
+		std::vector<DNSSDServiceID> registeredServices;
 		DNSSDServiceID* aliceServiceID;
 		DNSSDResolveServiceQuery::Result* aliceServiceInfo;
 		DNSSDServiceID* testServiceID;
-- 
cgit v0.10.2-6-g49f6