From 15103cc6eb3dd62c0e84c68bb08995247c653094 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Wed, 22 Jul 2009 21:28:48 +0200
Subject: Introduce LinkLocalServiceID to identify Link-Local services.


diff --git a/Swiften/LinkLocal/AppleDNSSDService.cpp b/Swiften/LinkLocal/AppleDNSSDService.cpp
index 969cbb2..5262357 100644
--- a/Swiften/LinkLocal/AppleDNSSDService.cpp
+++ b/Swiften/LinkLocal/AppleDNSSDService.cpp
@@ -70,11 +70,11 @@ void AppleDNSSDService::unregisterService() {
 	registerSDRef = NULL;
 }
 
-void AppleDNSSDService::startResolvingService(const Service& service) {
+void AppleDNSSDService::startResolvingService(const LinkLocalServiceID& service) {
 	boost::lock_guard<boost::mutex> lock(sdRefsMutex);
 
 	DNSServiceRef resolveSDRef;
-	DNSServiceErrorType result = DNSServiceResolve(&resolveSDRef, 0, service.networkInterface, service.name.getUTF8Data(), service.type.getUTF8Data(), service.domain.getUTF8Data(), &AppleDNSSDService::handleServiceResolvedGlobal, this);
+	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;
@@ -87,7 +87,7 @@ void AppleDNSSDService::startResolvingService(const Service& service) {
 	interruptSelect();
 }
 
-void AppleDNSSDService::stopResolvingService(const Service& service) {
+void AppleDNSSDService::stopResolvingService(const LinkLocalServiceID& service) {
 	boost::lock_guard<boost::mutex> lock(sdRefsMutex);
 
 	ServiceSDRefMap::iterator i = resolveSDRefs.find(service);
@@ -238,7 +238,7 @@ void AppleDNSSDService::handleServiceDiscovered(DNSServiceRef, DNSServiceFlags f
 		return;
 	}
 	else {
-		Service service(serviceName, regtype, replyDomain, interfaceIndex);
+		LinkLocalServiceID service(serviceName, regtype, replyDomain, interfaceIndex);
 		if (flags & kDNSServiceFlagsAdd) {
 			MainEventLoop::postEvent(boost::bind(boost::ref(onServiceAdded), service), shared_from_this());
 		}
@@ -258,7 +258,7 @@ void AppleDNSSDService::handleServiceRegistered(DNSServiceRef, DNSServiceFlags,
 		haveError = true;
 	}
 	else {
-		MainEventLoop::postEvent(boost::bind(boost::ref(onServiceRegistered), Service(name, regtype, domain, 0)), shared_from_this());
+		MainEventLoop::postEvent(boost::bind(boost::ref(onServiceRegistered), LinkLocalServiceID(name, regtype, domain, 0)), shared_from_this());
 	}
 }
 
diff --git a/Swiften/LinkLocal/AppleDNSSDService.h b/Swiften/LinkLocal/AppleDNSSDService.h
index fe4a648..7fdfd3e 100644
--- a/Swiften/LinkLocal/AppleDNSSDService.h
+++ b/Swiften/LinkLocal/AppleDNSSDService.h
@@ -6,6 +6,7 @@
 #include <dns_sd.h>
 
 #include "Swiften/LinkLocal/DNSSDService.h"
+#include "Swiften/LinkLocal/LinkLocalServiceID.h"
 #include "Swiften/EventLoop/EventOwner.h"
 
 namespace Swift {
@@ -21,8 +22,8 @@ namespace Swift {
 			virtual void updateService(const LinkLocalServiceInfo&);
 			virtual void unregisterService();
 
-			virtual void startResolvingService(const Service&);
-			virtual void stopResolvingService(const Service&);
+			virtual void startResolvingService(const LinkLocalServiceID&);
+			virtual void stopResolvingService(const LinkLocalServiceID&);
 
 			virtual void resolveHostname(const String& hostname, int interfaceIndex = 0);
 
@@ -48,7 +49,7 @@ namespace Swift {
 			boost::mutex sdRefsMutex;
 			DNSServiceRef browseSDRef;
 			DNSServiceRef registerSDRef;
-			typedef std::map<Service, DNSServiceRef> ServiceSDRefMap;
+			typedef std::map<LinkLocalServiceID, DNSServiceRef> ServiceSDRefMap;
 			ServiceSDRefMap resolveSDRefs;
 			typedef std::vector<DNSServiceRef> HostnameSDRefs;
 			HostnameSDRefs hostnameResolveSDRefs;
diff --git a/Swiften/LinkLocal/AvahiDNSSDService.cpp b/Swiften/LinkLocal/AvahiDNSSDService.cpp
index 1dd5c28..72039b7 100644
--- a/Swiften/LinkLocal/AvahiDNSSDService.cpp
+++ b/Swiften/LinkLocal/AvahiDNSSDService.cpp
@@ -62,16 +62,16 @@ void AvahiDNSSDService::unregisterService() {
 	avahi_threaded_poll_unlock(threadedPoll);
 }
 
-void AvahiDNSSDService::startResolvingService(const Service& service) {
+void AvahiDNSSDService::startResolvingService(const LinkLocalServiceID& service) {
 	avahi_threaded_poll_lock(threadedPoll);
 
 	AvahiServiceResolver* resolver = avahi_service_resolver_new(
 			client, 
-			service.networkInterface, 
+			service.getNetworkInterfaceID(), 
 			AVAHI_PROTO_INET,
-			service.name.getUTF8Data(), 
-			service.type.getUTF8Data(), 
-			service.domain.getUTF8Data(), 
+			service.getName().getUTF8Data(), 
+			service.getType().getUTF8Data(), 
+			service.getDomain().getUTF8Data(), 
 			AVAHI_PROTO_UNSPEC, 
 			static_cast<AvahiLookupFlags>(0), 
 			&AvahiDNSSDService::handleServiceResolvedGlobal, 
@@ -112,13 +112,13 @@ void AvahiDNSSDService::handleServiceDiscovered(AvahiServiceBrowser *, AvahiIfIn
 			return;
 		case AVAHI_BROWSER_NEW: {
 				std::cerr << "Service added: " << name << " " << type << " " << domain << std::endl;
-				Service service(name, type, domain, interfaceIndex);
+				LinkLocalServiceID 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;
-				Service service(name, type, domain, interfaceIndex);
+				LinkLocalServiceID service(name, type, domain, interfaceIndex);
 				MainEventLoop::postEvent(boost::bind(boost::ref(onServiceRemoved), service), shared_from_this());
 			}
 			break;
@@ -146,7 +146,7 @@ void AvahiDNSSDService::handleServiceResolved(AvahiServiceResolver *, AvahiIfInd
 			HostAddress hostAddress(reinterpret_cast<const unsigned char*>(&address->data.ipv4.address), 4);
 			hostnameAddresses[String(hostname)] = hostAddress;
 			MainEventLoop::postEvent(boost::bind(boost::ref(onServiceResolved), 
-					Service(name, type, domain, interfaceIndex), 
+					LinkLocalServiceID(name, type, domain, interfaceIndex), 
 					ResolveResult(hostname, port, 
 						LinkLocalServiceInfo::createFromTXTRecord(data))),
 					shared_from_this());
diff --git a/Swiften/LinkLocal/AvahiDNSSDService.h b/Swiften/LinkLocal/AvahiDNSSDService.h
index 8d31e41..a5be943 100644
--- a/Swiften/LinkLocal/AvahiDNSSDService.h
+++ b/Swiften/LinkLocal/AvahiDNSSDService.h
@@ -26,8 +26,8 @@ namespace Swift {
 			virtual void updateService(const LinkLocalServiceInfo&);
 			virtual void unregisterService();
 
-			virtual void startResolvingService(const Service&);
-			virtual void stopResolvingService(const Service&);
+			virtual void startResolvingService(const LinkLocalServiceID&);
+			virtual void stopResolvingService(const LinkLocalServiceID&);
 
 			virtual void resolveHostname(const String& hostname, int interfaceIndex = 0);
 		
diff --git a/Swiften/LinkLocal/DNSSDService.h b/Swiften/LinkLocal/DNSSDService.h
index 9689352..4cf1a6e 100644
--- a/Swiften/LinkLocal/DNSSDService.h
+++ b/Swiften/LinkLocal/DNSSDService.h
@@ -4,6 +4,7 @@
 #include <map>
 
 #include "Swiften/Base/String.h"
+#include "Swiften/LinkLocal/LinkLocalServiceID.h"
 #include "Swiften/LinkLocal/LinkLocalServiceInfo.h"
 
 namespace Swift {
@@ -12,36 +13,6 @@ namespace Swift {
 
 	class DNSSDService {
 		public:
-			struct Service {
-				Service(const String& name, const String& type, const String& domain, int networkInterface) : name(name), type(type), domain(domain), networkInterface(networkInterface) {}
-				bool operator==(const Service& o) const {
-					return name == o.name && type == o.type && domain == o.domain && (networkInterface != 0 && o.networkInterface != 0 ? networkInterface == o.networkInterface : true);
-				}
-				bool operator<(const Service& o) const {
-					if (o.name == name) {
-						if (o.type == type) {
-							if (o.domain == domain) {
-								return networkInterface < o.networkInterface;
-							}
-							else {
-								return domain < o.domain;
-							}
-						}
-						else {
-							return type < o.type;
-						}
-					}
-					else {
-						return o.name < name;
-					}
-				}
-
-				String name;
-				String type;
-				String domain;
-				int networkInterface;
-			};
-
 			struct ResolveResult {
 				ResolveResult(const String& host, int port, const LinkLocalServiceInfo& info) : host(host), port(port), info(info) {}
 				String host;
@@ -58,17 +29,17 @@ namespace Swift {
 			virtual void updateService(const LinkLocalServiceInfo&) = 0;
 			virtual void unregisterService() = 0;
 
-			virtual void startResolvingService(const Service&) = 0;
-			virtual void stopResolvingService(const Service&) = 0;
+			virtual void startResolvingService(const LinkLocalServiceID&) = 0;
+			virtual void stopResolvingService(const LinkLocalServiceID&) = 0;
 			
 			virtual void resolveHostname(const String& hostname, int interfaceIndex = 0) = 0;
 
 			boost::signal<void ()> onStarted;
 			boost::signal<void (bool)> onStopped;
-			boost::signal<void (const Service&)> onServiceAdded;
-			boost::signal<void (const Service&)> onServiceRemoved;
-			boost::signal<void (const Service&)> onServiceRegistered;
-			boost::signal<void (const Service&, const ResolveResult&)> onServiceResolved;
+			boost::signal<void (const LinkLocalServiceID&)> onServiceAdded;
+			boost::signal<void (const LinkLocalServiceID&)> onServiceRemoved;
+			boost::signal<void (const LinkLocalServiceID&)> onServiceRegistered;
+			boost::signal<void (const LinkLocalServiceID&, const ResolveResult&)> onServiceResolved;
 			boost::signal<void (const String&, const boost::optional<HostAddress>&)> onHostnameResolved;
 	};
 }
diff --git a/Swiften/LinkLocal/LinkLocalRoster.cpp b/Swiften/LinkLocal/LinkLocalRoster.cpp
index 25143a6..5a6ccfd 100644
--- a/Swiften/LinkLocal/LinkLocalRoster.cpp
+++ b/Swiften/LinkLocal/LinkLocalRoster.cpp
@@ -30,11 +30,11 @@ std::vector<boost::shared_ptr<Presence> > LinkLocalRoster::getAllPresence() cons
 	return result;
 }
 
-RosterItemPayload LinkLocalRoster::getRosterItem(const DNSSDService::Service& service, const DNSSDService::ResolveResult& resolveResult) const {
+RosterItemPayload LinkLocalRoster::getRosterItem(const LinkLocalServiceID& service, const DNSSDService::ResolveResult& resolveResult) const {
  return RosterItemPayload(getJIDForService(service), getRosterName(service, resolveResult), RosterItemPayload::Both);
 }
 
-String LinkLocalRoster::getRosterName(const DNSSDService::Service& service, const DNSSDService::ResolveResult& resolveResult) const {
+String LinkLocalRoster::getRosterName(const LinkLocalServiceID& service, const DNSSDService::ResolveResult& resolveResult) const {
 	if (!resolveResult.info.getNick().isEmpty()) {
 		return resolveResult.info.getNick();
 	}
@@ -48,14 +48,14 @@ String LinkLocalRoster::getRosterName(const DNSSDService::Service& service, cons
 	else if (!resolveResult.info.getLastName().isEmpty()) {
 		return resolveResult.info.getLastName();
 	}
-	return service.name;
+	return service.getName();
 }
 
-JID LinkLocalRoster::getJIDForService(const DNSSDService::Service& service) const {
-	return JID(service.name);
+JID LinkLocalRoster::getJIDForService(const LinkLocalServiceID& service) const {
+	return JID(service.getName());
 }
 
-boost::shared_ptr<Presence> LinkLocalRoster::getPresence(const DNSSDService::Service& service, const DNSSDService::ResolveResult& resolveResult) const {
+boost::shared_ptr<Presence> LinkLocalRoster::getPresence(const LinkLocalServiceID& service, const DNSSDService::ResolveResult& resolveResult) const {
 	boost::shared_ptr<Presence> presence(new Presence());
 	presence->setFrom(getJIDForService(service));
 	switch (resolveResult.info.getStatus()) {
@@ -73,14 +73,14 @@ boost::shared_ptr<Presence> LinkLocalRoster::getPresence(const DNSSDService::Ser
 	return presence;
 }
 
-void LinkLocalRoster::handleServiceAdded(const DNSSDService::Service& service) {
+void LinkLocalRoster::handleServiceAdded(const LinkLocalServiceID& service) {
 	if (selfService && *selfService == service) {
 		return;
 	}
 	dnsSDService->startResolvingService(service);
 }
 
-void LinkLocalRoster::handleServiceRemoved(const DNSSDService::Service& service) {
+void LinkLocalRoster::handleServiceRemoved(const LinkLocalServiceID& service) {
 	if (selfService && *selfService == service) {
 		return;
 	}
@@ -91,7 +91,7 @@ void LinkLocalRoster::handleServiceRemoved(const DNSSDService::Service& service)
 	onRosterChanged(roster);
 }
 
-void LinkLocalRoster::handleServiceResolved(const DNSSDService::Service& service, const DNSSDService::ResolveResult& result) {
+void LinkLocalRoster::handleServiceResolved(const LinkLocalServiceID& 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());
@@ -104,7 +104,7 @@ void LinkLocalRoster::handleServiceResolved(const DNSSDService::Service& service
 	onPresenceChanged(getPresence(service, result));
 }
 
-void LinkLocalRoster::handleServiceRegistered(const DNSSDService::Service& service) {
+void LinkLocalRoster::handleServiceRegistered(const LinkLocalServiceID& service) {
 	selfService = service;
 }
 
diff --git a/Swiften/LinkLocal/LinkLocalRoster.h b/Swiften/LinkLocal/LinkLocalRoster.h
index c18d8fc..128e39d 100644
--- a/Swiften/LinkLocal/LinkLocalRoster.h
+++ b/Swiften/LinkLocal/LinkLocalRoster.h
@@ -28,21 +28,21 @@ namespace Swift {
 			int getPort(const JID&) const;
 
 		private:
-			RosterItemPayload getRosterItem(const DNSSDService::Service& service, const DNSSDService::ResolveResult& info) const;
-			String getRosterName(const DNSSDService::Service& service, const DNSSDService::ResolveResult& info) const;
-			JID getJIDForService(const DNSSDService::Service& service) const;
-			boost::shared_ptr<Presence> getPresence(const DNSSDService::Service& service, const DNSSDService::ResolveResult& info) const;
+			RosterItemPayload getRosterItem(const LinkLocalServiceID& service, const DNSSDService::ResolveResult& info) const;
+			String getRosterName(const LinkLocalServiceID& service, const DNSSDService::ResolveResult& info) const;
+			JID getJIDForService(const LinkLocalServiceID& service) const;
+			boost::shared_ptr<Presence> getPresence(const LinkLocalServiceID& service, const DNSSDService::ResolveResult& info) const;
 
 			void handleStopped(bool);
-			void handleServiceRegistered(const DNSSDService::Service& service);
-			void handleServiceAdded(const DNSSDService::Service&);
-			void handleServiceRemoved(const DNSSDService::Service&);
-			void handleServiceResolved(const DNSSDService::Service& service, const DNSSDService::ResolveResult& result);
+			void handleServiceRegistered(const LinkLocalServiceID& service);
+			void handleServiceAdded(const LinkLocalServiceID&);
+			void handleServiceRemoved(const LinkLocalServiceID&);
+			void handleServiceResolved(const LinkLocalServiceID& service, const DNSSDService::ResolveResult& result);
 
 		private:
 			boost::shared_ptr<DNSSDService> dnsSDService;
-			boost::optional<DNSSDService::Service> selfService;
-			typedef std::map<DNSSDService::Service, DNSSDService::ResolveResult> ServiceMap;
+			boost::optional<LinkLocalServiceID> selfService;
+			typedef std::map<LinkLocalServiceID, DNSSDService::ResolveResult> ServiceMap;
 			ServiceMap services;
 	};
 }
diff --git a/Swiften/LinkLocal/LinkLocalServiceID.h b/Swiften/LinkLocal/LinkLocalServiceID.h
new file mode 100644
index 0000000..72615d4
--- /dev/null
+++ b/Swiften/LinkLocal/LinkLocalServiceID.h
@@ -0,0 +1,64 @@
+#pragma once
+
+#include "Swiften/Base/String.h"
+
+namespace Swift {
+	class LinkLocalServiceID {
+		public:
+			LinkLocalServiceID(
+				const String& name, 
+				const String& type, 
+				const String& domain, 
+				int networkInterface = 0) : 
+					name(name), 
+					type(type), 
+					domain(domain), 
+					networkInterface(networkInterface) {
+			}
+
+			bool operator==(const LinkLocalServiceID& o) const {
+				return name == o.name && type == o.type && domain == o.domain && (networkInterface != 0 && o.networkInterface != 0 ? networkInterface == o.networkInterface : true);
+			}
+
+			bool operator<(const LinkLocalServiceID& o) const {
+				if (o.name == name) {
+					if (o.type == type) {
+						if (o.domain == domain) {
+							return networkInterface < o.networkInterface;
+						}
+						else {
+							return domain < o.domain;
+						}
+					}
+					else {
+						return type < o.type;
+					}
+				}
+				else {
+					return o.name < name;
+				}
+			}
+
+			const String& getName() const {
+				return name;
+			}
+
+			const String& getType() const {
+				return type;
+			}
+
+			const String& getDomain() const {
+				return domain;
+			}
+
+			int getNetworkInterfaceID() const {
+				return networkInterface;
+			}
+
+		private:
+			String name;
+			String type;
+			String domain;
+			int networkInterface;
+	};
+}
-- 
cgit v0.10.2-6-g49f6


From 0a7336577f9609c70bb4d846c668e7853746cb52 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Wed, 22 Jul 2009 23:36:52 +0200
Subject: Started LinkLocalServiceBrowser.


diff --git a/Swiften/LinkLocal/AppleDNSSDService.cpp b/Swiften/LinkLocal/AppleDNSSDService.cpp
index 5262357..bf66e50 100644
--- a/Swiften/LinkLocal/AppleDNSSDService.cpp
+++ b/Swiften/LinkLocal/AppleDNSSDService.cpp
@@ -268,8 +268,6 @@ void AppleDNSSDService::handleServiceResolvedGlobal(DNSServiceRef sdRef, DNSServ
 
 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) {
-		// TODO
-		std::cerr << "Resolve error " << hosttarget << std::endl;
 		return;
 	}
 	for (ServiceSDRefMap::const_iterator i = resolveSDRefs.begin(); i != resolveSDRefs.end(); ++i) {
diff --git a/Swiften/LinkLocal/LinkLocalService.h b/Swiften/LinkLocal/LinkLocalService.h
new file mode 100644
index 0000000..446feb8
--- /dev/null
+++ b/Swiften/LinkLocal/LinkLocalService.h
@@ -0,0 +1,50 @@
+#pragma once
+
+#include "Swiften/Base/String.h"
+#include "Swiften/Network/HostAddress.h"
+#include "Swiften/LinkLocal/LinkLocalServiceInfo.h"
+
+namespace Swift {
+	class LinkLocalService {
+		public:
+			LinkLocalService();
+
+			const String& getName() const {
+				return name;
+			}
+
+			void setName(const String& n) {
+				name = n;
+			}
+
+			const String& getHostname() const {
+				return hostname;
+			}
+
+			void setHostname(const String& h) {
+				hostname = h;
+			}
+
+			const HostAddress& getAddress() const {
+				return address;
+			}
+
+			void setAddress(const HostAddress& a) {
+				address = a;
+			}
+
+			const LinkLocalServiceInfo& getInfo() const {
+				return info;
+			}
+
+			void setInfo(const LinkLocalServiceInfo& i) {
+				info = i;
+			}
+
+		private:
+			String name;
+			String hostname;
+			LinkLocalServiceInfo info;
+			HostAddress address;
+	};
+}
diff --git a/Swiften/LinkLocal/LinkLocalServiceBrowser.cpp b/Swiften/LinkLocal/LinkLocalServiceBrowser.cpp
new file mode 100644
index 0000000..63cf075
--- /dev/null
+++ b/Swiften/LinkLocal/LinkLocalServiceBrowser.cpp
@@ -0,0 +1,38 @@
+#include <boost/bind.hpp>
+#include <iostream>
+
+#include "Swiften/LinkLocal/LinkLocalServiceBrowser.h"
+#include "Swiften/Network/HostAddress.h"
+
+namespace Swift {
+
+LinkLocalServiceBrowser::LinkLocalServiceBrowser(boost::shared_ptr<DNSSDService> service) : dnsSDService(service) {
+	dnsSDService->onServiceAdded.connect(
+			boost::bind(&LinkLocalServiceBrowser::handleServiceAdded, this, _1));
+	dnsSDService->onServiceRemoved.connect(
+			boost::bind(&LinkLocalServiceBrowser::handleServiceRemoved, this, _1));
+	dnsSDService->onServiceResolved.connect(
+			boost::bind(&LinkLocalServiceBrowser::handleServiceResolved, this, _1, _2));
+}
+
+void LinkLocalServiceBrowser::handleServiceAdded(const LinkLocalServiceID& service) {
+	dnsSDService->startResolvingService(service);
+}
+
+void LinkLocalServiceBrowser::handleServiceRemoved(const LinkLocalServiceID& service) {
+	/*dnsSDService->stopResolvingService(service);
+	services.erase(service);*/
+}
+
+void LinkLocalServiceBrowser::handleServiceResolved(const LinkLocalServiceID& service, const DNSSDService::ResolveResult& result) {
+	std::pair<ServiceMap::iterator, bool> r = services.insert(std::make_pair(service, result));
+	if (r.second) {
+		onServiceAdded(service);
+	}
+	else {
+		onServiceChanged(service);
+	}
+}
+
+
+}
diff --git a/Swiften/LinkLocal/LinkLocalServiceBrowser.h b/Swiften/LinkLocal/LinkLocalServiceBrowser.h
new file mode 100644
index 0000000..c0788e6
--- /dev/null
+++ b/Swiften/LinkLocal/LinkLocalServiceBrowser.h
@@ -0,0 +1,32 @@
+#pragma once
+
+#include <boost/shared_ptr.hpp>
+#include <boost/optional.hpp>
+#include <map>
+#include <vector>
+
+#include "Swiften/Base/String.h"
+#include "Swiften/LinkLocal/DNSSDService.h"
+#include "Swiften/LinkLocal/LinkLocalService.h"
+
+namespace Swift {
+	class HostAddress;
+
+	class LinkLocalServiceBrowser {
+		public:
+			LinkLocalServiceBrowser(boost::shared_ptr<DNSSDService> service);
+
+			boost::signal<void (const LinkLocalServiceID&)> onServiceAdded;
+			boost::signal<void (const LinkLocalServiceID&)> onServiceChanged;
+
+		private:
+			void handleServiceAdded(const LinkLocalServiceID&);
+			void handleServiceRemoved(const LinkLocalServiceID&);
+			void handleServiceResolved(const LinkLocalServiceID& service, const DNSSDService::ResolveResult& result);
+
+		private:
+			boost::shared_ptr<DNSSDService> dnsSDService;
+			typedef std::map<LinkLocalServiceID, DNSSDService::ResolveResult> ServiceMap;
+			ServiceMap services;
+	};
+}
diff --git a/Swiften/LinkLocal/LinkLocalServiceID.cpp b/Swiften/LinkLocal/LinkLocalServiceID.cpp
new file mode 100644
index 0000000..4248d88
--- /dev/null
+++ b/Swiften/LinkLocal/LinkLocalServiceID.cpp
@@ -0,0 +1,7 @@
+#include "Swiften/LinkLocal/LinkLocalServiceID.h"
+
+namespace Swift {
+
+const String LinkLocalServiceID::PresenceServiceType = String("_presence._tcp");
+
+}
diff --git a/Swiften/LinkLocal/LinkLocalServiceID.h b/Swiften/LinkLocal/LinkLocalServiceID.h
index 72615d4..ca5ba17 100644
--- a/Swiften/LinkLocal/LinkLocalServiceID.h
+++ b/Swiften/LinkLocal/LinkLocalServiceID.h
@@ -5,10 +5,12 @@
 namespace Swift {
 	class LinkLocalServiceID {
 		public:
+			static const String PresenceServiceType;
+
 			LinkLocalServiceID(
 				const String& name, 
 				const String& type, 
-				const String& domain, 
+				const String& domain = PresenceServiceType, 
 				int networkInterface = 0) : 
 					name(name), 
 					type(type), 
diff --git a/Swiften/LinkLocal/Makefile.inc b/Swiften/LinkLocal/Makefile.inc
index 788c000..a890d0a 100644
--- a/Swiften/LinkLocal/Makefile.inc
+++ b/Swiften/LinkLocal/Makefile.inc
@@ -1,7 +1,9 @@
 SWIFTEN_SOURCES += \
 	Swiften/LinkLocal/DNSSDService.cpp \
 	Swiften/LinkLocal/LinkLocalRoster.cpp \
+	Swiften/LinkLocal/LinkLocalServiceID.cpp \
 	Swiften/LinkLocal/LinkLocalServiceInfo.cpp \
+	Swiften/LinkLocal/LinkLocalServiceBrowser.cpp \
 	Swiften/LinkLocal/IncomingLinkLocalSession.cpp \
 	Swiften/LinkLocal/OutgoingLinkLocalSession.cpp \
 	Swiften/LinkLocal/LinkLocalConnector.cpp
diff --git a/Swiften/LinkLocal/UnitTest/LinkLocalServiceBrowserTest.cpp b/Swiften/LinkLocal/UnitTest/LinkLocalServiceBrowserTest.cpp
new file mode 100644
index 0000000..449a823
--- /dev/null
+++ b/Swiften/LinkLocal/UnitTest/LinkLocalServiceBrowserTest.cpp
@@ -0,0 +1,95 @@
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+#include <boost/bind.hpp>
+#include <map>
+
+#include "Swiften/LinkLocal/LinkLocalServiceBrowser.h"
+#include "Swiften/LinkLocal/LinkLocalService.h"
+#include "Swiften/LinkLocal/UnitTest/MockDNSSDService.h"
+#include "Swiften/LinkLocal/DNSSDService.h"
+#include "Swiften/EventLoop/DummyEventLoop.h"
+
+// Test IP address change
+
+using namespace Swift;
+
+class LinkLocalServiceBrowserTest : public CppUnit::TestFixture {
+		CPPUNIT_TEST_SUITE(LinkLocalServiceBrowserTest);
+		CPPUNIT_TEST(testServiceAdded);
+		CPPUNIT_TEST(testServiceAdded_NoServiceInfo);
+		CPPUNIT_TEST(testServiceChanged);
+		CPPUNIT_TEST_SUITE_END();
+
+	public:
+		LinkLocalServiceBrowserTest() {}
+
+		void setUp() {
+			eventLoop = new DummyEventLoop();
+			dnsSDService = boost::shared_ptr<MockDNSSDService>(new MockDNSSDService());
+			testServiceID = new LinkLocalServiceID("foo", "bar.local");
+			testServiceInfo = new DNSSDService::ResolveResult("xmpp.bar.local", 1234, LinkLocalServiceInfo());
+			testServiceInfo2 = new DNSSDService::ResolveResult("xmpp.foo.local", 2345, LinkLocalServiceInfo());
+		}
+
+		void tearDown() {
+			delete testServiceInfo2;
+			delete testServiceInfo;
+			delete testServiceID;
+			delete eventLoop;
+		}
+
+		void testServiceAdded() {
+			boost::shared_ptr<LinkLocalServiceBrowser> testling = createTestling();
+
+			dnsSDService->setServiceInfo(*testServiceID,*testServiceInfo);
+			dnsSDService->addService(*testServiceID);
+			eventLoop->processEvents();
+
+			CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(addedServices.size()));
+			CPPUNIT_ASSERT(addedServices[0] == *testServiceID);
+			// TODO: Check getServices
+		}
+
+		void testServiceAdded_NoServiceInfo() {
+			boost::shared_ptr<LinkLocalServiceBrowser> testling = createTestling();
+
+			dnsSDService->addService(*testServiceID);
+			eventLoop->processEvents();
+
+			CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(addedServices.size()));
+		}
+
+		void testServiceChanged() {
+			boost::shared_ptr<LinkLocalServiceBrowser> testling = createTestling();
+			dnsSDService->setServiceInfo(*testServiceID,*testServiceInfo);
+			dnsSDService->addService(*testServiceID);
+			eventLoop->processEvents();
+
+			dnsSDService->setServiceInfo(*testServiceID,*testServiceInfo2);
+			eventLoop->processEvents();
+			// TODO: Check getServices
+		}
+
+	private:
+		boost::shared_ptr<LinkLocalServiceBrowser> createTestling() {
+			boost::shared_ptr<LinkLocalServiceBrowser> testling(
+					new LinkLocalServiceBrowser(dnsSDService));
+			testling->onServiceAdded.connect(boost::bind(
+					&LinkLocalServiceBrowserTest::handleServiceAdded, this, _1));
+			return testling;
+		}
+
+		void handleServiceAdded(const LinkLocalServiceID& service) {
+			addedServices.push_back(service);
+		}
+
+	private:
+		DummyEventLoop* eventLoop;
+		boost::shared_ptr<MockDNSSDService> dnsSDService;
+		std::vector<LinkLocalServiceID> addedServices;
+		LinkLocalServiceID* testServiceID;
+		DNSSDService::ResolveResult* testServiceInfo;
+		DNSSDService::ResolveResult* testServiceInfo2;
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(LinkLocalServiceBrowserTest);
diff --git a/Swiften/LinkLocal/UnitTest/Makefile.inc b/Swiften/LinkLocal/UnitTest/Makefile.inc
index abc1180..9640fa7 100644
--- a/Swiften/LinkLocal/UnitTest/Makefile.inc
+++ b/Swiften/LinkLocal/UnitTest/Makefile.inc
@@ -1,2 +1,3 @@
 UNITTEST_SOURCES += \
+	Swiften/LinkLocal/UnitTest/LinkLocalServiceBrowserTest.cpp \
 	Swiften/LinkLocal/UnitTest/LinkLocalServiceInfoTest.cpp
diff --git a/Swiften/LinkLocal/UnitTest/MockDNSSDService.h b/Swiften/LinkLocal/UnitTest/MockDNSSDService.h
new file mode 100644
index 0000000..5d857fb
--- /dev/null
+++ b/Swiften/LinkLocal/UnitTest/MockDNSSDService.h
@@ -0,0 +1,74 @@
+#pragma once
+
+#include <vector>
+#include <map>
+#include <boost/bind.hpp>
+
+#include "Swiften/EventLoop/MainEventLoop.h"
+#include "Swiften/LinkLocal/DNSSDService.h"
+
+namespace Swift {
+	class MockDNSSDService : public DNSSDService {
+		public:
+			MockDNSSDService() {
+			}
+			
+			void start() {
+			}
+
+			void stop() {
+			}
+
+			virtual void registerService(const String&, int, const LinkLocalServiceInfo&) {
+				assert(false);
+			}
+
+			virtual void updateService(const LinkLocalServiceInfo&) {
+				assert(false);
+			}
+
+			virtual void unregisterService() {
+				assert(false);
+			}
+
+			virtual void startResolvingService(const LinkLocalServiceID& id) {
+				resolvingServices.push_back(id);
+				broadcastServiceInfo(id);
+			}
+
+			virtual void stopResolvingService(const LinkLocalServiceID& id) {
+				resolvingServices.erase(std::remove(resolvingServices.begin(), resolvingServices.end(), id), resolvingServices.end());
+			}
+			
+			virtual void resolveHostname(const String&, int) {
+				assert(false);
+			}
+
+			void addService(const LinkLocalServiceID& id) {
+				MainEventLoop::postEvent(boost::bind(boost::ref(onServiceAdded), id));
+			}
+
+			void setServiceInfo(const LinkLocalServiceID& id, const DNSSDService::ResolveResult& info) {
+				serviceInfo.insert(std::make_pair(id, info));
+				broadcastServiceInfo(id);
+			}
+
+		private:
+			void broadcastServiceInfo(const LinkLocalServiceID& id) {
+				if (std::find(resolvingServices.begin(), resolvingServices.end(), id) != resolvingServices.end()) {
+					ServiceInfoMap::const_iterator i = serviceInfo.find(id);
+					if (i != serviceInfo.end()) {
+						MainEventLoop::postEvent(
+								boost::bind(boost::ref(onServiceResolved), id, i->second));
+					}
+				}
+			}
+
+		private:
+			typedef std::map<LinkLocalServiceID,DNSSDService::ResolveResult> ServiceInfoMap;
+			ServiceInfoMap serviceInfo;
+			std::vector<LinkLocalServiceID> resolvingServices;
+	};
+
+
+}
-- 
cgit v0.10.2-6-g49f6


From 1c1491cbbe9fca509ddc292dbeaedbba7b6a2b14 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Thu, 23 Jul 2009 08:54:10 +0200
Subject: Added more LinkLocalServiceBrowser tests.


diff --git a/Swiften/LinkLocal/LinkLocalService.h b/Swiften/LinkLocal/LinkLocalService.h
index 446feb8..6616303 100644
--- a/Swiften/LinkLocal/LinkLocalService.h
+++ b/Swiften/LinkLocal/LinkLocalService.h
@@ -2,49 +2,40 @@
 
 #include "Swiften/Base/String.h"
 #include "Swiften/Network/HostAddress.h"
+#include "Swiften/LinkLocal/LinkLocalServiceID.h"
 #include "Swiften/LinkLocal/LinkLocalServiceInfo.h"
 
 namespace Swift {
 	class LinkLocalService {
 		public:
-			LinkLocalService();
+			LinkLocalService(
+					const LinkLocalServiceID& id,
+					const DNSSDService::ResolveResult& info) :
+						id(id),
+						info(info) {}
 
-			const String& getName() const {
-				return name;
-			}
-
-			void setName(const String& n) {
-				name = n;
-			}
-
-			const String& getHostname() const {
-				return hostname;
+			const LinkLocalServiceID& getID() const {
+				return id;
 			}
 
-			void setHostname(const String& h) {
-				hostname = h;
+			const String& getName() const {
+				return id.getName();
 			}
 
-			const HostAddress& getAddress() const {
-				return address;
+			int getPort() const {
+				return info.port;
 			}
 
-			void setAddress(const HostAddress& a) {
-				address = a;
+			const String& getHostname() const {
+				return info.host;
 			}
 
 			const LinkLocalServiceInfo& getInfo() const {
-				return info;
-			}
-
-			void setInfo(const LinkLocalServiceInfo& i) {
-				info = i;
+				return info.info;
 			}
 
 		private:
-			String name;
-			String hostname;
-			LinkLocalServiceInfo info;
-			HostAddress address;
+			LinkLocalServiceID id;
+			DNSSDService::ResolveResult info;
 	};
 }
diff --git a/Swiften/LinkLocal/LinkLocalServiceBrowser.cpp b/Swiften/LinkLocal/LinkLocalServiceBrowser.cpp
index 63cf075..fbc3022 100644
--- a/Swiften/LinkLocal/LinkLocalServiceBrowser.cpp
+++ b/Swiften/LinkLocal/LinkLocalServiceBrowser.cpp
@@ -15,13 +15,22 @@ LinkLocalServiceBrowser::LinkLocalServiceBrowser(boost::shared_ptr<DNSSDService>
 			boost::bind(&LinkLocalServiceBrowser::handleServiceResolved, this, _1, _2));
 }
 
+std::vector<LinkLocalService> LinkLocalServiceBrowser::getServices() const {
+	std::vector<LinkLocalService> result;
+	for (ServiceMap::const_iterator i = services.begin(); i != services.end(); ++i) {
+		result.push_back(LinkLocalService(i->first, i->second));
+	}
+	return result;
+}
+
 void LinkLocalServiceBrowser::handleServiceAdded(const LinkLocalServiceID& service) {
 	dnsSDService->startResolvingService(service);
 }
 
 void LinkLocalServiceBrowser::handleServiceRemoved(const LinkLocalServiceID& service) {
-	/*dnsSDService->stopResolvingService(service);
-	services.erase(service);*/
+	dnsSDService->stopResolvingService(service);
+	services.erase(service);
+	onServiceRemoved(service);
 }
 
 void LinkLocalServiceBrowser::handleServiceResolved(const LinkLocalServiceID& service, const DNSSDService::ResolveResult& result) {
@@ -30,6 +39,7 @@ void LinkLocalServiceBrowser::handleServiceResolved(const LinkLocalServiceID& se
 		onServiceAdded(service);
 	}
 	else {
+		r.first->second = result;
 		onServiceChanged(service);
 	}
 }
diff --git a/Swiften/LinkLocal/LinkLocalServiceBrowser.h b/Swiften/LinkLocal/LinkLocalServiceBrowser.h
index c0788e6..6107557 100644
--- a/Swiften/LinkLocal/LinkLocalServiceBrowser.h
+++ b/Swiften/LinkLocal/LinkLocalServiceBrowser.h
@@ -16,8 +16,11 @@ namespace Swift {
 		public:
 			LinkLocalServiceBrowser(boost::shared_ptr<DNSSDService> service);
 
+			std::vector<LinkLocalService> getServices() const;
+
 			boost::signal<void (const LinkLocalServiceID&)> onServiceAdded;
 			boost::signal<void (const LinkLocalServiceID&)> onServiceChanged;
+			boost::signal<void (const LinkLocalServiceID&)> onServiceRemoved;
 
 		private:
 			void handleServiceAdded(const LinkLocalServiceID&);
diff --git a/Swiften/LinkLocal/UnitTest/LinkLocalServiceBrowserTest.cpp b/Swiften/LinkLocal/UnitTest/LinkLocalServiceBrowserTest.cpp
index 449a823..59a113d 100644
--- a/Swiften/LinkLocal/UnitTest/LinkLocalServiceBrowserTest.cpp
+++ b/Swiften/LinkLocal/UnitTest/LinkLocalServiceBrowserTest.cpp
@@ -18,6 +18,7 @@ class LinkLocalServiceBrowserTest : public CppUnit::TestFixture {
 		CPPUNIT_TEST(testServiceAdded);
 		CPPUNIT_TEST(testServiceAdded_NoServiceInfo);
 		CPPUNIT_TEST(testServiceChanged);
+		CPPUNIT_TEST(testServiceRemoved);
 		CPPUNIT_TEST_SUITE_END();
 
 	public:
@@ -32,6 +33,10 @@ class LinkLocalServiceBrowserTest : public CppUnit::TestFixture {
 		}
 
 		void tearDown() {
+			addedServices.clear();
+			removedServices.clear();
+			changedServices.clear();
+
 			delete testServiceInfo2;
 			delete testServiceInfo;
 			delete testServiceID;
@@ -47,7 +52,13 @@ class LinkLocalServiceBrowserTest : public CppUnit::TestFixture {
 
 			CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(addedServices.size()));
 			CPPUNIT_ASSERT(addedServices[0] == *testServiceID);
-			// TODO: Check getServices
+			CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(changedServices.size()));
+			CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(removedServices.size()));
+			std::vector<LinkLocalService> services = testling->getServices();
+			CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(services.size()));
+			CPPUNIT_ASSERT(*testServiceID == services[0].getID());
+			CPPUNIT_ASSERT(testServiceInfo->port == services[0].getPort());
+			CPPUNIT_ASSERT(testServiceInfo->host == services[0].getHostname());
 		}
 
 		void testServiceAdded_NoServiceInfo() {
@@ -57,6 +68,8 @@ class LinkLocalServiceBrowserTest : public CppUnit::TestFixture {
 			eventLoop->processEvents();
 
 			CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(addedServices.size()));
+			std::vector<LinkLocalService> services = testling->getServices();
+			CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(services.size()));
 		}
 
 		void testServiceChanged() {
@@ -67,7 +80,35 @@ class LinkLocalServiceBrowserTest : public CppUnit::TestFixture {
 
 			dnsSDService->setServiceInfo(*testServiceID,*testServiceInfo2);
 			eventLoop->processEvents();
-			// TODO: Check getServices
+
+			CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(addedServices.size()));
+			CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changedServices.size()));
+			CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(removedServices.size()));
+			CPPUNIT_ASSERT(changedServices[0] == *testServiceID);
+			std::vector<LinkLocalService> services = testling->getServices();
+			CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(services.size()));
+			CPPUNIT_ASSERT(*testServiceID == services[0].getID());
+			CPPUNIT_ASSERT(testServiceInfo2->port == services[0].getPort());
+			CPPUNIT_ASSERT(testServiceInfo2->host == services[0].getHostname());
+		}
+
+		void testServiceRemoved() {
+			boost::shared_ptr<LinkLocalServiceBrowser> testling = createTestling();
+			dnsSDService->setServiceInfo(*testServiceID,*testServiceInfo);
+			dnsSDService->addService(*testServiceID);
+			eventLoop->processEvents();
+
+			dnsSDService->removeService(*testServiceID);
+			eventLoop->processEvents();
+			dnsSDService->setServiceInfo(*testServiceID,*testServiceInfo2);
+			eventLoop->processEvents();
+
+			CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(addedServices.size()));
+			CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(changedServices.size()));
+			CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(removedServices.size()));
+			CPPUNIT_ASSERT(removedServices[0] == *testServiceID);
+			std::vector<LinkLocalService> services = testling->getServices();
+			CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(services.size()));
 		}
 
 	private:
@@ -76,6 +117,10 @@ class LinkLocalServiceBrowserTest : public CppUnit::TestFixture {
 					new LinkLocalServiceBrowser(dnsSDService));
 			testling->onServiceAdded.connect(boost::bind(
 					&LinkLocalServiceBrowserTest::handleServiceAdded, this, _1));
+			testling->onServiceChanged.connect(boost::bind(
+					&LinkLocalServiceBrowserTest::handleServiceChanged, this, _1));
+			testling->onServiceRemoved.connect(boost::bind(
+					&LinkLocalServiceBrowserTest::handleServiceRemoved, this, _1));
 			return testling;
 		}
 
@@ -83,10 +128,20 @@ class LinkLocalServiceBrowserTest : public CppUnit::TestFixture {
 			addedServices.push_back(service);
 		}
 
+		void handleServiceRemoved(const LinkLocalServiceID& service) {
+			removedServices.push_back(service);
+		}
+
+		void handleServiceChanged(const LinkLocalServiceID& service) {
+			changedServices.push_back(service);
+		}
+
 	private:
 		DummyEventLoop* eventLoop;
 		boost::shared_ptr<MockDNSSDService> dnsSDService;
 		std::vector<LinkLocalServiceID> addedServices;
+		std::vector<LinkLocalServiceID> changedServices;
+		std::vector<LinkLocalServiceID> removedServices;
 		LinkLocalServiceID* testServiceID;
 		DNSSDService::ResolveResult* testServiceInfo;
 		DNSSDService::ResolveResult* testServiceInfo2;
diff --git a/Swiften/LinkLocal/UnitTest/MockDNSSDService.h b/Swiften/LinkLocal/UnitTest/MockDNSSDService.h
index 5d857fb..56661ee 100644
--- a/Swiften/LinkLocal/UnitTest/MockDNSSDService.h
+++ b/Swiften/LinkLocal/UnitTest/MockDNSSDService.h
@@ -48,8 +48,16 @@ namespace Swift {
 				MainEventLoop::postEvent(boost::bind(boost::ref(onServiceAdded), id));
 			}
 
+			void removeService(const LinkLocalServiceID& id) {
+				serviceInfo.erase(id);
+				MainEventLoop::postEvent(boost::bind(boost::ref(onServiceRemoved), id));
+			}
+
 			void setServiceInfo(const LinkLocalServiceID& id, const DNSSDService::ResolveResult& info) {
-				serviceInfo.insert(std::make_pair(id, info));
+				std::pair<ServiceInfoMap::iterator, bool> r = serviceInfo.insert(std::make_pair(id, info));
+				if (!r.second) {
+					r.first->second = info;
+				}
 				broadcastServiceInfo(id);
 			}
 
-- 
cgit v0.10.2-6-g49f6


From 3a0309d2d897bf4f399610e52ad439c002e16f9c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Thu, 23 Jul 2009 21:03:11 +0200
Subject: Add DNS service factory.


diff --git a/Makefile.config.in b/Makefile.config.in
index 848f223..010075a 100644
--- a/Makefile.config.in
+++ b/Makefile.config.in
@@ -22,6 +22,7 @@ HAVE_EXPAT=@HAVE_EXPAT@
 USE_BUNDLED_EXPAT=@USE_BUNDLED_EXPAT@
 HAVE_LIBXML=@CONFIG_HAVE_LIBXML@
 HAVE_OPENSSL=@CONFIG_HAVE_OPENSSL@
+HAVE_BONJOUR=@HAVE_BONJOUR@
 HAVE_AVAHI=@HAVE_AVAHI@
 WIN32=@CONFIG_WIN32@
 MACOSX=@CONFIG_MACOSX@
diff --git a/Swiften/LinkLocal/AvahiDNSSDService.cpp b/Swiften/LinkLocal/AvahiDNSSDService.cpp
index 72039b7..fe9ac83 100644
--- a/Swiften/LinkLocal/AvahiDNSSDService.cpp
+++ b/Swiften/LinkLocal/AvahiDNSSDService.cpp
@@ -82,7 +82,7 @@ void AvahiDNSSDService::startResolvingService(const LinkLocalServiceID& service)
 	avahi_threaded_poll_unlock(threadedPoll);
 }
 
-void AvahiDNSSDService::stopResolvingService(const Service& service) {
+void AvahiDNSSDService::stopResolvingService(const LinkLocalServiceID& service) {
 	avahi_threaded_poll_lock(threadedPoll);
 
 	ServiceResolverMap::iterator i = serviceResolvers.find(service);
diff --git a/Swiften/LinkLocal/AvahiDNSSDService.h b/Swiften/LinkLocal/AvahiDNSSDService.h
index a5be943..99a1d23 100644
--- a/Swiften/LinkLocal/AvahiDNSSDService.h
+++ b/Swiften/LinkLocal/AvahiDNSSDService.h
@@ -47,7 +47,7 @@ namespace Swift {
 			AvahiClient* client;
 			AvahiThreadedPoll* threadedPoll;
 			AvahiServiceBrowser* serviceBrowser;
-			typedef std::map<Service, AvahiServiceResolver*> ServiceResolverMap;
+			typedef std::map<LinkLocalServiceID, AvahiServiceResolver*> ServiceResolverMap;
 			ServiceResolverMap serviceResolvers;
 			typedef std::map<String, HostAddress> HostnameAddressMap;
 			HostnameAddressMap hostnameAddresses;
diff --git a/Swiften/LinkLocal/DNSSDServiceFactory.cpp b/Swiften/LinkLocal/DNSSDServiceFactory.cpp
new file mode 100644
index 0000000..f53660a
--- /dev/null
+++ b/Swiften/LinkLocal/DNSSDServiceFactory.cpp
@@ -0,0 +1,8 @@
+#include "Swiften/LinkLocal/DNSSDServiceFactory.h"
+
+namespace Swift {
+
+DNSSDServiceFactory::~DNSSDServiceFactory() {
+}
+
+}
diff --git a/Swiften/LinkLocal/DNSSDServiceFactory.h b/Swiften/LinkLocal/DNSSDServiceFactory.h
new file mode 100644
index 0000000..6296165
--- /dev/null
+++ b/Swiften/LinkLocal/DNSSDServiceFactory.h
@@ -0,0 +1,15 @@
+#pragma once
+
+#include <boost/shared_ptr.hpp>
+
+namespace Swift {
+	class DNSSDService;
+
+	class DNSSDServiceFactory {
+		public:
+			virtual ~DNSSDServiceFactory();
+			virtual bool canCreate() const = 0;
+
+			virtual boost::shared_ptr<DNSSDService> createDNSSDService() = 0;
+	};
+}
diff --git a/Swiften/LinkLocal/LinkLocalServiceBrowser.cpp b/Swiften/LinkLocal/LinkLocalServiceBrowser.cpp
index fbc3022..904f8f0 100644
--- a/Swiften/LinkLocal/LinkLocalServiceBrowser.cpp
+++ b/Swiften/LinkLocal/LinkLocalServiceBrowser.cpp
@@ -6,7 +6,8 @@
 
 namespace Swift {
 
-LinkLocalServiceBrowser::LinkLocalServiceBrowser(boost::shared_ptr<DNSSDService> service) : dnsSDService(service) {
+LinkLocalServiceBrowser::LinkLocalServiceBrowser(DNSSDServiceFactory* factory) {
+  dnsSDService = factory->createDNSSDService();
 	dnsSDService->onServiceAdded.connect(
 			boost::bind(&LinkLocalServiceBrowser::handleServiceAdded, this, _1));
 	dnsSDService->onServiceRemoved.connect(
diff --git a/Swiften/LinkLocal/LinkLocalServiceBrowser.h b/Swiften/LinkLocal/LinkLocalServiceBrowser.h
index 6107557..879b286 100644
--- a/Swiften/LinkLocal/LinkLocalServiceBrowser.h
+++ b/Swiften/LinkLocal/LinkLocalServiceBrowser.h
@@ -7,6 +7,7 @@
 
 #include "Swiften/Base/String.h"
 #include "Swiften/LinkLocal/DNSSDService.h"
+#include "Swiften/LinkLocal/DNSSDServiceFactory.h"
 #include "Swiften/LinkLocal/LinkLocalService.h"
 
 namespace Swift {
@@ -14,7 +15,7 @@ namespace Swift {
 
 	class LinkLocalServiceBrowser {
 		public:
-			LinkLocalServiceBrowser(boost::shared_ptr<DNSSDService> service);
+			LinkLocalServiceBrowser(DNSSDServiceFactory*);
 
 			std::vector<LinkLocalService> getServices() const;
 
diff --git a/Swiften/LinkLocal/Makefile.inc b/Swiften/LinkLocal/Makefile.inc
index a890d0a..4bd1b0e 100644
--- a/Swiften/LinkLocal/Makefile.inc
+++ b/Swiften/LinkLocal/Makefile.inc
@@ -1,4 +1,6 @@
 SWIFTEN_SOURCES += \
+	Swiften/LinkLocal/DNSSDServiceFactory.cpp \
+	Swiften/LinkLocal/PlatformDNSSDServiceFactory.cpp \
 	Swiften/LinkLocal/DNSSDService.cpp \
 	Swiften/LinkLocal/LinkLocalRoster.cpp \
 	Swiften/LinkLocal/LinkLocalServiceID.cpp \
@@ -8,7 +10,7 @@ SWIFTEN_SOURCES += \
 	Swiften/LinkLocal/OutgoingLinkLocalSession.cpp \
 	Swiften/LinkLocal/LinkLocalConnector.cpp
 
-ifeq ($(MACOSX),1)
+ifeq ($(HAVE_BONJOUR),yes)
 SWIFTEN_SOURCES += \
 	Swiften/LinkLocal/AppleDNSSDService.cpp
 endif
diff --git a/Swiften/LinkLocal/PlatformDNSSDServiceFactory.cpp b/Swiften/LinkLocal/PlatformDNSSDServiceFactory.cpp
new file mode 100644
index 0000000..df70506
--- /dev/null
+++ b/Swiften/LinkLocal/PlatformDNSSDServiceFactory.cpp
@@ -0,0 +1,38 @@
+#include "Swiften/LinkLocal/PlatformDNSSDServiceFactory.h"
+
+#include <cassert>
+
+#ifdef HAVE_SWIFTEN_CONFIG_H
+#include "Swiften/config.h"
+#endif
+#if defined(HAVE_AVAHI)
+#include "Swiften/LinkLocal/AvahiDNSSDService.h"
+#elif defined(HAVE_BONJOUR)
+#include "Swiften/LinkLocal/AppleDNSSDService.h"
+#endif
+
+namespace Swift {
+
+PlatformDNSSDServiceFactory::PlatformDNSSDServiceFactory() {
+}
+
+bool PlatformDNSSDServiceFactory::canCreate() const {
+#if defined(HAVE_AVAHI) || defined(HAVE_BONJOUR)
+	return true;
+#else
+	return false;
+#endif
+}
+
+boost::shared_ptr<DNSSDService> PlatformDNSSDServiceFactory::createDNSSDService() {
+#if defined(HAVE_AVAHI)
+	return boost::shared_ptr<DNSSDService>(new AvahiDNSSDService());
+#elif defined(HAVE_BONJOUR)
+  return boost::shared_ptr<DNSSDService>(new AppleDNSSDService());
+#else
+	assert(false);
+	return boost::shared_ptr<DNSSDService>();
+#endif
+}
+
+}
diff --git a/Swiften/LinkLocal/PlatformDNSSDServiceFactory.h b/Swiften/LinkLocal/PlatformDNSSDServiceFactory.h
new file mode 100644
index 0000000..9c4e4e6
--- /dev/null
+++ b/Swiften/LinkLocal/PlatformDNSSDServiceFactory.h
@@ -0,0 +1,13 @@
+#pragma once
+
+#include "Swiften/LinkLocal/DNSSDServiceFactory.h"
+
+namespace Swift {
+	class PlatformDNSSDServiceFactory : public DNSSDServiceFactory {
+		public:
+			PlatformDNSSDServiceFactory();
+
+			bool canCreate() const;
+			virtual boost::shared_ptr<DNSSDService> createDNSSDService();
+	};
+}
diff --git a/Swiften/LinkLocal/UnitTest/LinkLocalServiceBrowserTest.cpp b/Swiften/LinkLocal/UnitTest/LinkLocalServiceBrowserTest.cpp
index 59a113d..34f797c 100644
--- a/Swiften/LinkLocal/UnitTest/LinkLocalServiceBrowserTest.cpp
+++ b/Swiften/LinkLocal/UnitTest/LinkLocalServiceBrowserTest.cpp
@@ -9,7 +9,7 @@
 #include "Swiften/LinkLocal/DNSSDService.h"
 #include "Swiften/EventLoop/DummyEventLoop.h"
 
-// Test IP address change
+// Test canCreate() == false
 
 using namespace Swift;
 
@@ -26,7 +26,7 @@ class LinkLocalServiceBrowserTest : public CppUnit::TestFixture {
 
 		void setUp() {
 			eventLoop = new DummyEventLoop();
-			dnsSDService = boost::shared_ptr<MockDNSSDService>(new MockDNSSDService());
+			dnsSDServiceFactory = new MockDNSSDServiceFactory();
 			testServiceID = new LinkLocalServiceID("foo", "bar.local");
 			testServiceInfo = new DNSSDService::ResolveResult("xmpp.bar.local", 1234, LinkLocalServiceInfo());
 			testServiceInfo2 = new DNSSDService::ResolveResult("xmpp.foo.local", 2345, LinkLocalServiceInfo());
@@ -40,14 +40,15 @@ class LinkLocalServiceBrowserTest : public CppUnit::TestFixture {
 			delete testServiceInfo2;
 			delete testServiceInfo;
 			delete testServiceID;
+      delete dnsSDServiceFactory;
 			delete eventLoop;
 		}
 
 		void testServiceAdded() {
 			boost::shared_ptr<LinkLocalServiceBrowser> testling = createTestling();
 
-			dnsSDService->setServiceInfo(*testServiceID,*testServiceInfo);
-			dnsSDService->addService(*testServiceID);
+			dnsSDService()->setServiceInfo(*testServiceID,*testServiceInfo);
+			dnsSDService()->addService(*testServiceID);
 			eventLoop->processEvents();
 
 			CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(addedServices.size()));
@@ -64,7 +65,7 @@ class LinkLocalServiceBrowserTest : public CppUnit::TestFixture {
 		void testServiceAdded_NoServiceInfo() {
 			boost::shared_ptr<LinkLocalServiceBrowser> testling = createTestling();
 
-			dnsSDService->addService(*testServiceID);
+			dnsSDService()->addService(*testServiceID);
 			eventLoop->processEvents();
 
 			CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(addedServices.size()));
@@ -74,11 +75,11 @@ class LinkLocalServiceBrowserTest : public CppUnit::TestFixture {
 
 		void testServiceChanged() {
 			boost::shared_ptr<LinkLocalServiceBrowser> testling = createTestling();
-			dnsSDService->setServiceInfo(*testServiceID,*testServiceInfo);
-			dnsSDService->addService(*testServiceID);
+			dnsSDService()->setServiceInfo(*testServiceID,*testServiceInfo);
+			dnsSDService()->addService(*testServiceID);
 			eventLoop->processEvents();
 
-			dnsSDService->setServiceInfo(*testServiceID,*testServiceInfo2);
+			dnsSDService()->setServiceInfo(*testServiceID,*testServiceInfo2);
 			eventLoop->processEvents();
 
 			CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(addedServices.size()));
@@ -94,13 +95,13 @@ class LinkLocalServiceBrowserTest : public CppUnit::TestFixture {
 
 		void testServiceRemoved() {
 			boost::shared_ptr<LinkLocalServiceBrowser> testling = createTestling();
-			dnsSDService->setServiceInfo(*testServiceID,*testServiceInfo);
-			dnsSDService->addService(*testServiceID);
+			dnsSDService()->setServiceInfo(*testServiceID,*testServiceInfo);
+			dnsSDService()->addService(*testServiceID);
 			eventLoop->processEvents();
 
-			dnsSDService->removeService(*testServiceID);
+			dnsSDService()->removeService(*testServiceID);
 			eventLoop->processEvents();
-			dnsSDService->setServiceInfo(*testServiceID,*testServiceInfo2);
+			dnsSDService()->setServiceInfo(*testServiceID,*testServiceInfo2);
 			eventLoop->processEvents();
 
 			CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(addedServices.size()));
@@ -114,7 +115,7 @@ class LinkLocalServiceBrowserTest : public CppUnit::TestFixture {
 	private:
 		boost::shared_ptr<LinkLocalServiceBrowser> createTestling() {
 			boost::shared_ptr<LinkLocalServiceBrowser> testling(
-					new LinkLocalServiceBrowser(dnsSDService));
+					new LinkLocalServiceBrowser(dnsSDServiceFactory));
 			testling->onServiceAdded.connect(boost::bind(
 					&LinkLocalServiceBrowserTest::handleServiceAdded, this, _1));
 			testling->onServiceChanged.connect(boost::bind(
@@ -136,9 +137,14 @@ class LinkLocalServiceBrowserTest : public CppUnit::TestFixture {
 			changedServices.push_back(service);
 		}
 
+    boost::shared_ptr<MockDNSSDService> dnsSDService() const {
+      CPPUNIT_ASSERT(dnsSDServiceFactory->services.size() > 0);
+      return dnsSDServiceFactory->services[0];
+    }
+
 	private:
 		DummyEventLoop* eventLoop;
-		boost::shared_ptr<MockDNSSDService> dnsSDService;
+		MockDNSSDServiceFactory* dnsSDServiceFactory;
 		std::vector<LinkLocalServiceID> addedServices;
 		std::vector<LinkLocalServiceID> changedServices;
 		std::vector<LinkLocalServiceID> removedServices;
diff --git a/Swiften/LinkLocal/UnitTest/MockDNSSDService.h b/Swiften/LinkLocal/UnitTest/MockDNSSDService.h
index 56661ee..69ac06d 100644
--- a/Swiften/LinkLocal/UnitTest/MockDNSSDService.h
+++ b/Swiften/LinkLocal/UnitTest/MockDNSSDService.h
@@ -6,6 +6,7 @@
 
 #include "Swiften/EventLoop/MainEventLoop.h"
 #include "Swiften/LinkLocal/DNSSDService.h"
+#include "Swiften/LinkLocal/DNSSDServiceFactory.h"
 
 namespace Swift {
 	class MockDNSSDService : public DNSSDService {
@@ -78,5 +79,19 @@ namespace Swift {
 			std::vector<LinkLocalServiceID> resolvingServices;
 	};
 
+  class MockDNSSDServiceFactory : public DNSSDServiceFactory {
+    public:
+      boost::shared_ptr<DNSSDService> createDNSSDService() {
+        boost::shared_ptr<MockDNSSDService> result(new MockDNSSDService());   
+        services.push_back(result);
+        return result;
+      }
+
+      bool canCreate() const {
+        return true;
+      }
+
+      std::vector<boost::shared_ptr<MockDNSSDService> > services;
+  };
 
 }
diff --git a/configure.in b/configure.in
index 9025855..3a10e2c 100644
--- a/configure.in
+++ b/configure.in
@@ -13,6 +13,7 @@ AC_CANONICAL_HOST
 AH_TEMPLATE(HAVE_OPENSSL, [OpenSSL library available])
 AH_TEMPLATE(HAVE_LIBXML, [LibXML library available])
 AH_TEMPLATE(HAVE_EXPAT, [Expat library available])
+AH_TEMPLATE(HAVE_BONJOUR, [Apple Bonjour SDK available])
 AH_TEMPLATE(HAVE_AVAHI, [Avahi library available])
 
 ################################################################################
@@ -194,11 +195,13 @@ fi
 # Resolv
 AC_CHECK_LIB(resolv, inet_aton)
 
-# Avahi
+# DNSSD Service
 case $host in
 	*-*-cygwin*)
+    AC_DEFINE(HAVE_BONJOUR)
 		;;
 	*-mingw32*)
+    AC_DEFINE(HAVE_BONJOUR)
 		;;
 	*-*-darwin*)
 		;;
@@ -239,6 +242,7 @@ echo
 AC_SUBST(SET_MAKE)
 AC_SUBST(HAVE_EXPAT)
 AC_SUBST(HAVE_AVAHI)
+AC_SUBST(HAVE_BONJOUR)
 AC_SUBST(CONFIG_CXX)
 AC_SUBST(CONFIG_CXXFLAGS)
 AC_SUBST(CONFIG_CC)
-- 
cgit v0.10.2-6-g49f6


From 714e831bb9ea2b14cba3c2696c12e2e13b1bb9d7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Thu, 23 Jul 2009 21:04:08 +0200
Subject: Add beginning of new DNS-SD query framework.


diff --git a/Slimber/Server.cpp b/Slimber/Server.cpp
index ba55403..c3c3d22 100644
--- a/Slimber/Server.cpp
+++ b/Slimber/Server.cpp
@@ -69,9 +69,9 @@ void Server::handleNewLinkLocalConnection(boost::shared_ptr<Connection> connecti
 	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::handleServiceRegistered(const LinkLocalServiceID& service) {
+	std::cout << "Service registered " << service.getName() << " " << service.getType() << " " << service.getDomain() << std::endl;
+	selfJID_ = JID(service.getName());
 }
 
 void Server::handleSessionStarted() {
diff --git a/Slimber/Server.h b/Slimber/Server.h
index ac80509..b40f576 100644
--- a/Slimber/Server.h
+++ b/Slimber/Server.h
@@ -33,7 +33,7 @@ namespace Swift {
 		private:
 			void handleNewClientConnection(boost::shared_ptr<Connection> c);
 			void handleNewLinkLocalConnection(boost::shared_ptr<Connection> connection);
-			void handleServiceRegistered(const DNSSDService::Service& service);
+			void handleServiceRegistered(const LinkLocalServiceID& service);
 			void handleSessionStarted();
 			void handleSessionFinished(boost::shared_ptr<ServerFromClientSession>);
 			void handleLinkLocalSessionFinished(boost::shared_ptr<Session> session);
diff --git a/Swiften/LinkLocal/BonjourBrowseQuery.h b/Swiften/LinkLocal/BonjourBrowseQuery.h
new file mode 100644
index 0000000..5b14d30
--- /dev/null
+++ b/Swiften/LinkLocal/BonjourBrowseQuery.h
@@ -0,0 +1,55 @@
+#pragma once
+
+#include "Swiften/LinkLocal/BonjourQuery.h"
+#include "Swiften/LinkLocal/DNSSDBrowseQuery.h"
+
+namespace Swift {
+	class BonjourQuerier;
+
+	class BonjourBrowseQuery : public DNSSDBrowseQuery, public BonjourQuery {
+		public:	
+			BonjourBrowseQuery(boost::shared_ptr<BonjourQuerier> q) : BonjourQuery(q) {
+				DNSServiceErrorType result = DNSServiceBrowse(
+						&sdRef, 0, 0, "_presence._tcp", 0, 
+						&BonjourBrowseQuery::handleServiceDiscoveredGlobal , this);
+				if (result != kDNSServiceErr_NoError) {
+					// TODO
+				}
+			}
+
+			void startBrowsing() {
+				assert(sdRef);
+				run();
+			}
+
+			void stopBrowsing() {
+				finish();
+			}
+
+		private:
+			static void handleServiceDiscoveredGlobal(DNSServiceRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *serviceName, const char *regtype, const char *replyDomain, void *context) {
+				static_cast<BonjourBrowseQuery*>(context)->handleServiceDiscovered(flags, interfaceIndex, errorCode, serviceName, regtype, replyDomain);
+			}
+
+			void handleServiceDiscovered(
+					DNSServiceFlags flags, 
+					uint32_t interfaceIndex, 
+					DNSServiceErrorType errorCode, 
+					const char *serviceName, 
+					const char *type, 
+					const char *domain) {
+				if (errorCode != kDNSServiceErr_NoError) {
+					return;
+				}
+				else {
+					LinkLocalServiceID service(serviceName, type, domain, interfaceIndex);
+					if (flags & kDNSServiceFlagsAdd) {
+						onServiceAdded(service);
+					}
+					else {
+						onServiceRemoved(service);
+					}
+				}
+		}
+	};
+}
diff --git a/Swiften/LinkLocal/BonjourQuerier.cpp b/Swiften/LinkLocal/BonjourQuerier.cpp
new file mode 100644
index 0000000..1ddbd9d
--- /dev/null
+++ b/Swiften/LinkLocal/BonjourQuerier.cpp
@@ -0,0 +1,115 @@
+#include "Swiften/LinkLocal/BonjourQuerier.h"
+
+#include <unistd.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <fcntl.h>
+
+#include "Swiften/EventLoop/MainEventLoop.h"
+#include "Swiften/LinkLocal/BonjourBrowseQuery.h"
+#include "Swiften/Base/foreach.h"
+
+namespace Swift {
+
+BonjourQuerier::BonjourQuerier() : stopRequested(false), thread(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];
+	// TODO: Schedule thread
+}
+
+BonjourQuerier::~BonjourQuerier() {
+	stop();
+}
+
+boost::shared_ptr<DNSSDBrowseQuery> BonjourQuerier::createBrowseQuery() {
+	return boost::shared_ptr<DNSSDBrowseQuery>(new BonjourBrowseQuery(shared_from_this()));
+}
+
+void BonjourQuerier::addRunningQuery(boost::shared_ptr<BonjourQuery> query) {
+	{
+		boost::lock_guard<boost::mutex> lock(runningQueriesMutex);
+		runningQueries.push_back(query);
+	}
+	runningQueriesAvailableEvent.notify_one();
+	interruptSelect();
+}
+
+void BonjourQuerier::removeRunningQuery(boost::shared_ptr<BonjourQuery> query) {
+	{
+		boost::lock_guard<boost::mutex> lock(runningQueriesMutex);
+		runningQueries.erase(std::remove(
+			runningQueries.begin(), runningQueries.end(), query), runningQueries.end());
+	}
+}
+
+void BonjourQuerier::interruptSelect() {
+	char c = 0;
+	write(interruptSelectWriteSocket, &c, 1);
+}
+
+void BonjourQuerier::start() {
+	stop();
+	thread = new boost::thread(boost::bind(&BonjourQuerier::run, shared_from_this()));
+}
+
+void BonjourQuerier::stop() {
+	if (thread) {
+		stopRequested = true;
+		runningQueries.clear(); // TODO: Is this the right thing to do?
+		runningQueriesAvailableEvent.notify_one();
+		interruptSelect();
+		thread->join();
+		delete thread;
+		stopRequested = false;
+	}
+}
+
+void BonjourQuerier::run() {
+	while (!stopRequested) {
+		fd_set fdSet;
+		int maxSocket;
+		{
+			boost::unique_lock<boost::mutex> lock(runningQueriesMutex);
+			runningQueriesAvailableEvent.wait(lock);
+			if (runningQueries.empty()) {
+				continue;
+			}
+
+			// Run all running queries
+			FD_ZERO(&fdSet);
+			int maxSocket = interruptSelectReadSocket;
+			FD_SET(interruptSelectReadSocket, &fdSet);
+
+			foreach(const boost::shared_ptr<BonjourQuery>& query, runningQueries) {
+				int socketID = query->getSocketID();
+				maxSocket = std::max(maxSocket, socketID);
+				FD_SET(socketID, &fdSet);
+			}
+		}
+
+		if (select(maxSocket+1, &fdSet, NULL, NULL, 0) <= 0) {
+			continue;
+		}
+
+		if (FD_ISSET(interruptSelectReadSocket, &fdSet)) {
+			char dummy;
+			while (read(interruptSelectReadSocket, &dummy, 1) > 0) {}
+		}
+
+		{
+			boost::lock_guard<boost::mutex> lock(runningQueriesMutex);
+			foreach(const boost::shared_ptr<BonjourQuery>& query, runningQueries) {
+				if (FD_ISSET(query->getSocketID(), &fdSet)) {
+					MainEventLoop::postEvent(
+							boost::bind(&BonjourQuery::processResult, query), shared_from_this());
+				}
+			}
+		}
+	}
+}
+
+}
diff --git a/Swiften/LinkLocal/BonjourQuerier.h b/Swiften/LinkLocal/BonjourQuerier.h
new file mode 100644
index 0000000..037d9e6
--- /dev/null
+++ b/Swiften/LinkLocal/BonjourQuerier.h
@@ -0,0 +1,45 @@
+#pragma once
+
+#include <boost/shared_ptr.hpp>
+#include <boost/enable_shared_from_this.hpp>
+#include <list>
+#include <boost/thread.hpp>
+#include <boost/thread/mutex.hpp>
+
+#include "Swiften/EventLoop/EventOwner.h"
+#include "Swiften/LinkLocal/DNSSDBrowseQuery.h"
+#include "Swiften/LinkLocal/BonjourQuery.h"
+
+namespace Swift {
+	class BonjourQuerier : 
+			public boost::enable_shared_from_this<BonjourQuerier>, 
+			public EventOwner {
+		public:
+			BonjourQuerier();
+			~BonjourQuerier();
+
+			boost::shared_ptr<DNSSDBrowseQuery> createBrowseQuery();
+
+			void start();
+			void stop();
+
+		private:
+			friend class BonjourQuery;
+
+			void addRunningQuery(boost::shared_ptr<BonjourQuery>);
+			void removeRunningQuery(boost::shared_ptr<BonjourQuery>);
+		
+		private:
+			void interruptSelect();
+			void run();
+
+		private:
+			bool stopRequested;
+			boost::thread* thread;
+			boost::mutex runningQueriesMutex;
+			std::list< boost::shared_ptr<BonjourQuery> > runningQueries;
+			int interruptSelectReadSocket;
+			int interruptSelectWriteSocket;
+			boost::condition_variable runningQueriesAvailableEvent;
+	};
+}
diff --git a/Swiften/LinkLocal/BonjourQuery.cpp b/Swiften/LinkLocal/BonjourQuery.cpp
new file mode 100644
index 0000000..a9c13fb
--- /dev/null
+++ b/Swiften/LinkLocal/BonjourQuery.cpp
@@ -0,0 +1,31 @@
+#include "Swiften/LinkLocal/BonjourQuery.h"
+#include "Swiften/LinkLocal/BonjourQuerier.h"
+
+namespace Swift {
+
+BonjourQuery::BonjourQuery(boost::shared_ptr<BonjourQuerier> q) : querier(q), sdRef(0) {
+}
+
+BonjourQuery::~BonjourQuery() {
+	DNSServiceRefDeallocate(sdRef);
+}
+
+void BonjourQuery::processResult() {
+	boost::lock_guard<boost::mutex> lock(sdRefMutex);
+	DNSServiceProcessResult(sdRef);
+}
+
+int BonjourQuery::getSocketID() const {
+	boost::lock_guard<boost::mutex> lock(sdRefMutex);
+	return DNSServiceRefSockFD(sdRef);
+}
+
+void BonjourQuery::run() {
+	querier->addRunningQuery(shared_from_this());
+}
+
+void BonjourQuery::finish() {
+	querier->removeRunningQuery(shared_from_this());
+}
+
+}
diff --git a/Swiften/LinkLocal/BonjourQuery.h b/Swiften/LinkLocal/BonjourQuery.h
new file mode 100644
index 0000000..2a47f73
--- /dev/null
+++ b/Swiften/LinkLocal/BonjourQuery.h
@@ -0,0 +1,28 @@
+#pragma once
+
+#include <dns_sd.h>
+#include <boost/shared_ptr.hpp>
+#include <boost/enable_shared_from_this.hpp>
+#include <boost/thread/mutex.hpp>
+
+namespace Swift {
+	class BonjourQuerier;
+
+	class BonjourQuery : public boost::enable_shared_from_this<BonjourQuery> {
+		public:
+			BonjourQuery(boost::shared_ptr<BonjourQuerier>);
+			virtual ~BonjourQuery();
+			
+			void processResult();
+			int getSocketID() const;
+
+		protected:
+			void run();
+			void finish();
+		
+		protected:
+			boost::shared_ptr<BonjourQuerier> querier;
+			mutable boost::mutex sdRefMutex;
+			DNSServiceRef sdRef;
+	};
+}
diff --git a/Swiften/LinkLocal/DNSSDBrowseQuery.cpp b/Swiften/LinkLocal/DNSSDBrowseQuery.cpp
new file mode 100644
index 0000000..4924247
--- /dev/null
+++ b/Swiften/LinkLocal/DNSSDBrowseQuery.cpp
@@ -0,0 +1,8 @@
+#include "Swiften/LinkLocal/DNSSDBrowseQuery.h"
+
+namespace Swift {
+
+DNSSDBrowseQuery::~DNSSDBrowseQuery() {
+}
+
+}
diff --git a/Swiften/LinkLocal/DNSSDBrowseQuery.h b/Swiften/LinkLocal/DNSSDBrowseQuery.h
new file mode 100644
index 0000000..b46d968
--- /dev/null
+++ b/Swiften/LinkLocal/DNSSDBrowseQuery.h
@@ -0,0 +1,15 @@
+#pragma once
+
+#include <boost/signal.hpp>
+
+#include "Swiften/LinkLocal/LinkLocalServiceID.h"
+
+namespace Swift {
+	class DNSSDBrowseQuery {
+		public:
+			virtual ~DNSSDBrowseQuery();
+
+			boost::signal<void (const LinkLocalServiceID&)> onServiceAdded;
+			boost::signal<void (const LinkLocalServiceID&)> onServiceRemoved;
+	};
+}
diff --git a/Swiften/LinkLocal/Makefile.inc b/Swiften/LinkLocal/Makefile.inc
index 4bd1b0e..b43a7e4 100644
--- a/Swiften/LinkLocal/Makefile.inc
+++ b/Swiften/LinkLocal/Makefile.inc
@@ -1,5 +1,8 @@
 SWIFTEN_SOURCES += \
+	Swiften/LinkLocal/BonjourQuery.cpp \
+	Swiften/LinkLocal/DNSSDBrowseQuery.cpp \
 	Swiften/LinkLocal/DNSSDServiceFactory.cpp \
+	Swiften/LinkLocal/BonjourQuerier.cpp \
 	Swiften/LinkLocal/PlatformDNSSDServiceFactory.cpp \
 	Swiften/LinkLocal/DNSSDService.cpp \
 	Swiften/LinkLocal/LinkLocalRoster.cpp \
-- 
cgit v0.10.2-6-g49f6


From 42e410208ca9aa8af5f27c85a6b33af488a0b6cc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Fri, 24 Jul 2009 08:30:33 +0200
Subject: More DNSSD framework.


diff --git a/Slimber/CLI/main.cpp b/Slimber/CLI/main.cpp
index 40f41c8..65af3bc 100644
--- a/Slimber/CLI/main.cpp
+++ b/Slimber/CLI/main.cpp
@@ -10,6 +10,7 @@
 #include "Slimber/Server.h"
 #include "Slimber/FileVCardCollection.h"
 #include "Swiften/LinkLocal/LinkLocalRoster.h"
+#include "Swiften/LinkLocal/BonjourQuerier.h"
 #include "Swiften/EventLoop/SimpleEventLoop.h"
 #include "Swiften/Application/Platform/PlatformApplication.h"
 
@@ -17,7 +18,14 @@ using namespace Swift;
 
 int main() {
 	SimpleEventLoop eventLoop;
+	boost::shared_ptr<BonjourQuerier> querier(new BonjourQuerier());
+	querier->start();
+	boost::shared_ptr<DNSSDBrowseQuery> query = querier->createBrowseQuery();
+	query->startBrowsing();
+	boost::shared_ptr<DNSSDPublishQuery> query2 = querier->createPublishQuery("remko", 1234, LinkLocalServiceInfo());
+	query2->publish();
 
+/*
 	boost::shared_ptr<DNSSDService> dnsSDService;
 #if defined(SWIFTEN_PLATFORM_MACOSX) || defined(SWIFTEN_PLATFORM_WINDOWS)
 	dnsSDService = boost::shared_ptr<AppleDNSSDService>(
@@ -32,6 +40,8 @@ int main() {
 	FileVCardCollection vCardCollection(PlatformApplication("Slimber").getSettingsDir());
 
 	Server server(5222, 5562, linkLocalRoster, dnsSDService, &vCardCollection);
+	*/
+	
 	eventLoop.run();
 	return 0;
 }
diff --git a/Swiften/LinkLocal/BonjourBrowseQuery.h b/Swiften/LinkLocal/BonjourBrowseQuery.h
index 5b14d30..6a50a61 100644
--- a/Swiften/LinkLocal/BonjourBrowseQuery.h
+++ b/Swiften/LinkLocal/BonjourBrowseQuery.h
@@ -11,8 +11,9 @@ namespace Swift {
 			BonjourBrowseQuery(boost::shared_ptr<BonjourQuerier> q) : BonjourQuery(q) {
 				DNSServiceErrorType result = DNSServiceBrowse(
 						&sdRef, 0, 0, "_presence._tcp", 0, 
-						&BonjourBrowseQuery::handleServiceDiscoveredGlobal , this);
+						&BonjourBrowseQuery::handleServiceDiscovered, this);
 				if (result != kDNSServiceErr_NoError) {
+					std::cout << "Error" << std::endl;
 					// TODO
 				}
 			}
@@ -27,29 +28,21 @@ namespace Swift {
 			}
 
 		private:
-			static void handleServiceDiscoveredGlobal(DNSServiceRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *serviceName, const char *regtype, const char *replyDomain, void *context) {
-				static_cast<BonjourBrowseQuery*>(context)->handleServiceDiscovered(flags, interfaceIndex, errorCode, serviceName, regtype, replyDomain);
-			}
-
-			void handleServiceDiscovered(
-					DNSServiceFlags flags, 
-					uint32_t interfaceIndex, 
-					DNSServiceErrorType errorCode, 
-					const char *serviceName, 
-					const char *type, 
-					const char *domain) {
+			static void handleServiceDiscovered(DNSServiceRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *name, const char *type, const char *domain, void *context) {
 				if (errorCode != kDNSServiceErr_NoError) {
 					return;
 				}
 				else {
-					LinkLocalServiceID service(serviceName, type, domain, interfaceIndex);
+					BonjourBrowseQuery* query = static_cast<BonjourBrowseQuery*>(context);
+					LinkLocalServiceID service(name, type, domain, interfaceIndex);
+					std::cout << "Service discovered: " << name << std::endl;
 					if (flags & kDNSServiceFlagsAdd) {
-						onServiceAdded(service);
+						query->onServiceAdded(service);
 					}
 					else {
-						onServiceRemoved(service);
+						query->onServiceRemoved(service);
 					}
 				}
-		}
+			}
 	};
 }
diff --git a/Swiften/LinkLocal/BonjourPublishQuery.h b/Swiften/LinkLocal/BonjourPublishQuery.h
new file mode 100644
index 0000000..4e7fd2f
--- /dev/null
+++ b/Swiften/LinkLocal/BonjourPublishQuery.h
@@ -0,0 +1,41 @@
+#pragma once
+
+#include "Swiften/LinkLocal/BonjourQuery.h"
+#include "Swiften/LinkLocal/DNSSDPublishQuery.h"
+#include "Swiften/LinkLocal/LinkLocalServiceInfo.h"
+#include "Swiften/Base/ByteArray.h"
+
+namespace Swift {
+	class BonjourQuerier;
+
+	class BonjourPublishQuery : public DNSSDPublishQuery, public BonjourQuery {
+		public:	
+			BonjourPublishQuery(const String& name, int port, const LinkLocalServiceInfo& info, boost::shared_ptr<BonjourQuerier> querier) : BonjourQuery(querier) {
+				ByteArray txtRecord = info.toTXTRecord();
+				DNSServiceErrorType result = DNSServiceRegister(
+						&sdRef, 0, 0, name.getUTF8Data(), "_presence._tcp", NULL, NULL, port, 
+						txtRecord.getSize(), txtRecord.getData(), 
+						&BonjourPublishQuery::handleServiceRegistered, this);
+				if (result != kDNSServiceErr_NoError) {
+					// TODO
+					std::cerr << "Error creating service registration" << std::endl;
+				}
+			}
+
+			void publish() {
+				run();
+			}
+
+		private:
+			static void handleServiceRegistered(DNSServiceRef, DNSServiceFlags, DNSServiceErrorType errorCode, const char *name, const char *regtype, const char *domain, void *context) {
+				std::cout << "Publish finished " << name << std::endl;
+				BonjourPublishQuery* query = static_cast<BonjourPublishQuery*>(context);
+				if (errorCode != kDNSServiceErr_NoError) {
+					query->onPublishFinished(boost::optional<LinkLocalServiceID>());
+				}
+				else {
+					query->onPublishFinished(boost::optional<LinkLocalServiceID>(LinkLocalServiceID(name, regtype, domain, 0)));
+				}
+			}
+	};
+}
diff --git a/Swiften/LinkLocal/BonjourQuerier.cpp b/Swiften/LinkLocal/BonjourQuerier.cpp
index 1ddbd9d..93259c1 100644
--- a/Swiften/LinkLocal/BonjourQuerier.cpp
+++ b/Swiften/LinkLocal/BonjourQuerier.cpp
@@ -7,6 +7,7 @@
 
 #include "Swiften/EventLoop/MainEventLoop.h"
 #include "Swiften/LinkLocal/BonjourBrowseQuery.h"
+#include "Swiften/LinkLocal/BonjourPublishQuery.h"
 #include "Swiften/Base/foreach.h"
 
 namespace Swift {
@@ -18,7 +19,6 @@ BonjourQuerier::BonjourQuerier() : stopRequested(false), thread(0) {
 	interruptSelectReadSocket = fds[0];
 	fcntl(interruptSelectReadSocket, F_SETFL, fcntl(interruptSelectReadSocket, F_GETFL)|O_NONBLOCK);
 	interruptSelectWriteSocket = fds[1];
-	// TODO: Schedule thread
 }
 
 BonjourQuerier::~BonjourQuerier() {
@@ -29,6 +29,10 @@ boost::shared_ptr<DNSSDBrowseQuery> BonjourQuerier::createBrowseQuery() {
 	return boost::shared_ptr<DNSSDBrowseQuery>(new BonjourBrowseQuery(shared_from_this()));
 }
 
+boost::shared_ptr<DNSSDPublishQuery> BonjourQuerier::createPublishQuery(const String& name, int port, const LinkLocalServiceInfo& info) {
+	return boost::shared_ptr<DNSSDPublishQuery>(new BonjourPublishQuery(name, port, info, shared_from_this()));
+}
+
 void BonjourQuerier::addRunningQuery(boost::shared_ptr<BonjourQuery> query) {
 	{
 		boost::lock_guard<boost::mutex> lock(runningQueriesMutex);
@@ -74,14 +78,16 @@ void BonjourQuerier::run() {
 		int maxSocket;
 		{
 			boost::unique_lock<boost::mutex> lock(runningQueriesMutex);
-			runningQueriesAvailableEvent.wait(lock);
 			if (runningQueries.empty()) {
-				continue;
+				runningQueriesAvailableEvent.wait(lock);
+				if (runningQueries.empty()) {
+					continue;
+				}
 			}
 
 			// Run all running queries
 			FD_ZERO(&fdSet);
-			int maxSocket = interruptSelectReadSocket;
+			maxSocket = interruptSelectReadSocket;
 			FD_SET(interruptSelectReadSocket, &fdSet);
 
 			foreach(const boost::shared_ptr<BonjourQuery>& query, runningQueries) {
diff --git a/Swiften/LinkLocal/BonjourQuerier.h b/Swiften/LinkLocal/BonjourQuerier.h
index 037d9e6..5f69ad6 100644
--- a/Swiften/LinkLocal/BonjourQuerier.h
+++ b/Swiften/LinkLocal/BonjourQuerier.h
@@ -8,9 +8,12 @@
 
 #include "Swiften/EventLoop/EventOwner.h"
 #include "Swiften/LinkLocal/DNSSDBrowseQuery.h"
+#include "Swiften/LinkLocal/DNSSDPublishQuery.h"
 #include "Swiften/LinkLocal/BonjourQuery.h"
 
 namespace Swift {
+	class LinkLocalServiceInfo;
+
 	class BonjourQuerier : 
 			public boost::enable_shared_from_this<BonjourQuerier>, 
 			public EventOwner {
@@ -19,6 +22,7 @@ namespace Swift {
 			~BonjourQuerier();
 
 			boost::shared_ptr<DNSSDBrowseQuery> createBrowseQuery();
+			boost::shared_ptr<DNSSDPublishQuery> createPublishQuery(const String& name, int port, const LinkLocalServiceInfo& info);
 
 			void start();
 			void stop();
diff --git a/Swiften/LinkLocal/BonjourQuery.cpp b/Swiften/LinkLocal/BonjourQuery.cpp
index a9c13fb..965a845 100644
--- a/Swiften/LinkLocal/BonjourQuery.cpp
+++ b/Swiften/LinkLocal/BonjourQuery.cpp
@@ -11,7 +11,9 @@ BonjourQuery::~BonjourQuery() {
 }
 
 void BonjourQuery::processResult() {
+	std::cout << "Process result" << std::endl;
 	boost::lock_guard<boost::mutex> lock(sdRefMutex);
+	std::cout << "DNSSDServiceProcessResult" << std::endl;
 	DNSServiceProcessResult(sdRef);
 }
 
diff --git a/Swiften/LinkLocal/DNSSDBrowseQuery.h b/Swiften/LinkLocal/DNSSDBrowseQuery.h
index b46d968..e548ca5 100644
--- a/Swiften/LinkLocal/DNSSDBrowseQuery.h
+++ b/Swiften/LinkLocal/DNSSDBrowseQuery.h
@@ -9,6 +9,9 @@ namespace Swift {
 		public:
 			virtual ~DNSSDBrowseQuery();
 
+			virtual void startBrowsing() = 0;
+			virtual void stopBrowsing() = 0;
+
 			boost::signal<void (const LinkLocalServiceID&)> onServiceAdded;
 			boost::signal<void (const LinkLocalServiceID&)> onServiceRemoved;
 	};
diff --git a/Swiften/LinkLocal/DNSSDPublishQuery.cpp b/Swiften/LinkLocal/DNSSDPublishQuery.cpp
new file mode 100644
index 0000000..cf3fd25
--- /dev/null
+++ b/Swiften/LinkLocal/DNSSDPublishQuery.cpp
@@ -0,0 +1,8 @@
+#include "Swiften/LinkLocal/DNSSDPublishQuery.h"
+
+namespace Swift {
+
+DNSSDPublishQuery::~DNSSDPublishQuery() {
+}
+
+}
diff --git a/Swiften/LinkLocal/DNSSDPublishQuery.h b/Swiften/LinkLocal/DNSSDPublishQuery.h
new file mode 100644
index 0000000..48c86dc
--- /dev/null
+++ b/Swiften/LinkLocal/DNSSDPublishQuery.h
@@ -0,0 +1,17 @@
+#pragma once
+
+#include <boost/signal.hpp>
+#include <boost/optional.hpp>
+
+#include "Swiften/LinkLocal/LinkLocalServiceID.h"
+
+namespace Swift {
+	class DNSSDPublishQuery {
+		public:
+			virtual ~DNSSDPublishQuery();
+
+			virtual void publish() = 0;
+
+			boost::signal<void (boost::optional<LinkLocalServiceID>)> onPublishFinished;
+	};
+}
diff --git a/Swiften/LinkLocal/Makefile.inc b/Swiften/LinkLocal/Makefile.inc
index b43a7e4..093ac70 100644
--- a/Swiften/LinkLocal/Makefile.inc
+++ b/Swiften/LinkLocal/Makefile.inc
@@ -1,6 +1,7 @@
 SWIFTEN_SOURCES += \
 	Swiften/LinkLocal/BonjourQuery.cpp \
 	Swiften/LinkLocal/DNSSDBrowseQuery.cpp \
+	Swiften/LinkLocal/DNSSDPublishQuery.cpp \
 	Swiften/LinkLocal/DNSSDServiceFactory.cpp \
 	Swiften/LinkLocal/BonjourQuerier.cpp \
 	Swiften/LinkLocal/PlatformDNSSDServiceFactory.cpp \
-- 
cgit v0.10.2-6-g49f6


From 0dd979a856719f16925f84d6be532bd31044fa82 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Fri, 24 Jul 2009 20:09:11 +0200
Subject: Fix uninitialized streamstack.


diff --git a/Swiften/Client/UnitTest/ClientSessionTest.cpp b/Swiften/Client/UnitTest/ClientSessionTest.cpp
index a91216c..bb10cfd 100644
--- a/Swiften/Client/UnitTest/ClientSessionTest.cpp
+++ b/Swiften/Client/UnitTest/ClientSessionTest.cpp
@@ -38,7 +38,7 @@ using namespace Swift;
 
 class ClientSessionTest : public CppUnit::TestFixture {
 		CPPUNIT_TEST_SUITE(ClientSessionTest);
-		//CPPUNIT_TEST(testConstructor);
+		CPPUNIT_TEST(testConstructor);
 		/*
 		CPPUNIT_TEST(testStart_Error);
 		CPPUNIT_TEST(testStart_XMLError);
diff --git a/Swiften/Session/Session.cpp b/Swiften/Session/Session.cpp
index 5ee98e7..92d1fdc 100644
--- a/Swiften/Session/Session.cpp
+++ b/Swiften/Session/Session.cpp
@@ -14,6 +14,7 @@ Session::Session(
 			connection(connection),
 			payloadParserFactories(payloadParserFactories),
 			payloadSerializers(payloadSerializers),
+      streamStack(0),
 			initialized(false) {
 }
 
-- 
cgit v0.10.2-6-g49f6


From f6e73393afbe7ce8d1a5c5fc55565582cb8906cc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Fri, 24 Jul 2009 20:09:29 +0200
Subject: Update the build system.

Coverage now works better.
Some files are cleaned by default (without the need of CLEANFILES).

diff --git a/.gitignore b/.gitignore
index 8a6563e..697ca06 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,6 @@
 .DS_Store
 *.dep
+*.gcov
 *.gcda
 *.gcno
 *.app
diff --git a/3rdParty/Boost/Makefile.inc b/3rdParty/Boost/Makefile.inc
index 27aed09..d28bbcb 100644
--- a/3rdParty/Boost/Makefile.inc
+++ b/3rdParty/Boost/Makefile.inc
@@ -57,6 +57,3 @@ endif
 
 BOOST_OBJECTS = \
 	$(BOOST_SOURCES:.cpp=.o)
-
-CLEANFILES += \
-	$(BOOST_OBJECTS)
diff --git a/3rdParty/CppUnit/Makefile.inc b/3rdParty/CppUnit/Makefile.inc
index 27aadc2..3749144 100644
--- a/3rdParty/CppUnit/Makefile.inc
+++ b/3rdParty/CppUnit/Makefile.inc
@@ -39,9 +39,5 @@ CPPUNIT_SOURCES = \
 CPPUNIT_OBJECTS = \
 	$(CPPUNIT_SOURCES:.cpp=.o)
 
-CLEANFILES += \
-	$(CPPUNIT_OBJECTS) \
-	$(CPPUNIT_TARGET)
-
 $(CPPUNIT_TARGET): $(CPPUNIT_OBJECTS)
 	$(QUIET_AR)$(AR) $(ARFLAGS) $@ $(CPPUNIT_OBJECTS)
diff --git a/3rdParty/Expat/Makefile.inc b/3rdParty/Expat/Makefile.inc
index c143263..a241cf1 100644
--- a/3rdParty/Expat/Makefile.inc
+++ b/3rdParty/Expat/Makefile.inc
@@ -8,10 +8,6 @@ EXPAT_SOURCES = \
 EXPAT_OBJECTS = \
 	$(EXPAT_SOURCES:.c=.o)
 
-CLEANFILES += \
-	$(EXPAT_OBJECTS) \
-	$(EXPAT_TARGET)
-
 $(EXPAT_TARGET): $(EXPAT_OBJECTS)
 	$(QUIET_AR)$(AR) $(ARFLAGS) $@ $(EXPAT_OBJECTS)
 
diff --git a/3rdParty/LibIDN/Makefile.inc b/3rdParty/LibIDN/Makefile.inc
index f0f64ac..2aeb34b 100644
--- a/3rdParty/LibIDN/Makefile.inc
+++ b/3rdParty/LibIDN/Makefile.inc
@@ -18,8 +18,3 @@ LIBIDN_SOURCES += \
 
 LIBIDN_OBJECTS = \
 	$(LIBIDN_SOURCES:.c=.o)
-
-CLEANFILES += \
-	$(LIBIDN_OBJECTS)
-
-
diff --git a/3rdParty/SQLite/Makefile.inc b/3rdParty/SQLite/Makefile.inc
index 339e7a0..141cfca 100644
--- a/3rdParty/SQLite/Makefile.inc
+++ b/3rdParty/SQLite/Makefile.inc
@@ -5,7 +5,3 @@ SQLITE_SOURCES = \
 
 SQLITE_OBJECTS = \
 	$(SQLITE_SOURCES:.c=.o)
-
-CLEANFILES += \
-	$(SQLITE_OBJECTS) \
-	$(SQLITE_TARGET)
diff --git a/3rdParty/ZLib/Makefile.inc b/3rdParty/ZLib/Makefile.inc
index dccfcf4..a30f65d 100644
--- a/3rdParty/ZLib/Makefile.inc
+++ b/3rdParty/ZLib/Makefile.inc
@@ -17,6 +17,3 @@ ZLIB_SOURCES += \
 
 ZLIB_OBJECTS = \
 	$(ZLIB_SOURCES:.c=.o)
-
-CLEANFILES += \
-	$(ZLIB_OBJECTS)
diff --git a/Limber/Makefile.inc b/Limber/Makefile.inc
index ea0d288..fe0e7d2 100644
--- a/Limber/Makefile.inc
+++ b/Limber/Makefile.inc
@@ -11,6 +11,5 @@ $(LIMBER_TARGET): $(SWIFTEN_TARGET) $(LIMBER_OBJECTS)
 	$(QUIET_LINK)$(CXX) -o $(LIMBER_TARGET) $(LIMBER_OBJECTS) $(LDFLAGS) $(SWIFTEN_TARGET) $(LIBS)
 
 #TARGETS += $(LIMBER_TARGET)
-CLEANFILES += $(LIMBER_OBJECTS)
 DEPS += \
 	$(LIMBER_SOURCES:.cpp=.dep) \
diff --git a/Makefile b/Makefile
index 8ea2c13..b93c85f 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 include Makefile.config
 
-CXXFLAGS += -I.
-CFLAGS += -I.
+CXXFLAGS += -I$(PWD)
+CFLAGS += -I$(PWD)
 ARFLAGS = rcs
 
 .DEFAULT_GOAL = all
@@ -66,16 +66,9 @@ coverage:
 	tools/coverage/GenerateCoverageResults.sh
 
 .PHONY: clean
-clean: clean-deps $(CLEAN_TARGETS)
-
-	-$(RM) $(CLEANFILES) *.gcov
-	-find . -name "*.gcda" -exec rm {} \;
-	-find . -name "*.gcno" -exec rm {} \;
-
-.PHONY: clean-deps
-clean-deps:
-		-$(RM) $(DEPS)
-
+clean: $(CLEAN_TARGETS)
+	-rm -rf $(CLEANFILES)
+	-find . \( -name "*.dep" -or -name "*.a" -or -name "*.o" -or -name "*.obj" -or -name "*.gcda" -or -name "*.gcno" -or -name "*.gcov" \) -exec rm {} \;
 
 ################################################################################
 # Automatic dependency detection
diff --git a/QA/UnitTest/Makefile.inc b/QA/UnitTest/Makefile.inc
index 531f616..f51828e 100644
--- a/QA/UnitTest/Makefile.inc
+++ b/QA/UnitTest/Makefile.inc
@@ -6,7 +6,7 @@ UNITTEST_OBJECTS = \
 
 TEST_TARGETS += check
 
-CLEANFILES += $(UNITTEST_OBJECTS) $(UNITTEST_TARGET)
+CLEANFILES += $(UNITTEST_TARGET)
 DEPS += $(UNITTEST_SOURCES:.cpp=.dep)
 
 .PHONY: check
diff --git a/Slimber/CLI/Makefile.inc b/Slimber/CLI/Makefile.inc
index 601929c..974b835 100644
--- a/Slimber/CLI/Makefile.inc
+++ b/Slimber/CLI/Makefile.inc
@@ -7,10 +7,9 @@ SLIMBER_CLI_OBJECTS = \
 $(SLIMBER_CLI_TARGET): $(SWIFTEN_TARGET) $(SLIMBER_TARGET) $(SLIMBER_CLI_OBJECTS)
 	$(QUIET_LINK)$(CXX) -o $(SLIMBER_CLI_TARGET) $(SLIMBER_CLI_OBJECTS) $(LDFLAGS) $(SLIMBER_TARGET) $(SWIFTEN_TARGET) $(LIBS)
 
-TARGETS += $(SLIMBER_CLI_TARGET)
+#TARGETS += $(SLIMBER_CLI_TARGET)
 SLIMBER_TARGETS += $(SLIMBER_CLI_TARGET)
 CLEANFILES += \
-	$(SLIMBER_CLI_OBJECTS) \
 	$(SLIMBER_CLI_TARGET)
 DEPS += \
 	$(SLIMBER_CLI_SOURCES:.cpp=.dep) \
diff --git a/Slimber/Cocoa/Makefile.inc b/Slimber/Cocoa/Makefile.inc
index 73b0f5d..28495f7 100644
--- a/Slimber/Cocoa/Makefile.inc
+++ b/Slimber/Cocoa/Makefile.inc
@@ -25,7 +25,6 @@ SLIMBER_COCOA_OBJECTS = \
 	$(patsubst %.m,%.o,$(patsubst %.mm,%.o,$(patsubst %.cpp,%.o, $(SLIMBER_COCOA_SOURCES))))
 CLEANFILES += \
 	Slimber/Cocoa/PkgInfo \
-	$(SLIMBER_COCOA_OBJECTS) \
 	$(SLIMBER_COCOA_NIBS) \
 	$(SLIMBER_COCOA_TARGET) \
 	$(SLIMBER_COCOA_BINARY)
diff --git a/Slimber/Makefile.inc b/Slimber/Makefile.inc
index 539646c..fea164f 100644
--- a/Slimber/Makefile.inc
+++ b/Slimber/Makefile.inc
@@ -6,9 +6,6 @@ SLIMBER_SOURCES = \
 SLIMBER_OBJECTS = \
 	$(SLIMBER_SOURCES:.cpp=.o)
 
-CLEANFILES += \
-	$(SLIMBER_OBJECTS) \
-	$(SLIMBER_TARGET)
 DEPS += \
 	$(SLIMBER_SOURCES:.cpp=.dep) \
 
diff --git a/Swift/Controllers/Makefile.inc b/Swift/Controllers/Makefile.inc
index 4c69e34..b145c54 100644
--- a/Swift/Controllers/Makefile.inc
+++ b/Swift/Controllers/Makefile.inc
@@ -18,7 +18,6 @@ SWIFT_CONTROLLERS_OBJECTS = \
 
 TARGETS += $(SWIFT_CONTROLLERS_TARGET)
 UNITTEST_LIBS += $(SWIFT_CONTROLLERS_TARGET)
-CLEANFILES += $(SWIFT_CONTROLLERS_TARGET) $(SWIFT_CONTROLLERS_OBJECTS)
 DEPS += $(SWIFT_CONTROLLERS_SOURCES:.cpp=.dep)
 
 $(SWIFT_CONTROLLERS_TARGET): $(SWIFT_CONTROLLERS_OBJECTS)
diff --git a/Swiften/Examples/EchoBot/Makefile.inc b/Swiften/Examples/EchoBot/Makefile.inc
index 09c63d5..beab023 100644
--- a/Swiften/Examples/EchoBot/Makefile.inc
+++ b/Swiften/Examples/EchoBot/Makefile.inc
@@ -4,7 +4,7 @@ ECHOBOT_SOURCES += \
 ECHOBOT_OBJECTS = \
 	$(ECHOBOT_SOURCES:.cpp=.o)
 
-CLEANFILES += $(ECHOBOT_OBJECTS) $(ECHOBOT_TARGET)
+CLEANFILES += $(ECHOBOT_TARGET)
 DEPS += $(ECHOBOT_SOURCES:.cpp=.dep)
 EXAMPLES_TARGETS += $(ECHOBOT_TARGET)
 
diff --git a/Swiften/LinkLocal/Makefile.inc b/Swiften/LinkLocal/Makefile.inc
index 093ac70..902fa7a 100644
--- a/Swiften/LinkLocal/Makefile.inc
+++ b/Swiften/LinkLocal/Makefile.inc
@@ -1,9 +1,7 @@
 SWIFTEN_SOURCES += \
-	Swiften/LinkLocal/BonjourQuery.cpp \
 	Swiften/LinkLocal/DNSSDBrowseQuery.cpp \
 	Swiften/LinkLocal/DNSSDPublishQuery.cpp \
 	Swiften/LinkLocal/DNSSDServiceFactory.cpp \
-	Swiften/LinkLocal/BonjourQuerier.cpp \
 	Swiften/LinkLocal/PlatformDNSSDServiceFactory.cpp \
 	Swiften/LinkLocal/DNSSDService.cpp \
 	Swiften/LinkLocal/LinkLocalRoster.cpp \
@@ -16,6 +14,8 @@ SWIFTEN_SOURCES += \
 
 ifeq ($(HAVE_BONJOUR),yes)
 SWIFTEN_SOURCES += \
+	Swiften/LinkLocal/BonjourQuery.cpp \
+	Swiften/LinkLocal/BonjourQuerier.cpp \
 	Swiften/LinkLocal/AppleDNSSDService.cpp
 endif
 ifeq ($(HAVE_AVAHI),yes)
diff --git a/Swiften/Makefile.inc b/Swiften/Makefile.inc
index 57ff329..d7c3340 100644
--- a/Swiften/Makefile.inc
+++ b/Swiften/Makefile.inc
@@ -41,7 +41,6 @@ SWIFTEN_HEADERS += \
 TARGETS += $(SWIFTEN_TARGET)
 INSTALL_TARGETS += install-swiften
 UNITTEST_LIBS += $(SWIFTEN_TARGET)
-CLEANFILES += $(SWIFTEN_TARGET) $(SWIFTEN_OBJECTS)
 DEPS += \
 	$(SWIFTEN_SOURCES:.cpp=.dep) 
 //TODO: Add objective stuff
diff --git a/Swiften/QA/ClientTest/Makefile.inc b/Swiften/QA/ClientTest/Makefile.inc
index 16a87cf..b9ab167 100644
--- a/Swiften/QA/ClientTest/Makefile.inc
+++ b/Swiften/QA/ClientTest/Makefile.inc
@@ -6,7 +6,7 @@ CLIENTTEST_OBJECTS = \
 
 TEST_TARGETS += ClientTest
 
-CLEANFILES += $(CLIENTTEST_OBJECTS) $(CLIENTTEST_TARGET)
+CLEANFILES += $(CLIENTTEST_TARGET)
 DEPS += $(CLIENTTEST_SOURCES:.cpp=.dep)
 
 $(CLIENTTEST_TARGET): $(SWIFTEN_TARGET) $(CLIENTTEST_OBJECTS) $(BUNDLED_LIBS)
diff --git a/Swiften/QA/NetworkTest/Makefile.inc b/Swiften/QA/NetworkTest/Makefile.inc
index 5ac14c0..b263cdb 100644
--- a/Swiften/QA/NetworkTest/Makefile.inc
+++ b/Swiften/QA/NetworkTest/Makefile.inc
@@ -8,7 +8,7 @@ NETWORKTEST_OBJECTS = \
 
 TEST_TARGETS += NetworkTest
 
-CLEANFILES += $(NETWORKTEST_OBJECTS) $(NETWORKTEST_TARGET)
+CLEANFILES += $(NETWORKTEST_TARGET)
 DEPS += $(NETWORKTEST_SOURCES:.cpp=.dep)
 
 $(NETWORKTEST_TARGET): $(SWIFTEN_TARGET) $(CPPUNIT_TARGET) $(NETWORKTEST_OBJECTS) $(BUNDLED_LIBS)
diff --git a/tools/coverage/FilterLCovData.py b/tools/coverage/FilterLCovData.py
index 8b8d24e..b1dd74e 100755
--- a/tools/coverage/FilterLCovData.py
+++ b/tools/coverage/FilterLCovData.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 
-import sys, re
+import sys, re, os.path
 
 assert(len(sys.argv) == 2)
 
@@ -15,8 +15,9 @@ for line in inputFile.readlines() :
     if line.startswith("SF:") and (line.find("/Swiften/") == -1 or line.find("/UnitTest/") != -1 or line.find("/QA/") != -1 or line.find("/3rdParty/") != -1):
       inIgnoredFile = True
     else :
-      if line.startswith("SF:") :
-        line = line.replace("/./Swiften/", "/Swiften/")
+      m = re.match("SF:(.*)", line)
+      if m :
+        line = "SF:" + os.path.realpath(m.group(1)) + "\n"
       output.append(line)
 inputFile.close()
 
-- 
cgit v0.10.2-6-g49f6


From 30f99a2bcbbeb41bfd61768b98c243ebcfdf67c7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Fri, 24 Jul 2009 20:07:47 +0200
Subject: Make BonjourQuerier thread-safe.


diff --git a/Swiften/LinkLocal/BonjourBrowseQuery.h b/Swiften/LinkLocal/BonjourBrowseQuery.h
index 6a50a61..6db108d 100644
--- a/Swiften/LinkLocal/BonjourBrowseQuery.h
+++ b/Swiften/LinkLocal/BonjourBrowseQuery.h
@@ -2,6 +2,7 @@
 
 #include "Swiften/LinkLocal/BonjourQuery.h"
 #include "Swiften/LinkLocal/DNSSDBrowseQuery.h"
+#include "Swiften/EventLoop/MainEventLoop.h"
 
 namespace Swift {
 	class BonjourQuerier;
@@ -11,7 +12,7 @@ namespace Swift {
 			BonjourBrowseQuery(boost::shared_ptr<BonjourQuerier> q) : BonjourQuery(q) {
 				DNSServiceErrorType result = DNSServiceBrowse(
 						&sdRef, 0, 0, "_presence._tcp", 0, 
-						&BonjourBrowseQuery::handleServiceDiscovered, this);
+						&BonjourBrowseQuery::handleServiceDiscoveredStatic, this);
 				if (result != kDNSServiceErr_NoError) {
 					std::cout << "Error" << std::endl;
 					// TODO
@@ -28,19 +29,21 @@ namespace Swift {
 			}
 
 		private:
-			static void handleServiceDiscovered(DNSServiceRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *name, const char *type, const char *domain, void *context) {
+			static void handleServiceDiscoveredStatic(DNSServiceRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *name, const char *type, const char *domain, void *context) {
+				static_cast<BonjourBrowseQuery*>(context)->handleServiceDiscovered(flags, interfaceIndex, errorCode, name, type, domain);
+			}
+
+			void handleServiceDiscovered(DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *name, const char *type, const char *domain) {
 				if (errorCode != kDNSServiceErr_NoError) {
 					return;
 				}
 				else {
-					BonjourBrowseQuery* query = static_cast<BonjourBrowseQuery*>(context);
 					LinkLocalServiceID service(name, type, domain, interfaceIndex);
-					std::cout << "Service discovered: " << name << std::endl;
 					if (flags & kDNSServiceFlagsAdd) {
-						query->onServiceAdded(service);
+						MainEventLoop::postEvent(boost::bind(boost::ref(onServiceAdded), service), shared_from_this());
 					}
 					else {
-						query->onServiceRemoved(service);
+						MainEventLoop::postEvent(boost::bind(boost::ref(onServiceRemoved), service), shared_from_this());
 					}
 				}
 			}
diff --git a/Swiften/LinkLocal/BonjourPublishQuery.h b/Swiften/LinkLocal/BonjourPublishQuery.h
index 4e7fd2f..a96e25a 100644
--- a/Swiften/LinkLocal/BonjourPublishQuery.h
+++ b/Swiften/LinkLocal/BonjourPublishQuery.h
@@ -4,6 +4,7 @@
 #include "Swiften/LinkLocal/DNSSDPublishQuery.h"
 #include "Swiften/LinkLocal/LinkLocalServiceInfo.h"
 #include "Swiften/Base/ByteArray.h"
+#include "Swiften/EventLoop/MainEventLoop.h"
 
 namespace Swift {
 	class BonjourQuerier;
@@ -15,7 +16,7 @@ namespace Swift {
 				DNSServiceErrorType result = DNSServiceRegister(
 						&sdRef, 0, 0, name.getUTF8Data(), "_presence._tcp", NULL, NULL, port, 
 						txtRecord.getSize(), txtRecord.getData(), 
-						&BonjourPublishQuery::handleServiceRegistered, this);
+						&BonjourPublishQuery::handleServicePublishedStatic, this);
 				if (result != kDNSServiceErr_NoError) {
 					// TODO
 					std::cerr << "Error creating service registration" << std::endl;
@@ -26,15 +27,23 @@ namespace Swift {
 				run();
 			}
 
+			void update(const LinkLocalService& info) {
+				boost::lock_guard<boost::mutex> lock(sdRefMutex);
+				ByteArray txtRecord = info.toTXTRecord();
+				DNSServiceUpdateRecord(sdRef, NULL, NULL, txtRecord.getSize(), txtRecord.getData(), 0);
+			}
+
 		private:
-			static void handleServiceRegistered(DNSServiceRef, DNSServiceFlags, DNSServiceErrorType errorCode, const char *name, const char *regtype, const char *domain, void *context) {
-				std::cout << "Publish finished " << name << std::endl;
-				BonjourPublishQuery* query = static_cast<BonjourPublishQuery*>(context);
+			static void handleServicePublishedStatic(DNSServiceRef, DNSServiceFlags, DNSServiceErrorType errorCode, const char *name, const char *regtype, const char *domain, void *context) {
+				static_cast<BonjourPublishQuery*>(context)->handleServicePublished(errorCode, name, regtype, domain);
+			}
+
+			void handleServicePublished(DNSServiceErrorType errorCode, const char *name, const char *regtype, const char *domain) {
 				if (errorCode != kDNSServiceErr_NoError) {
-					query->onPublishFinished(boost::optional<LinkLocalServiceID>());
+					MainEventLoop::postEvent(boost::bind(boost::ref(onPublishFinished), boost::optional<LinkLocalServiceID>()), shared_from_this());
 				}
 				else {
-					query->onPublishFinished(boost::optional<LinkLocalServiceID>(LinkLocalServiceID(name, regtype, domain, 0)));
+					MainEventLoop::postEvent(boost::bind(boost::ref(onPublishFinished), boost::optional<LinkLocalServiceID>(LinkLocalServiceID(name, regtype, domain, 0))), shared_from_this());
 				}
 			}
 	};
diff --git a/Swiften/LinkLocal/BonjourQuerier.cpp b/Swiften/LinkLocal/BonjourQuerier.cpp
index 93259c1..3080869 100644
--- a/Swiften/LinkLocal/BonjourQuerier.cpp
+++ b/Swiften/LinkLocal/BonjourQuerier.cpp
@@ -5,7 +5,6 @@
 #include <netinet/in.h>
 #include <fcntl.h>
 
-#include "Swiften/EventLoop/MainEventLoop.h"
 #include "Swiften/LinkLocal/BonjourBrowseQuery.h"
 #include "Swiften/LinkLocal/BonjourPublishQuery.h"
 #include "Swiften/Base/foreach.h"
@@ -108,10 +107,9 @@ void BonjourQuerier::run() {
 
 		{
 			boost::lock_guard<boost::mutex> lock(runningQueriesMutex);
-			foreach(const boost::shared_ptr<BonjourQuery>& query, runningQueries) {
+			foreach(boost::shared_ptr<BonjourQuery> query, runningQueries) {
 				if (FD_ISSET(query->getSocketID(), &fdSet)) {
-					MainEventLoop::postEvent(
-							boost::bind(&BonjourQuery::processResult, query), shared_from_this());
+					query->processResult();
 				}
 			}
 		}
diff --git a/Swiften/LinkLocal/BonjourQuerier.h b/Swiften/LinkLocal/BonjourQuerier.h
index 5f69ad6..e5ffa49 100644
--- a/Swiften/LinkLocal/BonjourQuerier.h
+++ b/Swiften/LinkLocal/BonjourQuerier.h
@@ -6,7 +6,6 @@
 #include <boost/thread.hpp>
 #include <boost/thread/mutex.hpp>
 
-#include "Swiften/EventLoop/EventOwner.h"
 #include "Swiften/LinkLocal/DNSSDBrowseQuery.h"
 #include "Swiften/LinkLocal/DNSSDPublishQuery.h"
 #include "Swiften/LinkLocal/BonjourQuery.h"
@@ -14,9 +13,7 @@
 namespace Swift {
 	class LinkLocalServiceInfo;
 
-	class BonjourQuerier : 
-			public boost::enable_shared_from_this<BonjourQuerier>, 
-			public EventOwner {
+	class BonjourQuerier : public boost::enable_shared_from_this<BonjourQuerier> {
 		public:
 			BonjourQuerier();
 			~BonjourQuerier();
diff --git a/Swiften/LinkLocal/BonjourQuery.cpp b/Swiften/LinkLocal/BonjourQuery.cpp
index 965a845..a9c13fb 100644
--- a/Swiften/LinkLocal/BonjourQuery.cpp
+++ b/Swiften/LinkLocal/BonjourQuery.cpp
@@ -11,9 +11,7 @@ BonjourQuery::~BonjourQuery() {
 }
 
 void BonjourQuery::processResult() {
-	std::cout << "Process result" << std::endl;
 	boost::lock_guard<boost::mutex> lock(sdRefMutex);
-	std::cout << "DNSSDServiceProcessResult" << std::endl;
 	DNSServiceProcessResult(sdRef);
 }
 
diff --git a/Swiften/LinkLocal/BonjourQuery.h b/Swiften/LinkLocal/BonjourQuery.h
index 2a47f73..bdb91a4 100644
--- a/Swiften/LinkLocal/BonjourQuery.h
+++ b/Swiften/LinkLocal/BonjourQuery.h
@@ -5,10 +5,14 @@
 #include <boost/enable_shared_from_this.hpp>
 #include <boost/thread/mutex.hpp>
 
+#include "Swiften/EventLoop/EventOwner.h"
+
 namespace Swift {
 	class BonjourQuerier;
 
-	class BonjourQuery : public boost::enable_shared_from_this<BonjourQuery> {
+	class BonjourQuery : 
+			public EventOwner,
+			public boost::enable_shared_from_this<BonjourQuery> {
 		public:
 			BonjourQuery(boost::shared_ptr<BonjourQuerier>);
 			virtual ~BonjourQuery();
diff --git a/configure.in b/configure.in
index 3a10e2c..186bc3c 100644
--- a/configure.in
+++ b/configure.in
@@ -198,12 +198,11 @@ AC_CHECK_LIB(resolv, inet_aton)
 # DNSSD Service
 case $host in
 	*-*-cygwin*)
-    AC_DEFINE(HAVE_BONJOUR)
 		;;
 	*-mingw32*)
-    AC_DEFINE(HAVE_BONJOUR)
 		;;
 	*-*-darwin*)
+    AC_DEFINE(HAVE_BONJOUR)
 		;;
 	*)
     AX_AVAHI()
-- 
cgit v0.10.2-6-g49f6


From 8cad7cff0462d8a48a5bc9762ce6d6b62e74d0e5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Fri, 24 Jul 2009 21:04:05 +0200
Subject: Remove unnecessary Slimber Cocoa menu entries.


diff --git a/Slimber/Cocoa/MainMenu.xib b/Slimber/Cocoa/MainMenu.xib
index a5eb7e1..50e4ca3 100644
--- a/Slimber/Cocoa/MainMenu.xib
+++ b/Slimber/Cocoa/MainMenu.xib
@@ -8,7 +8,7 @@
 		<string key="IBDocument.HIToolboxVersion">353.00</string>
 		<object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
 			<bool key="EncodedWithXMLCoder">YES</bool>
-			<integer value="205"/>
+			<integer value="136"/>
 		</object>
 		<object class="NSArray" key="IBDocument.PluginDependencies">
 			<bool key="EncodedWithXMLCoder">YES</bool>
@@ -41,7 +41,7 @@
 					<bool key="EncodedWithXMLCoder">YES</bool>
 					<object class="NSMenuItem" id="694149608">
 						<reference key="NSMenu" ref="649796088"/>
-						<string key="NSTitle">NewApplication</string>
+						<string key="NSTitle">Slimber</string>
 						<string key="NSKeyEquiv"/>
 						<int key="NSKeyEquivModMask">1048576</int>
 						<int key="NSMnemonicLoc">2147483647</int>
@@ -55,12 +55,12 @@
 						</object>
 						<string key="NSAction">submenuAction:</string>
 						<object class="NSMenu" key="NSSubmenu" id="110575045">
-							<string key="NSTitle">NewApplication</string>
+							<string key="NSTitle">Slimber</string>
 							<object class="NSMutableArray" key="NSMenuItems">
 								<bool key="EncodedWithXMLCoder">YES</bool>
 								<object class="NSMenuItem" id="238522557">
 									<reference key="NSMenu" ref="110575045"/>
-									<string key="NSTitle">About NewApplication</string>
+									<string key="NSTitle">About Slimber</string>
 									<string key="NSKeyEquiv"/>
 									<int key="NSMnemonicLoc">2147483647</int>
 									<reference key="NSOnImage" ref="35465992"/>
@@ -127,7 +127,7 @@
 								</object>
 								<object class="NSMenuItem" id="755159360">
 									<reference key="NSMenu" ref="110575045"/>
-									<string key="NSTitle">Hide NewApplication</string>
+									<string key="NSTitle">Hide Slimber</string>
 									<string key="NSKeyEquiv">h</string>
 									<int key="NSKeyEquivModMask">1048576</int>
 									<int key="NSMnemonicLoc">2147483647</int>
@@ -165,7 +165,7 @@
 								</object>
 								<object class="NSMenuItem" id="632727374">
 									<reference key="NSMenu" ref="110575045"/>
-									<string key="NSTitle">Quit NewApplication</string>
+									<string key="NSTitle">Quit Slimber</string>
 									<string key="NSKeyEquiv">q</string>
 									<int key="NSKeyEquivModMask">1048576</int>
 									<int key="NSMnemonicLoc">2147483647</int>
@@ -176,2364 +176,194 @@
 							<string key="NSName">_NSAppleMenu</string>
 						</object>
 					</object>
-					<object class="NSMenuItem" id="379814623">
-						<reference key="NSMenu" ref="649796088"/>
-						<string key="NSTitle">File</string>
-						<string key="NSKeyEquiv"/>
-						<int key="NSKeyEquivModMask">1048576</int>
-						<int key="NSMnemonicLoc">2147483647</int>
-						<reference key="NSOnImage" ref="35465992"/>
-						<reference key="NSMixedImage" ref="502551668"/>
-						<string key="NSAction">submenuAction:</string>
-						<object class="NSMenu" key="NSSubmenu" id="720053764">
-							<string key="NSTitle">File</string>
-							<object class="NSMutableArray" key="NSMenuItems">
-								<bool key="EncodedWithXMLCoder">YES</bool>
-								<object class="NSMenuItem" id="705341025">
-									<reference key="NSMenu" ref="720053764"/>
-									<string key="NSTitle">New</string>
-									<string key="NSKeyEquiv">n</string>
-									<int key="NSKeyEquivModMask">1048576</int>
-									<int key="NSMnemonicLoc">2147483647</int>
-									<reference key="NSOnImage" ref="35465992"/>
-									<reference key="NSMixedImage" ref="502551668"/>
-								</object>
-								<object class="NSMenuItem" id="722745758">
-									<reference key="NSMenu" ref="720053764"/>
-									<string type="base64-UTF8" key="NSTitle">T3BlbuKApg</string>
-									<string key="NSKeyEquiv">o</string>
-									<int key="NSKeyEquivModMask">1048576</int>
-									<int key="NSMnemonicLoc">2147483647</int>
-									<reference key="NSOnImage" ref="35465992"/>
-									<reference key="NSMixedImage" ref="502551668"/>
-								</object>
-								<object class="NSMenuItem" id="1025936716">
-									<reference key="NSMenu" ref="720053764"/>
-									<string key="NSTitle">Open Recent</string>
-									<string key="NSKeyEquiv"/>
-									<int key="NSKeyEquivModMask">1048576</int>
-									<int key="NSMnemonicLoc">2147483647</int>
-									<reference key="NSOnImage" ref="35465992"/>
-									<reference key="NSMixedImage" ref="502551668"/>
-									<string key="NSAction">submenuAction:</string>
-									<object class="NSMenu" key="NSSubmenu" id="1065607017">
-										<string key="NSTitle">Open Recent</string>
-										<object class="NSMutableArray" key="NSMenuItems">
-											<bool key="EncodedWithXMLCoder">YES</bool>
-											<object class="NSMenuItem" id="759406840">
-												<reference key="NSMenu" ref="1065607017"/>
-												<string key="NSTitle">Clear Menu</string>
-												<string key="NSKeyEquiv"/>
-												<int key="NSKeyEquivModMask">1048576</int>
-												<int key="NSMnemonicLoc">2147483647</int>
-												<reference key="NSOnImage" ref="35465992"/>
-												<reference key="NSMixedImage" ref="502551668"/>
-											</object>
-										</object>
-										<string key="NSName">_NSRecentDocumentsMenu</string>
-									</object>
-								</object>
-								<object class="NSMenuItem" id="425164168">
-									<reference key="NSMenu" ref="720053764"/>
-									<bool key="NSIsDisabled">YES</bool>
-									<bool key="NSIsSeparator">YES</bool>
-									<string key="NSTitle"/>
-									<string key="NSKeyEquiv"/>
-									<int key="NSKeyEquivModMask">1048576</int>
-									<int key="NSMnemonicLoc">2147483647</int>
-									<reference key="NSOnImage" ref="35465992"/>
-									<reference key="NSMixedImage" ref="502551668"/>
-								</object>
-								<object class="NSMenuItem" id="776162233">
-									<reference key="NSMenu" ref="720053764"/>
-									<string key="NSTitle">Close</string>
-									<string key="NSKeyEquiv">w</string>
-									<int key="NSKeyEquivModMask">1048576</int>
-									<int key="NSMnemonicLoc">2147483647</int>
-									<reference key="NSOnImage" ref="35465992"/>
-									<reference key="NSMixedImage" ref="502551668"/>
-								</object>
-								<object class="NSMenuItem" id="1023925487">
-									<reference key="NSMenu" ref="720053764"/>
-									<string key="NSTitle">Save</string>
-									<string key="NSKeyEquiv">s</string>
-									<int key="NSKeyEquivModMask">1048576</int>
-									<int key="NSMnemonicLoc">2147483647</int>
-									<reference key="NSOnImage" ref="35465992"/>
-									<reference key="NSMixedImage" ref="502551668"/>
-								</object>
-								<object class="NSMenuItem" id="117038363">
-									<reference key="NSMenu" ref="720053764"/>
-									<string type="base64-UTF8" key="NSTitle">U2F2ZSBBc+KApg</string>
-									<string key="NSKeyEquiv">S</string>
-									<int key="NSKeyEquivModMask">1179648</int>
-									<int key="NSMnemonicLoc">2147483647</int>
-									<reference key="NSOnImage" ref="35465992"/>
-									<reference key="NSMixedImage" ref="502551668"/>
-								</object>
-								<object class="NSMenuItem" id="579971712">
-									<reference key="NSMenu" ref="720053764"/>
-									<string key="NSTitle">Revert to Saved</string>
-									<string key="NSKeyEquiv"/>
-									<int key="NSMnemonicLoc">2147483647</int>
-									<reference key="NSOnImage" ref="35465992"/>
-									<reference key="NSMixedImage" ref="502551668"/>
-								</object>
-								<object class="NSMenuItem" id="1010469920">
-									<reference key="NSMenu" ref="720053764"/>
-									<bool key="NSIsDisabled">YES</bool>
-									<bool key="NSIsSeparator">YES</bool>
-									<string key="NSTitle"/>
-									<string key="NSKeyEquiv"/>
-									<int key="NSKeyEquivModMask">1048576</int>
-									<int key="NSMnemonicLoc">2147483647</int>
-									<reference key="NSOnImage" ref="35465992"/>
-									<reference key="NSMixedImage" ref="502551668"/>
-								</object>
-								<object class="NSMenuItem" id="294629803">
-									<reference key="NSMenu" ref="720053764"/>
-									<string key="NSTitle">Page Setup...</string>
-									<string key="NSKeyEquiv">P</string>
-									<int key="NSKeyEquivModMask">1179648</int>
-									<int key="NSMnemonicLoc">2147483647</int>
-									<reference key="NSOnImage" ref="35465992"/>
-									<reference key="NSMixedImage" ref="502551668"/>
-									<string key="NSToolTip"/>
-								</object>
-								<object class="NSMenuItem" id="49223823">
-									<reference key="NSMenu" ref="720053764"/>
-									<string type="base64-UTF8" key="NSTitle">UHJpbnTigKY</string>
-									<string key="NSKeyEquiv">p</string>
-									<int key="NSKeyEquivModMask">1048576</int>
-									<int key="NSMnemonicLoc">2147483647</int>
-									<reference key="NSOnImage" ref="35465992"/>
-									<reference key="NSMixedImage" ref="502551668"/>
-								</object>
-							</object>
-						</object>
-					</object>
-					<object class="NSMenuItem" id="952259628">
-						<reference key="NSMenu" ref="649796088"/>
-						<string key="NSTitle">Edit</string>
-						<string key="NSKeyEquiv"/>
-						<int key="NSKeyEquivModMask">1048576</int>
-						<int key="NSMnemonicLoc">2147483647</int>
-						<reference key="NSOnImage" ref="35465992"/>
-						<reference key="NSMixedImage" ref="502551668"/>
-						<string key="NSAction">submenuAction:</string>
-						<object class="NSMenu" key="NSSubmenu" id="789758025">
-							<string key="NSTitle">Edit</string>
-							<object class="NSMutableArray" key="NSMenuItems">
-								<bool key="EncodedWithXMLCoder">YES</bool>
-								<object class="NSMenuItem" id="1058277027">
-									<reference key="NSMenu" ref="789758025"/>
-									<string key="NSTitle">Undo</string>
-									<string key="NSKeyEquiv">z</string>
-									<int key="NSKeyEquivModMask">1048576</int>
-									<int key="NSMnemonicLoc">2147483647</int>
-									<reference key="NSOnImage" ref="35465992"/>
-									<reference key="NSMixedImage" ref="502551668"/>
-								</object>
-								<object class="NSMenuItem" id="790794224">
-									<reference key="NSMenu" ref="789758025"/>
-									<string key="NSTitle">Redo</string>
-									<string key="NSKeyEquiv">Z</string>
-									<int key="NSKeyEquivModMask">1179648</int>
-									<int key="NSMnemonicLoc">2147483647</int>
-									<reference key="NSOnImage" ref="35465992"/>
-									<reference key="NSMixedImage" ref="502551668"/>
-								</object>
-								<object class="NSMenuItem" id="1040322652">
-									<reference key="NSMenu" ref="789758025"/>
-									<bool key="NSIsDisabled">YES</bool>
-									<bool key="NSIsSeparator">YES</bool>
-									<string key="NSTitle"/>
-									<string key="NSKeyEquiv"/>
-									<int key="NSKeyEquivModMask">1048576</int>
-									<int key="NSMnemonicLoc">2147483647</int>
-									<reference key="NSOnImage" ref="35465992"/>
-									<reference key="NSMixedImage" ref="502551668"/>
-								</object>
-								<object class="NSMenuItem" id="296257095">
-									<reference key="NSMenu" ref="789758025"/>
-									<string key="NSTitle">Cut</string>
-									<string key="NSKeyEquiv">x</string>
-									<int key="NSKeyEquivModMask">1048576</int>
-									<int key="NSMnemonicLoc">2147483647</int>
-									<reference key="NSOnImage" ref="35465992"/>
-									<reference key="NSMixedImage" ref="502551668"/>
-								</object>
-								<object class="NSMenuItem" id="860595796">
-									<reference key="NSMenu" ref="789758025"/>
-									<string key="NSTitle">Copy</string>
-									<string key="NSKeyEquiv">c</string>
-									<int key="NSKeyEquivModMask">1048576</int>
-									<int key="NSMnemonicLoc">2147483647</int>
-									<reference key="NSOnImage" ref="35465992"/>
-									<reference key="NSMixedImage" ref="502551668"/>
-								</object>
-								<object class="NSMenuItem" id="29853731">
-									<reference key="NSMenu" ref="789758025"/>
-									<string key="NSTitle">Paste</string>
-									<string key="NSKeyEquiv">v</string>
-									<int key="NSKeyEquivModMask">1048576</int>
-									<int key="NSMnemonicLoc">2147483647</int>
-									<reference key="NSOnImage" ref="35465992"/>
-									<reference key="NSMixedImage" ref="502551668"/>
-								</object>
-								<object class="NSMenuItem" id="437104165">
-									<reference key="NSMenu" ref="789758025"/>
-									<string key="NSTitle">Delete</string>
-									<string key="NSKeyEquiv"/>
-									<int key="NSKeyEquivModMask">1048576</int>
-									<int key="NSMnemonicLoc">2147483647</int>
-									<reference key="NSOnImage" ref="35465992"/>
-									<reference key="NSMixedImage" ref="502551668"/>
-								</object>
-								<object class="NSMenuItem" id="583158037">
-									<reference key="NSMenu" ref="789758025"/>
-									<string key="NSTitle">Select All</string>
-									<string key="NSKeyEquiv">a</string>
-									<int key="NSKeyEquivModMask">1048576</int>
-									<int key="NSMnemonicLoc">2147483647</int>
-									<reference key="NSOnImage" ref="35465992"/>
-									<reference key="NSMixedImage" ref="502551668"/>
-								</object>
-								<object class="NSMenuItem" id="212016141">
-									<reference key="NSMenu" ref="789758025"/>
-									<bool key="NSIsDisabled">YES</bool>
-									<bool key="NSIsSeparator">YES</bool>
-									<string key="NSTitle"/>
-									<string key="NSKeyEquiv"/>
-									<int key="NSKeyEquivModMask">1048576</int>
-									<int key="NSMnemonicLoc">2147483647</int>
-									<reference key="NSOnImage" ref="35465992"/>
-									<reference key="NSMixedImage" ref="502551668"/>
-								</object>
-								<object class="NSMenuItem" id="892235320">
-									<reference key="NSMenu" ref="789758025"/>
-									<string key="NSTitle">Find</string>
-									<string key="NSKeyEquiv"/>
-									<int key="NSKeyEquivModMask">1048576</int>
-									<int key="NSMnemonicLoc">2147483647</int>
-									<reference key="NSOnImage" ref="35465992"/>
-									<reference key="NSMixedImage" ref="502551668"/>
-									<string key="NSAction">submenuAction:</string>
-									<object class="NSMenu" key="NSSubmenu" id="963351320">
-										<string key="NSTitle">Find</string>
-										<object class="NSMutableArray" key="NSMenuItems">
-											<bool key="EncodedWithXMLCoder">YES</bool>
-											<object class="NSMenuItem" id="447796847">
-												<reference key="NSMenu" ref="963351320"/>
-												<string type="base64-UTF8" key="NSTitle">RmluZOKApg</string>
-												<string key="NSKeyEquiv">f</string>
-												<int key="NSKeyEquivModMask">1048576</int>
-												<int key="NSMnemonicLoc">2147483647</int>
-												<reference key="NSOnImage" ref="35465992"/>
-												<reference key="NSMixedImage" ref="502551668"/>
-												<int key="NSTag">1</int>
-											</object>
-											<object class="NSMenuItem" id="326711663">
-												<reference key="NSMenu" ref="963351320"/>
-												<string key="NSTitle">Find Next</string>
-												<string key="NSKeyEquiv">g</string>
-												<int key="NSKeyEquivModMask">1048576</int>
-												<int key="NSMnemonicLoc">2147483647</int>
-												<reference key="NSOnImage" ref="35465992"/>
-												<reference key="NSMixedImage" ref="502551668"/>
-												<int key="NSTag">2</int>
-											</object>
-											<object class="NSMenuItem" id="270902937">
-												<reference key="NSMenu" ref="963351320"/>
-												<string key="NSTitle">Find Previous</string>
-												<string key="NSKeyEquiv">G</string>
-												<int key="NSKeyEquivModMask">1179648</int>
-												<int key="NSMnemonicLoc">2147483647</int>
-												<reference key="NSOnImage" ref="35465992"/>
-												<reference key="NSMixedImage" ref="502551668"/>
-												<int key="NSTag">3</int>
-											</object>
-											<object class="NSMenuItem" id="159080638">
-												<reference key="NSMenu" ref="963351320"/>
-												<string key="NSTitle">Use Selection for Find</string>
-												<string key="NSKeyEquiv">e</string>
-												<int key="NSKeyEquivModMask">1048576</int>
-												<int key="NSMnemonicLoc">2147483647</int>
-												<reference key="NSOnImage" ref="35465992"/>
-												<reference key="NSMixedImage" ref="502551668"/>
-												<int key="NSTag">7</int>
-											</object>
-											<object class="NSMenuItem" id="88285865">
-												<reference key="NSMenu" ref="963351320"/>
-												<string key="NSTitle">Jump to Selection</string>
-												<string key="NSKeyEquiv">j</string>
-												<int key="NSKeyEquivModMask">1048576</int>
-												<int key="NSMnemonicLoc">2147483647</int>
-												<reference key="NSOnImage" ref="35465992"/>
-												<reference key="NSMixedImage" ref="502551668"/>
-											</object>
-										</object>
-									</object>
-								</object>
-								<object class="NSMenuItem" id="972420730">
-									<reference key="NSMenu" ref="789758025"/>
-									<string key="NSTitle">Spelling and Grammar</string>
-									<string key="NSKeyEquiv"/>
-									<int key="NSKeyEquivModMask">1048576</int>
-									<int key="NSMnemonicLoc">2147483647</int>
-									<reference key="NSOnImage" ref="35465992"/>
-									<reference key="NSMixedImage" ref="502551668"/>
-									<string key="NSAction">submenuAction:</string>
-									<object class="NSMenu" key="NSSubmenu" id="769623530">
-										<string key="NSTitle">Spelling and Grammar</string>
-										<object class="NSMutableArray" key="NSMenuItems">
-											<bool key="EncodedWithXMLCoder">YES</bool>
-											<object class="NSMenuItem" id="679648819">
-												<reference key="NSMenu" ref="769623530"/>
-												<string type="base64-UTF8" key="NSTitle">U2hvdyBTcGVsbGluZ+KApg</string>
-												<string key="NSKeyEquiv">:</string>
-												<int key="NSKeyEquivModMask">1048576</int>
-												<int key="NSMnemonicLoc">2147483647</int>
-												<reference key="NSOnImage" ref="35465992"/>
-												<reference key="NSMixedImage" ref="502551668"/>
-											</object>
-											<object class="NSMenuItem" id="96193923">
-												<reference key="NSMenu" ref="769623530"/>
-												<string key="NSTitle">Check Spelling</string>
-												<string key="NSKeyEquiv">;</string>
-												<int key="NSKeyEquivModMask">1048576</int>
-												<int key="NSMnemonicLoc">2147483647</int>
-												<reference key="NSOnImage" ref="35465992"/>
-												<reference key="NSMixedImage" ref="502551668"/>
-											</object>
-											<object class="NSMenuItem" id="948374510">
-												<reference key="NSMenu" ref="769623530"/>
-												<string key="NSTitle">Check Spelling While Typing</string>
-												<string key="NSKeyEquiv"/>
-												<int key="NSKeyEquivModMask">1048576</int>
-												<int key="NSMnemonicLoc">2147483647</int>
-												<reference key="NSOnImage" ref="35465992"/>
-												<reference key="NSMixedImage" ref="502551668"/>
-											</object>
-											<object class="NSMenuItem" id="967646866">
-												<reference key="NSMenu" ref="769623530"/>
-												<string key="NSTitle">Check Grammar With Spelling</string>
-												<string key="NSKeyEquiv"/>
-												<int key="NSKeyEquivModMask">1048576</int>
-												<int key="NSMnemonicLoc">2147483647</int>
-												<reference key="NSOnImage" ref="35465992"/>
-												<reference key="NSMixedImage" ref="502551668"/>
-											</object>
-										</object>
-									</object>
-								</object>
-								<object class="NSMenuItem" id="507821607">
-									<reference key="NSMenu" ref="789758025"/>
-									<string key="NSTitle">Substitutions</string>
-									<string key="NSKeyEquiv"/>
-									<int key="NSKeyEquivModMask">1048576</int>
-									<int key="NSMnemonicLoc">2147483647</int>
-									<reference key="NSOnImage" ref="35465992"/>
-									<reference key="NSMixedImage" ref="502551668"/>
-									<string key="NSAction">submenuAction:</string>
-									<object class="NSMenu" key="NSSubmenu" id="698887838">
-										<string key="NSTitle">Substitutions</string>
-										<object class="NSMutableArray" key="NSMenuItems">
-											<bool key="EncodedWithXMLCoder">YES</bool>
-											<object class="NSMenuItem" id="605118523">
-												<reference key="NSMenu" ref="698887838"/>
-												<string key="NSTitle">Smart Copy/Paste</string>
-												<string key="NSKeyEquiv">f</string>
-												<int key="NSKeyEquivModMask">1048576</int>
-												<int key="NSMnemonicLoc">2147483647</int>
-												<reference key="NSOnImage" ref="35465992"/>
-												<reference key="NSMixedImage" ref="502551668"/>
-												<int key="NSTag">1</int>
-											</object>
-											<object class="NSMenuItem" id="197661976">
-												<reference key="NSMenu" ref="698887838"/>
-												<string key="NSTitle">Smart Quotes</string>
-												<string key="NSKeyEquiv">g</string>
-												<int key="NSKeyEquivModMask">1048576</int>
-												<int key="NSMnemonicLoc">2147483647</int>
-												<reference key="NSOnImage" ref="35465992"/>
-												<reference key="NSMixedImage" ref="502551668"/>
-												<int key="NSTag">2</int>
-											</object>
-											<object class="NSMenuItem" id="708854459">
-												<reference key="NSMenu" ref="698887838"/>
-												<string key="NSTitle">Smart Links</string>
-												<string key="NSKeyEquiv">G</string>
-												<int key="NSKeyEquivModMask">1179648</int>
-												<int key="NSMnemonicLoc">2147483647</int>
-												<reference key="NSOnImage" ref="35465992"/>
-												<reference key="NSMixedImage" ref="502551668"/>
-												<int key="NSTag">3</int>
-											</object>
-										</object>
-									</object>
-								</object>
-								<object class="NSMenuItem" id="676164635">
-									<reference key="NSMenu" ref="789758025"/>
-									<string key="NSTitle">Speech</string>
-									<string key="NSKeyEquiv"/>
-									<int key="NSKeyEquivModMask">1048576</int>
-									<int key="NSMnemonicLoc">2147483647</int>
-									<reference key="NSOnImage" ref="35465992"/>
-									<reference key="NSMixedImage" ref="502551668"/>
-									<string key="NSAction">submenuAction:</string>
-									<object class="NSMenu" key="NSSubmenu" id="785027613">
-										<string key="NSTitle">Speech</string>
-										<object class="NSMutableArray" key="NSMenuItems">
-											<bool key="EncodedWithXMLCoder">YES</bool>
-											<object class="NSMenuItem" id="731782645">
-												<reference key="NSMenu" ref="785027613"/>
-												<string key="NSTitle">Start Speaking</string>
-												<string key="NSKeyEquiv"/>
-												<int key="NSKeyEquivModMask">1048576</int>
-												<int key="NSMnemonicLoc">2147483647</int>
-												<reference key="NSOnImage" ref="35465992"/>
-												<reference key="NSMixedImage" ref="502551668"/>
-											</object>
-											<object class="NSMenuItem" id="680220178">
-												<reference key="NSMenu" ref="785027613"/>
-												<string key="NSTitle">Stop Speaking</string>
-												<string key="NSKeyEquiv"/>
-												<int key="NSKeyEquivModMask">1048576</int>
-												<int key="NSMnemonicLoc">2147483647</int>
-												<reference key="NSOnImage" ref="35465992"/>
-												<reference key="NSMixedImage" ref="502551668"/>
-											</object>
-										</object>
-									</object>
-								</object>
-							</object>
-						</object>
-					</object>
-					<object class="NSMenuItem" id="302598603">
-						<reference key="NSMenu" ref="649796088"/>
-						<string key="NSTitle">Format</string>
-						<string key="NSKeyEquiv"/>
-						<int key="NSMnemonicLoc">2147483647</int>
-						<reference key="NSOnImage" ref="35465992"/>
-						<reference key="NSMixedImage" ref="502551668"/>
-						<string key="NSAction">submenuAction:</string>
-						<object class="NSMenu" key="NSSubmenu" id="941447902">
-							<string key="NSTitle">Format</string>
-							<object class="NSMutableArray" key="NSMenuItems">
-								<bool key="EncodedWithXMLCoder">YES</bool>
-								<object class="NSMenuItem" id="792887677">
-									<reference key="NSMenu" ref="941447902"/>
-									<string key="NSTitle">Font</string>
-									<string key="NSKeyEquiv"/>
-									<int key="NSMnemonicLoc">2147483647</int>
-									<reference key="NSOnImage" ref="35465992"/>
-									<reference key="NSMixedImage" ref="502551668"/>
-									<string key="NSAction">submenuAction:</string>
-									<object class="NSMenu" key="NSSubmenu" id="786677654">
-										<string key="NSTitle">Font</string>
-										<object class="NSMutableArray" key="NSMenuItems">
-											<bool key="EncodedWithXMLCoder">YES</bool>
-											<object class="NSMenuItem" id="159677712">
-												<reference key="NSMenu" ref="786677654"/>
-												<string key="NSTitle">Show Fonts</string>
-												<string key="NSKeyEquiv">t</string>
-												<int key="NSKeyEquivModMask">1048576</int>
-												<int key="NSMnemonicLoc">2147483647</int>
-												<reference key="NSOnImage" ref="35465992"/>
-												<reference key="NSMixedImage" ref="502551668"/>
-											</object>
-											<object class="NSMenuItem" id="305399458">
-												<reference key="NSMenu" ref="786677654"/>
-												<string key="NSTitle">Bold</string>
-												<string key="NSKeyEquiv">b</string>
-												<int key="NSKeyEquivModMask">1048576</int>
-												<int key="NSMnemonicLoc">2147483647</int>
-												<reference key="NSOnImage" ref="35465992"/>
-												<reference key="NSMixedImage" ref="502551668"/>
-												<int key="NSTag">2</int>
-											</object>
-											<object class="NSMenuItem" id="814362025">
-												<reference key="NSMenu" ref="786677654"/>
-												<string key="NSTitle">Italic</string>
-												<string key="NSKeyEquiv">i</string>
-												<int key="NSKeyEquivModMask">1048576</int>
-												<int key="NSMnemonicLoc">2147483647</int>
-												<reference key="NSOnImage" ref="35465992"/>
-												<reference key="NSMixedImage" ref="502551668"/>
-												<int key="NSTag">1</int>
-											</object>
-											<object class="NSMenuItem" id="330926929">
-												<reference key="NSMenu" ref="786677654"/>
-												<string key="NSTitle">Underline</string>
-												<string key="NSKeyEquiv">u</string>
-												<int key="NSKeyEquivModMask">1048576</int>
-												<int key="NSMnemonicLoc">2147483647</int>
-												<reference key="NSOnImage" ref="35465992"/>
-												<reference key="NSMixedImage" ref="502551668"/>
-											</object>
-											<object class="NSMenuItem" id="533507878">
-												<reference key="NSMenu" ref="786677654"/>
-												<bool key="NSIsDisabled">YES</bool>
-												<bool key="NSIsSeparator">YES</bool>
-												<string key="NSTitle"/>
-												<string key="NSKeyEquiv"/>
-												<int key="NSMnemonicLoc">2147483647</int>
-												<reference key="NSOnImage" ref="35465992"/>
-												<reference key="NSMixedImage" ref="502551668"/>
-											</object>
-											<object class="NSMenuItem" id="158063935">
-												<reference key="NSMenu" ref="786677654"/>
-												<string key="NSTitle">Bigger</string>
-												<string key="NSKeyEquiv">+</string>
-												<int key="NSKeyEquivModMask">1048576</int>
-												<int key="NSMnemonicLoc">2147483647</int>
-												<reference key="NSOnImage" ref="35465992"/>
-												<reference key="NSMixedImage" ref="502551668"/>
-												<int key="NSTag">3</int>
-											</object>
-											<object class="NSMenuItem" id="885547335">
-												<reference key="NSMenu" ref="786677654"/>
-												<string key="NSTitle">Smaller</string>
-												<string key="NSKeyEquiv">-</string>
-												<int key="NSKeyEquivModMask">1048576</int>
-												<int key="NSMnemonicLoc">2147483647</int>
-												<reference key="NSOnImage" ref="35465992"/>
-												<reference key="NSMixedImage" ref="502551668"/>
-												<int key="NSTag">4</int>
-											</object>
-											<object class="NSMenuItem" id="901062459">
-												<reference key="NSMenu" ref="786677654"/>
-												<bool key="NSIsDisabled">YES</bool>
-												<bool key="NSIsSeparator">YES</bool>
-												<string key="NSTitle"/>
-												<string key="NSKeyEquiv"/>
-												<int key="NSMnemonicLoc">2147483647</int>
-												<reference key="NSOnImage" ref="35465992"/>
-												<reference key="NSMixedImage" ref="502551668"/>
-											</object>
-											<object class="NSMenuItem" id="767671776">
-												<reference key="NSMenu" ref="786677654"/>
-												<string key="NSTitle">Kern</string>
-												<string key="NSKeyEquiv"/>
-												<int key="NSMnemonicLoc">2147483647</int>
-												<reference key="NSOnImage" ref="35465992"/>
-												<reference key="NSMixedImage" ref="502551668"/>
-												<string key="NSAction">submenuAction:</string>
-												<object class="NSMenu" key="NSSubmenu" id="175441468">
-													<string key="NSTitle">Kern</string>
-													<object class="NSMutableArray" key="NSMenuItems">
-														<bool key="EncodedWithXMLCoder">YES</bool>
-														<object class="NSMenuItem" id="252969304">
-															<reference key="NSMenu" ref="175441468"/>
-															<string key="NSTitle">Use Default</string>
-															<string key="NSKeyEquiv"/>
-															<int key="NSMnemonicLoc">2147483647</int>
-															<reference key="NSOnImage" ref="35465992"/>
-															<reference key="NSMixedImage" ref="502551668"/>
-														</object>
-														<object class="NSMenuItem" id="766922938">
-															<reference key="NSMenu" ref="175441468"/>
-															<string key="NSTitle">Use None</string>
-															<string key="NSKeyEquiv"/>
-															<int key="NSMnemonicLoc">2147483647</int>
-															<reference key="NSOnImage" ref="35465992"/>
-															<reference key="NSMixedImage" ref="502551668"/>
-														</object>
-														<object class="NSMenuItem" id="677519740">
-															<reference key="NSMenu" ref="175441468"/>
-															<string key="NSTitle">Tighten</string>
-															<string key="NSKeyEquiv"/>
-															<int key="NSMnemonicLoc">2147483647</int>
-															<reference key="NSOnImage" ref="35465992"/>
-															<reference key="NSMixedImage" ref="502551668"/>
-														</object>
-														<object class="NSMenuItem" id="238351151">
-															<reference key="NSMenu" ref="175441468"/>
-															<string key="NSTitle">Loosen</string>
-															<string key="NSKeyEquiv"/>
-															<int key="NSMnemonicLoc">2147483647</int>
-															<reference key="NSOnImage" ref="35465992"/>
-															<reference key="NSMixedImage" ref="502551668"/>
-														</object>
-													</object>
-												</object>
-											</object>
-											<object class="NSMenuItem" id="691570813">
-												<reference key="NSMenu" ref="786677654"/>
-												<string key="NSTitle">Ligature</string>
-												<string key="NSKeyEquiv"/>
-												<int key="NSMnemonicLoc">2147483647</int>
-												<reference key="NSOnImage" ref="35465992"/>
-												<reference key="NSMixedImage" ref="502551668"/>
-												<string key="NSAction">submenuAction:</string>
-												<object class="NSMenu" key="NSSubmenu" id="1058217995">
-													<string key="NSTitle">Ligature</string>
-													<object class="NSMutableArray" key="NSMenuItems">
-														<bool key="EncodedWithXMLCoder">YES</bool>
-														<object class="NSMenuItem" id="706297211">
-															<reference key="NSMenu" ref="1058217995"/>
-															<string key="NSTitle">Use Default</string>
-															<string key="NSKeyEquiv"/>
-															<int key="NSMnemonicLoc">2147483647</int>
-															<reference key="NSOnImage" ref="35465992"/>
-															<reference key="NSMixedImage" ref="502551668"/>
-														</object>
-														<object class="NSMenuItem" id="568384683">
-															<reference key="NSMenu" ref="1058217995"/>
-															<string key="NSTitle">Use None</string>
-															<string key="NSKeyEquiv"/>
-															<int key="NSMnemonicLoc">2147483647</int>
-															<reference key="NSOnImage" ref="35465992"/>
-															<reference key="NSMixedImage" ref="502551668"/>
-														</object>
-														<object class="NSMenuItem" id="663508465">
-															<reference key="NSMenu" ref="1058217995"/>
-															<string key="NSTitle">Use All</string>
-															<string key="NSKeyEquiv"/>
-															<int key="NSMnemonicLoc">2147483647</int>
-															<reference key="NSOnImage" ref="35465992"/>
-															<reference key="NSMixedImage" ref="502551668"/>
-														</object>
-													</object>
-												</object>
-											</object>
-											<object class="NSMenuItem" id="769124883">
-												<reference key="NSMenu" ref="786677654"/>
-												<string key="NSTitle">Baseline</string>
-												<string key="NSKeyEquiv"/>
-												<int key="NSMnemonicLoc">2147483647</int>
-												<reference key="NSOnImage" ref="35465992"/>
-												<reference key="NSMixedImage" ref="502551668"/>
-												<string key="NSAction">submenuAction:</string>
-												<object class="NSMenu" key="NSSubmenu" id="18263474">
-													<string key="NSTitle">Baseline</string>
-													<object class="NSMutableArray" key="NSMenuItems">
-														<bool key="EncodedWithXMLCoder">YES</bool>
-														<object class="NSMenuItem" id="257962622">
-															<reference key="NSMenu" ref="18263474"/>
-															<string key="NSTitle">Use Default</string>
-															<string key="NSKeyEquiv"/>
-															<int key="NSMnemonicLoc">2147483647</int>
-															<reference key="NSOnImage" ref="35465992"/>
-															<reference key="NSMixedImage" ref="502551668"/>
-														</object>
-														<object class="NSMenuItem" id="644725453">
-															<reference key="NSMenu" ref="18263474"/>
-															<string key="NSTitle">Superscript</string>
-															<string key="NSKeyEquiv"/>
-															<int key="NSMnemonicLoc">2147483647</int>
-															<reference key="NSOnImage" ref="35465992"/>
-															<reference key="NSMixedImage" ref="502551668"/>
-														</object>
-														<object class="NSMenuItem" id="1037576581">
-															<reference key="NSMenu" ref="18263474"/>
-															<string key="NSTitle">Subscript</string>
-															<string key="NSKeyEquiv"/>
-															<int key="NSMnemonicLoc">2147483647</int>
-															<reference key="NSOnImage" ref="35465992"/>
-															<reference key="NSMixedImage" ref="502551668"/>
-														</object>
-														<object class="NSMenuItem" id="941806246">
-															<reference key="NSMenu" ref="18263474"/>
-															<string key="NSTitle">Raise</string>
-															<string key="NSKeyEquiv"/>
-															<int key="NSMnemonicLoc">2147483647</int>
-															<reference key="NSOnImage" ref="35465992"/>
-															<reference key="NSMixedImage" ref="502551668"/>
-														</object>
-														<object class="NSMenuItem" id="1045724900">
-															<reference key="NSMenu" ref="18263474"/>
-															<string key="NSTitle">Lower</string>
-															<string key="NSKeyEquiv"/>
-															<int key="NSMnemonicLoc">2147483647</int>
-															<reference key="NSOnImage" ref="35465992"/>
-															<reference key="NSMixedImage" ref="502551668"/>
-														</object>
-													</object>
-												</object>
-											</object>
-											<object class="NSMenuItem" id="739652853">
-												<reference key="NSMenu" ref="786677654"/>
-												<bool key="NSIsDisabled">YES</bool>
-												<bool key="NSIsSeparator">YES</bool>
-												<string key="NSTitle"/>
-												<string key="NSKeyEquiv"/>
-												<int key="NSMnemonicLoc">2147483647</int>
-												<reference key="NSOnImage" ref="35465992"/>
-												<reference key="NSMixedImage" ref="502551668"/>
-											</object>
-											<object class="NSMenuItem" id="1012600125">
-												<reference key="NSMenu" ref="786677654"/>
-												<string key="NSTitle">Show Colors</string>
-												<string key="NSKeyEquiv">C</string>
-												<int key="NSKeyEquivModMask">1048576</int>
-												<int key="NSMnemonicLoc">2147483647</int>
-												<reference key="NSOnImage" ref="35465992"/>
-												<reference key="NSMixedImage" ref="502551668"/>
-											</object>
-											<object class="NSMenuItem" id="214559597">
-												<reference key="NSMenu" ref="786677654"/>
-												<bool key="NSIsDisabled">YES</bool>
-												<bool key="NSIsSeparator">YES</bool>
-												<string key="NSTitle"/>
-												<string key="NSKeyEquiv"/>
-												<int key="NSMnemonicLoc">2147483647</int>
-												<reference key="NSOnImage" ref="35465992"/>
-												<reference key="NSMixedImage" ref="502551668"/>
-											</object>
-											<object class="NSMenuItem" id="596732606">
-												<reference key="NSMenu" ref="786677654"/>
-												<string key="NSTitle">Copy Style</string>
-												<string key="NSKeyEquiv">c</string>
-												<int key="NSKeyEquivModMask">1572864</int>
-												<int key="NSMnemonicLoc">2147483647</int>
-												<reference key="NSOnImage" ref="35465992"/>
-												<reference key="NSMixedImage" ref="502551668"/>
-											</object>
-											<object class="NSMenuItem" id="393423671">
-												<reference key="NSMenu" ref="786677654"/>
-												<string key="NSTitle">Paste Style</string>
-												<string key="NSKeyEquiv">v</string>
-												<int key="NSKeyEquivModMask">1572864</int>
-												<int key="NSMnemonicLoc">2147483647</int>
-												<reference key="NSOnImage" ref="35465992"/>
-												<reference key="NSMixedImage" ref="502551668"/>
-											</object>
-										</object>
-										<string key="NSName">_NSFontMenu</string>
-									</object>
-								</object>
-								<object class="NSMenuItem" id="15516124">
-									<reference key="NSMenu" ref="941447902"/>
-									<string key="NSTitle">Text</string>
-									<string key="NSKeyEquiv"/>
-									<int key="NSMnemonicLoc">2147483647</int>
-									<reference key="NSOnImage" ref="35465992"/>
-									<reference key="NSMixedImage" ref="502551668"/>
-									<string key="NSAction">submenuAction:</string>
-									<object class="NSMenu" key="NSSubmenu" id="23081656">
-										<string key="NSTitle">Text</string>
-										<object class="NSMutableArray" key="NSMenuItems">
-											<bool key="EncodedWithXMLCoder">YES</bool>
-											<object class="NSMenuItem" id="135107054">
-												<reference key="NSMenu" ref="23081656"/>
-												<string key="NSTitle">Align Left</string>
-												<string key="NSKeyEquiv">{</string>
-												<int key="NSKeyEquivModMask">1048576</int>
-												<int key="NSMnemonicLoc">2147483647</int>
-												<reference key="NSOnImage" ref="35465992"/>
-												<reference key="NSMixedImage" ref="502551668"/>
-											</object>
-											<object class="NSMenuItem" id="310547522">
-												<reference key="NSMenu" ref="23081656"/>
-												<string key="NSTitle">Center</string>
-												<string key="NSKeyEquiv">|</string>
-												<int key="NSKeyEquivModMask">1048576</int>
-												<int key="NSMnemonicLoc">2147483647</int>
-												<reference key="NSOnImage" ref="35465992"/>
-												<reference key="NSMixedImage" ref="502551668"/>
-											</object>
-											<object class="NSMenuItem" id="436088763">
-												<reference key="NSMenu" ref="23081656"/>
-												<string key="NSTitle">Justify</string>
-												<string key="NSKeyEquiv"/>
-												<int key="NSMnemonicLoc">2147483647</int>
-												<reference key="NSOnImage" ref="35465992"/>
-												<reference key="NSMixedImage" ref="502551668"/>
-											</object>
-											<object class="NSMenuItem" id="498119243">
-												<reference key="NSMenu" ref="23081656"/>
-												<string key="NSTitle">Align Right</string>
-												<string key="NSKeyEquiv">}</string>
-												<int key="NSKeyEquivModMask">1048576</int>
-												<int key="NSMnemonicLoc">2147483647</int>
-												<reference key="NSOnImage" ref="35465992"/>
-												<reference key="NSMixedImage" ref="502551668"/>
-											</object>
-											<object class="NSMenuItem" id="607995063">
-												<reference key="NSMenu" ref="23081656"/>
-												<bool key="NSIsDisabled">YES</bool>
-												<bool key="NSIsSeparator">YES</bool>
-												<string key="NSTitle"/>
-												<string key="NSKeyEquiv"/>
-												<int key="NSMnemonicLoc">2147483647</int>
-												<reference key="NSOnImage" ref="35465992"/>
-												<reference key="NSMixedImage" ref="502551668"/>
-											</object>
-											<object class="NSMenuItem" id="420564933">
-												<reference key="NSMenu" ref="23081656"/>
-												<string key="NSTitle">Show Ruler</string>
-												<string key="NSKeyEquiv"/>
-												<int key="NSMnemonicLoc">2147483647</int>
-												<reference key="NSOnImage" ref="35465992"/>
-												<reference key="NSMixedImage" ref="502551668"/>
-											</object>
-											<object class="NSMenuItem" id="479856769">
-												<reference key="NSMenu" ref="23081656"/>
-												<string key="NSTitle">Copy Ruler</string>
-												<string key="NSKeyEquiv">c</string>
-												<int key="NSKeyEquivModMask">1310720</int>
-												<int key="NSMnemonicLoc">2147483647</int>
-												<reference key="NSOnImage" ref="35465992"/>
-												<reference key="NSMixedImage" ref="502551668"/>
-											</object>
-											<object class="NSMenuItem" id="333628178">
-												<reference key="NSMenu" ref="23081656"/>
-												<string key="NSTitle">Paste Ruler</string>
-												<string key="NSKeyEquiv">v</string>
-												<int key="NSKeyEquivModMask">1310720</int>
-												<int key="NSMnemonicLoc">2147483647</int>
-												<reference key="NSOnImage" ref="35465992"/>
-												<reference key="NSMixedImage" ref="502551668"/>
-											</object>
-										</object>
-									</object>
-								</object>
-							</object>
-						</object>
-					</object>
-					<object class="NSMenuItem" id="586577488">
-						<reference key="NSMenu" ref="649796088"/>
-						<string key="NSTitle">View</string>
-						<string key="NSKeyEquiv"/>
-						<int key="NSKeyEquivModMask">1048576</int>
-						<int key="NSMnemonicLoc">2147483647</int>
-						<reference key="NSOnImage" ref="35465992"/>
-						<reference key="NSMixedImage" ref="502551668"/>
-						<string key="NSAction">submenuAction:</string>
-						<object class="NSMenu" key="NSSubmenu" id="466310130">
-							<string key="NSTitle">View</string>
-							<object class="NSMutableArray" key="NSMenuItems">
-								<bool key="EncodedWithXMLCoder">YES</bool>
-								<object class="NSMenuItem" id="102151532">
-									<reference key="NSMenu" ref="466310130"/>
-									<string key="NSTitle">Show Toolbar</string>
-									<string key="NSKeyEquiv">t</string>
-									<int key="NSKeyEquivModMask">1572864</int>
-									<int key="NSMnemonicLoc">2147483647</int>
-									<reference key="NSOnImage" ref="35465992"/>
-									<reference key="NSMixedImage" ref="502551668"/>
-								</object>
-								<object class="NSMenuItem" id="237841660">
-									<reference key="NSMenu" ref="466310130"/>
-									<string type="base64-UTF8" key="NSTitle">Q3VzdG9taXplIFRvb2xiYXLigKY</string>
-									<string key="NSKeyEquiv"/>
-									<int key="NSKeyEquivModMask">1048576</int>
-									<int key="NSMnemonicLoc">2147483647</int>
-									<reference key="NSOnImage" ref="35465992"/>
-									<reference key="NSMixedImage" ref="502551668"/>
-								</object>
-							</object>
-						</object>
-					</object>
-					<object class="NSMenuItem" id="713487014">
-						<reference key="NSMenu" ref="649796088"/>
-						<string key="NSTitle">Window</string>
-						<string key="NSKeyEquiv"/>
-						<int key="NSKeyEquivModMask">1048576</int>
-						<int key="NSMnemonicLoc">2147483647</int>
-						<reference key="NSOnImage" ref="35465992"/>
-						<reference key="NSMixedImage" ref="502551668"/>
-						<string key="NSAction">submenuAction:</string>
-						<object class="NSMenu" key="NSSubmenu" id="835318025">
-							<string key="NSTitle">Window</string>
-							<object class="NSMutableArray" key="NSMenuItems">
-								<bool key="EncodedWithXMLCoder">YES</bool>
-								<object class="NSMenuItem" id="1011231497">
-									<reference key="NSMenu" ref="835318025"/>
-									<string key="NSTitle">Minimize</string>
-									<string key="NSKeyEquiv">m</string>
-									<int key="NSKeyEquivModMask">1048576</int>
-									<int key="NSMnemonicLoc">2147483647</int>
-									<reference key="NSOnImage" ref="35465992"/>
-									<reference key="NSMixedImage" ref="502551668"/>
-								</object>
-								<object class="NSMenuItem" id="575023229">
-									<reference key="NSMenu" ref="835318025"/>
-									<string key="NSTitle">Zoom</string>
-									<string key="NSKeyEquiv"/>
-									<int key="NSKeyEquivModMask">1048576</int>
-									<int key="NSMnemonicLoc">2147483647</int>
-									<reference key="NSOnImage" ref="35465992"/>
-									<reference key="NSMixedImage" ref="502551668"/>
-								</object>
-								<object class="NSMenuItem" id="299356726">
-									<reference key="NSMenu" ref="835318025"/>
-									<bool key="NSIsDisabled">YES</bool>
-									<bool key="NSIsSeparator">YES</bool>
-									<string key="NSTitle"/>
-									<string key="NSKeyEquiv"/>
-									<int key="NSKeyEquivModMask">1048576</int>
-									<int key="NSMnemonicLoc">2147483647</int>
-									<reference key="NSOnImage" ref="35465992"/>
-									<reference key="NSMixedImage" ref="502551668"/>
-								</object>
-								<object class="NSMenuItem" id="625202149">
-									<reference key="NSMenu" ref="835318025"/>
-									<string key="NSTitle">Bring All to Front</string>
-									<string key="NSKeyEquiv"/>
-									<int key="NSKeyEquivModMask">1048576</int>
-									<int key="NSMnemonicLoc">2147483647</int>
-									<reference key="NSOnImage" ref="35465992"/>
-									<reference key="NSMixedImage" ref="502551668"/>
-								</object>
-							</object>
-							<string key="NSName">_NSWindowsMenu</string>
-						</object>
-					</object>
-					<object class="NSMenuItem" id="391199113">
-						<reference key="NSMenu" ref="649796088"/>
-						<string key="NSTitle">Help</string>
-						<string key="NSKeyEquiv"/>
-						<int key="NSKeyEquivModMask">1048576</int>
-						<int key="NSMnemonicLoc">2147483647</int>
-						<reference key="NSOnImage" ref="35465992"/>
-						<reference key="NSMixedImage" ref="502551668"/>
-						<string key="NSAction">submenuAction:</string>
-						<object class="NSMenu" key="NSSubmenu" id="374024848">
-							<string key="NSTitle">Help</string>
-							<object class="NSMutableArray" key="NSMenuItems">
-								<bool key="EncodedWithXMLCoder">YES</bool>
-								<object class="NSMenuItem" id="238773614">
-									<reference key="NSMenu" ref="374024848"/>
-									<string key="NSTitle">NewApplication Help</string>
-									<string key="NSKeyEquiv">?</string>
-									<int key="NSKeyEquivModMask">1048576</int>
-									<int key="NSMnemonicLoc">2147483647</int>
-									<reference key="NSOnImage" ref="35465992"/>
-									<reference key="NSMixedImage" ref="502551668"/>
-								</object>
-							</object>
-						</object>
-					</object>
-				</object>
-				<string key="NSName">_NSMainMenu</string>
-			</object>
-			<object class="NSCustomObject" id="755631768">
-				<string key="NSClassName">NSFontManager</string>
-			</object>
-			<object class="NSCustomObject" id="16040424">
-				<string key="NSClassName">MainController</string>
-			</object>
-		</object>
-		<object class="IBObjectContainer" key="IBDocument.Objects">
-			<object class="NSMutableArray" key="connectionRecords">
-				<bool key="EncodedWithXMLCoder">YES</bool>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">performMiniaturize:</string>
-						<reference key="source" ref="1014"/>
-						<reference key="destination" ref="1011231497"/>
-					</object>
-					<int key="connectionID">37</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">arrangeInFront:</string>
-						<reference key="source" ref="1014"/>
-						<reference key="destination" ref="625202149"/>
-					</object>
-					<int key="connectionID">39</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">print:</string>
-						<reference key="source" ref="1014"/>
-						<reference key="destination" ref="49223823"/>
-					</object>
-					<int key="connectionID">86</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">runPageLayout:</string>
-						<reference key="source" ref="1014"/>
-						<reference key="destination" ref="294629803"/>
-					</object>
-					<int key="connectionID">87</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">clearRecentDocuments:</string>
-						<reference key="source" ref="1014"/>
-						<reference key="destination" ref="759406840"/>
-					</object>
-					<int key="connectionID">127</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">orderFrontStandardAboutPanel:</string>
-						<reference key="source" ref="1021"/>
-						<reference key="destination" ref="238522557"/>
-					</object>
-					<int key="connectionID">142</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">performClose:</string>
-						<reference key="source" ref="1014"/>
-						<reference key="destination" ref="776162233"/>
-					</object>
-					<int key="connectionID">193</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">toggleContinuousSpellChecking:</string>
-						<reference key="source" ref="1014"/>
-						<reference key="destination" ref="948374510"/>
-					</object>
-					<int key="connectionID">222</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">undo:</string>
-						<reference key="source" ref="1014"/>
-						<reference key="destination" ref="1058277027"/>
-					</object>
-					<int key="connectionID">223</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">copy:</string>
-						<reference key="source" ref="1014"/>
-						<reference key="destination" ref="860595796"/>
-					</object>
-					<int key="connectionID">224</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">checkSpelling:</string>
-						<reference key="source" ref="1014"/>
-						<reference key="destination" ref="96193923"/>
-					</object>
-					<int key="connectionID">225</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">paste:</string>
-						<reference key="source" ref="1014"/>
-						<reference key="destination" ref="29853731"/>
-					</object>
-					<int key="connectionID">226</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">stopSpeaking:</string>
-						<reference key="source" ref="1014"/>
-						<reference key="destination" ref="680220178"/>
-					</object>
-					<int key="connectionID">227</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">cut:</string>
-						<reference key="source" ref="1014"/>
-						<reference key="destination" ref="296257095"/>
-					</object>
-					<int key="connectionID">228</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">showGuessPanel:</string>
-						<reference key="source" ref="1014"/>
-						<reference key="destination" ref="679648819"/>
-					</object>
-					<int key="connectionID">230</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">redo:</string>
-						<reference key="source" ref="1014"/>
-						<reference key="destination" ref="790794224"/>
-					</object>
-					<int key="connectionID">231</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">selectAll:</string>
-						<reference key="source" ref="1014"/>
-						<reference key="destination" ref="583158037"/>
-					</object>
-					<int key="connectionID">232</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">startSpeaking:</string>
-						<reference key="source" ref="1014"/>
-						<reference key="destination" ref="731782645"/>
-					</object>
-					<int key="connectionID">233</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">delete:</string>
-						<reference key="source" ref="1014"/>
-						<reference key="destination" ref="437104165"/>
-					</object>
-					<int key="connectionID">235</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">performZoom:</string>
-						<reference key="source" ref="1014"/>
-						<reference key="destination" ref="575023229"/>
-					</object>
-					<int key="connectionID">240</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">performFindPanelAction:</string>
-						<reference key="source" ref="1014"/>
-						<reference key="destination" ref="447796847"/>
-					</object>
-					<int key="connectionID">241</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">centerSelectionInVisibleArea:</string>
-						<reference key="source" ref="1014"/>
-						<reference key="destination" ref="88285865"/>
-					</object>
-					<int key="connectionID">245</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">toggleGrammarChecking:</string>
-						<reference key="source" ref="1014"/>
-						<reference key="destination" ref="967646866"/>
-					</object>
-					<int key="connectionID">347</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">toggleSmartInsertDelete:</string>
-						<reference key="source" ref="1014"/>
-						<reference key="destination" ref="605118523"/>
-					</object>
-					<int key="connectionID">355</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">toggleAutomaticQuoteSubstitution:</string>
-						<reference key="source" ref="1014"/>
-						<reference key="destination" ref="197661976"/>
-					</object>
-					<int key="connectionID">356</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">toggleAutomaticLinkDetection:</string>
-						<reference key="source" ref="1014"/>
-						<reference key="destination" ref="708854459"/>
-					</object>
-					<int key="connectionID">357</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">showHelp:</string>
-						<reference key="source" ref="1014"/>
-						<reference key="destination" ref="238773614"/>
-					</object>
-					<int key="connectionID">360</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">saveDocument:</string>
-						<reference key="source" ref="1014"/>
-						<reference key="destination" ref="1023925487"/>
-					</object>
-					<int key="connectionID">362</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">saveDocumentAs:</string>
-						<reference key="source" ref="1014"/>
-						<reference key="destination" ref="117038363"/>
-					</object>
-					<int key="connectionID">363</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">revertDocumentToSaved:</string>
-						<reference key="source" ref="1014"/>
-						<reference key="destination" ref="579971712"/>
-					</object>
-					<int key="connectionID">364</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">runToolbarCustomizationPalette:</string>
-						<reference key="source" ref="1014"/>
-						<reference key="destination" ref="237841660"/>
-					</object>
-					<int key="connectionID">365</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">toggleToolbarShown:</string>
-						<reference key="source" ref="1014"/>
-						<reference key="destination" ref="102151532"/>
-					</object>
-					<int key="connectionID">366</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">hide:</string>
-						<reference key="source" ref="1014"/>
-						<reference key="destination" ref="755159360"/>
-					</object>
-					<int key="connectionID">367</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">hideOtherApplications:</string>
-						<reference key="source" ref="1014"/>
-						<reference key="destination" ref="342932134"/>
-					</object>
-					<int key="connectionID">368</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">unhideAllApplications:</string>
-						<reference key="source" ref="1014"/>
-						<reference key="destination" ref="908899353"/>
-					</object>
-					<int key="connectionID">370</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">newDocument:</string>
-						<reference key="source" ref="1014"/>
-						<reference key="destination" ref="705341025"/>
-					</object>
-					<int key="connectionID">373</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">openDocument:</string>
-						<reference key="source" ref="1014"/>
-						<reference key="destination" ref="722745758"/>
-					</object>
-					<int key="connectionID">374</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">addFontTrait:</string>
-						<reference key="source" ref="755631768"/>
-						<reference key="destination" ref="305399458"/>
-					</object>
-					<int key="connectionID">421</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">addFontTrait:</string>
-						<reference key="source" ref="755631768"/>
-						<reference key="destination" ref="814362025"/>
-					</object>
-					<int key="connectionID">422</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">modifyFont:</string>
-						<reference key="source" ref="755631768"/>
-						<reference key="destination" ref="885547335"/>
-					</object>
-					<int key="connectionID">423</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">orderFrontFontPanel:</string>
-						<reference key="source" ref="755631768"/>
-						<reference key="destination" ref="159677712"/>
-					</object>
-					<int key="connectionID">424</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">modifyFont:</string>
-						<reference key="source" ref="755631768"/>
-						<reference key="destination" ref="158063935"/>
-					</object>
-					<int key="connectionID">425</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">raiseBaseline:</string>
-						<reference key="source" ref="1014"/>
-						<reference key="destination" ref="941806246"/>
-					</object>
-					<int key="connectionID">426</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">lowerBaseline:</string>
-						<reference key="source" ref="1014"/>
-						<reference key="destination" ref="1045724900"/>
-					</object>
-					<int key="connectionID">427</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">copyFont:</string>
-						<reference key="source" ref="1014"/>
-						<reference key="destination" ref="596732606"/>
-					</object>
-					<int key="connectionID">428</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">subscript:</string>
-						<reference key="source" ref="1014"/>
-						<reference key="destination" ref="1037576581"/>
-					</object>
-					<int key="connectionID">429</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">superscript:</string>
-						<reference key="source" ref="1014"/>
-						<reference key="destination" ref="644725453"/>
-					</object>
-					<int key="connectionID">430</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">tightenKerning:</string>
-						<reference key="source" ref="1014"/>
-						<reference key="destination" ref="677519740"/>
-					</object>
-					<int key="connectionID">431</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">underline:</string>
-						<reference key="source" ref="1014"/>
-						<reference key="destination" ref="330926929"/>
-					</object>
-					<int key="connectionID">432</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">orderFrontColorPanel:</string>
-						<reference key="source" ref="1014"/>
-						<reference key="destination" ref="1012600125"/>
-					</object>
-					<int key="connectionID">433</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">useAllLigatures:</string>
-						<reference key="source" ref="1014"/>
-						<reference key="destination" ref="663508465"/>
-					</object>
-					<int key="connectionID">434</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">loosenKerning:</string>
-						<reference key="source" ref="1014"/>
-						<reference key="destination" ref="238351151"/>
-					</object>
-					<int key="connectionID">435</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">pasteFont:</string>
-						<reference key="source" ref="1014"/>
-						<reference key="destination" ref="393423671"/>
-					</object>
-					<int key="connectionID">436</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">unscript:</string>
-						<reference key="source" ref="1014"/>
-						<reference key="destination" ref="257962622"/>
-					</object>
-					<int key="connectionID">437</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">useStandardKerning:</string>
-						<reference key="source" ref="1014"/>
-						<reference key="destination" ref="252969304"/>
-					</object>
-					<int key="connectionID">438</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">useStandardLigatures:</string>
-						<reference key="source" ref="1014"/>
-						<reference key="destination" ref="706297211"/>
-					</object>
-					<int key="connectionID">439</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">turnOffLigatures:</string>
-						<reference key="source" ref="1014"/>
-						<reference key="destination" ref="568384683"/>
-					</object>
-					<int key="connectionID">440</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">turnOffKerning:</string>
-						<reference key="source" ref="1014"/>
-						<reference key="destination" ref="766922938"/>
-					</object>
-					<int key="connectionID">441</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">alignLeft:</string>
-						<reference key="source" ref="1014"/>
-						<reference key="destination" ref="135107054"/>
-					</object>
-					<int key="connectionID">442</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">alignJustified:</string>
-						<reference key="source" ref="1014"/>
-						<reference key="destination" ref="436088763"/>
-					</object>
-					<int key="connectionID">443</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">copyRuler:</string>
-						<reference key="source" ref="1014"/>
-						<reference key="destination" ref="479856769"/>
-					</object>
-					<int key="connectionID">444</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">alignCenter:</string>
-						<reference key="source" ref="1014"/>
-						<reference key="destination" ref="310547522"/>
-					</object>
-					<int key="connectionID">445</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">toggleRuler:</string>
-						<reference key="source" ref="1014"/>
-						<reference key="destination" ref="420564933"/>
-					</object>
-					<int key="connectionID">446</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">alignRight:</string>
-						<reference key="source" ref="1014"/>
-						<reference key="destination" ref="498119243"/>
-					</object>
-					<int key="connectionID">447</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">pasteRuler:</string>
-						<reference key="source" ref="1014"/>
-						<reference key="destination" ref="333628178"/>
-					</object>
-					<int key="connectionID">448</int>
-				</object>
-				<object class="IBConnectionRecord">
-					<object class="IBActionConnection" key="connection">
-						<string key="label">terminate:</string>
-						<reference key="source" ref="1050"/>
-						<reference key="destination" ref="632727374"/>
-					</object>
-					<int key="connectionID">449</int>
-				</object>
-			</object>
-			<object class="IBMutableOrderedSet" key="objectRecords">
-				<object class="NSArray" key="orderedObjects">
-					<bool key="EncodedWithXMLCoder">YES</bool>
-					<object class="IBObjectRecord">
-						<int key="objectID">0</int>
-						<object class="NSArray" key="object" id="1049">
-							<bool key="EncodedWithXMLCoder">YES</bool>
-						</object>
-						<reference key="children" ref="1048"/>
-						<nil key="parent"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">-2</int>
-						<reference key="object" ref="1021"/>
-						<reference key="parent" ref="1049"/>
-						<string type="base64-UTF8" key="objectName">RmlsZSdzIE93bmVyA</string>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">-1</int>
-						<reference key="object" ref="1014"/>
-						<reference key="parent" ref="1049"/>
-						<string key="objectName">First Responder</string>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">-3</int>
-						<reference key="object" ref="1050"/>
-						<reference key="parent" ref="1049"/>
-						<string key="objectName">Application</string>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">29</int>
-						<reference key="object" ref="649796088"/>
-						<object class="NSMutableArray" key="children">
-							<bool key="EncodedWithXMLCoder">YES</bool>
-							<reference ref="713487014"/>
-							<reference ref="694149608"/>
-							<reference ref="391199113"/>
-							<reference ref="952259628"/>
-							<reference ref="379814623"/>
-							<reference ref="586577488"/>
-							<reference ref="302598603"/>
-						</object>
-						<reference key="parent" ref="1049"/>
-						<string key="objectName">MainMenu</string>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">19</int>
-						<reference key="object" ref="713487014"/>
-						<object class="NSMutableArray" key="children">
-							<bool key="EncodedWithXMLCoder">YES</bool>
-							<reference ref="835318025"/>
-						</object>
-						<reference key="parent" ref="649796088"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">56</int>
-						<reference key="object" ref="694149608"/>
-						<object class="NSMutableArray" key="children">
-							<bool key="EncodedWithXMLCoder">YES</bool>
-							<reference ref="110575045"/>
-						</object>
-						<reference key="parent" ref="649796088"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">103</int>
-						<reference key="object" ref="391199113"/>
-						<object class="NSMutableArray" key="children">
-							<bool key="EncodedWithXMLCoder">YES</bool>
-							<reference ref="374024848"/>
-						</object>
-						<reference key="parent" ref="649796088"/>
-						<string key="objectName">1</string>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">217</int>
-						<reference key="object" ref="952259628"/>
-						<object class="NSMutableArray" key="children">
-							<bool key="EncodedWithXMLCoder">YES</bool>
-							<reference ref="789758025"/>
-						</object>
-						<reference key="parent" ref="649796088"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">83</int>
-						<reference key="object" ref="379814623"/>
-						<object class="NSMutableArray" key="children">
-							<bool key="EncodedWithXMLCoder">YES</bool>
-							<reference ref="720053764"/>
-						</object>
-						<reference key="parent" ref="649796088"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">81</int>
-						<reference key="object" ref="720053764"/>
-						<object class="NSMutableArray" key="children">
-							<bool key="EncodedWithXMLCoder">YES</bool>
-							<reference ref="1023925487"/>
-							<reference ref="117038363"/>
-							<reference ref="49223823"/>
-							<reference ref="722745758"/>
-							<reference ref="705341025"/>
-							<reference ref="1025936716"/>
-							<reference ref="294629803"/>
-							<reference ref="776162233"/>
-							<reference ref="425164168"/>
-							<reference ref="579971712"/>
-							<reference ref="1010469920"/>
-						</object>
-						<reference key="parent" ref="379814623"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">75</int>
-						<reference key="object" ref="1023925487"/>
-						<reference key="parent" ref="720053764"/>
-						<string key="objectName">3</string>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">80</int>
-						<reference key="object" ref="117038363"/>
-						<reference key="parent" ref="720053764"/>
-						<string key="objectName">8</string>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">78</int>
-						<reference key="object" ref="49223823"/>
-						<reference key="parent" ref="720053764"/>
-						<string key="objectName">6</string>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">72</int>
-						<reference key="object" ref="722745758"/>
-						<reference key="parent" ref="720053764"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">82</int>
-						<reference key="object" ref="705341025"/>
-						<reference key="parent" ref="720053764"/>
-						<string key="objectName">9</string>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">124</int>
-						<reference key="object" ref="1025936716"/>
-						<object class="NSMutableArray" key="children">
-							<bool key="EncodedWithXMLCoder">YES</bool>
-							<reference ref="1065607017"/>
-						</object>
-						<reference key="parent" ref="720053764"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">77</int>
-						<reference key="object" ref="294629803"/>
-						<reference key="parent" ref="720053764"/>
-						<string key="objectName">5</string>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">73</int>
-						<reference key="object" ref="776162233"/>
-						<reference key="parent" ref="720053764"/>
-						<string key="objectName">1</string>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">79</int>
-						<reference key="object" ref="425164168"/>
-						<reference key="parent" ref="720053764"/>
-						<string key="objectName">7</string>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">112</int>
-						<reference key="object" ref="579971712"/>
-						<reference key="parent" ref="720053764"/>
-						<string key="objectName">10</string>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">74</int>
-						<reference key="object" ref="1010469920"/>
-						<reference key="parent" ref="720053764"/>
-						<string key="objectName">2</string>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">125</int>
-						<reference key="object" ref="1065607017"/>
-						<object class="NSMutableArray" key="children">
-							<bool key="EncodedWithXMLCoder">YES</bool>
-							<reference ref="759406840"/>
-						</object>
-						<reference key="parent" ref="1025936716"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">126</int>
-						<reference key="object" ref="759406840"/>
-						<reference key="parent" ref="1065607017"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">205</int>
-						<reference key="object" ref="789758025"/>
-						<object class="NSMutableArray" key="children">
-							<bool key="EncodedWithXMLCoder">YES</bool>
-							<reference ref="437104165"/>
-							<reference ref="583158037"/>
-							<reference ref="1058277027"/>
-							<reference ref="212016141"/>
-							<reference ref="296257095"/>
-							<reference ref="29853731"/>
-							<reference ref="860595796"/>
-							<reference ref="1040322652"/>
-							<reference ref="790794224"/>
-							<reference ref="892235320"/>
-							<reference ref="972420730"/>
-							<reference ref="676164635"/>
-							<reference ref="507821607"/>
-						</object>
-						<reference key="parent" ref="952259628"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">202</int>
-						<reference key="object" ref="437104165"/>
-						<reference key="parent" ref="789758025"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">198</int>
-						<reference key="object" ref="583158037"/>
-						<reference key="parent" ref="789758025"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">207</int>
-						<reference key="object" ref="1058277027"/>
-						<reference key="parent" ref="789758025"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">214</int>
-						<reference key="object" ref="212016141"/>
-						<reference key="parent" ref="789758025"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">199</int>
-						<reference key="object" ref="296257095"/>
-						<reference key="parent" ref="789758025"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">203</int>
-						<reference key="object" ref="29853731"/>
-						<reference key="parent" ref="789758025"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">197</int>
-						<reference key="object" ref="860595796"/>
-						<reference key="parent" ref="789758025"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">206</int>
-						<reference key="object" ref="1040322652"/>
-						<reference key="parent" ref="789758025"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">215</int>
-						<reference key="object" ref="790794224"/>
-						<reference key="parent" ref="789758025"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">218</int>
-						<reference key="object" ref="892235320"/>
-						<object class="NSMutableArray" key="children">
-							<bool key="EncodedWithXMLCoder">YES</bool>
-							<reference ref="963351320"/>
-						</object>
-						<reference key="parent" ref="789758025"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">216</int>
-						<reference key="object" ref="972420730"/>
-						<object class="NSMutableArray" key="children">
-							<bool key="EncodedWithXMLCoder">YES</bool>
-							<reference ref="769623530"/>
-						</object>
-						<reference key="parent" ref="789758025"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">200</int>
-						<reference key="object" ref="769623530"/>
-						<object class="NSMutableArray" key="children">
-							<bool key="EncodedWithXMLCoder">YES</bool>
-							<reference ref="948374510"/>
-							<reference ref="96193923"/>
-							<reference ref="679648819"/>
-							<reference ref="967646866"/>
-						</object>
-						<reference key="parent" ref="972420730"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">219</int>
-						<reference key="object" ref="948374510"/>
-						<reference key="parent" ref="769623530"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">201</int>
-						<reference key="object" ref="96193923"/>
-						<reference key="parent" ref="769623530"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">204</int>
-						<reference key="object" ref="679648819"/>
-						<reference key="parent" ref="769623530"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">220</int>
-						<reference key="object" ref="963351320"/>
-						<object class="NSMutableArray" key="children">
-							<bool key="EncodedWithXMLCoder">YES</bool>
-							<reference ref="270902937"/>
-							<reference ref="88285865"/>
-							<reference ref="159080638"/>
-							<reference ref="326711663"/>
-							<reference ref="447796847"/>
-						</object>
-						<reference key="parent" ref="892235320"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">213</int>
-						<reference key="object" ref="270902937"/>
-						<reference key="parent" ref="963351320"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">210</int>
-						<reference key="object" ref="88285865"/>
-						<reference key="parent" ref="963351320"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">221</int>
-						<reference key="object" ref="159080638"/>
-						<reference key="parent" ref="963351320"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">208</int>
-						<reference key="object" ref="326711663"/>
-						<reference key="parent" ref="963351320"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">209</int>
-						<reference key="object" ref="447796847"/>
-						<reference key="parent" ref="963351320"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">106</int>
-						<reference key="object" ref="374024848"/>
-						<object class="NSMutableArray" key="children">
-							<bool key="EncodedWithXMLCoder">YES</bool>
-							<reference ref="238773614"/>
-						</object>
-						<reference key="parent" ref="391199113"/>
-						<string key="objectName">2</string>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">111</int>
-						<reference key="object" ref="238773614"/>
-						<reference key="parent" ref="374024848"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">57</int>
-						<reference key="object" ref="110575045"/>
-						<object class="NSMutableArray" key="children">
-							<bool key="EncodedWithXMLCoder">YES</bool>
-							<reference ref="238522557"/>
-							<reference ref="755159360"/>
-							<reference ref="908899353"/>
-							<reference ref="632727374"/>
-							<reference ref="646227648"/>
-							<reference ref="609285721"/>
-							<reference ref="481834944"/>
-							<reference ref="304266470"/>
-							<reference ref="1046388886"/>
-							<reference ref="1056857174"/>
-							<reference ref="342932134"/>
-						</object>
-						<reference key="parent" ref="694149608"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">58</int>
-						<reference key="object" ref="238522557"/>
-						<reference key="parent" ref="110575045"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">134</int>
-						<reference key="object" ref="755159360"/>
-						<reference key="parent" ref="110575045"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">150</int>
-						<reference key="object" ref="908899353"/>
-						<reference key="parent" ref="110575045"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">136</int>
-						<reference key="object" ref="632727374"/>
-						<reference key="parent" ref="110575045"/>
-						<string key="objectName">1111</string>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">144</int>
-						<reference key="object" ref="646227648"/>
-						<reference key="parent" ref="110575045"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">129</int>
-						<reference key="object" ref="609285721"/>
-						<reference key="parent" ref="110575045"/>
-						<string key="objectName">121</string>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">143</int>
-						<reference key="object" ref="481834944"/>
-						<reference key="parent" ref="110575045"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">236</int>
-						<reference key="object" ref="304266470"/>
-						<reference key="parent" ref="110575045"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">131</int>
-						<reference key="object" ref="1046388886"/>
-						<object class="NSMutableArray" key="children">
-							<bool key="EncodedWithXMLCoder">YES</bool>
-							<reference ref="752062318"/>
-						</object>
-						<reference key="parent" ref="110575045"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">149</int>
-						<reference key="object" ref="1056857174"/>
-						<reference key="parent" ref="110575045"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">145</int>
-						<reference key="object" ref="342932134"/>
-						<reference key="parent" ref="110575045"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">130</int>
-						<reference key="object" ref="752062318"/>
-						<reference key="parent" ref="1046388886"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">24</int>
-						<reference key="object" ref="835318025"/>
-						<object class="NSMutableArray" key="children">
-							<bool key="EncodedWithXMLCoder">YES</bool>
-							<reference ref="299356726"/>
-							<reference ref="625202149"/>
-							<reference ref="575023229"/>
-							<reference ref="1011231497"/>
-						</object>
-						<reference key="parent" ref="713487014"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">92</int>
-						<reference key="object" ref="299356726"/>
-						<reference key="parent" ref="835318025"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">5</int>
-						<reference key="object" ref="625202149"/>
-						<reference key="parent" ref="835318025"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">239</int>
-						<reference key="object" ref="575023229"/>
-						<reference key="parent" ref="835318025"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">23</int>
-						<reference key="object" ref="1011231497"/>
-						<reference key="parent" ref="835318025"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">295</int>
-						<reference key="object" ref="586577488"/>
-						<object class="NSMutableArray" key="children">
-							<bool key="EncodedWithXMLCoder">YES</bool>
-							<reference ref="466310130"/>
-						</object>
-						<reference key="parent" ref="649796088"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">296</int>
-						<reference key="object" ref="466310130"/>
-						<object class="NSMutableArray" key="children">
-							<bool key="EncodedWithXMLCoder">YES</bool>
-							<reference ref="102151532"/>
-							<reference ref="237841660"/>
-						</object>
-						<reference key="parent" ref="586577488"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">297</int>
-						<reference key="object" ref="102151532"/>
-						<reference key="parent" ref="466310130"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">298</int>
-						<reference key="object" ref="237841660"/>
-						<reference key="parent" ref="466310130"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">211</int>
-						<reference key="object" ref="676164635"/>
-						<object class="NSMutableArray" key="children">
-							<bool key="EncodedWithXMLCoder">YES</bool>
-							<reference ref="785027613"/>
-						</object>
-						<reference key="parent" ref="789758025"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">212</int>
-						<reference key="object" ref="785027613"/>
-						<object class="NSMutableArray" key="children">
-							<bool key="EncodedWithXMLCoder">YES</bool>
-							<reference ref="680220178"/>
-							<reference ref="731782645"/>
-						</object>
-						<reference key="parent" ref="676164635"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">195</int>
-						<reference key="object" ref="680220178"/>
-						<reference key="parent" ref="785027613"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">196</int>
-						<reference key="object" ref="731782645"/>
-						<reference key="parent" ref="785027613"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">346</int>
-						<reference key="object" ref="967646866"/>
-						<reference key="parent" ref="769623530"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">348</int>
-						<reference key="object" ref="507821607"/>
-						<object class="NSMutableArray" key="children">
-							<bool key="EncodedWithXMLCoder">YES</bool>
-							<reference ref="698887838"/>
-						</object>
-						<reference key="parent" ref="789758025"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">349</int>
-						<reference key="object" ref="698887838"/>
-						<object class="NSMutableArray" key="children">
-							<bool key="EncodedWithXMLCoder">YES</bool>
-							<reference ref="605118523"/>
-							<reference ref="197661976"/>
-							<reference ref="708854459"/>
-						</object>
-						<reference key="parent" ref="507821607"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">350</int>
-						<reference key="object" ref="605118523"/>
-						<reference key="parent" ref="698887838"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">351</int>
-						<reference key="object" ref="197661976"/>
-						<reference key="parent" ref="698887838"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">354</int>
-						<reference key="object" ref="708854459"/>
-						<reference key="parent" ref="698887838"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">375</int>
-						<reference key="object" ref="302598603"/>
-						<object class="NSMutableArray" key="children">
-							<bool key="EncodedWithXMLCoder">YES</bool>
-							<reference ref="941447902"/>
-						</object>
-						<reference key="parent" ref="649796088"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">376</int>
-						<reference key="object" ref="941447902"/>
-						<object class="NSMutableArray" key="children">
-							<bool key="EncodedWithXMLCoder">YES</bool>
-							<reference ref="792887677"/>
-							<reference ref="15516124"/>
-						</object>
-						<reference key="parent" ref="302598603"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">377</int>
-						<reference key="object" ref="792887677"/>
-						<object class="NSMutableArray" key="children">
-							<bool key="EncodedWithXMLCoder">YES</bool>
-							<reference ref="786677654"/>
-						</object>
-						<reference key="parent" ref="941447902"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">378</int>
-						<reference key="object" ref="15516124"/>
-						<object class="NSMutableArray" key="children">
-							<bool key="EncodedWithXMLCoder">YES</bool>
-							<reference ref="23081656"/>
-						</object>
-						<reference key="parent" ref="941447902"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">379</int>
-						<reference key="object" ref="23081656"/>
-						<object class="NSMutableArray" key="children">
-							<bool key="EncodedWithXMLCoder">YES</bool>
-							<reference ref="135107054"/>
-							<reference ref="310547522"/>
-							<reference ref="436088763"/>
-							<reference ref="498119243"/>
-							<reference ref="607995063"/>
-							<reference ref="420564933"/>
-							<reference ref="479856769"/>
-							<reference ref="333628178"/>
-						</object>
-						<reference key="parent" ref="15516124"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">380</int>
-						<reference key="object" ref="135107054"/>
-						<reference key="parent" ref="23081656"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">381</int>
-						<reference key="object" ref="310547522"/>
-						<reference key="parent" ref="23081656"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">382</int>
-						<reference key="object" ref="436088763"/>
-						<reference key="parent" ref="23081656"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">383</int>
-						<reference key="object" ref="498119243"/>
-						<reference key="parent" ref="23081656"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">384</int>
-						<reference key="object" ref="607995063"/>
-						<reference key="parent" ref="23081656"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">385</int>
-						<reference key="object" ref="420564933"/>
-						<reference key="parent" ref="23081656"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">386</int>
-						<reference key="object" ref="479856769"/>
-						<reference key="parent" ref="23081656"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">387</int>
-						<reference key="object" ref="333628178"/>
-						<reference key="parent" ref="23081656"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">388</int>
-						<reference key="object" ref="786677654"/>
-						<object class="NSMutableArray" key="children">
-							<bool key="EncodedWithXMLCoder">YES</bool>
-							<reference ref="159677712"/>
-							<reference ref="305399458"/>
-							<reference ref="814362025"/>
-							<reference ref="330926929"/>
-							<reference ref="533507878"/>
-							<reference ref="158063935"/>
-							<reference ref="885547335"/>
-							<reference ref="901062459"/>
-							<reference ref="767671776"/>
-							<reference ref="691570813"/>
-							<reference ref="769124883"/>
-							<reference ref="739652853"/>
-							<reference ref="1012600125"/>
-							<reference ref="214559597"/>
-							<reference ref="596732606"/>
-							<reference ref="393423671"/>
-						</object>
-						<reference key="parent" ref="792887677"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">389</int>
-						<reference key="object" ref="159677712"/>
-						<reference key="parent" ref="786677654"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">390</int>
-						<reference key="object" ref="305399458"/>
-						<reference key="parent" ref="786677654"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">391</int>
-						<reference key="object" ref="814362025"/>
-						<reference key="parent" ref="786677654"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">392</int>
-						<reference key="object" ref="330926929"/>
-						<reference key="parent" ref="786677654"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">393</int>
-						<reference key="object" ref="533507878"/>
-						<reference key="parent" ref="786677654"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">394</int>
-						<reference key="object" ref="158063935"/>
-						<reference key="parent" ref="786677654"/>
+				</object>
+				<string key="NSName">_NSMainMenu</string>
+			</object>
+			<object class="NSCustomObject" id="16040424">
+				<string key="NSClassName">MainController</string>
+			</object>
+		</object>
+		<object class="IBObjectContainer" key="IBDocument.Objects">
+			<object class="NSMutableArray" key="connectionRecords">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">orderFrontStandardAboutPanel:</string>
+						<reference key="source" ref="1021"/>
+						<reference key="destination" ref="238522557"/>
 					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">395</int>
-						<reference key="object" ref="885547335"/>
-						<reference key="parent" ref="786677654"/>
+					<int key="connectionID">142</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">hide:</string>
+						<reference key="source" ref="1014"/>
+						<reference key="destination" ref="755159360"/>
 					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">396</int>
-						<reference key="object" ref="901062459"/>
-						<reference key="parent" ref="786677654"/>
+					<int key="connectionID">367</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">hideOtherApplications:</string>
+						<reference key="source" ref="1014"/>
+						<reference key="destination" ref="342932134"/>
 					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">397</int>
-						<reference key="object" ref="767671776"/>
-						<object class="NSMutableArray" key="children">
-							<bool key="EncodedWithXMLCoder">YES</bool>
-							<reference ref="175441468"/>
-						</object>
-						<reference key="parent" ref="786677654"/>
+					<int key="connectionID">368</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">unhideAllApplications:</string>
+						<reference key="source" ref="1014"/>
+						<reference key="destination" ref="908899353"/>
 					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">398</int>
-						<reference key="object" ref="691570813"/>
-						<object class="NSMutableArray" key="children">
-							<bool key="EncodedWithXMLCoder">YES</bool>
-							<reference ref="1058217995"/>
-						</object>
-						<reference key="parent" ref="786677654"/>
+					<int key="connectionID">370</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">terminate:</string>
+						<reference key="source" ref="1050"/>
+						<reference key="destination" ref="632727374"/>
 					</object>
+					<int key="connectionID">449</int>
+				</object>
+			</object>
+			<object class="IBMutableOrderedSet" key="objectRecords">
+				<object class="NSArray" key="orderedObjects">
+					<bool key="EncodedWithXMLCoder">YES</bool>
 					<object class="IBObjectRecord">
-						<int key="objectID">399</int>
-						<reference key="object" ref="769124883"/>
-						<object class="NSMutableArray" key="children">
+						<int key="objectID">0</int>
+						<object class="NSArray" key="object" id="1049">
 							<bool key="EncodedWithXMLCoder">YES</bool>
-							<reference ref="18263474"/>
 						</object>
-						<reference key="parent" ref="786677654"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">400</int>
-						<reference key="object" ref="739652853"/>
-						<reference key="parent" ref="786677654"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">401</int>
-						<reference key="object" ref="1012600125"/>
-						<reference key="parent" ref="786677654"/>
+						<reference key="children" ref="1048"/>
+						<nil key="parent"/>
 					</object>
 					<object class="IBObjectRecord">
-						<int key="objectID">402</int>
-						<reference key="object" ref="214559597"/>
-						<reference key="parent" ref="786677654"/>
+						<int key="objectID">-2</int>
+						<reference key="object" ref="1021"/>
+						<reference key="parent" ref="1049"/>
+						<string type="base64-UTF8" key="objectName">RmlsZSdzIE93bmVyA</string>
 					</object>
 					<object class="IBObjectRecord">
-						<int key="objectID">403</int>
-						<reference key="object" ref="596732606"/>
-						<reference key="parent" ref="786677654"/>
+						<int key="objectID">-1</int>
+						<reference key="object" ref="1014"/>
+						<reference key="parent" ref="1049"/>
+						<string key="objectName">First Responder</string>
 					</object>
 					<object class="IBObjectRecord">
-						<int key="objectID">404</int>
-						<reference key="object" ref="393423671"/>
-						<reference key="parent" ref="786677654"/>
+						<int key="objectID">-3</int>
+						<reference key="object" ref="1050"/>
+						<reference key="parent" ref="1049"/>
+						<string key="objectName">Application</string>
 					</object>
 					<object class="IBObjectRecord">
-						<int key="objectID">405</int>
-						<reference key="object" ref="18263474"/>
+						<int key="objectID">29</int>
+						<reference key="object" ref="649796088"/>
 						<object class="NSMutableArray" key="children">
 							<bool key="EncodedWithXMLCoder">YES</bool>
-							<reference ref="257962622"/>
-							<reference ref="644725453"/>
-							<reference ref="1037576581"/>
-							<reference ref="941806246"/>
-							<reference ref="1045724900"/>
+							<reference ref="694149608"/>
 						</object>
-						<reference key="parent" ref="769124883"/>
+						<reference key="parent" ref="1049"/>
+						<string key="objectName">MainMenu</string>
 					</object>
 					<object class="IBObjectRecord">
-						<int key="objectID">406</int>
-						<reference key="object" ref="257962622"/>
-						<reference key="parent" ref="18263474"/>
+						<int key="objectID">458</int>
+						<reference key="object" ref="16040424"/>
+						<reference key="parent" ref="1049"/>
 					</object>
 					<object class="IBObjectRecord">
-						<int key="objectID">407</int>
-						<reference key="object" ref="644725453"/>
-						<reference key="parent" ref="18263474"/>
+						<int key="objectID">56</int>
+						<reference key="object" ref="694149608"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="110575045"/>
+						</object>
+						<reference key="parent" ref="649796088"/>
 					</object>
 					<object class="IBObjectRecord">
-						<int key="objectID">408</int>
-						<reference key="object" ref="1037576581"/>
-						<reference key="parent" ref="18263474"/>
+						<int key="objectID">57</int>
+						<reference key="object" ref="110575045"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="342932134"/>
+							<reference ref="1056857174"/>
+							<reference ref="1046388886"/>
+							<reference ref="304266470"/>
+							<reference ref="481834944"/>
+							<reference ref="609285721"/>
+							<reference ref="646227648"/>
+							<reference ref="632727374"/>
+							<reference ref="908899353"/>
+							<reference ref="755159360"/>
+							<reference ref="238522557"/>
+						</object>
+						<reference key="parent" ref="694149608"/>
 					</object>
 					<object class="IBObjectRecord">
-						<int key="objectID">409</int>
-						<reference key="object" ref="941806246"/>
-						<reference key="parent" ref="18263474"/>
+						<int key="objectID">145</int>
+						<reference key="object" ref="342932134"/>
+						<reference key="parent" ref="110575045"/>
 					</object>
 					<object class="IBObjectRecord">
-						<int key="objectID">410</int>
-						<reference key="object" ref="1045724900"/>
-						<reference key="parent" ref="18263474"/>
+						<int key="objectID">149</int>
+						<reference key="object" ref="1056857174"/>
+						<reference key="parent" ref="110575045"/>
 					</object>
 					<object class="IBObjectRecord">
-						<int key="objectID">411</int>
-						<reference key="object" ref="1058217995"/>
+						<int key="objectID">131</int>
+						<reference key="object" ref="1046388886"/>
 						<object class="NSMutableArray" key="children">
 							<bool key="EncodedWithXMLCoder">YES</bool>
-							<reference ref="706297211"/>
-							<reference ref="568384683"/>
-							<reference ref="663508465"/>
+							<reference ref="752062318"/>
 						</object>
-						<reference key="parent" ref="691570813"/>
-					</object>
-					<object class="IBObjectRecord">
-						<int key="objectID">412</int>
-						<reference key="object" ref="706297211"/>
-						<reference key="parent" ref="1058217995"/>
+						<reference key="parent" ref="110575045"/>
 					</object>
 					<object class="IBObjectRecord">
-						<int key="objectID">413</int>
-						<reference key="object" ref="568384683"/>
-						<reference key="parent" ref="1058217995"/>
+						<int key="objectID">130</int>
+						<reference key="object" ref="752062318"/>
+						<reference key="parent" ref="1046388886"/>
 					</object>
 					<object class="IBObjectRecord">
-						<int key="objectID">414</int>
-						<reference key="object" ref="663508465"/>
-						<reference key="parent" ref="1058217995"/>
+						<int key="objectID">236</int>
+						<reference key="object" ref="304266470"/>
+						<reference key="parent" ref="110575045"/>
 					</object>
 					<object class="IBObjectRecord">
-						<int key="objectID">415</int>
-						<reference key="object" ref="175441468"/>
-						<object class="NSMutableArray" key="children">
-							<bool key="EncodedWithXMLCoder">YES</bool>
-							<reference ref="252969304"/>
-							<reference ref="766922938"/>
-							<reference ref="677519740"/>
-							<reference ref="238351151"/>
-						</object>
-						<reference key="parent" ref="767671776"/>
+						<int key="objectID">143</int>
+						<reference key="object" ref="481834944"/>
+						<reference key="parent" ref="110575045"/>
 					</object>
 					<object class="IBObjectRecord">
-						<int key="objectID">416</int>
-						<reference key="object" ref="252969304"/>
-						<reference key="parent" ref="175441468"/>
+						<int key="objectID">129</int>
+						<reference key="object" ref="609285721"/>
+						<reference key="parent" ref="110575045"/>
+						<string key="objectName">121</string>
 					</object>
 					<object class="IBObjectRecord">
-						<int key="objectID">417</int>
-						<reference key="object" ref="766922938"/>
-						<reference key="parent" ref="175441468"/>
+						<int key="objectID">144</int>
+						<reference key="object" ref="646227648"/>
+						<reference key="parent" ref="110575045"/>
 					</object>
 					<object class="IBObjectRecord">
-						<int key="objectID">418</int>
-						<reference key="object" ref="677519740"/>
-						<reference key="parent" ref="175441468"/>
+						<int key="objectID">136</int>
+						<reference key="object" ref="632727374"/>
+						<reference key="parent" ref="110575045"/>
+						<string key="objectName">1111</string>
 					</object>
 					<object class="IBObjectRecord">
-						<int key="objectID">419</int>
-						<reference key="object" ref="238351151"/>
-						<reference key="parent" ref="175441468"/>
+						<int key="objectID">150</int>
+						<reference key="object" ref="908899353"/>
+						<reference key="parent" ref="110575045"/>
 					</object>
 					<object class="IBObjectRecord">
-						<int key="objectID">420</int>
-						<reference key="object" ref="755631768"/>
-						<reference key="parent" ref="1049"/>
+						<int key="objectID">134</int>
+						<reference key="object" ref="755159360"/>
+						<reference key="parent" ref="110575045"/>
 					</object>
 					<object class="IBObjectRecord">
-						<int key="objectID">458</int>
-						<reference key="object" ref="16040424"/>
-						<reference key="parent" ref="1049"/>
+						<int key="objectID">58</int>
+						<reference key="object" ref="238522557"/>
+						<reference key="parent" ref="110575045"/>
 					</object>
 				</object>
 			</object>
@@ -2544,22 +374,6 @@
 					<string>-1.IBPluginDependency</string>
 					<string>-2.IBPluginDependency</string>
 					<string>-3.IBPluginDependency</string>
-					<string>103.IBPluginDependency</string>
-					<string>103.ImportedFromIB2</string>
-					<string>106.IBPluginDependency</string>
-					<string>106.ImportedFromIB2</string>
-					<string>106.editorWindowContentRectSynchronizationRect</string>
-					<string>111.IBPluginDependency</string>
-					<string>111.ImportedFromIB2</string>
-					<string>112.IBPluginDependency</string>
-					<string>112.ImportedFromIB2</string>
-					<string>124.IBPluginDependency</string>
-					<string>124.ImportedFromIB2</string>
-					<string>125.IBPluginDependency</string>
-					<string>125.ImportedFromIB2</string>
-					<string>125.editorWindowContentRectSynchronizationRect</string>
-					<string>126.IBPluginDependency</string>
-					<string>126.ImportedFromIB2</string>
 					<string>129.IBPluginDependency</string>
 					<string>129.ImportedFromIB2</string>
 					<string>130.IBPluginDependency</string>
@@ -2581,150 +395,14 @@
 					<string>149.ImportedFromIB2</string>
 					<string>150.IBPluginDependency</string>
 					<string>150.ImportedFromIB2</string>
-					<string>19.IBPluginDependency</string>
-					<string>19.ImportedFromIB2</string>
-					<string>195.IBPluginDependency</string>
-					<string>195.ImportedFromIB2</string>
-					<string>196.IBPluginDependency</string>
-					<string>196.ImportedFromIB2</string>
-					<string>197.IBPluginDependency</string>
-					<string>197.ImportedFromIB2</string>
-					<string>198.IBPluginDependency</string>
-					<string>198.ImportedFromIB2</string>
-					<string>199.IBPluginDependency</string>
-					<string>199.ImportedFromIB2</string>
-					<string>200.IBPluginDependency</string>
-					<string>200.ImportedFromIB2</string>
-					<string>200.editorWindowContentRectSynchronizationRect</string>
-					<string>201.IBPluginDependency</string>
-					<string>201.ImportedFromIB2</string>
-					<string>202.IBPluginDependency</string>
-					<string>202.ImportedFromIB2</string>
-					<string>203.IBPluginDependency</string>
-					<string>203.ImportedFromIB2</string>
-					<string>204.IBPluginDependency</string>
-					<string>204.ImportedFromIB2</string>
-					<string>205.IBEditorWindowLastContentRect</string>
-					<string>205.IBPluginDependency</string>
-					<string>205.ImportedFromIB2</string>
-					<string>205.editorWindowContentRectSynchronizationRect</string>
-					<string>206.IBPluginDependency</string>
-					<string>206.ImportedFromIB2</string>
-					<string>207.IBPluginDependency</string>
-					<string>207.ImportedFromIB2</string>
-					<string>208.IBPluginDependency</string>
-					<string>208.ImportedFromIB2</string>
-					<string>209.IBPluginDependency</string>
-					<string>209.ImportedFromIB2</string>
-					<string>210.IBPluginDependency</string>
-					<string>210.ImportedFromIB2</string>
-					<string>211.IBPluginDependency</string>
-					<string>211.ImportedFromIB2</string>
-					<string>212.IBPluginDependency</string>
-					<string>212.ImportedFromIB2</string>
-					<string>212.editorWindowContentRectSynchronizationRect</string>
-					<string>213.IBPluginDependency</string>
-					<string>213.ImportedFromIB2</string>
-					<string>214.IBPluginDependency</string>
-					<string>214.ImportedFromIB2</string>
-					<string>215.IBPluginDependency</string>
-					<string>215.ImportedFromIB2</string>
-					<string>216.IBPluginDependency</string>
-					<string>216.ImportedFromIB2</string>
-					<string>217.IBPluginDependency</string>
-					<string>217.ImportedFromIB2</string>
-					<string>218.IBPluginDependency</string>
-					<string>218.ImportedFromIB2</string>
-					<string>219.IBPluginDependency</string>
-					<string>219.ImportedFromIB2</string>
-					<string>220.IBPluginDependency</string>
-					<string>220.ImportedFromIB2</string>
-					<string>220.editorWindowContentRectSynchronizationRect</string>
-					<string>221.IBPluginDependency</string>
-					<string>221.ImportedFromIB2</string>
-					<string>23.IBPluginDependency</string>
-					<string>23.ImportedFromIB2</string>
 					<string>236.IBPluginDependency</string>
 					<string>236.ImportedFromIB2</string>
-					<string>239.IBPluginDependency</string>
-					<string>239.ImportedFromIB2</string>
-					<string>24.IBPluginDependency</string>
-					<string>24.ImportedFromIB2</string>
-					<string>24.editorWindowContentRectSynchronizationRect</string>
 					<string>29.IBEditorWindowLastContentRect</string>
 					<string>29.IBPluginDependency</string>
 					<string>29.ImportedFromIB2</string>
 					<string>29.WindowOrigin</string>
 					<string>29.editorWindowContentRectSynchronizationRect</string>
-					<string>295.IBPluginDependency</string>
-					<string>296.IBPluginDependency</string>
-					<string>296.editorWindowContentRectSynchronizationRect</string>
-					<string>297.IBPluginDependency</string>
-					<string>298.IBPluginDependency</string>
-					<string>346.IBPluginDependency</string>
-					<string>346.ImportedFromIB2</string>
-					<string>348.IBPluginDependency</string>
-					<string>348.ImportedFromIB2</string>
-					<string>349.IBPluginDependency</string>
-					<string>349.ImportedFromIB2</string>
-					<string>349.editorWindowContentRectSynchronizationRect</string>
-					<string>350.IBPluginDependency</string>
-					<string>350.ImportedFromIB2</string>
-					<string>351.IBPluginDependency</string>
-					<string>351.ImportedFromIB2</string>
-					<string>354.IBPluginDependency</string>
-					<string>354.ImportedFromIB2</string>
-					<string>375.IBPluginDependency</string>
-					<string>376.IBEditorWindowLastContentRect</string>
-					<string>376.IBPluginDependency</string>
-					<string>377.IBPluginDependency</string>
-					<string>378.IBPluginDependency</string>
-					<string>379.IBPluginDependency</string>
-					<string>380.IBPluginDependency</string>
-					<string>381.IBPluginDependency</string>
-					<string>382.IBPluginDependency</string>
-					<string>383.IBPluginDependency</string>
-					<string>384.IBPluginDependency</string>
-					<string>385.IBPluginDependency</string>
-					<string>386.IBPluginDependency</string>
-					<string>387.IBPluginDependency</string>
-					<string>388.IBEditorWindowLastContentRect</string>
-					<string>388.IBPluginDependency</string>
-					<string>389.IBPluginDependency</string>
-					<string>390.IBPluginDependency</string>
-					<string>391.IBPluginDependency</string>
-					<string>392.IBPluginDependency</string>
-					<string>393.IBPluginDependency</string>
-					<string>394.IBPluginDependency</string>
-					<string>395.IBPluginDependency</string>
-					<string>396.IBPluginDependency</string>
-					<string>397.IBPluginDependency</string>
-					<string>398.IBPluginDependency</string>
-					<string>399.IBPluginDependency</string>
-					<string>400.IBPluginDependency</string>
-					<string>401.IBPluginDependency</string>
-					<string>402.IBPluginDependency</string>
-					<string>403.IBPluginDependency</string>
-					<string>404.IBPluginDependency</string>
-					<string>405.IBPluginDependency</string>
-					<string>406.IBPluginDependency</string>
-					<string>407.IBPluginDependency</string>
-					<string>408.IBPluginDependency</string>
-					<string>409.IBPluginDependency</string>
-					<string>410.IBPluginDependency</string>
-					<string>411.IBPluginDependency</string>
-					<string>412.IBPluginDependency</string>
-					<string>413.IBPluginDependency</string>
-					<string>414.IBPluginDependency</string>
-					<string>415.IBPluginDependency</string>
-					<string>416.IBPluginDependency</string>
-					<string>417.IBPluginDependency</string>
-					<string>418.IBPluginDependency</string>
-					<string>419.IBPluginDependency</string>
-					<string>420.IBPluginDependency</string>
 					<string>458.IBPluginDependency</string>
-					<string>5.IBPluginDependency</string>
-					<string>5.ImportedFromIB2</string>
 					<string>56.IBPluginDependency</string>
 					<string>56.ImportedFromIB2</string>
 					<string>57.IBEditorWindowLastContentRect</string>
@@ -2733,32 +411,6 @@
 					<string>57.editorWindowContentRectSynchronizationRect</string>
 					<string>58.IBPluginDependency</string>
 					<string>58.ImportedFromIB2</string>
-					<string>72.IBPluginDependency</string>
-					<string>72.ImportedFromIB2</string>
-					<string>73.IBPluginDependency</string>
-					<string>73.ImportedFromIB2</string>
-					<string>74.IBPluginDependency</string>
-					<string>74.ImportedFromIB2</string>
-					<string>75.IBPluginDependency</string>
-					<string>75.ImportedFromIB2</string>
-					<string>77.IBPluginDependency</string>
-					<string>77.ImportedFromIB2</string>
-					<string>78.IBPluginDependency</string>
-					<string>78.ImportedFromIB2</string>
-					<string>79.IBPluginDependency</string>
-					<string>79.ImportedFromIB2</string>
-					<string>80.IBPluginDependency</string>
-					<string>80.ImportedFromIB2</string>
-					<string>81.IBEditorWindowLastContentRect</string>
-					<string>81.IBPluginDependency</string>
-					<string>81.ImportedFromIB2</string>
-					<string>81.editorWindowContentRectSynchronizationRect</string>
-					<string>82.IBPluginDependency</string>
-					<string>82.ImportedFromIB2</string>
-					<string>83.IBPluginDependency</string>
-					<string>83.ImportedFromIB2</string>
-					<string>92.IBPluginDependency</string>
-					<string>92.ImportedFromIB2</string>
 				</object>
 				<object class="NSMutableArray" key="dict.values">
 					<bool key="EncodedWithXMLCoder">YES</bool>
@@ -2769,22 +421,6 @@
 					<integer value="1" id="9"/>
 					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
 					<reference ref="9"/>
-					<string>{{596, 852}, {216, 23}}</string>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<reference ref="9"/>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<reference ref="9"/>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<reference ref="9"/>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<reference ref="9"/>
-					<string>{{522, 812}, {146, 23}}</string>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<reference ref="9"/>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<reference ref="9"/>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<reference ref="9"/>
 					<string>{{436, 809}, {64, 6}}</string>
 					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
 					<reference ref="9"/>
@@ -2804,182 +440,20 @@
 					<reference ref="9"/>
 					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
 					<reference ref="9"/>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<reference ref="9"/>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<reference ref="9"/>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<reference ref="9"/>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<reference ref="9"/>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<reference ref="9"/>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<reference ref="9"/>
-					<string>{{608, 612}, {275, 83}}</string>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<reference ref="9"/>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<reference ref="9"/>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<reference ref="9"/>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<reference ref="9"/>
-					<string>{{492, 116}, {243, 243}}</string>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<reference ref="9"/>
-					<string>{{187, 434}, {243, 243}}</string>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<reference ref="9"/>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<reference ref="9"/>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<reference ref="9"/>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<reference ref="9"/>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<reference ref="9"/>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<reference ref="9"/>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<reference ref="9"/>
-					<string>{{608, 612}, {167, 43}}</string>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<reference ref="9"/>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<reference ref="9"/>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<reference ref="9"/>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<reference ref="9"/>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<reference ref="9"/>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<reference ref="9"/>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<reference ref="9"/>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<reference ref="9"/>
-					<string>{{608, 612}, {241, 103}}</string>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<reference ref="9"/>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<reference ref="9"/>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<reference ref="9"/>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<reference ref="9"/>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<reference ref="9"/>
-					<string>{{525, 802}, {197, 73}}</string>
-					<string>{{306, 359}, {478, 20}}</string>
+					<string>{{306, 359}, {97, 20}}</string>
 					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
 					<reference ref="9"/>
 					<string>{74, 862}</string>
 					<string>{{6, 978}, {478, 20}}</string>
 					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
 					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<string>{{475, 832}, {234, 43}}</string>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<reference ref="9"/>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<reference ref="9"/>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<reference ref="9"/>
-					<string>{{608, 612}, {215, 63}}</string>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<reference ref="9"/>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<reference ref="9"/>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<reference ref="9"/>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<string>{{437, 242}, {86, 43}}</string>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<string>{{523, 2}, {178, 283}}</string>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<reference ref="9"/>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
 					<reference ref="9"/>
-					<string>{{318, 176}, {245, 183}}</string>
+					<string>{{318, 176}, {190, 183}}</string>
 					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
 					<reference ref="9"/>
 					<string>{{23, 794}, {245, 183}}</string>
 					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
 					<reference ref="9"/>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<reference ref="9"/>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<reference ref="9"/>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<reference ref="9"/>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<reference ref="9"/>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<reference ref="9"/>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<reference ref="9"/>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<reference ref="9"/>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<reference ref="9"/>
-					<string>{{450, 156}, {199, 203}}</string>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<reference ref="9"/>
-					<string>{{145, 474}, {199, 203}}</string>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<reference ref="9"/>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<reference ref="9"/>
-					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
-					<reference ref="9"/>
 				</object>
 			</object>
 			<object class="NSMutableDictionary" key="unlocalizedProperties">
-- 
cgit v0.10.2-6-g49f6


From ef4284acb29aca0bdf792ab40356c7955902e307 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Fri, 24 Jul 2009 21:28:19 +0200
Subject: LinkLocal: Publish->Register.


diff --git a/Swiften/LinkLocal/BonjourPublishQuery.h b/Swiften/LinkLocal/BonjourPublishQuery.h
deleted file mode 100644
index a96e25a..0000000
--- a/Swiften/LinkLocal/BonjourPublishQuery.h
+++ /dev/null
@@ -1,50 +0,0 @@
-#pragma once
-
-#include "Swiften/LinkLocal/BonjourQuery.h"
-#include "Swiften/LinkLocal/DNSSDPublishQuery.h"
-#include "Swiften/LinkLocal/LinkLocalServiceInfo.h"
-#include "Swiften/Base/ByteArray.h"
-#include "Swiften/EventLoop/MainEventLoop.h"
-
-namespace Swift {
-	class BonjourQuerier;
-
-	class BonjourPublishQuery : public DNSSDPublishQuery, public BonjourQuery {
-		public:	
-			BonjourPublishQuery(const String& name, int port, const LinkLocalServiceInfo& info, boost::shared_ptr<BonjourQuerier> querier) : BonjourQuery(querier) {
-				ByteArray txtRecord = info.toTXTRecord();
-				DNSServiceErrorType result = DNSServiceRegister(
-						&sdRef, 0, 0, name.getUTF8Data(), "_presence._tcp", NULL, NULL, port, 
-						txtRecord.getSize(), txtRecord.getData(), 
-						&BonjourPublishQuery::handleServicePublishedStatic, this);
-				if (result != kDNSServiceErr_NoError) {
-					// TODO
-					std::cerr << "Error creating service registration" << std::endl;
-				}
-			}
-
-			void publish() {
-				run();
-			}
-
-			void update(const LinkLocalService& info) {
-				boost::lock_guard<boost::mutex> lock(sdRefMutex);
-				ByteArray txtRecord = info.toTXTRecord();
-				DNSServiceUpdateRecord(sdRef, NULL, NULL, txtRecord.getSize(), txtRecord.getData(), 0);
-			}
-
-		private:
-			static void handleServicePublishedStatic(DNSServiceRef, DNSServiceFlags, DNSServiceErrorType errorCode, const char *name, const char *regtype, const char *domain, void *context) {
-				static_cast<BonjourPublishQuery*>(context)->handleServicePublished(errorCode, name, regtype, domain);
-			}
-
-			void handleServicePublished(DNSServiceErrorType errorCode, const char *name, const char *regtype, const char *domain) {
-				if (errorCode != kDNSServiceErr_NoError) {
-					MainEventLoop::postEvent(boost::bind(boost::ref(onPublishFinished), boost::optional<LinkLocalServiceID>()), shared_from_this());
-				}
-				else {
-					MainEventLoop::postEvent(boost::bind(boost::ref(onPublishFinished), boost::optional<LinkLocalServiceID>(LinkLocalServiceID(name, regtype, domain, 0))), shared_from_this());
-				}
-			}
-	};
-}
diff --git a/Swiften/LinkLocal/BonjourQuerier.cpp b/Swiften/LinkLocal/BonjourQuerier.cpp
index 3080869..7764f51 100644
--- a/Swiften/LinkLocal/BonjourQuerier.cpp
+++ b/Swiften/LinkLocal/BonjourQuerier.cpp
@@ -6,7 +6,7 @@
 #include <fcntl.h>
 
 #include "Swiften/LinkLocal/BonjourBrowseQuery.h"
-#include "Swiften/LinkLocal/BonjourPublishQuery.h"
+#include "Swiften/LinkLocal/BonjourRegisterQuery.h"
 #include "Swiften/Base/foreach.h"
 
 namespace Swift {
@@ -28,8 +28,8 @@ boost::shared_ptr<DNSSDBrowseQuery> BonjourQuerier::createBrowseQuery() {
 	return boost::shared_ptr<DNSSDBrowseQuery>(new BonjourBrowseQuery(shared_from_this()));
 }
 
-boost::shared_ptr<DNSSDPublishQuery> BonjourQuerier::createPublishQuery(const String& name, int port, const LinkLocalServiceInfo& info) {
-	return boost::shared_ptr<DNSSDPublishQuery>(new BonjourPublishQuery(name, port, info, shared_from_this()));
+boost::shared_ptr<DNSSDRegisterQuery> BonjourQuerier::createRegisterQuery(const String& name, int port, const LinkLocalServiceInfo& info) {
+	return boost::shared_ptr<DNSSDRegisterQuery>(new BonjourRegisterQuery(name, port, info, shared_from_this()));
 }
 
 void BonjourQuerier::addRunningQuery(boost::shared_ptr<BonjourQuery> query) {
diff --git a/Swiften/LinkLocal/BonjourQuerier.h b/Swiften/LinkLocal/BonjourQuerier.h
index e5ffa49..a35483c 100644
--- a/Swiften/LinkLocal/BonjourQuerier.h
+++ b/Swiften/LinkLocal/BonjourQuerier.h
@@ -7,7 +7,7 @@
 #include <boost/thread/mutex.hpp>
 
 #include "Swiften/LinkLocal/DNSSDBrowseQuery.h"
-#include "Swiften/LinkLocal/DNSSDPublishQuery.h"
+#include "Swiften/LinkLocal/DNSSDRegisterQuery.h"
 #include "Swiften/LinkLocal/BonjourQuery.h"
 
 namespace Swift {
@@ -19,7 +19,7 @@ namespace Swift {
 			~BonjourQuerier();
 
 			boost::shared_ptr<DNSSDBrowseQuery> createBrowseQuery();
-			boost::shared_ptr<DNSSDPublishQuery> createPublishQuery(const String& name, int port, const LinkLocalServiceInfo& info);
+			boost::shared_ptr<DNSSDRegisterQuery> createRegisterQuery(const String& name, int port, const LinkLocalServiceInfo& info);
 
 			void start();
 			void stop();
diff --git a/Swiften/LinkLocal/BonjourRegisterQuery.h b/Swiften/LinkLocal/BonjourRegisterQuery.h
new file mode 100644
index 0000000..c34ba02
--- /dev/null
+++ b/Swiften/LinkLocal/BonjourRegisterQuery.h
@@ -0,0 +1,50 @@
+#pragma once
+
+#include "Swiften/LinkLocal/BonjourQuery.h"
+#include "Swiften/LinkLocal/DNSSDRegisterQuery.h"
+#include "Swiften/LinkLocal/LinkLocalServiceInfo.h"
+#include "Swiften/Base/ByteArray.h"
+#include "Swiften/EventLoop/MainEventLoop.h"
+
+namespace Swift {
+	class BonjourQuerier;
+
+	class BonjourRegisterQuery : public DNSSDRegisterQuery, public BonjourQuery {
+		public:	
+			BonjourRegisterQuery(const String& name, int port, const LinkLocalServiceInfo& info, boost::shared_ptr<BonjourQuerier> querier) : BonjourQuery(querier) {
+				ByteArray txtRecord = info.toTXTRecord();
+				DNSServiceErrorType result = DNSServiceRegister(
+						&sdRef, 0, 0, name.getUTF8Data(), "_presence._tcp", NULL, NULL, port, 
+						txtRecord.getSize(), txtRecord.getData(), 
+						&BonjourRegisterQuery::handleServiceRegisteredStatic, this);
+				if (result != kDNSServiceErr_NoError) {
+					// TODO
+					std::cerr << "Error creating service registration" << std::endl;
+				}
+			}
+
+			void registerService() {
+				run();
+			}
+
+			void updateServiceInfo(const LinkLocalServiceInfo& info) {
+				boost::lock_guard<boost::mutex> lock(sdRefMutex);
+				ByteArray txtRecord = info.toTXTRecord();
+				DNSServiceUpdateRecord(sdRef, NULL, NULL, txtRecord.getSize(), txtRecord.getData(), 0);
+			}
+
+		private:
+			static void handleServiceRegisteredStatic(DNSServiceRef, DNSServiceFlags, DNSServiceErrorType errorCode, const char *name, const char *regtype, const char *domain, void *context) {
+				static_cast<BonjourRegisterQuery*>(context)->handleServiceRegistered(errorCode, name, regtype, domain);
+			}
+
+			void handleServiceRegistered(DNSServiceErrorType errorCode, const char *name, const char *regtype, const char *domain) {
+				if (errorCode != kDNSServiceErr_NoError) {
+					MainEventLoop::postEvent(boost::bind(boost::ref(onRegisterFinished), boost::optional<LinkLocalServiceID>()), shared_from_this());
+				}
+				else {
+					MainEventLoop::postEvent(boost::bind(boost::ref(onRegisterFinished), boost::optional<LinkLocalServiceID>(LinkLocalServiceID(name, regtype, domain, 0))), shared_from_this());
+				}
+			}
+	};
+}
diff --git a/Swiften/LinkLocal/DNSSDPublishQuery.cpp b/Swiften/LinkLocal/DNSSDPublishQuery.cpp
deleted file mode 100644
index cf3fd25..0000000
--- a/Swiften/LinkLocal/DNSSDPublishQuery.cpp
+++ /dev/null
@@ -1,8 +0,0 @@
-#include "Swiften/LinkLocal/DNSSDPublishQuery.h"
-
-namespace Swift {
-
-DNSSDPublishQuery::~DNSSDPublishQuery() {
-}
-
-}
diff --git a/Swiften/LinkLocal/DNSSDPublishQuery.h b/Swiften/LinkLocal/DNSSDPublishQuery.h
deleted file mode 100644
index 48c86dc..0000000
--- a/Swiften/LinkLocal/DNSSDPublishQuery.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#pragma once
-
-#include <boost/signal.hpp>
-#include <boost/optional.hpp>
-
-#include "Swiften/LinkLocal/LinkLocalServiceID.h"
-
-namespace Swift {
-	class DNSSDPublishQuery {
-		public:
-			virtual ~DNSSDPublishQuery();
-
-			virtual void publish() = 0;
-
-			boost::signal<void (boost::optional<LinkLocalServiceID>)> onPublishFinished;
-	};
-}
diff --git a/Swiften/LinkLocal/DNSSDRegisterQuery.cpp b/Swiften/LinkLocal/DNSSDRegisterQuery.cpp
new file mode 100644
index 0000000..fe00b02
--- /dev/null
+++ b/Swiften/LinkLocal/DNSSDRegisterQuery.cpp
@@ -0,0 +1,8 @@
+#include "Swiften/LinkLocal/DNSSDRegisterQuery.h"
+
+namespace Swift {
+
+DNSSDRegisterQuery::~DNSSDRegisterQuery() {
+}
+
+}
diff --git a/Swiften/LinkLocal/DNSSDRegisterQuery.h b/Swiften/LinkLocal/DNSSDRegisterQuery.h
new file mode 100644
index 0000000..252fbf0
--- /dev/null
+++ b/Swiften/LinkLocal/DNSSDRegisterQuery.h
@@ -0,0 +1,20 @@
+#pragma once
+
+#include <boost/signal.hpp>
+#include <boost/optional.hpp>
+
+#include "Swiften/LinkLocal/LinkLocalServiceID.h"
+
+namespace Swift {
+	class LinkLocalServiceInfo;
+
+	class DNSSDRegisterQuery {
+		public:
+			virtual ~DNSSDRegisterQuery();
+
+			virtual void registerService() = 0;
+			virtual void updateServiceInfo(const LinkLocalServiceInfo& info) = 0;
+
+			boost::signal<void (boost::optional<LinkLocalServiceID>)> onRegisterFinished;
+	};
+}
diff --git a/Swiften/LinkLocal/Makefile.inc b/Swiften/LinkLocal/Makefile.inc
index 902fa7a..a3144ac 100644
--- a/Swiften/LinkLocal/Makefile.inc
+++ b/Swiften/LinkLocal/Makefile.inc
@@ -1,6 +1,6 @@
 SWIFTEN_SOURCES += \
 	Swiften/LinkLocal/DNSSDBrowseQuery.cpp \
-	Swiften/LinkLocal/DNSSDPublishQuery.cpp \
+	Swiften/LinkLocal/DNSSDRegisterQuery.cpp \
 	Swiften/LinkLocal/DNSSDServiceFactory.cpp \
 	Swiften/LinkLocal/PlatformDNSSDServiceFactory.cpp \
 	Swiften/LinkLocal/DNSSDService.cpp \
diff --git a/configure.in b/configure.in
index 186bc3c..80e69c0 100644
--- a/configure.in
+++ b/configure.in
@@ -202,6 +202,7 @@ case $host in
 	*-mingw32*)
 		;;
 	*-*-darwin*)
+		HAVE_BONJOUR=yes
     AC_DEFINE(HAVE_BONJOUR)
 		;;
 	*)
-- 
cgit v0.10.2-6-g49f6


From b33a2937fe4a3cae0017892ad7f5c27b8a6f976d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Sat, 25 Jul 2009 10:35:33 +0200
Subject: Implement more DNSSD queries.


diff --git a/Slimber/CLI/main.cpp b/Slimber/CLI/main.cpp
index 65af3bc..3a72ca1 100644
--- a/Slimber/CLI/main.cpp
+++ b/Slimber/CLI/main.cpp
@@ -22,8 +22,8 @@ int main() {
 	querier->start();
 	boost::shared_ptr<DNSSDBrowseQuery> query = querier->createBrowseQuery();
 	query->startBrowsing();
-	boost::shared_ptr<DNSSDPublishQuery> query2 = querier->createPublishQuery("remko", 1234, LinkLocalServiceInfo());
-	query2->publish();
+	boost::shared_ptr<DNSSDRegisterQuery> query2 = querier->createRegisterQuery("remko", 1234, LinkLocalServiceInfo());
+	query2->registerService();
 
 /*
 	boost::shared_ptr<DNSSDService> dnsSDService;
diff --git a/Swiften/LinkLocal/BonjourQuerier.cpp b/Swiften/LinkLocal/BonjourQuerier.cpp
index 7764f51..42ba12a 100644
--- a/Swiften/LinkLocal/BonjourQuerier.cpp
+++ b/Swiften/LinkLocal/BonjourQuerier.cpp
@@ -2,11 +2,12 @@
 
 #include <unistd.h>
 #include <sys/socket.h>
-#include <netinet/in.h>
 #include <fcntl.h>
 
 #include "Swiften/LinkLocal/BonjourBrowseQuery.h"
 #include "Swiften/LinkLocal/BonjourRegisterQuery.h"
+#include "Swiften/LinkLocal/BonjourResolveServiceQuery.h"
+#include "Swiften/LinkLocal/BonjourResolveHostnameQuery.h"
 #include "Swiften/Base/foreach.h"
 
 namespace Swift {
@@ -32,6 +33,14 @@ boost::shared_ptr<DNSSDRegisterQuery> BonjourQuerier::createRegisterQuery(const
 	return boost::shared_ptr<DNSSDRegisterQuery>(new BonjourRegisterQuery(name, port, info, shared_from_this()));
 }
 
+boost::shared_ptr<DNSSDResolveServiceQuery> BonjourQuerier::createResolveServiceQuery(const LinkLocalServiceID& service) {
+	return boost::shared_ptr<DNSSDResolveServiceQuery>(new BonjourResolveServiceQuery(service, shared_from_this()));
+}
+
+boost::shared_ptr<DNSSDResolveHostnameQuery> BonjourQuerier::createResolveHostnameQuery(const String& hostname, int interfaceIndex) {
+	return boost::shared_ptr<DNSSDResolveHostnameQuery>(new BonjourResolveHostnameQuery(hostname, interfaceIndex, shared_from_this()));
+}
+
 void BonjourQuerier::addRunningQuery(boost::shared_ptr<BonjourQuery> query) {
 	{
 		boost::lock_guard<boost::mutex> lock(runningQueriesMutex);
diff --git a/Swiften/LinkLocal/BonjourQuerier.h b/Swiften/LinkLocal/BonjourQuerier.h
index a35483c..324e79e 100644
--- a/Swiften/LinkLocal/BonjourQuerier.h
+++ b/Swiften/LinkLocal/BonjourQuerier.h
@@ -6,20 +6,26 @@
 #include <boost/thread.hpp>
 #include <boost/thread/mutex.hpp>
 
-#include "Swiften/LinkLocal/DNSSDBrowseQuery.h"
-#include "Swiften/LinkLocal/DNSSDRegisterQuery.h"
+#include "Swiften/LinkLocal/DNSSDQuerier.h"
 #include "Swiften/LinkLocal/BonjourQuery.h"
 
 namespace Swift {
 	class LinkLocalServiceInfo;
 
-	class BonjourQuerier : public boost::enable_shared_from_this<BonjourQuerier> {
+	class BonjourQuerier : 
+			public DNSSDQuerier, 
+			public boost::enable_shared_from_this<BonjourQuerier> {
 		public:
 			BonjourQuerier();
 			~BonjourQuerier();
 
 			boost::shared_ptr<DNSSDBrowseQuery> createBrowseQuery();
-			boost::shared_ptr<DNSSDRegisterQuery> createRegisterQuery(const String& name, int port, const LinkLocalServiceInfo& info);
+			boost::shared_ptr<DNSSDRegisterQuery> createRegisterQuery(
+					const String& name, int port, const LinkLocalServiceInfo& info);
+			boost::shared_ptr<DNSSDResolveServiceQuery> createResolveServiceQuery(
+					const LinkLocalServiceID&);
+			boost::shared_ptr<DNSSDResolveHostnameQuery> createResolveHostnameQuery(
+					const String& hostname, int interfaceIndex);
 
 			void start();
 			void stop();
@@ -29,8 +35,6 @@ namespace Swift {
 
 			void addRunningQuery(boost::shared_ptr<BonjourQuery>);
 			void removeRunningQuery(boost::shared_ptr<BonjourQuery>);
-		
-		private:
 			void interruptSelect();
 			void run();
 
diff --git a/Swiften/LinkLocal/BonjourResolveHostnameQuery.h b/Swiften/LinkLocal/BonjourResolveHostnameQuery.h
new file mode 100644
index 0000000..771fc84
--- /dev/null
+++ b/Swiften/LinkLocal/BonjourResolveHostnameQuery.h
@@ -0,0 +1,54 @@
+#pragma once
+
+#include "Swiften/Base/String.h"
+#include "Swiften/LinkLocal/BonjourQuery.h"
+#include "Swiften/LinkLocal/DNSSDResolveHostnameQuery.h"
+#include "Swiften/EventLoop/MainEventLoop.h"
+#include "Swiften/Network/HostAddress.h"
+
+#include <netinet/in.h>
+
+namespace Swift {
+	class BonjourQuerier;
+
+	class BonjourResolveHostnameQuery : public DNSSDResolveHostnameQuery, public BonjourQuery {
+		public:	
+			BonjourResolveHostnameQuery(const String& hostname, int interfaceIndex, boost::shared_ptr<BonjourQuerier> querier) : BonjourQuery(querier) {
+				DNSServiceErrorType result = DNSServiceGetAddrInfo(
+						&sdRef, 0, interfaceIndex, kDNSServiceProtocol_IPv4, 
+						hostname.getUTF8Data(), 
+						&BonjourResolveHostnameQuery::handleHostnameResolvedStatic, this);
+				if (result != kDNSServiceErr_NoError) {
+					MainEventLoop::postEvent(boost::bind(boost::ref(onHostnameResolved), boost::optional<HostAddress>()), shared_from_this());
+				}
+			}
+
+			//void DNSSDResolveHostnameQuery::run() {
+			void run() {
+				BonjourQuery::run();
+			}
+
+		private:
+			static void handleHostnameResolvedStatic(DNSServiceRef, DNSServiceFlags, uint32_t, DNSServiceErrorType errorCode, const char*, const struct sockaddr *address, uint32_t, void *context) {
+				static_cast<BonjourResolveHostnameQuery*>(context)->handleHostnameResolved(errorCode, address);
+			} 
+
+			void handleHostnameResolved(DNSServiceErrorType errorCode, const struct sockaddr *rawAddress) {
+				if (errorCode) {
+					MainEventLoop::postEvent(
+								boost::bind(boost::ref(onHostnameResolved), 
+								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), 
+								HostAddress(reinterpret_cast<unsigned char*>(&address), 4)), 
+							shared_from_this());
+				}
+			}
+	};
+}
diff --git a/Swiften/LinkLocal/BonjourResolveServiceQuery.h b/Swiften/LinkLocal/BonjourResolveServiceQuery.h
new file mode 100644
index 0000000..e4f02ee
--- /dev/null
+++ b/Swiften/LinkLocal/BonjourResolveServiceQuery.h
@@ -0,0 +1,53 @@
+#pragma once
+
+#include "Swiften/LinkLocal/BonjourQuery.h"
+#include "Swiften/LinkLocal/DNSSDResolveServiceQuery.h"
+#include "Swiften/LinkLocal/LinkLocalServiceInfo.h"
+#include "Swiften/Base/ByteArray.h"
+#include "Swiften/EventLoop/MainEventLoop.h"
+
+namespace Swift {
+	class BonjourQuerier;
+
+	class BonjourResolveServiceQuery : public DNSSDResolveServiceQuery, public BonjourQuery {
+		public:	
+			BonjourResolveServiceQuery(const LinkLocalServiceID& service, boost::shared_ptr<BonjourQuerier> querier) : BonjourQuery(querier) {
+				DNSServiceErrorType result = DNSServiceResolve(
+						&sdRef, 0, service.getNetworkInterfaceID(), 
+						service.getName().getUTF8Data(), service.getType().getUTF8Data(), 
+						service.getDomain().getUTF8Data(), 
+						&BonjourResolveServiceQuery::handleServiceResolvedStatic, this);
+				if (result != kDNSServiceErr_NoError) {
+					MainEventLoop::postEvent(boost::bind(boost::ref(onServiceResolved), boost::optional<Result>()), shared_from_this());
+				}
+			}
+
+			void start() {
+				run();
+			}
+
+			void stop() {
+				finish();
+			}
+
+		private:
+			static void handleServiceResolvedStatic(DNSServiceRef, DNSServiceFlags, uint32_t, DNSServiceErrorType errorCode, const char *fullname, const char *hosttarget, uint16_t port, uint16_t txtLen, const unsigned char *txtRecord, void *context) {
+				static_cast<BonjourResolveServiceQuery*>(context)->handleServiceResolved(errorCode, fullname, hosttarget, port, txtLen, txtRecord);
+			}
+
+			void handleServiceResolved(DNSServiceErrorType errorCode, const char* fullName, const char* host, uint16_t port, uint16_t txtLen, const unsigned char *txtRecord) {
+				if (errorCode != kDNSServiceErr_NoError) {
+					MainEventLoop::postEvent(boost::bind(boost::ref(onServiceResolved), boost::optional<Result>()), shared_from_this());
+				}
+				else {
+					MainEventLoop::postEvent(
+							boost::bind(
+								boost::ref(onServiceResolved), 
+								Result(String(fullName), String(host), port, 
+									LinkLocalServiceInfo::createFromTXTRecord(
+										ByteArray(reinterpret_cast<const char*>(txtRecord), txtLen)))), 
+							shared_from_this());
+				}
+			}
+	};
+}
diff --git a/Swiften/LinkLocal/DNSSDQuerier.cpp b/Swiften/LinkLocal/DNSSDQuerier.cpp
new file mode 100644
index 0000000..be87a3c
--- /dev/null
+++ b/Swiften/LinkLocal/DNSSDQuerier.cpp
@@ -0,0 +1,8 @@
+#include "Swiften/LinkLocal/DNSSDQuerier.h"
+
+namespace Swift {
+
+DNSSDQuerier::~DNSSDQuerier() {
+}
+
+}
diff --git a/Swiften/LinkLocal/DNSSDQuerier.h b/Swiften/LinkLocal/DNSSDQuerier.h
new file mode 100644
index 0000000..528a6ea
--- /dev/null
+++ b/Swiften/LinkLocal/DNSSDQuerier.h
@@ -0,0 +1,26 @@
+#pragma once
+
+#include <boost/shared_ptr.hpp>
+
+namespace Swift {
+	class String;
+	class LinkLocalServiceInfo;
+	class LinkLocalServiceID;
+	class DNSSDBrowseQuery;
+	class DNSSDRegisterQuery;
+	class DNSSDResolveServiceQuery;
+	class DNSSDResolveHostnameQuery;
+
+	class DNSSDQuerier {
+		public:
+			virtual ~DNSSDQuerier();
+
+			virtual boost::shared_ptr<DNSSDBrowseQuery> createBrowseQuery() = 0;
+			virtual boost::shared_ptr<DNSSDRegisterQuery> createRegisterQuery(
+					const String& name, int port, const LinkLocalServiceInfo& info) = 0;
+			virtual boost::shared_ptr<DNSSDResolveServiceQuery> createResolveServiceQuery(
+					const LinkLocalServiceID&) = 0;
+			virtual boost::shared_ptr<DNSSDResolveHostnameQuery> createResolveHostnameQuery(
+					const String& hostname, int interfaceIndex) = 0;
+	};
+}
diff --git a/Swiften/LinkLocal/DNSSDResolveHostnameQuery.cpp b/Swiften/LinkLocal/DNSSDResolveHostnameQuery.cpp
new file mode 100644
index 0000000..f7c88bd
--- /dev/null
+++ b/Swiften/LinkLocal/DNSSDResolveHostnameQuery.cpp
@@ -0,0 +1,8 @@
+#include "Swiften/LinkLocal/DNSSDResolveHostnameQuery.h"
+
+namespace Swift {
+
+DNSSDResolveHostnameQuery::~DNSSDResolveHostnameQuery() {
+}
+
+}
diff --git a/Swiften/LinkLocal/DNSSDResolveHostnameQuery.h b/Swiften/LinkLocal/DNSSDResolveHostnameQuery.h
new file mode 100644
index 0000000..a2e218c
--- /dev/null
+++ b/Swiften/LinkLocal/DNSSDResolveHostnameQuery.h
@@ -0,0 +1,17 @@
+#pragma once
+
+#include <boost/signal.hpp>
+#include <boost/optional.hpp>
+
+#include "Swiften/Network/HostAddress.h"
+
+namespace Swift {
+	class DNSSDResolveHostnameQuery {
+		public:
+			virtual ~DNSSDResolveHostnameQuery();
+
+			virtual void run() = 0;
+
+			boost::signal<void (const boost::optional<HostAddress>&)> onHostnameResolved;
+	};
+}
diff --git a/Swiften/LinkLocal/DNSSDResolveServiceQuery.cpp b/Swiften/LinkLocal/DNSSDResolveServiceQuery.cpp
new file mode 100644
index 0000000..83a9ccd
--- /dev/null
+++ b/Swiften/LinkLocal/DNSSDResolveServiceQuery.cpp
@@ -0,0 +1,8 @@
+#include "Swiften/LinkLocal/DNSSDResolveServiceQuery.h"
+
+namespace Swift {
+
+DNSSDResolveServiceQuery::~DNSSDResolveServiceQuery() {
+}
+
+}
diff --git a/Swiften/LinkLocal/DNSSDResolveServiceQuery.h b/Swiften/LinkLocal/DNSSDResolveServiceQuery.h
new file mode 100644
index 0000000..d8b5cf1
--- /dev/null
+++ b/Swiften/LinkLocal/DNSSDResolveServiceQuery.h
@@ -0,0 +1,29 @@
+#pragma once
+
+#include <boost/signal.hpp>
+#include <boost/optional.hpp>
+
+#include "Swiften/LinkLocal/LinkLocalServiceID.h"
+#include "Swiften/LinkLocal/LinkLocalServiceInfo.h"
+
+namespace Swift {
+	class DNSSDResolveServiceQuery {
+		public:
+			struct Result {
+				Result(const String& fullName, const String& host, int port, 
+						const LinkLocalServiceInfo& info) : 
+							fullName(fullName), host(host), port(port), info(info) {}
+				String fullName;
+				String host;
+				int port;
+				LinkLocalServiceInfo info;
+			};
+
+			virtual ~DNSSDResolveServiceQuery();
+
+			virtual void start() = 0;
+			virtual void stop() = 0;
+
+			boost::signal<void (const boost::optional<Result>&)> onServiceResolved;
+	};
+}
diff --git a/Swiften/LinkLocal/Makefile.inc b/Swiften/LinkLocal/Makefile.inc
index a3144ac..9522cbb 100644
--- a/Swiften/LinkLocal/Makefile.inc
+++ b/Swiften/LinkLocal/Makefile.inc
@@ -1,6 +1,9 @@
 SWIFTEN_SOURCES += \
+	Swiften/LinkLocal/DNSSDQuerier.cpp \
 	Swiften/LinkLocal/DNSSDBrowseQuery.cpp \
 	Swiften/LinkLocal/DNSSDRegisterQuery.cpp \
+	Swiften/LinkLocal/DNSSDResolveServiceQuery.cpp \
+	Swiften/LinkLocal/DNSSDResolveHostnameQuery.cpp \
 	Swiften/LinkLocal/DNSSDServiceFactory.cpp \
 	Swiften/LinkLocal/PlatformDNSSDServiceFactory.cpp \
 	Swiften/LinkLocal/DNSSDService.cpp \
-- 
cgit v0.10.2-6-g49f6


From 0f77a684b42f25052eb1cfa688721e321526a90d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Sat, 25 Jul 2009 11:37:42 +0200
Subject: Created DNSSD submodule for LinkLocal.


diff --git a/Swiften/LinkLocal/BonjourBrowseQuery.h b/Swiften/LinkLocal/BonjourBrowseQuery.h
deleted file mode 100644
index 6db108d..0000000
--- a/Swiften/LinkLocal/BonjourBrowseQuery.h
+++ /dev/null
@@ -1,51 +0,0 @@
-#pragma once
-
-#include "Swiften/LinkLocal/BonjourQuery.h"
-#include "Swiften/LinkLocal/DNSSDBrowseQuery.h"
-#include "Swiften/EventLoop/MainEventLoop.h"
-
-namespace Swift {
-	class BonjourQuerier;
-
-	class BonjourBrowseQuery : public DNSSDBrowseQuery, public BonjourQuery {
-		public:	
-			BonjourBrowseQuery(boost::shared_ptr<BonjourQuerier> q) : BonjourQuery(q) {
-				DNSServiceErrorType result = DNSServiceBrowse(
-						&sdRef, 0, 0, "_presence._tcp", 0, 
-						&BonjourBrowseQuery::handleServiceDiscoveredStatic, this);
-				if (result != kDNSServiceErr_NoError) {
-					std::cout << "Error" << std::endl;
-					// TODO
-				}
-			}
-
-			void startBrowsing() {
-				assert(sdRef);
-				run();
-			}
-
-			void stopBrowsing() {
-				finish();
-			}
-
-		private:
-			static void handleServiceDiscoveredStatic(DNSServiceRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *name, const char *type, const char *domain, void *context) {
-				static_cast<BonjourBrowseQuery*>(context)->handleServiceDiscovered(flags, interfaceIndex, errorCode, name, type, domain);
-			}
-
-			void handleServiceDiscovered(DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *name, const char *type, const char *domain) {
-				if (errorCode != kDNSServiceErr_NoError) {
-					return;
-				}
-				else {
-					LinkLocalServiceID service(name, type, domain, 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());
-					}
-				}
-			}
-	};
-}
diff --git a/Swiften/LinkLocal/BonjourQuerier.cpp b/Swiften/LinkLocal/BonjourQuerier.cpp
deleted file mode 100644
index 42ba12a..0000000
--- a/Swiften/LinkLocal/BonjourQuerier.cpp
+++ /dev/null
@@ -1,128 +0,0 @@
-#include "Swiften/LinkLocal/BonjourQuerier.h"
-
-#include <unistd.h>
-#include <sys/socket.h>
-#include <fcntl.h>
-
-#include "Swiften/LinkLocal/BonjourBrowseQuery.h"
-#include "Swiften/LinkLocal/BonjourRegisterQuery.h"
-#include "Swiften/LinkLocal/BonjourResolveServiceQuery.h"
-#include "Swiften/LinkLocal/BonjourResolveHostnameQuery.h"
-#include "Swiften/Base/foreach.h"
-
-namespace Swift {
-
-BonjourQuerier::BonjourQuerier() : stopRequested(false), thread(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];
-}
-
-BonjourQuerier::~BonjourQuerier() {
-	stop();
-}
-
-boost::shared_ptr<DNSSDBrowseQuery> BonjourQuerier::createBrowseQuery() {
-	return boost::shared_ptr<DNSSDBrowseQuery>(new BonjourBrowseQuery(shared_from_this()));
-}
-
-boost::shared_ptr<DNSSDRegisterQuery> BonjourQuerier::createRegisterQuery(const String& name, int port, const LinkLocalServiceInfo& info) {
-	return boost::shared_ptr<DNSSDRegisterQuery>(new BonjourRegisterQuery(name, port, info, shared_from_this()));
-}
-
-boost::shared_ptr<DNSSDResolveServiceQuery> BonjourQuerier::createResolveServiceQuery(const LinkLocalServiceID& service) {
-	return boost::shared_ptr<DNSSDResolveServiceQuery>(new BonjourResolveServiceQuery(service, shared_from_this()));
-}
-
-boost::shared_ptr<DNSSDResolveHostnameQuery> BonjourQuerier::createResolveHostnameQuery(const String& hostname, int interfaceIndex) {
-	return boost::shared_ptr<DNSSDResolveHostnameQuery>(new BonjourResolveHostnameQuery(hostname, interfaceIndex, shared_from_this()));
-}
-
-void BonjourQuerier::addRunningQuery(boost::shared_ptr<BonjourQuery> query) {
-	{
-		boost::lock_guard<boost::mutex> lock(runningQueriesMutex);
-		runningQueries.push_back(query);
-	}
-	runningQueriesAvailableEvent.notify_one();
-	interruptSelect();
-}
-
-void BonjourQuerier::removeRunningQuery(boost::shared_ptr<BonjourQuery> query) {
-	{
-		boost::lock_guard<boost::mutex> lock(runningQueriesMutex);
-		runningQueries.erase(std::remove(
-			runningQueries.begin(), runningQueries.end(), query), runningQueries.end());
-	}
-}
-
-void BonjourQuerier::interruptSelect() {
-	char c = 0;
-	write(interruptSelectWriteSocket, &c, 1);
-}
-
-void BonjourQuerier::start() {
-	stop();
-	thread = new boost::thread(boost::bind(&BonjourQuerier::run, shared_from_this()));
-}
-
-void BonjourQuerier::stop() {
-	if (thread) {
-		stopRequested = true;
-		runningQueries.clear(); // TODO: Is this the right thing to do?
-		runningQueriesAvailableEvent.notify_one();
-		interruptSelect();
-		thread->join();
-		delete thread;
-		stopRequested = false;
-	}
-}
-
-void BonjourQuerier::run() {
-	while (!stopRequested) {
-		fd_set fdSet;
-		int maxSocket;
-		{
-			boost::unique_lock<boost::mutex> lock(runningQueriesMutex);
-			if (runningQueries.empty()) {
-				runningQueriesAvailableEvent.wait(lock);
-				if (runningQueries.empty()) {
-					continue;
-				}
-			}
-
-			// Run all running queries
-			FD_ZERO(&fdSet);
-			maxSocket = interruptSelectReadSocket;
-			FD_SET(interruptSelectReadSocket, &fdSet);
-
-			foreach(const boost::shared_ptr<BonjourQuery>& query, runningQueries) {
-				int socketID = query->getSocketID();
-				maxSocket = std::max(maxSocket, socketID);
-				FD_SET(socketID, &fdSet);
-			}
-		}
-
-		if (select(maxSocket+1, &fdSet, NULL, NULL, 0) <= 0) {
-			continue;
-		}
-
-		if (FD_ISSET(interruptSelectReadSocket, &fdSet)) {
-			char dummy;
-			while (read(interruptSelectReadSocket, &dummy, 1) > 0) {}
-		}
-
-		{
-			boost::lock_guard<boost::mutex> lock(runningQueriesMutex);
-			foreach(boost::shared_ptr<BonjourQuery> query, runningQueries) {
-				if (FD_ISSET(query->getSocketID(), &fdSet)) {
-					query->processResult();
-				}
-			}
-		}
-	}
-}
-
-}
diff --git a/Swiften/LinkLocal/BonjourQuerier.h b/Swiften/LinkLocal/BonjourQuerier.h
deleted file mode 100644
index 324e79e..0000000
--- a/Swiften/LinkLocal/BonjourQuerier.h
+++ /dev/null
@@ -1,50 +0,0 @@
-#pragma once
-
-#include <boost/shared_ptr.hpp>
-#include <boost/enable_shared_from_this.hpp>
-#include <list>
-#include <boost/thread.hpp>
-#include <boost/thread/mutex.hpp>
-
-#include "Swiften/LinkLocal/DNSSDQuerier.h"
-#include "Swiften/LinkLocal/BonjourQuery.h"
-
-namespace Swift {
-	class LinkLocalServiceInfo;
-
-	class BonjourQuerier : 
-			public DNSSDQuerier, 
-			public boost::enable_shared_from_this<BonjourQuerier> {
-		public:
-			BonjourQuerier();
-			~BonjourQuerier();
-
-			boost::shared_ptr<DNSSDBrowseQuery> createBrowseQuery();
-			boost::shared_ptr<DNSSDRegisterQuery> createRegisterQuery(
-					const String& name, int port, const LinkLocalServiceInfo& info);
-			boost::shared_ptr<DNSSDResolveServiceQuery> createResolveServiceQuery(
-					const LinkLocalServiceID&);
-			boost::shared_ptr<DNSSDResolveHostnameQuery> createResolveHostnameQuery(
-					const String& hostname, int interfaceIndex);
-
-			void start();
-			void stop();
-
-		private:
-			friend class BonjourQuery;
-
-			void addRunningQuery(boost::shared_ptr<BonjourQuery>);
-			void removeRunningQuery(boost::shared_ptr<BonjourQuery>);
-			void interruptSelect();
-			void run();
-
-		private:
-			bool stopRequested;
-			boost::thread* thread;
-			boost::mutex runningQueriesMutex;
-			std::list< boost::shared_ptr<BonjourQuery> > runningQueries;
-			int interruptSelectReadSocket;
-			int interruptSelectWriteSocket;
-			boost::condition_variable runningQueriesAvailableEvent;
-	};
-}
diff --git a/Swiften/LinkLocal/BonjourQuery.cpp b/Swiften/LinkLocal/BonjourQuery.cpp
deleted file mode 100644
index a9c13fb..0000000
--- a/Swiften/LinkLocal/BonjourQuery.cpp
+++ /dev/null
@@ -1,31 +0,0 @@
-#include "Swiften/LinkLocal/BonjourQuery.h"
-#include "Swiften/LinkLocal/BonjourQuerier.h"
-
-namespace Swift {
-
-BonjourQuery::BonjourQuery(boost::shared_ptr<BonjourQuerier> q) : querier(q), sdRef(0) {
-}
-
-BonjourQuery::~BonjourQuery() {
-	DNSServiceRefDeallocate(sdRef);
-}
-
-void BonjourQuery::processResult() {
-	boost::lock_guard<boost::mutex> lock(sdRefMutex);
-	DNSServiceProcessResult(sdRef);
-}
-
-int BonjourQuery::getSocketID() const {
-	boost::lock_guard<boost::mutex> lock(sdRefMutex);
-	return DNSServiceRefSockFD(sdRef);
-}
-
-void BonjourQuery::run() {
-	querier->addRunningQuery(shared_from_this());
-}
-
-void BonjourQuery::finish() {
-	querier->removeRunningQuery(shared_from_this());
-}
-
-}
diff --git a/Swiften/LinkLocal/BonjourQuery.h b/Swiften/LinkLocal/BonjourQuery.h
deleted file mode 100644
index bdb91a4..0000000
--- a/Swiften/LinkLocal/BonjourQuery.h
+++ /dev/null
@@ -1,32 +0,0 @@
-#pragma once
-
-#include <dns_sd.h>
-#include <boost/shared_ptr.hpp>
-#include <boost/enable_shared_from_this.hpp>
-#include <boost/thread/mutex.hpp>
-
-#include "Swiften/EventLoop/EventOwner.h"
-
-namespace Swift {
-	class BonjourQuerier;
-
-	class BonjourQuery : 
-			public EventOwner,
-			public boost::enable_shared_from_this<BonjourQuery> {
-		public:
-			BonjourQuery(boost::shared_ptr<BonjourQuerier>);
-			virtual ~BonjourQuery();
-			
-			void processResult();
-			int getSocketID() const;
-
-		protected:
-			void run();
-			void finish();
-		
-		protected:
-			boost::shared_ptr<BonjourQuerier> querier;
-			mutable boost::mutex sdRefMutex;
-			DNSServiceRef sdRef;
-	};
-}
diff --git a/Swiften/LinkLocal/BonjourRegisterQuery.h b/Swiften/LinkLocal/BonjourRegisterQuery.h
deleted file mode 100644
index c34ba02..0000000
--- a/Swiften/LinkLocal/BonjourRegisterQuery.h
+++ /dev/null
@@ -1,50 +0,0 @@
-#pragma once
-
-#include "Swiften/LinkLocal/BonjourQuery.h"
-#include "Swiften/LinkLocal/DNSSDRegisterQuery.h"
-#include "Swiften/LinkLocal/LinkLocalServiceInfo.h"
-#include "Swiften/Base/ByteArray.h"
-#include "Swiften/EventLoop/MainEventLoop.h"
-
-namespace Swift {
-	class BonjourQuerier;
-
-	class BonjourRegisterQuery : public DNSSDRegisterQuery, public BonjourQuery {
-		public:	
-			BonjourRegisterQuery(const String& name, int port, const LinkLocalServiceInfo& info, boost::shared_ptr<BonjourQuerier> querier) : BonjourQuery(querier) {
-				ByteArray txtRecord = info.toTXTRecord();
-				DNSServiceErrorType result = DNSServiceRegister(
-						&sdRef, 0, 0, name.getUTF8Data(), "_presence._tcp", NULL, NULL, port, 
-						txtRecord.getSize(), txtRecord.getData(), 
-						&BonjourRegisterQuery::handleServiceRegisteredStatic, this);
-				if (result != kDNSServiceErr_NoError) {
-					// TODO
-					std::cerr << "Error creating service registration" << std::endl;
-				}
-			}
-
-			void registerService() {
-				run();
-			}
-
-			void updateServiceInfo(const LinkLocalServiceInfo& info) {
-				boost::lock_guard<boost::mutex> lock(sdRefMutex);
-				ByteArray txtRecord = info.toTXTRecord();
-				DNSServiceUpdateRecord(sdRef, NULL, NULL, txtRecord.getSize(), txtRecord.getData(), 0);
-			}
-
-		private:
-			static void handleServiceRegisteredStatic(DNSServiceRef, DNSServiceFlags, DNSServiceErrorType errorCode, const char *name, const char *regtype, const char *domain, void *context) {
-				static_cast<BonjourRegisterQuery*>(context)->handleServiceRegistered(errorCode, name, regtype, domain);
-			}
-
-			void handleServiceRegistered(DNSServiceErrorType errorCode, const char *name, const char *regtype, const char *domain) {
-				if (errorCode != kDNSServiceErr_NoError) {
-					MainEventLoop::postEvent(boost::bind(boost::ref(onRegisterFinished), boost::optional<LinkLocalServiceID>()), shared_from_this());
-				}
-				else {
-					MainEventLoop::postEvent(boost::bind(boost::ref(onRegisterFinished), boost::optional<LinkLocalServiceID>(LinkLocalServiceID(name, regtype, domain, 0))), shared_from_this());
-				}
-			}
-	};
-}
diff --git a/Swiften/LinkLocal/BonjourResolveHostnameQuery.h b/Swiften/LinkLocal/BonjourResolveHostnameQuery.h
deleted file mode 100644
index 771fc84..0000000
--- a/Swiften/LinkLocal/BonjourResolveHostnameQuery.h
+++ /dev/null
@@ -1,54 +0,0 @@
-#pragma once
-
-#include "Swiften/Base/String.h"
-#include "Swiften/LinkLocal/BonjourQuery.h"
-#include "Swiften/LinkLocal/DNSSDResolveHostnameQuery.h"
-#include "Swiften/EventLoop/MainEventLoop.h"
-#include "Swiften/Network/HostAddress.h"
-
-#include <netinet/in.h>
-
-namespace Swift {
-	class BonjourQuerier;
-
-	class BonjourResolveHostnameQuery : public DNSSDResolveHostnameQuery, public BonjourQuery {
-		public:	
-			BonjourResolveHostnameQuery(const String& hostname, int interfaceIndex, boost::shared_ptr<BonjourQuerier> querier) : BonjourQuery(querier) {
-				DNSServiceErrorType result = DNSServiceGetAddrInfo(
-						&sdRef, 0, interfaceIndex, kDNSServiceProtocol_IPv4, 
-						hostname.getUTF8Data(), 
-						&BonjourResolveHostnameQuery::handleHostnameResolvedStatic, this);
-				if (result != kDNSServiceErr_NoError) {
-					MainEventLoop::postEvent(boost::bind(boost::ref(onHostnameResolved), boost::optional<HostAddress>()), shared_from_this());
-				}
-			}
-
-			//void DNSSDResolveHostnameQuery::run() {
-			void run() {
-				BonjourQuery::run();
-			}
-
-		private:
-			static void handleHostnameResolvedStatic(DNSServiceRef, DNSServiceFlags, uint32_t, DNSServiceErrorType errorCode, const char*, const struct sockaddr *address, uint32_t, void *context) {
-				static_cast<BonjourResolveHostnameQuery*>(context)->handleHostnameResolved(errorCode, address);
-			} 
-
-			void handleHostnameResolved(DNSServiceErrorType errorCode, const struct sockaddr *rawAddress) {
-				if (errorCode) {
-					MainEventLoop::postEvent(
-								boost::bind(boost::ref(onHostnameResolved), 
-								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), 
-								HostAddress(reinterpret_cast<unsigned char*>(&address), 4)), 
-							shared_from_this());
-				}
-			}
-	};
-}
diff --git a/Swiften/LinkLocal/BonjourResolveServiceQuery.h b/Swiften/LinkLocal/BonjourResolveServiceQuery.h
deleted file mode 100644
index e4f02ee..0000000
--- a/Swiften/LinkLocal/BonjourResolveServiceQuery.h
+++ /dev/null
@@ -1,53 +0,0 @@
-#pragma once
-
-#include "Swiften/LinkLocal/BonjourQuery.h"
-#include "Swiften/LinkLocal/DNSSDResolveServiceQuery.h"
-#include "Swiften/LinkLocal/LinkLocalServiceInfo.h"
-#include "Swiften/Base/ByteArray.h"
-#include "Swiften/EventLoop/MainEventLoop.h"
-
-namespace Swift {
-	class BonjourQuerier;
-
-	class BonjourResolveServiceQuery : public DNSSDResolveServiceQuery, public BonjourQuery {
-		public:	
-			BonjourResolveServiceQuery(const LinkLocalServiceID& service, boost::shared_ptr<BonjourQuerier> querier) : BonjourQuery(querier) {
-				DNSServiceErrorType result = DNSServiceResolve(
-						&sdRef, 0, service.getNetworkInterfaceID(), 
-						service.getName().getUTF8Data(), service.getType().getUTF8Data(), 
-						service.getDomain().getUTF8Data(), 
-						&BonjourResolveServiceQuery::handleServiceResolvedStatic, this);
-				if (result != kDNSServiceErr_NoError) {
-					MainEventLoop::postEvent(boost::bind(boost::ref(onServiceResolved), boost::optional<Result>()), shared_from_this());
-				}
-			}
-
-			void start() {
-				run();
-			}
-
-			void stop() {
-				finish();
-			}
-
-		private:
-			static void handleServiceResolvedStatic(DNSServiceRef, DNSServiceFlags, uint32_t, DNSServiceErrorType errorCode, const char *fullname, const char *hosttarget, uint16_t port, uint16_t txtLen, const unsigned char *txtRecord, void *context) {
-				static_cast<BonjourResolveServiceQuery*>(context)->handleServiceResolved(errorCode, fullname, hosttarget, port, txtLen, txtRecord);
-			}
-
-			void handleServiceResolved(DNSServiceErrorType errorCode, const char* fullName, const char* host, uint16_t port, uint16_t txtLen, const unsigned char *txtRecord) {
-				if (errorCode != kDNSServiceErr_NoError) {
-					MainEventLoop::postEvent(boost::bind(boost::ref(onServiceResolved), boost::optional<Result>()), shared_from_this());
-				}
-				else {
-					MainEventLoop::postEvent(
-							boost::bind(
-								boost::ref(onServiceResolved), 
-								Result(String(fullName), String(host), port, 
-									LinkLocalServiceInfo::createFromTXTRecord(
-										ByteArray(reinterpret_cast<const char*>(txtRecord), txtLen)))), 
-							shared_from_this());
-				}
-			}
-	};
-}
diff --git a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourBrowseQuery.h b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourBrowseQuery.h
new file mode 100644
index 0000000..edff064
--- /dev/null
+++ b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourBrowseQuery.h
@@ -0,0 +1,51 @@
+#pragma once
+
+#include "Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuery.h"
+#include "Swiften/LinkLocal/DNSSD/DNSSDBrowseQuery.h"
+#include "Swiften/EventLoop/MainEventLoop.h"
+
+namespace Swift {
+	class BonjourQuerier;
+
+	class BonjourBrowseQuery : public DNSSDBrowseQuery, public BonjourQuery {
+		public:	
+			BonjourBrowseQuery(boost::shared_ptr<BonjourQuerier> q) : BonjourQuery(q) {
+				DNSServiceErrorType result = DNSServiceBrowse(
+						&sdRef, 0, 0, "_presence._tcp", 0, 
+						&BonjourBrowseQuery::handleServiceDiscoveredStatic, this);
+				if (result != kDNSServiceErr_NoError) {
+					std::cout << "Error" << std::endl;
+					// TODO
+				}
+			}
+
+			void startBrowsing() {
+				assert(sdRef);
+				run();
+			}
+
+			void stopBrowsing() {
+				finish();
+			}
+
+		private:
+			static void handleServiceDiscoveredStatic(DNSServiceRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *name, const char *type, const char *domain, void *context) {
+				static_cast<BonjourBrowseQuery*>(context)->handleServiceDiscovered(flags, interfaceIndex, errorCode, name, type, domain);
+			}
+
+			void handleServiceDiscovered(DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *name, const char *type, const char *domain) {
+				if (errorCode != kDNSServiceErr_NoError) {
+					return;
+				}
+				else {
+					LinkLocalServiceID service(name, type, domain, 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());
+					}
+				}
+			}
+	};
+}
diff --git a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuerier.cpp b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuerier.cpp
new file mode 100644
index 0000000..064e3c5
--- /dev/null
+++ b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuerier.cpp
@@ -0,0 +1,128 @@
+#include "Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuerier.h"
+
+#include <unistd.h>
+#include <sys/socket.h>
+#include <fcntl.h>
+
+#include "Swiften/LinkLocal/DNSSD/Bonjour/BonjourBrowseQuery.h"
+#include "Swiften/LinkLocal/DNSSD/Bonjour/BonjourRegisterQuery.h"
+#include "Swiften/LinkLocal/DNSSD/Bonjour/BonjourResolveServiceQuery.h"
+#include "Swiften/LinkLocal/DNSSD/Bonjour/BonjourResolveHostnameQuery.h"
+#include "Swiften/Base/foreach.h"
+
+namespace Swift {
+
+BonjourQuerier::BonjourQuerier() : stopRequested(false), thread(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];
+}
+
+BonjourQuerier::~BonjourQuerier() {
+	stop();
+}
+
+boost::shared_ptr<DNSSDBrowseQuery> BonjourQuerier::createBrowseQuery() {
+	return boost::shared_ptr<DNSSDBrowseQuery>(new BonjourBrowseQuery(shared_from_this()));
+}
+
+boost::shared_ptr<DNSSDRegisterQuery> BonjourQuerier::createRegisterQuery(const String& name, int port, const LinkLocalServiceInfo& info) {
+	return boost::shared_ptr<DNSSDRegisterQuery>(new BonjourRegisterQuery(name, port, info, shared_from_this()));
+}
+
+boost::shared_ptr<DNSSDResolveServiceQuery> BonjourQuerier::createResolveServiceQuery(const LinkLocalServiceID& service) {
+	return boost::shared_ptr<DNSSDResolveServiceQuery>(new BonjourResolveServiceQuery(service, shared_from_this()));
+}
+
+boost::shared_ptr<DNSSDResolveHostnameQuery> BonjourQuerier::createResolveHostnameQuery(const String& hostname, int interfaceIndex) {
+	return boost::shared_ptr<DNSSDResolveHostnameQuery>(new BonjourResolveHostnameQuery(hostname, interfaceIndex, shared_from_this()));
+}
+
+void BonjourQuerier::addRunningQuery(boost::shared_ptr<BonjourQuery> query) {
+	{
+		boost::lock_guard<boost::mutex> lock(runningQueriesMutex);
+		runningQueries.push_back(query);
+	}
+	runningQueriesAvailableEvent.notify_one();
+	interruptSelect();
+}
+
+void BonjourQuerier::removeRunningQuery(boost::shared_ptr<BonjourQuery> query) {
+	{
+		boost::lock_guard<boost::mutex> lock(runningQueriesMutex);
+		runningQueries.erase(std::remove(
+			runningQueries.begin(), runningQueries.end(), query), runningQueries.end());
+	}
+}
+
+void BonjourQuerier::interruptSelect() {
+	char c = 0;
+	write(interruptSelectWriteSocket, &c, 1);
+}
+
+void BonjourQuerier::start() {
+	stop();
+	thread = new boost::thread(boost::bind(&BonjourQuerier::run, shared_from_this()));
+}
+
+void BonjourQuerier::stop() {
+	if (thread) {
+		stopRequested = true;
+		runningQueries.clear(); // TODO: Is this the right thing to do?
+		runningQueriesAvailableEvent.notify_one();
+		interruptSelect();
+		thread->join();
+		delete thread;
+		stopRequested = false;
+	}
+}
+
+void BonjourQuerier::run() {
+	while (!stopRequested) {
+		fd_set fdSet;
+		int maxSocket;
+		{
+			boost::unique_lock<boost::mutex> lock(runningQueriesMutex);
+			if (runningQueries.empty()) {
+				runningQueriesAvailableEvent.wait(lock);
+				if (runningQueries.empty()) {
+					continue;
+				}
+			}
+
+			// Run all running queries
+			FD_ZERO(&fdSet);
+			maxSocket = interruptSelectReadSocket;
+			FD_SET(interruptSelectReadSocket, &fdSet);
+
+			foreach(const boost::shared_ptr<BonjourQuery>& query, runningQueries) {
+				int socketID = query->getSocketID();
+				maxSocket = std::max(maxSocket, socketID);
+				FD_SET(socketID, &fdSet);
+			}
+		}
+
+		if (select(maxSocket+1, &fdSet, NULL, NULL, 0) <= 0) {
+			continue;
+		}
+
+		if (FD_ISSET(interruptSelectReadSocket, &fdSet)) {
+			char dummy;
+			while (read(interruptSelectReadSocket, &dummy, 1) > 0) {}
+		}
+
+		{
+			boost::lock_guard<boost::mutex> lock(runningQueriesMutex);
+			foreach(boost::shared_ptr<BonjourQuery> query, runningQueries) {
+				if (FD_ISSET(query->getSocketID(), &fdSet)) {
+					query->processResult();
+				}
+			}
+		}
+	}
+}
+
+}
diff --git a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuerier.h b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuerier.h
new file mode 100644
index 0000000..79f9a81
--- /dev/null
+++ b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuerier.h
@@ -0,0 +1,50 @@
+#pragma once
+
+#include <boost/shared_ptr.hpp>
+#include <boost/enable_shared_from_this.hpp>
+#include <list>
+#include <boost/thread.hpp>
+#include <boost/thread/mutex.hpp>
+
+#include "Swiften/LinkLocal/DNSSD/DNSSDQuerier.h"
+#include "Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuery.h"
+
+namespace Swift {
+	class LinkLocalServiceInfo;
+
+	class BonjourQuerier : 
+			public DNSSDQuerier, 
+			public boost::enable_shared_from_this<BonjourQuerier> {
+		public:
+			BonjourQuerier();
+			~BonjourQuerier();
+
+			boost::shared_ptr<DNSSDBrowseQuery> createBrowseQuery();
+			boost::shared_ptr<DNSSDRegisterQuery> createRegisterQuery(
+					const String& name, int port, const LinkLocalServiceInfo& info);
+			boost::shared_ptr<DNSSDResolveServiceQuery> createResolveServiceQuery(
+					const LinkLocalServiceID&);
+			boost::shared_ptr<DNSSDResolveHostnameQuery> createResolveHostnameQuery(
+					const String& hostname, int interfaceIndex);
+
+			void start();
+			void stop();
+
+		private:
+			friend class BonjourQuery;
+
+			void addRunningQuery(boost::shared_ptr<BonjourQuery>);
+			void removeRunningQuery(boost::shared_ptr<BonjourQuery>);
+			void interruptSelect();
+			void run();
+
+		private:
+			bool stopRequested;
+			boost::thread* thread;
+			boost::mutex runningQueriesMutex;
+			std::list< boost::shared_ptr<BonjourQuery> > runningQueries;
+			int interruptSelectReadSocket;
+			int interruptSelectWriteSocket;
+			boost::condition_variable runningQueriesAvailableEvent;
+	};
+}
diff --git a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuery.cpp b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuery.cpp
new file mode 100644
index 0000000..c1c481b
--- /dev/null
+++ b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuery.cpp
@@ -0,0 +1,31 @@
+#include "Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuery.h"
+#include "Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuerier.h"
+
+namespace Swift {
+
+BonjourQuery::BonjourQuery(boost::shared_ptr<BonjourQuerier> q) : querier(q), sdRef(0) {
+}
+
+BonjourQuery::~BonjourQuery() {
+	DNSServiceRefDeallocate(sdRef);
+}
+
+void BonjourQuery::processResult() {
+	boost::lock_guard<boost::mutex> lock(sdRefMutex);
+	DNSServiceProcessResult(sdRef);
+}
+
+int BonjourQuery::getSocketID() const {
+	boost::lock_guard<boost::mutex> lock(sdRefMutex);
+	return DNSServiceRefSockFD(sdRef);
+}
+
+void BonjourQuery::run() {
+	querier->addRunningQuery(shared_from_this());
+}
+
+void BonjourQuery::finish() {
+	querier->removeRunningQuery(shared_from_this());
+}
+
+}
diff --git a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuery.h b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuery.h
new file mode 100644
index 0000000..bdb91a4
--- /dev/null
+++ b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuery.h
@@ -0,0 +1,32 @@
+#pragma once
+
+#include <dns_sd.h>
+#include <boost/shared_ptr.hpp>
+#include <boost/enable_shared_from_this.hpp>
+#include <boost/thread/mutex.hpp>
+
+#include "Swiften/EventLoop/EventOwner.h"
+
+namespace Swift {
+	class BonjourQuerier;
+
+	class BonjourQuery : 
+			public EventOwner,
+			public boost::enable_shared_from_this<BonjourQuery> {
+		public:
+			BonjourQuery(boost::shared_ptr<BonjourQuerier>);
+			virtual ~BonjourQuery();
+			
+			void processResult();
+			int getSocketID() const;
+
+		protected:
+			void run();
+			void finish();
+		
+		protected:
+			boost::shared_ptr<BonjourQuerier> querier;
+			mutable boost::mutex sdRefMutex;
+			DNSServiceRef sdRef;
+	};
+}
diff --git a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourRegisterQuery.h b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourRegisterQuery.h
new file mode 100644
index 0000000..31e86fc
--- /dev/null
+++ b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourRegisterQuery.h
@@ -0,0 +1,50 @@
+#pragma once
+
+#include "Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuery.h"
+#include "Swiften/LinkLocal/DNSSD/DNSSDRegisterQuery.h"
+#include "Swiften/LinkLocal/LinkLocalServiceInfo.h"
+#include "Swiften/Base/ByteArray.h"
+#include "Swiften/EventLoop/MainEventLoop.h"
+
+namespace Swift {
+	class BonjourQuerier;
+
+	class BonjourRegisterQuery : public DNSSDRegisterQuery, public BonjourQuery {
+		public:	
+			BonjourRegisterQuery(const String& name, int port, const LinkLocalServiceInfo& info, boost::shared_ptr<BonjourQuerier> querier) : BonjourQuery(querier) {
+				ByteArray txtRecord = info.toTXTRecord();
+				DNSServiceErrorType result = DNSServiceRegister(
+						&sdRef, 0, 0, name.getUTF8Data(), "_presence._tcp", NULL, NULL, port, 
+						txtRecord.getSize(), txtRecord.getData(), 
+						&BonjourRegisterQuery::handleServiceRegisteredStatic, this);
+				if (result != kDNSServiceErr_NoError) {
+					// TODO
+					std::cerr << "Error creating service registration" << std::endl;
+				}
+			}
+
+			void registerService() {
+				run();
+			}
+
+			void updateServiceInfo(const LinkLocalServiceInfo& info) {
+				boost::lock_guard<boost::mutex> lock(sdRefMutex);
+				ByteArray txtRecord = info.toTXTRecord();
+				DNSServiceUpdateRecord(sdRef, NULL, NULL, txtRecord.getSize(), txtRecord.getData(), 0);
+			}
+
+		private:
+			static void handleServiceRegisteredStatic(DNSServiceRef, DNSServiceFlags, DNSServiceErrorType errorCode, const char *name, const char *regtype, const char *domain, void *context) {
+				static_cast<BonjourRegisterQuery*>(context)->handleServiceRegistered(errorCode, name, regtype, domain);
+			}
+
+			void handleServiceRegistered(DNSServiceErrorType errorCode, const char *name, const char *regtype, const char *domain) {
+				if (errorCode != kDNSServiceErr_NoError) {
+					MainEventLoop::postEvent(boost::bind(boost::ref(onRegisterFinished), boost::optional<LinkLocalServiceID>()), shared_from_this());
+				}
+				else {
+					MainEventLoop::postEvent(boost::bind(boost::ref(onRegisterFinished), boost::optional<LinkLocalServiceID>(LinkLocalServiceID(name, regtype, domain, 0))), shared_from_this());
+				}
+			}
+	};
+}
diff --git a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourResolveHostnameQuery.h b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourResolveHostnameQuery.h
new file mode 100644
index 0000000..58c6588
--- /dev/null
+++ b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourResolveHostnameQuery.h
@@ -0,0 +1,54 @@
+#pragma once
+
+#include "Swiften/Base/String.h"
+#include "Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuery.h"
+#include "Swiften/LinkLocal/DNSSD/DNSSDResolveHostnameQuery.h"
+#include "Swiften/EventLoop/MainEventLoop.h"
+#include "Swiften/Network/HostAddress.h"
+
+#include <netinet/in.h>
+
+namespace Swift {
+	class BonjourQuerier;
+
+	class BonjourResolveHostnameQuery : public DNSSDResolveHostnameQuery, public BonjourQuery {
+		public:	
+			BonjourResolveHostnameQuery(const String& hostname, int interfaceIndex, boost::shared_ptr<BonjourQuerier> querier) : BonjourQuery(querier) {
+				DNSServiceErrorType result = DNSServiceGetAddrInfo(
+						&sdRef, 0, interfaceIndex, kDNSServiceProtocol_IPv4, 
+						hostname.getUTF8Data(), 
+						&BonjourResolveHostnameQuery::handleHostnameResolvedStatic, this);
+				if (result != kDNSServiceErr_NoError) {
+					MainEventLoop::postEvent(boost::bind(boost::ref(onHostnameResolved), boost::optional<HostAddress>()), shared_from_this());
+				}
+			}
+
+			//void DNSSDResolveHostnameQuery::run() {
+			void run() {
+				BonjourQuery::run();
+			}
+
+		private:
+			static void handleHostnameResolvedStatic(DNSServiceRef, DNSServiceFlags, uint32_t, DNSServiceErrorType errorCode, const char*, const struct sockaddr *address, uint32_t, void *context) {
+				static_cast<BonjourResolveHostnameQuery*>(context)->handleHostnameResolved(errorCode, address);
+			} 
+
+			void handleHostnameResolved(DNSServiceErrorType errorCode, const struct sockaddr *rawAddress) {
+				if (errorCode) {
+					MainEventLoop::postEvent(
+								boost::bind(boost::ref(onHostnameResolved), 
+								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), 
+								HostAddress(reinterpret_cast<unsigned char*>(&address), 4)), 
+							shared_from_this());
+				}
+			}
+	};
+}
diff --git a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourResolveServiceQuery.h b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourResolveServiceQuery.h
new file mode 100644
index 0000000..1afdf5a
--- /dev/null
+++ b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourResolveServiceQuery.h
@@ -0,0 +1,53 @@
+#pragma once
+
+#include "Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuery.h"
+#include "Swiften/LinkLocal/DNSSD/DNSSDResolveServiceQuery.h"
+#include "Swiften/LinkLocal/LinkLocalServiceInfo.h"
+#include "Swiften/Base/ByteArray.h"
+#include "Swiften/EventLoop/MainEventLoop.h"
+
+namespace Swift {
+	class BonjourQuerier;
+
+	class BonjourResolveServiceQuery : public DNSSDResolveServiceQuery, public BonjourQuery {
+		public:	
+			BonjourResolveServiceQuery(const LinkLocalServiceID& service, boost::shared_ptr<BonjourQuerier> querier) : BonjourQuery(querier) {
+				DNSServiceErrorType result = DNSServiceResolve(
+						&sdRef, 0, service.getNetworkInterfaceID(), 
+						service.getName().getUTF8Data(), service.getType().getUTF8Data(), 
+						service.getDomain().getUTF8Data(), 
+						&BonjourResolveServiceQuery::handleServiceResolvedStatic, this);
+				if (result != kDNSServiceErr_NoError) {
+					MainEventLoop::postEvent(boost::bind(boost::ref(onServiceResolved), boost::optional<Result>()), shared_from_this());
+				}
+			}
+
+			void start() {
+				run();
+			}
+
+			void stop() {
+				finish();
+			}
+
+		private:
+			static void handleServiceResolvedStatic(DNSServiceRef, DNSServiceFlags, uint32_t, DNSServiceErrorType errorCode, const char *fullname, const char *hosttarget, uint16_t port, uint16_t txtLen, const unsigned char *txtRecord, void *context) {
+				static_cast<BonjourResolveServiceQuery*>(context)->handleServiceResolved(errorCode, fullname, hosttarget, port, txtLen, txtRecord);
+			}
+
+			void handleServiceResolved(DNSServiceErrorType errorCode, const char* fullName, const char* host, uint16_t port, uint16_t txtLen, const unsigned char *txtRecord) {
+				if (errorCode != kDNSServiceErr_NoError) {
+					MainEventLoop::postEvent(boost::bind(boost::ref(onServiceResolved), boost::optional<Result>()), shared_from_this());
+				}
+				else {
+					MainEventLoop::postEvent(
+							boost::bind(
+								boost::ref(onServiceResolved), 
+								Result(String(fullName), String(host), port, 
+									LinkLocalServiceInfo::createFromTXTRecord(
+										ByteArray(reinterpret_cast<const char*>(txtRecord), txtLen)))), 
+							shared_from_this());
+				}
+			}
+	};
+}
diff --git a/Swiften/LinkLocal/DNSSD/Bonjour/Makefile.inc b/Swiften/LinkLocal/DNSSD/Bonjour/Makefile.inc
new file mode 100644
index 0000000..efa329d
--- /dev/null
+++ b/Swiften/LinkLocal/DNSSD/Bonjour/Makefile.inc
@@ -0,0 +1,3 @@
+SWIFTEN_SOURCES += \
+	Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuery.cpp \
+	Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuerier.cpp
diff --git a/Swiften/LinkLocal/DNSSD/DNSSDBrowseQuery.cpp b/Swiften/LinkLocal/DNSSD/DNSSDBrowseQuery.cpp
new file mode 100644
index 0000000..1dbff2c
--- /dev/null
+++ b/Swiften/LinkLocal/DNSSD/DNSSDBrowseQuery.cpp
@@ -0,0 +1,8 @@
+#include "Swiften/LinkLocal/DNSSD/DNSSDBrowseQuery.h"
+
+namespace Swift {
+
+DNSSDBrowseQuery::~DNSSDBrowseQuery() {
+}
+
+}
diff --git a/Swiften/LinkLocal/DNSSD/DNSSDBrowseQuery.h b/Swiften/LinkLocal/DNSSD/DNSSDBrowseQuery.h
new file mode 100644
index 0000000..e548ca5
--- /dev/null
+++ b/Swiften/LinkLocal/DNSSD/DNSSDBrowseQuery.h
@@ -0,0 +1,18 @@
+#pragma once
+
+#include <boost/signal.hpp>
+
+#include "Swiften/LinkLocal/LinkLocalServiceID.h"
+
+namespace Swift {
+	class DNSSDBrowseQuery {
+		public:
+			virtual ~DNSSDBrowseQuery();
+
+			virtual void startBrowsing() = 0;
+			virtual void stopBrowsing() = 0;
+
+			boost::signal<void (const LinkLocalServiceID&)> onServiceAdded;
+			boost::signal<void (const LinkLocalServiceID&)> onServiceRemoved;
+	};
+}
diff --git a/Swiften/LinkLocal/DNSSD/DNSSDQuerier.cpp b/Swiften/LinkLocal/DNSSD/DNSSDQuerier.cpp
new file mode 100644
index 0000000..cc8d6ef
--- /dev/null
+++ b/Swiften/LinkLocal/DNSSD/DNSSDQuerier.cpp
@@ -0,0 +1,8 @@
+#include "Swiften/LinkLocal/DNSSD/DNSSDQuerier.h"
+
+namespace Swift {
+
+DNSSDQuerier::~DNSSDQuerier() {
+}
+
+}
diff --git a/Swiften/LinkLocal/DNSSD/DNSSDQuerier.h b/Swiften/LinkLocal/DNSSD/DNSSDQuerier.h
new file mode 100644
index 0000000..528a6ea
--- /dev/null
+++ b/Swiften/LinkLocal/DNSSD/DNSSDQuerier.h
@@ -0,0 +1,26 @@
+#pragma once
+
+#include <boost/shared_ptr.hpp>
+
+namespace Swift {
+	class String;
+	class LinkLocalServiceInfo;
+	class LinkLocalServiceID;
+	class DNSSDBrowseQuery;
+	class DNSSDRegisterQuery;
+	class DNSSDResolveServiceQuery;
+	class DNSSDResolveHostnameQuery;
+
+	class DNSSDQuerier {
+		public:
+			virtual ~DNSSDQuerier();
+
+			virtual boost::shared_ptr<DNSSDBrowseQuery> createBrowseQuery() = 0;
+			virtual boost::shared_ptr<DNSSDRegisterQuery> createRegisterQuery(
+					const String& name, int port, const LinkLocalServiceInfo& info) = 0;
+			virtual boost::shared_ptr<DNSSDResolveServiceQuery> createResolveServiceQuery(
+					const LinkLocalServiceID&) = 0;
+			virtual boost::shared_ptr<DNSSDResolveHostnameQuery> createResolveHostnameQuery(
+					const String& hostname, int interfaceIndex) = 0;
+	};
+}
diff --git a/Swiften/LinkLocal/DNSSD/DNSSDRegisterQuery.cpp b/Swiften/LinkLocal/DNSSD/DNSSDRegisterQuery.cpp
new file mode 100644
index 0000000..bbb8692
--- /dev/null
+++ b/Swiften/LinkLocal/DNSSD/DNSSDRegisterQuery.cpp
@@ -0,0 +1,8 @@
+#include "Swiften/LinkLocal/DNSSD/DNSSDRegisterQuery.h"
+
+namespace Swift {
+
+DNSSDRegisterQuery::~DNSSDRegisterQuery() {
+}
+
+}
diff --git a/Swiften/LinkLocal/DNSSD/DNSSDRegisterQuery.h b/Swiften/LinkLocal/DNSSD/DNSSDRegisterQuery.h
new file mode 100644
index 0000000..252fbf0
--- /dev/null
+++ b/Swiften/LinkLocal/DNSSD/DNSSDRegisterQuery.h
@@ -0,0 +1,20 @@
+#pragma once
+
+#include <boost/signal.hpp>
+#include <boost/optional.hpp>
+
+#include "Swiften/LinkLocal/LinkLocalServiceID.h"
+
+namespace Swift {
+	class LinkLocalServiceInfo;
+
+	class DNSSDRegisterQuery {
+		public:
+			virtual ~DNSSDRegisterQuery();
+
+			virtual void registerService() = 0;
+			virtual void updateServiceInfo(const LinkLocalServiceInfo& info) = 0;
+
+			boost::signal<void (boost::optional<LinkLocalServiceID>)> onRegisterFinished;
+	};
+}
diff --git a/Swiften/LinkLocal/DNSSD/DNSSDResolveHostnameQuery.cpp b/Swiften/LinkLocal/DNSSD/DNSSDResolveHostnameQuery.cpp
new file mode 100644
index 0000000..e247e39
--- /dev/null
+++ b/Swiften/LinkLocal/DNSSD/DNSSDResolveHostnameQuery.cpp
@@ -0,0 +1,8 @@
+#include "Swiften/LinkLocal/DNSSD/DNSSDResolveHostnameQuery.h"
+
+namespace Swift {
+
+DNSSDResolveHostnameQuery::~DNSSDResolveHostnameQuery() {
+}
+
+}
diff --git a/Swiften/LinkLocal/DNSSD/DNSSDResolveHostnameQuery.h b/Swiften/LinkLocal/DNSSD/DNSSDResolveHostnameQuery.h
new file mode 100644
index 0000000..a2e218c
--- /dev/null
+++ b/Swiften/LinkLocal/DNSSD/DNSSDResolveHostnameQuery.h
@@ -0,0 +1,17 @@
+#pragma once
+
+#include <boost/signal.hpp>
+#include <boost/optional.hpp>
+
+#include "Swiften/Network/HostAddress.h"
+
+namespace Swift {
+	class DNSSDResolveHostnameQuery {
+		public:
+			virtual ~DNSSDResolveHostnameQuery();
+
+			virtual void run() = 0;
+
+			boost::signal<void (const boost::optional<HostAddress>&)> onHostnameResolved;
+	};
+}
diff --git a/Swiften/LinkLocal/DNSSD/DNSSDResolveServiceQuery.cpp b/Swiften/LinkLocal/DNSSD/DNSSDResolveServiceQuery.cpp
new file mode 100644
index 0000000..67a5d66
--- /dev/null
+++ b/Swiften/LinkLocal/DNSSD/DNSSDResolveServiceQuery.cpp
@@ -0,0 +1,8 @@
+#include "Swiften/LinkLocal/DNSSD/DNSSDResolveServiceQuery.h"
+
+namespace Swift {
+
+DNSSDResolveServiceQuery::~DNSSDResolveServiceQuery() {
+}
+
+}
diff --git a/Swiften/LinkLocal/DNSSD/DNSSDResolveServiceQuery.h b/Swiften/LinkLocal/DNSSD/DNSSDResolveServiceQuery.h
new file mode 100644
index 0000000..d8b5cf1
--- /dev/null
+++ b/Swiften/LinkLocal/DNSSD/DNSSDResolveServiceQuery.h
@@ -0,0 +1,29 @@
+#pragma once
+
+#include <boost/signal.hpp>
+#include <boost/optional.hpp>
+
+#include "Swiften/LinkLocal/LinkLocalServiceID.h"
+#include "Swiften/LinkLocal/LinkLocalServiceInfo.h"
+
+namespace Swift {
+	class DNSSDResolveServiceQuery {
+		public:
+			struct Result {
+				Result(const String& fullName, const String& host, int port, 
+						const LinkLocalServiceInfo& info) : 
+							fullName(fullName), host(host), port(port), info(info) {}
+				String fullName;
+				String host;
+				int port;
+				LinkLocalServiceInfo info;
+			};
+
+			virtual ~DNSSDResolveServiceQuery();
+
+			virtual void start() = 0;
+			virtual void stop() = 0;
+
+			boost::signal<void (const boost::optional<Result>&)> onServiceResolved;
+	};
+}
diff --git a/Swiften/LinkLocal/DNSSD/Makefile.inc b/Swiften/LinkLocal/DNSSD/Makefile.inc
new file mode 100644
index 0000000..81beee0
--- /dev/null
+++ b/Swiften/LinkLocal/DNSSD/Makefile.inc
@@ -0,0 +1,12 @@
+SWIFTEN_SOURCES += \
+	Swiften/LinkLocal/DNSSD/DNSSDQuerier.cpp \
+	Swiften/LinkLocal/DNSSD/DNSSDBrowseQuery.cpp \
+	Swiften/LinkLocal/DNSSD/DNSSDRegisterQuery.cpp \
+	Swiften/LinkLocal/DNSSD/DNSSDResolveServiceQuery.cpp \
+	Swiften/LinkLocal/DNSSD/DNSSDResolveHostnameQuery.cpp
+
+ifeq ($(HAVE_BONJOUR),yes)
+include Swiften/LinkLocal/DNSSD/Bonjour/Makefile.inc
+endif
+ifeq ($(HAVE_AVAHI),yes)
+endif
diff --git a/Swiften/LinkLocal/DNSSDBrowseQuery.cpp b/Swiften/LinkLocal/DNSSDBrowseQuery.cpp
deleted file mode 100644
index 4924247..0000000
--- a/Swiften/LinkLocal/DNSSDBrowseQuery.cpp
+++ /dev/null
@@ -1,8 +0,0 @@
-#include "Swiften/LinkLocal/DNSSDBrowseQuery.h"
-
-namespace Swift {
-
-DNSSDBrowseQuery::~DNSSDBrowseQuery() {
-}
-
-}
diff --git a/Swiften/LinkLocal/DNSSDBrowseQuery.h b/Swiften/LinkLocal/DNSSDBrowseQuery.h
deleted file mode 100644
index e548ca5..0000000
--- a/Swiften/LinkLocal/DNSSDBrowseQuery.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#pragma once
-
-#include <boost/signal.hpp>
-
-#include "Swiften/LinkLocal/LinkLocalServiceID.h"
-
-namespace Swift {
-	class DNSSDBrowseQuery {
-		public:
-			virtual ~DNSSDBrowseQuery();
-
-			virtual void startBrowsing() = 0;
-			virtual void stopBrowsing() = 0;
-
-			boost::signal<void (const LinkLocalServiceID&)> onServiceAdded;
-			boost::signal<void (const LinkLocalServiceID&)> onServiceRemoved;
-	};
-}
diff --git a/Swiften/LinkLocal/DNSSDQuerier.cpp b/Swiften/LinkLocal/DNSSDQuerier.cpp
deleted file mode 100644
index be87a3c..0000000
--- a/Swiften/LinkLocal/DNSSDQuerier.cpp
+++ /dev/null
@@ -1,8 +0,0 @@
-#include "Swiften/LinkLocal/DNSSDQuerier.h"
-
-namespace Swift {
-
-DNSSDQuerier::~DNSSDQuerier() {
-}
-
-}
diff --git a/Swiften/LinkLocal/DNSSDQuerier.h b/Swiften/LinkLocal/DNSSDQuerier.h
deleted file mode 100644
index 528a6ea..0000000
--- a/Swiften/LinkLocal/DNSSDQuerier.h
+++ /dev/null
@@ -1,26 +0,0 @@
-#pragma once
-
-#include <boost/shared_ptr.hpp>
-
-namespace Swift {
-	class String;
-	class LinkLocalServiceInfo;
-	class LinkLocalServiceID;
-	class DNSSDBrowseQuery;
-	class DNSSDRegisterQuery;
-	class DNSSDResolveServiceQuery;
-	class DNSSDResolveHostnameQuery;
-
-	class DNSSDQuerier {
-		public:
-			virtual ~DNSSDQuerier();
-
-			virtual boost::shared_ptr<DNSSDBrowseQuery> createBrowseQuery() = 0;
-			virtual boost::shared_ptr<DNSSDRegisterQuery> createRegisterQuery(
-					const String& name, int port, const LinkLocalServiceInfo& info) = 0;
-			virtual boost::shared_ptr<DNSSDResolveServiceQuery> createResolveServiceQuery(
-					const LinkLocalServiceID&) = 0;
-			virtual boost::shared_ptr<DNSSDResolveHostnameQuery> createResolveHostnameQuery(
-					const String& hostname, int interfaceIndex) = 0;
-	};
-}
diff --git a/Swiften/LinkLocal/DNSSDRegisterQuery.cpp b/Swiften/LinkLocal/DNSSDRegisterQuery.cpp
deleted file mode 100644
index fe00b02..0000000
--- a/Swiften/LinkLocal/DNSSDRegisterQuery.cpp
+++ /dev/null
@@ -1,8 +0,0 @@
-#include "Swiften/LinkLocal/DNSSDRegisterQuery.h"
-
-namespace Swift {
-
-DNSSDRegisterQuery::~DNSSDRegisterQuery() {
-}
-
-}
diff --git a/Swiften/LinkLocal/DNSSDRegisterQuery.h b/Swiften/LinkLocal/DNSSDRegisterQuery.h
deleted file mode 100644
index 252fbf0..0000000
--- a/Swiften/LinkLocal/DNSSDRegisterQuery.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#pragma once
-
-#include <boost/signal.hpp>
-#include <boost/optional.hpp>
-
-#include "Swiften/LinkLocal/LinkLocalServiceID.h"
-
-namespace Swift {
-	class LinkLocalServiceInfo;
-
-	class DNSSDRegisterQuery {
-		public:
-			virtual ~DNSSDRegisterQuery();
-
-			virtual void registerService() = 0;
-			virtual void updateServiceInfo(const LinkLocalServiceInfo& info) = 0;
-
-			boost::signal<void (boost::optional<LinkLocalServiceID>)> onRegisterFinished;
-	};
-}
diff --git a/Swiften/LinkLocal/DNSSDResolveHostnameQuery.cpp b/Swiften/LinkLocal/DNSSDResolveHostnameQuery.cpp
deleted file mode 100644
index f7c88bd..0000000
--- a/Swiften/LinkLocal/DNSSDResolveHostnameQuery.cpp
+++ /dev/null
@@ -1,8 +0,0 @@
-#include "Swiften/LinkLocal/DNSSDResolveHostnameQuery.h"
-
-namespace Swift {
-
-DNSSDResolveHostnameQuery::~DNSSDResolveHostnameQuery() {
-}
-
-}
diff --git a/Swiften/LinkLocal/DNSSDResolveHostnameQuery.h b/Swiften/LinkLocal/DNSSDResolveHostnameQuery.h
deleted file mode 100644
index a2e218c..0000000
--- a/Swiften/LinkLocal/DNSSDResolveHostnameQuery.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#pragma once
-
-#include <boost/signal.hpp>
-#include <boost/optional.hpp>
-
-#include "Swiften/Network/HostAddress.h"
-
-namespace Swift {
-	class DNSSDResolveHostnameQuery {
-		public:
-			virtual ~DNSSDResolveHostnameQuery();
-
-			virtual void run() = 0;
-
-			boost::signal<void (const boost::optional<HostAddress>&)> onHostnameResolved;
-	};
-}
diff --git a/Swiften/LinkLocal/DNSSDResolveServiceQuery.cpp b/Swiften/LinkLocal/DNSSDResolveServiceQuery.cpp
deleted file mode 100644
index 83a9ccd..0000000
--- a/Swiften/LinkLocal/DNSSDResolveServiceQuery.cpp
+++ /dev/null
@@ -1,8 +0,0 @@
-#include "Swiften/LinkLocal/DNSSDResolveServiceQuery.h"
-
-namespace Swift {
-
-DNSSDResolveServiceQuery::~DNSSDResolveServiceQuery() {
-}
-
-}
diff --git a/Swiften/LinkLocal/DNSSDResolveServiceQuery.h b/Swiften/LinkLocal/DNSSDResolveServiceQuery.h
deleted file mode 100644
index d8b5cf1..0000000
--- a/Swiften/LinkLocal/DNSSDResolveServiceQuery.h
+++ /dev/null
@@ -1,29 +0,0 @@
-#pragma once
-
-#include <boost/signal.hpp>
-#include <boost/optional.hpp>
-
-#include "Swiften/LinkLocal/LinkLocalServiceID.h"
-#include "Swiften/LinkLocal/LinkLocalServiceInfo.h"
-
-namespace Swift {
-	class DNSSDResolveServiceQuery {
-		public:
-			struct Result {
-				Result(const String& fullName, const String& host, int port, 
-						const LinkLocalServiceInfo& info) : 
-							fullName(fullName), host(host), port(port), info(info) {}
-				String fullName;
-				String host;
-				int port;
-				LinkLocalServiceInfo info;
-			};
-
-			virtual ~DNSSDResolveServiceQuery();
-
-			virtual void start() = 0;
-			virtual void stop() = 0;
-
-			boost::signal<void (const boost::optional<Result>&)> onServiceResolved;
-	};
-}
diff --git a/Swiften/LinkLocal/Makefile.inc b/Swiften/LinkLocal/Makefile.inc
index 9522cbb..86a25fd 100644
--- a/Swiften/LinkLocal/Makefile.inc
+++ b/Swiften/LinkLocal/Makefile.inc
@@ -1,12 +1,7 @@
 SWIFTEN_SOURCES += \
-	Swiften/LinkLocal/DNSSDQuerier.cpp \
-	Swiften/LinkLocal/DNSSDBrowseQuery.cpp \
-	Swiften/LinkLocal/DNSSDRegisterQuery.cpp \
-	Swiften/LinkLocal/DNSSDResolveServiceQuery.cpp \
-	Swiften/LinkLocal/DNSSDResolveHostnameQuery.cpp \
 	Swiften/LinkLocal/DNSSDServiceFactory.cpp \
-	Swiften/LinkLocal/PlatformDNSSDServiceFactory.cpp \
 	Swiften/LinkLocal/DNSSDService.cpp \
+	Swiften/LinkLocal/PlatformDNSSDServiceFactory.cpp \
 	Swiften/LinkLocal/LinkLocalRoster.cpp \
 	Swiften/LinkLocal/LinkLocalServiceID.cpp \
 	Swiften/LinkLocal/LinkLocalServiceInfo.cpp \
@@ -17,8 +12,6 @@ SWIFTEN_SOURCES += \
 
 ifeq ($(HAVE_BONJOUR),yes)
 SWIFTEN_SOURCES += \
-	Swiften/LinkLocal/BonjourQuery.cpp \
-	Swiften/LinkLocal/BonjourQuerier.cpp \
 	Swiften/LinkLocal/AppleDNSSDService.cpp
 endif
 ifeq ($(HAVE_AVAHI),yes)
@@ -26,4 +19,5 @@ SWIFTEN_SOURCES += \
 	Swiften/LinkLocal/AvahiDNSSDService.cpp
 endif
 
+include Swiften/LinkLocal/DNSSD/Makefile.inc
 include Swiften/LinkLocal/UnitTest/Makefile.inc
-- 
cgit v0.10.2-6-g49f6


From c54914a3666c0687f5bba776db34263eeb8e810f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Sat, 25 Jul 2009 15:17:19 +0200
Subject: Added About menu.


diff --git a/Slimber/CLI/main.cpp b/Slimber/CLI/main.cpp
index 3a72ca1..8b70625 100644
--- a/Slimber/CLI/main.cpp
+++ b/Slimber/CLI/main.cpp
@@ -10,7 +10,9 @@
 #include "Slimber/Server.h"
 #include "Slimber/FileVCardCollection.h"
 #include "Swiften/LinkLocal/LinkLocalRoster.h"
-#include "Swiften/LinkLocal/BonjourQuerier.h"
+#include "Swiften/LinkLocal/DNSSD/DNSSDBrowseQuery.h"
+#include "Swiften/LinkLocal/DNSSD/DNSSDRegisterQuery.h"
+#include "Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuerier.h"
 #include "Swiften/EventLoop/SimpleEventLoop.h"
 #include "Swiften/Application/Platform/PlatformApplication.h"
 
diff --git a/Slimber/Cocoa/Info.plist b/Slimber/Cocoa/Info.plist
index bcbed49..f934a10 100644
--- a/Slimber/Cocoa/Info.plist
+++ b/Slimber/Cocoa/Info.plist
@@ -24,5 +24,7 @@
 	<string>NSApplication</string>
   <key>LSUIElement</key>
   <string>1</string>
+	<key>NSHumanReadableCopyright</key>
+	<string>© 2009 Swift Development Team. All Rights Reserved.</string>
 </dict>
 </plist>
diff --git a/Slimber/Cocoa/Menulet.m b/Slimber/Cocoa/Menulet.m
index b2af97f..4fa7fed 100644
--- a/Slimber/Cocoa/Menulet.m
+++ b/Slimber/Cocoa/Menulet.m
@@ -75,6 +75,12 @@
 	[statusMenu addItem: loggedInItem];
 	[statusMenu addItem: [NSMenuItem separatorItem]];
 
+	// About menu
+	NSMenuItem* aboutMenuItem = [[NSMenuItem alloc] initWithTitle: @"About Slimber" action: @selector(orderFrontStandardAboutPanel:) keyEquivalent: @""];
+	[aboutMenuItem setTarget: [NSApplication sharedApplication]];
+	[statusMenu addItem: aboutMenuItem];
+	[statusMenu addItem: [NSMenuItem separatorItem]];
+
 	// Exit item
 	NSMenuItem* exitMenuItem = [[NSMenuItem alloc] initWithTitle: @"Exit" action: @selector(terminate:) keyEquivalent: @""];
 	[exitMenuItem setTarget: [NSApplication sharedApplication]];
-- 
cgit v0.10.2-6-g49f6


From d2807a77d39bd1a359f5b85869113ed83e01c204 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Sat, 25 Jul 2009 15:24:05 +0200
Subject: Added credts to about box.


diff --git a/Slimber/Cocoa/Makefile.inc b/Slimber/Cocoa/Makefile.inc
index 28495f7..8068350 100644
--- a/Slimber/Cocoa/Makefile.inc
+++ b/Slimber/Cocoa/Makefile.inc
@@ -12,6 +12,7 @@ SLIMBER_COCOA_SOURCES = \
 SLIMBER_COCOA_XIBS = \
 	Slimber/Cocoa/MainMenu.xib
 SLIMBER_COCOA_RESOURCES = \
+	Slimber/Resources/Credits.html \
 	Slimber/Resources/Online.png \
 	Slimber/Resources/Offline.png \
 	Slimber/Resources/UsersOnline.png \
diff --git a/Slimber/Resources/Credits.html b/Slimber/Resources/Credits.html
new file mode 100644
index 0000000..66ecb13
--- /dev/null
+++ b/Slimber/Resources/Credits.html
@@ -0,0 +1 @@
+<a href="http://swift.im/slimber">http://swift.im/slimber</a>
-- 
cgit v0.10.2-6-g49f6


From 9f51e6c6279ae7fb541774ac4bf9debfa61395c1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Sat, 25 Jul 2009 19:32:55 +0200
Subject: Move LinkLocalServiceID->DNSSDServiceID.


diff --git a/Swiften/LinkLocal/AppleDNSSDService.cpp b/Swiften/LinkLocal/AppleDNSSDService.cpp
index bf66e50..a052eb1 100644
--- a/Swiften/LinkLocal/AppleDNSSDService.cpp
+++ b/Swiften/LinkLocal/AppleDNSSDService.cpp
@@ -70,7 +70,7 @@ void AppleDNSSDService::unregisterService() {
 	registerSDRef = NULL;
 }
 
-void AppleDNSSDService::startResolvingService(const LinkLocalServiceID& service) {
+void AppleDNSSDService::startResolvingService(const DNSSDServiceID& service) {
 	boost::lock_guard<boost::mutex> lock(sdRefsMutex);
 
 	DNSServiceRef resolveSDRef;
@@ -87,7 +87,7 @@ void AppleDNSSDService::startResolvingService(const LinkLocalServiceID& service)
 	interruptSelect();
 }
 
-void AppleDNSSDService::stopResolvingService(const LinkLocalServiceID& service) {
+void AppleDNSSDService::stopResolvingService(const DNSSDServiceID& service) {
 	boost::lock_guard<boost::mutex> lock(sdRefsMutex);
 
 	ServiceSDRefMap::iterator i = resolveSDRefs.find(service);
@@ -238,7 +238,7 @@ void AppleDNSSDService::handleServiceDiscovered(DNSServiceRef, DNSServiceFlags f
 		return;
 	}
 	else {
-		LinkLocalServiceID service(serviceName, regtype, replyDomain, interfaceIndex);
+		DNSSDServiceID service(serviceName, regtype, replyDomain, interfaceIndex);
 		if (flags & kDNSServiceFlagsAdd) {
 			MainEventLoop::postEvent(boost::bind(boost::ref(onServiceAdded), service), shared_from_this());
 		}
@@ -258,7 +258,7 @@ void AppleDNSSDService::handleServiceRegistered(DNSServiceRef, DNSServiceFlags,
 		haveError = true;
 	}
 	else {
-		MainEventLoop::postEvent(boost::bind(boost::ref(onServiceRegistered), LinkLocalServiceID(name, regtype, domain, 0)), shared_from_this());
+		MainEventLoop::postEvent(boost::bind(boost::ref(onServiceRegistered), DNSSDServiceID(name, regtype, domain, 0)), shared_from_this());
 	}
 }
 
diff --git a/Swiften/LinkLocal/AppleDNSSDService.h b/Swiften/LinkLocal/AppleDNSSDService.h
index 7fdfd3e..554a154 100644
--- a/Swiften/LinkLocal/AppleDNSSDService.h
+++ b/Swiften/LinkLocal/AppleDNSSDService.h
@@ -6,7 +6,7 @@
 #include <dns_sd.h>
 
 #include "Swiften/LinkLocal/DNSSDService.h"
-#include "Swiften/LinkLocal/LinkLocalServiceID.h"
+#include "Swiften/LinkLocal/DNSSD/DNSSDServiceID.h"
 #include "Swiften/EventLoop/EventOwner.h"
 
 namespace Swift {
@@ -22,8 +22,8 @@ namespace Swift {
 			virtual void updateService(const LinkLocalServiceInfo&);
 			virtual void unregisterService();
 
-			virtual void startResolvingService(const LinkLocalServiceID&);
-			virtual void stopResolvingService(const LinkLocalServiceID&);
+			virtual void startResolvingService(const DNSSDServiceID&);
+			virtual void stopResolvingService(const DNSSDServiceID&);
 
 			virtual void resolveHostname(const String& hostname, int interfaceIndex = 0);
 
@@ -49,7 +49,7 @@ namespace Swift {
 			boost::mutex sdRefsMutex;
 			DNSServiceRef browseSDRef;
 			DNSServiceRef registerSDRef;
-			typedef std::map<LinkLocalServiceID, DNSServiceRef> ServiceSDRefMap;
+			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
index fe9ac83..5f6295f 100644
--- a/Swiften/LinkLocal/AvahiDNSSDService.cpp
+++ b/Swiften/LinkLocal/AvahiDNSSDService.cpp
@@ -62,7 +62,7 @@ void AvahiDNSSDService::unregisterService() {
 	avahi_threaded_poll_unlock(threadedPoll);
 }
 
-void AvahiDNSSDService::startResolvingService(const LinkLocalServiceID& service) {
+void AvahiDNSSDService::startResolvingService(const DNSSDServiceID& service) {
 	avahi_threaded_poll_lock(threadedPoll);
 
 	AvahiServiceResolver* resolver = avahi_service_resolver_new(
@@ -82,7 +82,7 @@ void AvahiDNSSDService::startResolvingService(const LinkLocalServiceID& service)
 	avahi_threaded_poll_unlock(threadedPoll);
 }
 
-void AvahiDNSSDService::stopResolvingService(const LinkLocalServiceID& service) {
+void AvahiDNSSDService::stopResolvingService(const DNSSDServiceID& service) {
 	avahi_threaded_poll_lock(threadedPoll);
 
 	ServiceResolverMap::iterator i = serviceResolvers.find(service);
@@ -112,13 +112,13 @@ void AvahiDNSSDService::handleServiceDiscovered(AvahiServiceBrowser *, AvahiIfIn
 			return;
 		case AVAHI_BROWSER_NEW: {
 				std::cerr << "Service added: " << name << " " << type << " " << domain << std::endl;
-				LinkLocalServiceID service(name, type, domain, interfaceIndex);
+				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;
-				LinkLocalServiceID service(name, type, domain, interfaceIndex);
+				DNSSDServiceID service(name, type, domain, interfaceIndex);
 				MainEventLoop::postEvent(boost::bind(boost::ref(onServiceRemoved), service), shared_from_this());
 			}
 			break;
@@ -146,7 +146,7 @@ void AvahiDNSSDService::handleServiceResolved(AvahiServiceResolver *, AvahiIfInd
 			HostAddress hostAddress(reinterpret_cast<const unsigned char*>(&address->data.ipv4.address), 4);
 			hostnameAddresses[String(hostname)] = hostAddress;
 			MainEventLoop::postEvent(boost::bind(boost::ref(onServiceResolved), 
-					LinkLocalServiceID(name, type, domain, interfaceIndex), 
+					DNSSDServiceID(name, type, domain, interfaceIndex), 
 					ResolveResult(hostname, port, 
 						LinkLocalServiceInfo::createFromTXTRecord(data))),
 					shared_from_this());
diff --git a/Swiften/LinkLocal/AvahiDNSSDService.h b/Swiften/LinkLocal/AvahiDNSSDService.h
index 99a1d23..7162ade 100644
--- a/Swiften/LinkLocal/AvahiDNSSDService.h
+++ b/Swiften/LinkLocal/AvahiDNSSDService.h
@@ -26,8 +26,8 @@ namespace Swift {
 			virtual void updateService(const LinkLocalServiceInfo&);
 			virtual void unregisterService();
 
-			virtual void startResolvingService(const LinkLocalServiceID&);
-			virtual void stopResolvingService(const LinkLocalServiceID&);
+			virtual void startResolvingService(const DNSSDServiceID&);
+			virtual void stopResolvingService(const DNSSDServiceID&);
 
 			virtual void resolveHostname(const String& hostname, int interfaceIndex = 0);
 		
@@ -47,7 +47,7 @@ namespace Swift {
 			AvahiClient* client;
 			AvahiThreadedPoll* threadedPoll;
 			AvahiServiceBrowser* serviceBrowser;
-			typedef std::map<LinkLocalServiceID, AvahiServiceResolver*> ServiceResolverMap;
+			typedef std::map<DNSSDServiceID, AvahiServiceResolver*> ServiceResolverMap;
 			ServiceResolverMap serviceResolvers;
 			typedef std::map<String, HostAddress> HostnameAddressMap;
 			HostnameAddressMap hostnameAddresses;
diff --git a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourBrowseQuery.h b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourBrowseQuery.h
index edff064..62d8606 100644
--- a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourBrowseQuery.h
+++ b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourBrowseQuery.h
@@ -38,7 +38,7 @@ namespace Swift {
 					return;
 				}
 				else {
-					LinkLocalServiceID service(name, type, domain, interfaceIndex);
+					DNSSDServiceID service(name, type, domain, interfaceIndex);
 					if (flags & kDNSServiceFlagsAdd) {
 						MainEventLoop::postEvent(boost::bind(boost::ref(onServiceAdded), service), shared_from_this());
 					}
diff --git a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuerier.cpp b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuerier.cpp
index 064e3c5..c065d4d 100644
--- a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuerier.cpp
+++ b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuerier.cpp
@@ -33,7 +33,7 @@ boost::shared_ptr<DNSSDRegisterQuery> BonjourQuerier::createRegisterQuery(const
 	return boost::shared_ptr<DNSSDRegisterQuery>(new BonjourRegisterQuery(name, port, info, shared_from_this()));
 }
 
-boost::shared_ptr<DNSSDResolveServiceQuery> BonjourQuerier::createResolveServiceQuery(const LinkLocalServiceID& service) {
+boost::shared_ptr<DNSSDResolveServiceQuery> BonjourQuerier::createResolveServiceQuery(const DNSSDServiceID& service) {
 	return boost::shared_ptr<DNSSDResolveServiceQuery>(new BonjourResolveServiceQuery(service, shared_from_this()));
 }
 
diff --git a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuerier.h b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuerier.h
index 79f9a81..644a8d9 100644
--- a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuerier.h
+++ b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuerier.h
@@ -23,7 +23,7 @@ namespace Swift {
 			boost::shared_ptr<DNSSDRegisterQuery> createRegisterQuery(
 					const String& name, int port, const LinkLocalServiceInfo& info);
 			boost::shared_ptr<DNSSDResolveServiceQuery> createResolveServiceQuery(
-					const LinkLocalServiceID&);
+					const DNSSDServiceID&);
 			boost::shared_ptr<DNSSDResolveHostnameQuery> createResolveHostnameQuery(
 					const String& hostname, int interfaceIndex);
 
diff --git a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourRegisterQuery.h b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourRegisterQuery.h
index 31e86fc..9c4db13 100644
--- a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourRegisterQuery.h
+++ b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourRegisterQuery.h
@@ -40,10 +40,10 @@ namespace Swift {
 
 			void handleServiceRegistered(DNSServiceErrorType errorCode, const char *name, const char *regtype, const char *domain) {
 				if (errorCode != kDNSServiceErr_NoError) {
-					MainEventLoop::postEvent(boost::bind(boost::ref(onRegisterFinished), boost::optional<LinkLocalServiceID>()), shared_from_this());
+					MainEventLoop::postEvent(boost::bind(boost::ref(onRegisterFinished), boost::optional<DNSSDServiceID>()), shared_from_this());
 				}
 				else {
-					MainEventLoop::postEvent(boost::bind(boost::ref(onRegisterFinished), boost::optional<LinkLocalServiceID>(LinkLocalServiceID(name, regtype, domain, 0))), shared_from_this());
+					MainEventLoop::postEvent(boost::bind(boost::ref(onRegisterFinished), boost::optional<DNSSDServiceID>(DNSSDServiceID(name, regtype, domain, 0))), shared_from_this());
 				}
 			}
 	};
diff --git a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourResolveServiceQuery.h b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourResolveServiceQuery.h
index 1afdf5a..1ebd487 100644
--- a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourResolveServiceQuery.h
+++ b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourResolveServiceQuery.h
@@ -11,7 +11,7 @@ namespace Swift {
 
 	class BonjourResolveServiceQuery : public DNSSDResolveServiceQuery, public BonjourQuery {
 		public:	
-			BonjourResolveServiceQuery(const LinkLocalServiceID& service, boost::shared_ptr<BonjourQuerier> querier) : BonjourQuery(querier) {
+			BonjourResolveServiceQuery(const DNSSDServiceID& service, boost::shared_ptr<BonjourQuerier> querier) : BonjourQuery(querier) {
 				DNSServiceErrorType result = DNSServiceResolve(
 						&sdRef, 0, service.getNetworkInterfaceID(), 
 						service.getName().getUTF8Data(), service.getType().getUTF8Data(), 
diff --git a/Swiften/LinkLocal/DNSSD/DNSSDBrowseQuery.h b/Swiften/LinkLocal/DNSSD/DNSSDBrowseQuery.h
index e548ca5..86967ed 100644
--- a/Swiften/LinkLocal/DNSSD/DNSSDBrowseQuery.h
+++ b/Swiften/LinkLocal/DNSSD/DNSSDBrowseQuery.h
@@ -2,7 +2,7 @@
 
 #include <boost/signal.hpp>
 
-#include "Swiften/LinkLocal/LinkLocalServiceID.h"
+#include "Swiften/LinkLocal/DNSSD/DNSSDServiceID.h"
 
 namespace Swift {
 	class DNSSDBrowseQuery {
@@ -12,7 +12,7 @@ namespace Swift {
 			virtual void startBrowsing() = 0;
 			virtual void stopBrowsing() = 0;
 
-			boost::signal<void (const LinkLocalServiceID&)> onServiceAdded;
-			boost::signal<void (const LinkLocalServiceID&)> onServiceRemoved;
+			boost::signal<void (const DNSSDServiceID&)> onServiceAdded;
+			boost::signal<void (const DNSSDServiceID&)> onServiceRemoved;
 	};
 }
diff --git a/Swiften/LinkLocal/DNSSD/DNSSDQuerier.h b/Swiften/LinkLocal/DNSSD/DNSSDQuerier.h
index 528a6ea..6c7b576 100644
--- a/Swiften/LinkLocal/DNSSD/DNSSDQuerier.h
+++ b/Swiften/LinkLocal/DNSSD/DNSSDQuerier.h
@@ -5,7 +5,7 @@
 namespace Swift {
 	class String;
 	class LinkLocalServiceInfo;
-	class LinkLocalServiceID;
+	class DNSSDServiceID;
 	class DNSSDBrowseQuery;
 	class DNSSDRegisterQuery;
 	class DNSSDResolveServiceQuery;
@@ -19,7 +19,7 @@ namespace Swift {
 			virtual boost::shared_ptr<DNSSDRegisterQuery> createRegisterQuery(
 					const String& name, int port, const LinkLocalServiceInfo& info) = 0;
 			virtual boost::shared_ptr<DNSSDResolveServiceQuery> createResolveServiceQuery(
-					const LinkLocalServiceID&) = 0;
+					const DNSSDServiceID&) = 0;
 			virtual boost::shared_ptr<DNSSDResolveHostnameQuery> createResolveHostnameQuery(
 					const String& hostname, int interfaceIndex) = 0;
 	};
diff --git a/Swiften/LinkLocal/DNSSD/DNSSDRegisterQuery.h b/Swiften/LinkLocal/DNSSD/DNSSDRegisterQuery.h
index 252fbf0..a643880 100644
--- a/Swiften/LinkLocal/DNSSD/DNSSDRegisterQuery.h
+++ b/Swiften/LinkLocal/DNSSD/DNSSDRegisterQuery.h
@@ -3,7 +3,7 @@
 #include <boost/signal.hpp>
 #include <boost/optional.hpp>
 
-#include "Swiften/LinkLocal/LinkLocalServiceID.h"
+#include "Swiften/LinkLocal/DNSSD/DNSSDServiceID.h"
 
 namespace Swift {
 	class LinkLocalServiceInfo;
@@ -15,6 +15,6 @@ namespace Swift {
 			virtual void registerService() = 0;
 			virtual void updateServiceInfo(const LinkLocalServiceInfo& info) = 0;
 
-			boost::signal<void (boost::optional<LinkLocalServiceID>)> onRegisterFinished;
+			boost::signal<void (boost::optional<DNSSDServiceID>)> onRegisterFinished;
 	};
 }
diff --git a/Swiften/LinkLocal/DNSSD/DNSSDResolveServiceQuery.h b/Swiften/LinkLocal/DNSSD/DNSSDResolveServiceQuery.h
index d8b5cf1..f79b537 100644
--- a/Swiften/LinkLocal/DNSSD/DNSSDResolveServiceQuery.h
+++ b/Swiften/LinkLocal/DNSSD/DNSSDResolveServiceQuery.h
@@ -3,7 +3,7 @@
 #include <boost/signal.hpp>
 #include <boost/optional.hpp>
 
-#include "Swiften/LinkLocal/LinkLocalServiceID.h"
+#include "Swiften/LinkLocal/DNSSD/DNSSDServiceID.h"
 #include "Swiften/LinkLocal/LinkLocalServiceInfo.h"
 
 namespace Swift {
diff --git a/Swiften/LinkLocal/DNSSD/DNSSDServiceID.cpp b/Swiften/LinkLocal/DNSSD/DNSSDServiceID.cpp
new file mode 100644
index 0000000..06a5b81
--- /dev/null
+++ b/Swiften/LinkLocal/DNSSD/DNSSDServiceID.cpp
@@ -0,0 +1,7 @@
+#include "Swiften/LinkLocal/DNSSD/DNSSDServiceID.h"
+
+namespace Swift {
+
+const String DNSSDServiceID::PresenceServiceType = String("_presence._tcp");
+
+}
diff --git a/Swiften/LinkLocal/DNSSD/DNSSDServiceID.h b/Swiften/LinkLocal/DNSSD/DNSSDServiceID.h
new file mode 100644
index 0000000..b1986d3
--- /dev/null
+++ b/Swiften/LinkLocal/DNSSD/DNSSDServiceID.h
@@ -0,0 +1,66 @@
+#pragma once
+
+#include "Swiften/Base/String.h"
+
+namespace Swift {
+	class DNSSDServiceID {
+		public:
+			static const String PresenceServiceType;
+
+			DNSSDServiceID(
+				const String& name, 
+				const String& type, 
+				const String& domain = PresenceServiceType, 
+				int networkInterface = 0) : 
+					name(name), 
+					type(type), 
+					domain(domain), 
+					networkInterface(networkInterface) {
+			}
+
+			bool operator==(const DNSSDServiceID& o) const {
+				return name == o.name && type == o.type && domain == o.domain && (networkInterface != 0 && o.networkInterface != 0 ? networkInterface == o.networkInterface : true);
+			}
+
+			bool operator<(const DNSSDServiceID& o) const {
+				if (o.name == name) {
+					if (o.type == type) {
+						if (o.domain == domain) {
+							return networkInterface < o.networkInterface;
+						}
+						else {
+							return domain < o.domain;
+						}
+					}
+					else {
+						return type < o.type;
+					}
+				}
+				else {
+					return o.name < name;
+				}
+			}
+
+			const String& getName() const {
+				return name;
+			}
+
+			const String& getType() const {
+				return type;
+			}
+
+			const String& getDomain() const {
+				return domain;
+			}
+
+			int getNetworkInterfaceID() const {
+				return networkInterface;
+			}
+
+		private:
+			String name;
+			String type;
+			String domain;
+			int networkInterface;
+	};
+}
diff --git a/Swiften/LinkLocal/DNSSD/Makefile.inc b/Swiften/LinkLocal/DNSSD/Makefile.inc
index 81beee0..8612fee 100644
--- a/Swiften/LinkLocal/DNSSD/Makefile.inc
+++ b/Swiften/LinkLocal/DNSSD/Makefile.inc
@@ -1,4 +1,5 @@
 SWIFTEN_SOURCES += \
+	Swiften/LinkLocal/DNSSD/DNSSDServiceID.cpp \
 	Swiften/LinkLocal/DNSSD/DNSSDQuerier.cpp \
 	Swiften/LinkLocal/DNSSD/DNSSDBrowseQuery.cpp \
 	Swiften/LinkLocal/DNSSD/DNSSDRegisterQuery.cpp \
diff --git a/Swiften/LinkLocal/DNSSDService.h b/Swiften/LinkLocal/DNSSDService.h
index 4cf1a6e..0ace21b 100644
--- a/Swiften/LinkLocal/DNSSDService.h
+++ b/Swiften/LinkLocal/DNSSDService.h
@@ -4,7 +4,7 @@
 #include <map>
 
 #include "Swiften/Base/String.h"
-#include "Swiften/LinkLocal/LinkLocalServiceID.h"
+#include "Swiften/LinkLocal/DNSSD/DNSSDServiceID.h"
 #include "Swiften/LinkLocal/LinkLocalServiceInfo.h"
 
 namespace Swift {
@@ -29,17 +29,17 @@ namespace Swift {
 			virtual void updateService(const LinkLocalServiceInfo&) = 0;
 			virtual void unregisterService() = 0;
 
-			virtual void startResolvingService(const LinkLocalServiceID&) = 0;
-			virtual void stopResolvingService(const LinkLocalServiceID&) = 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 LinkLocalServiceID&)> onServiceAdded;
-			boost::signal<void (const LinkLocalServiceID&)> onServiceRemoved;
-			boost::signal<void (const LinkLocalServiceID&)> onServiceRegistered;
-			boost::signal<void (const LinkLocalServiceID&, const ResolveResult&)> onServiceResolved;
+			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/LinkLocalRoster.cpp b/Swiften/LinkLocal/LinkLocalRoster.cpp
index 5a6ccfd..af3c1af 100644
--- a/Swiften/LinkLocal/LinkLocalRoster.cpp
+++ b/Swiften/LinkLocal/LinkLocalRoster.cpp
@@ -30,11 +30,11 @@ std::vector<boost::shared_ptr<Presence> > LinkLocalRoster::getAllPresence() cons
 	return result;
 }
 
-RosterItemPayload LinkLocalRoster::getRosterItem(const LinkLocalServiceID& service, const DNSSDService::ResolveResult& resolveResult) const {
+RosterItemPayload LinkLocalRoster::getRosterItem(const DNSSDServiceID& service, const DNSSDService::ResolveResult& resolveResult) const {
  return RosterItemPayload(getJIDForService(service), getRosterName(service, resolveResult), RosterItemPayload::Both);
 }
 
-String LinkLocalRoster::getRosterName(const LinkLocalServiceID& service, const DNSSDService::ResolveResult& resolveResult) const {
+String LinkLocalRoster::getRosterName(const DNSSDServiceID& service, const DNSSDService::ResolveResult& resolveResult) const {
 	if (!resolveResult.info.getNick().isEmpty()) {
 		return resolveResult.info.getNick();
 	}
@@ -51,11 +51,11 @@ String LinkLocalRoster::getRosterName(const LinkLocalServiceID& service, const D
 	return service.getName();
 }
 
-JID LinkLocalRoster::getJIDForService(const LinkLocalServiceID& service) const {
+JID LinkLocalRoster::getJIDForService(const DNSSDServiceID& service) const {
 	return JID(service.getName());
 }
 
-boost::shared_ptr<Presence> LinkLocalRoster::getPresence(const LinkLocalServiceID& service, const DNSSDService::ResolveResult& resolveResult) const {
+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()) {
@@ -73,14 +73,14 @@ boost::shared_ptr<Presence> LinkLocalRoster::getPresence(const LinkLocalServiceI
 	return presence;
 }
 
-void LinkLocalRoster::handleServiceAdded(const LinkLocalServiceID& service) {
+void LinkLocalRoster::handleServiceAdded(const DNSSDServiceID& service) {
 	if (selfService && *selfService == service) {
 		return;
 	}
 	dnsSDService->startResolvingService(service);
 }
 
-void LinkLocalRoster::handleServiceRemoved(const LinkLocalServiceID& service) {
+void LinkLocalRoster::handleServiceRemoved(const DNSSDServiceID& service) {
 	if (selfService && *selfService == service) {
 		return;
 	}
@@ -91,7 +91,7 @@ void LinkLocalRoster::handleServiceRemoved(const LinkLocalServiceID& service) {
 	onRosterChanged(roster);
 }
 
-void LinkLocalRoster::handleServiceResolved(const LinkLocalServiceID& service, const DNSSDService::ResolveResult& result) {
+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());
@@ -104,7 +104,7 @@ void LinkLocalRoster::handleServiceResolved(const LinkLocalServiceID& service, c
 	onPresenceChanged(getPresence(service, result));
 }
 
-void LinkLocalRoster::handleServiceRegistered(const LinkLocalServiceID& service) {
+void LinkLocalRoster::handleServiceRegistered(const DNSSDServiceID& service) {
 	selfService = service;
 }
 
diff --git a/Swiften/LinkLocal/LinkLocalRoster.h b/Swiften/LinkLocal/LinkLocalRoster.h
index 128e39d..03ed2d5 100644
--- a/Swiften/LinkLocal/LinkLocalRoster.h
+++ b/Swiften/LinkLocal/LinkLocalRoster.h
@@ -28,21 +28,21 @@ namespace Swift {
 			int getPort(const JID&) const;
 
 		private:
-			RosterItemPayload getRosterItem(const LinkLocalServiceID& service, const DNSSDService::ResolveResult& info) const;
-			String getRosterName(const LinkLocalServiceID& service, const DNSSDService::ResolveResult& info) const;
-			JID getJIDForService(const LinkLocalServiceID& service) const;
-			boost::shared_ptr<Presence> getPresence(const LinkLocalServiceID& service, const DNSSDService::ResolveResult& info) const;
+			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 LinkLocalServiceID& service);
-			void handleServiceAdded(const LinkLocalServiceID&);
-			void handleServiceRemoved(const LinkLocalServiceID&);
-			void handleServiceResolved(const LinkLocalServiceID& service, const DNSSDService::ResolveResult& result);
+			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<LinkLocalServiceID> selfService;
-			typedef std::map<LinkLocalServiceID, DNSSDService::ResolveResult> ServiceMap;
+			boost::optional<DNSSDServiceID> selfService;
+			typedef std::map<DNSSDServiceID, DNSSDService::ResolveResult> ServiceMap;
 			ServiceMap services;
 	};
 }
diff --git a/Swiften/LinkLocal/LinkLocalService.h b/Swiften/LinkLocal/LinkLocalService.h
index 6616303..2c62307 100644
--- a/Swiften/LinkLocal/LinkLocalService.h
+++ b/Swiften/LinkLocal/LinkLocalService.h
@@ -2,19 +2,19 @@
 
 #include "Swiften/Base/String.h"
 #include "Swiften/Network/HostAddress.h"
-#include "Swiften/LinkLocal/LinkLocalServiceID.h"
+#include "Swiften/LinkLocal/DNSSD/DNSSDServiceID.h"
 #include "Swiften/LinkLocal/LinkLocalServiceInfo.h"
 
 namespace Swift {
 	class LinkLocalService {
 		public:
 			LinkLocalService(
-					const LinkLocalServiceID& id,
+					const DNSSDServiceID& id,
 					const DNSSDService::ResolveResult& info) :
 						id(id),
 						info(info) {}
 
-			const LinkLocalServiceID& getID() const {
+			const DNSSDServiceID& getID() const {
 				return id;
 			}
 
@@ -35,7 +35,7 @@ namespace Swift {
 			}
 
 		private:
-			LinkLocalServiceID id;
+			DNSSDServiceID id;
 			DNSSDService::ResolveResult info;
 	};
 }
diff --git a/Swiften/LinkLocal/LinkLocalServiceBrowser.cpp b/Swiften/LinkLocal/LinkLocalServiceBrowser.cpp
index 904f8f0..ab56695 100644
--- a/Swiften/LinkLocal/LinkLocalServiceBrowser.cpp
+++ b/Swiften/LinkLocal/LinkLocalServiceBrowser.cpp
@@ -6,35 +6,35 @@
 
 namespace Swift {
 
-LinkLocalServiceBrowser::LinkLocalServiceBrowser(DNSSDServiceFactory* factory) {
-  dnsSDService = factory->createDNSSDService();
+LinkLocalServiceBrowser::LinkLocalServiceBrowser(boost::shared_ptr<DNSSDQuerier> querier) : querier(querier) {
+  /*dnsSDService = factory->createDNSSDService();
 	dnsSDService->onServiceAdded.connect(
 			boost::bind(&LinkLocalServiceBrowser::handleServiceAdded, this, _1));
 	dnsSDService->onServiceRemoved.connect(
 			boost::bind(&LinkLocalServiceBrowser::handleServiceRemoved, this, _1));
 	dnsSDService->onServiceResolved.connect(
-			boost::bind(&LinkLocalServiceBrowser::handleServiceResolved, this, _1, _2));
+			boost::bind(&LinkLocalServiceBrowser::handleServiceResolved, this, _1, _2));*/
 }
 
 std::vector<LinkLocalService> LinkLocalServiceBrowser::getServices() const {
 	std::vector<LinkLocalService> result;
-	for (ServiceMap::const_iterator i = services.begin(); i != services.end(); ++i) {
+	/*for (ServiceMap::const_iterator i = services.begin(); i != services.end(); ++i) {
 		result.push_back(LinkLocalService(i->first, i->second));
-	}
+	}*/
 	return result;
 }
 
-void LinkLocalServiceBrowser::handleServiceAdded(const LinkLocalServiceID& service) {
+/*void LinkLocalServiceBrowser::handleServiceAdded(const DNSSDServiceID& service) {
 	dnsSDService->startResolvingService(service);
 }
 
-void LinkLocalServiceBrowser::handleServiceRemoved(const LinkLocalServiceID& service) {
+void LinkLocalServiceBrowser::handleServiceRemoved(const DNSSDServiceID& service) {
 	dnsSDService->stopResolvingService(service);
 	services.erase(service);
 	onServiceRemoved(service);
 }
 
-void LinkLocalServiceBrowser::handleServiceResolved(const LinkLocalServiceID& service, const DNSSDService::ResolveResult& result) {
+void LinkLocalServiceBrowser::handleServiceResolved(const DNSSDServiceID& service, const DNSSDService::ResolveResult& result) {
 	std::pair<ServiceMap::iterator, bool> r = services.insert(std::make_pair(service, result));
 	if (r.second) {
 		onServiceAdded(service);
@@ -44,6 +44,6 @@ void LinkLocalServiceBrowser::handleServiceResolved(const LinkLocalServiceID& se
 		onServiceChanged(service);
 	}
 }
-
+*/
 
 }
diff --git a/Swiften/LinkLocal/LinkLocalServiceBrowser.h b/Swiften/LinkLocal/LinkLocalServiceBrowser.h
index 879b286..10b12b7 100644
--- a/Swiften/LinkLocal/LinkLocalServiceBrowser.h
+++ b/Swiften/LinkLocal/LinkLocalServiceBrowser.h
@@ -6,31 +6,31 @@
 #include <vector>
 
 #include "Swiften/Base/String.h"
-#include "Swiften/LinkLocal/DNSSDService.h"
-#include "Swiften/LinkLocal/DNSSDServiceFactory.h"
 #include "Swiften/LinkLocal/LinkLocalService.h"
+#include "Swiften/LinkLocal/DNSSD/DNSSDQuerier.h"
+#include "Swiften/LinkLocal/DNSSD/DNSSDServiceID.h"
 
 namespace Swift {
 	class HostAddress;
 
 	class LinkLocalServiceBrowser {
 		public:
-			LinkLocalServiceBrowser(DNSSDServiceFactory*);
+			LinkLocalServiceBrowser(boost::shared_ptr<DNSSDQuerier> querier);
 
 			std::vector<LinkLocalService> getServices() const;
 
-			boost::signal<void (const LinkLocalServiceID&)> onServiceAdded;
-			boost::signal<void (const LinkLocalServiceID&)> onServiceChanged;
-			boost::signal<void (const LinkLocalServiceID&)> onServiceRemoved;
+			boost::signal<void (const DNSSDServiceID&)> onServiceAdded;
+			boost::signal<void (const DNSSDServiceID&)> onServiceChanged;
+			boost::signal<void (const DNSSDServiceID&)> onServiceRemoved;
 
 		private:
-			void handleServiceAdded(const LinkLocalServiceID&);
-			void handleServiceRemoved(const LinkLocalServiceID&);
-			void handleServiceResolved(const LinkLocalServiceID& service, const DNSSDService::ResolveResult& result);
+			//void handleServiceAdded(const DNSSDServiceID&);
+			//void handleServiceRemoved(const DNSSDServiceID&);
+			//void handleServiceResolved(const DNSSDServiceID& service, const DNSSDService::ResolveResult& result);
 
 		private:
-			boost::shared_ptr<DNSSDService> dnsSDService;
-			typedef std::map<LinkLocalServiceID, DNSSDService::ResolveResult> ServiceMap;
-			ServiceMap services;
+			boost::shared_ptr<DNSSDQuerier> querier;
+			//typedef std::map<DNSSDServiceID, DNSSDService::ResolveResult> ServiceMap;
+			//ServiceMap services;
 	};
 }
diff --git a/Swiften/LinkLocal/LinkLocalServiceID.cpp b/Swiften/LinkLocal/LinkLocalServiceID.cpp
deleted file mode 100644
index 4248d88..0000000
--- a/Swiften/LinkLocal/LinkLocalServiceID.cpp
+++ /dev/null
@@ -1,7 +0,0 @@
-#include "Swiften/LinkLocal/LinkLocalServiceID.h"
-
-namespace Swift {
-
-const String LinkLocalServiceID::PresenceServiceType = String("_presence._tcp");
-
-}
diff --git a/Swiften/LinkLocal/LinkLocalServiceID.h b/Swiften/LinkLocal/LinkLocalServiceID.h
deleted file mode 100644
index ca5ba17..0000000
--- a/Swiften/LinkLocal/LinkLocalServiceID.h
+++ /dev/null
@@ -1,66 +0,0 @@
-#pragma once
-
-#include "Swiften/Base/String.h"
-
-namespace Swift {
-	class LinkLocalServiceID {
-		public:
-			static const String PresenceServiceType;
-
-			LinkLocalServiceID(
-				const String& name, 
-				const String& type, 
-				const String& domain = PresenceServiceType, 
-				int networkInterface = 0) : 
-					name(name), 
-					type(type), 
-					domain(domain), 
-					networkInterface(networkInterface) {
-			}
-
-			bool operator==(const LinkLocalServiceID& o) const {
-				return name == o.name && type == o.type && domain == o.domain && (networkInterface != 0 && o.networkInterface != 0 ? networkInterface == o.networkInterface : true);
-			}
-
-			bool operator<(const LinkLocalServiceID& o) const {
-				if (o.name == name) {
-					if (o.type == type) {
-						if (o.domain == domain) {
-							return networkInterface < o.networkInterface;
-						}
-						else {
-							return domain < o.domain;
-						}
-					}
-					else {
-						return type < o.type;
-					}
-				}
-				else {
-					return o.name < name;
-				}
-			}
-
-			const String& getName() const {
-				return name;
-			}
-
-			const String& getType() const {
-				return type;
-			}
-
-			const String& getDomain() const {
-				return domain;
-			}
-
-			int getNetworkInterfaceID() const {
-				return networkInterface;
-			}
-
-		private:
-			String name;
-			String type;
-			String domain;
-			int networkInterface;
-	};
-}
diff --git a/Swiften/LinkLocal/Makefile.inc b/Swiften/LinkLocal/Makefile.inc
index 86a25fd..0980194 100644
--- a/Swiften/LinkLocal/Makefile.inc
+++ b/Swiften/LinkLocal/Makefile.inc
@@ -3,12 +3,11 @@ SWIFTEN_SOURCES += \
 	Swiften/LinkLocal/DNSSDService.cpp \
 	Swiften/LinkLocal/PlatformDNSSDServiceFactory.cpp \
 	Swiften/LinkLocal/LinkLocalRoster.cpp \
-	Swiften/LinkLocal/LinkLocalServiceID.cpp \
 	Swiften/LinkLocal/LinkLocalServiceInfo.cpp \
-	Swiften/LinkLocal/LinkLocalServiceBrowser.cpp \
 	Swiften/LinkLocal/IncomingLinkLocalSession.cpp \
 	Swiften/LinkLocal/OutgoingLinkLocalSession.cpp \
 	Swiften/LinkLocal/LinkLocalConnector.cpp
+#Swiften/LinkLocal/LinkLocalServiceBrowser.cpp 
 
 ifeq ($(HAVE_BONJOUR),yes)
 SWIFTEN_SOURCES += \
diff --git a/Swiften/LinkLocal/UnitTest/Makefile.inc b/Swiften/LinkLocal/UnitTest/Makefile.inc
index 9640fa7..abc1180 100644
--- a/Swiften/LinkLocal/UnitTest/Makefile.inc
+++ b/Swiften/LinkLocal/UnitTest/Makefile.inc
@@ -1,3 +1,2 @@
 UNITTEST_SOURCES += \
-	Swiften/LinkLocal/UnitTest/LinkLocalServiceBrowserTest.cpp \
 	Swiften/LinkLocal/UnitTest/LinkLocalServiceInfoTest.cpp
-- 
cgit v0.10.2-6-g49f6


From 2b749bb5665adf893188faec1c299e23dd9c6c9f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Sat, 25 Jul 2009 19:38:11 +0200
Subject: Remove obsolete DNSSD factories.


diff --git a/Swiften/LinkLocal/DNSSDServiceFactory.cpp b/Swiften/LinkLocal/DNSSDServiceFactory.cpp
deleted file mode 100644
index f53660a..0000000
--- a/Swiften/LinkLocal/DNSSDServiceFactory.cpp
+++ /dev/null
@@ -1,8 +0,0 @@
-#include "Swiften/LinkLocal/DNSSDServiceFactory.h"
-
-namespace Swift {
-
-DNSSDServiceFactory::~DNSSDServiceFactory() {
-}
-
-}
diff --git a/Swiften/LinkLocal/DNSSDServiceFactory.h b/Swiften/LinkLocal/DNSSDServiceFactory.h
deleted file mode 100644
index 6296165..0000000
--- a/Swiften/LinkLocal/DNSSDServiceFactory.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#pragma once
-
-#include <boost/shared_ptr.hpp>
-
-namespace Swift {
-	class DNSSDService;
-
-	class DNSSDServiceFactory {
-		public:
-			virtual ~DNSSDServiceFactory();
-			virtual bool canCreate() const = 0;
-
-			virtual boost::shared_ptr<DNSSDService> createDNSSDService() = 0;
-	};
-}
diff --git a/Swiften/LinkLocal/LinkLocalServiceBrowser.cpp b/Swiften/LinkLocal/LinkLocalServiceBrowser.cpp
index ab56695..6634a0a 100644
--- a/Swiften/LinkLocal/LinkLocalServiceBrowser.cpp
+++ b/Swiften/LinkLocal/LinkLocalServiceBrowser.cpp
@@ -2,48 +2,68 @@
 #include <iostream>
 
 #include "Swiften/LinkLocal/LinkLocalServiceBrowser.h"
+#include "Swiften/LinkLocal/DNSSD/DNSSDBrowseQuery.h"
 #include "Swiften/Network/HostAddress.h"
 
 namespace Swift {
 
 LinkLocalServiceBrowser::LinkLocalServiceBrowser(boost::shared_ptr<DNSSDQuerier> querier) : querier(querier) {
-  /*dnsSDService = factory->createDNSSDService();
-	dnsSDService->onServiceAdded.connect(
+	browseQuery = querier->createBrowseQuery();
+	browseQuery->onServiceAdded.connect(
 			boost::bind(&LinkLocalServiceBrowser::handleServiceAdded, this, _1));
-	dnsSDService->onServiceRemoved.connect(
+	browseQuery->onServiceRemoved.connect(
 			boost::bind(&LinkLocalServiceBrowser::handleServiceRemoved, this, _1));
-	dnsSDService->onServiceResolved.connect(
-			boost::bind(&LinkLocalServiceBrowser::handleServiceResolved, this, _1, _2));*/
+	browseQuery->startBrowsing();
 }
 
+LinkLocalServiceBrowser::~LinkLocalServiceBrowser() {
+	browseQuery->stopBrowsing();
+}
+
+/*
 std::vector<LinkLocalService> LinkLocalServiceBrowser::getServices() const {
 	std::vector<LinkLocalService> result;
-	/*for (ServiceMap::const_iterator i = services.begin(); i != services.end(); ++i) {
+	for (ServiceMap::const_iterator i = services.begin(); i != services.end(); ++i) {
 		result.push_back(LinkLocalService(i->first, i->second));
-	}*/
+	}
 	return result;
 }
+*/
 
-/*void LinkLocalServiceBrowser::handleServiceAdded(const DNSSDServiceID& service) {
-	dnsSDService->startResolvingService(service);
+void LinkLocalServiceBrowser::handleServiceAdded(const DNSSDServiceID& service) {
+	boost::shared_ptr<DNSSDResolveServiceQuery> resolveQuery = querier->createResolveServiceQuery(service);
+	resolveQuery->onServiceResolved.connect(
+		boost::bind(&LinkLocalServiceBrowser::handleServiceResolved, this, service, _1));
+	std::pair<ResolveQueryMap::iterator, bool> r = resolveQueries.insert(std::make_pair(service, resolveQuery));
+	if (!r.second) {
+		r.first->second = resolveQuery;
+	}
+	resolveQuery->start();
 }
 
 void LinkLocalServiceBrowser::handleServiceRemoved(const DNSSDServiceID& service) {
-	dnsSDService->stopResolvingService(service);
-	services.erase(service);
+	ResolveQueryMap::iterator i = resolveQueries.find(service);
+	assert(i != resolveQueries.end());
+	i->second->stop();
+	resolveQueries.erase(i);
 	onServiceRemoved(service);
 }
 
-void LinkLocalServiceBrowser::handleServiceResolved(const DNSSDServiceID& service, const DNSSDService::ResolveResult& result) {
-	std::pair<ServiceMap::iterator, bool> r = services.insert(std::make_pair(service, result));
-	if (r.second) {
-		onServiceAdded(service);
+void LinkLocalServiceBrowser::handleServiceResolved(const DNSSDServiceID& service, const boost::optional<DNSSDResolveServiceQuery::Result>& result) {
+	if (!result) {
+		// TODO
+		std::cerr << "Error resolving" << std::endl;
 	}
 	else {
-		r.first->second = result;
-		onServiceChanged(service);
+		std::pair<ServiceMap::iterator, bool> r = services.insert(std::make_pair(service, *result));
+		if (r.second) {
+			onServiceAdded(service);
+		}
+		else {
+			r.first->second = *result;
+			onServiceChanged(service);
+		}
 	}
 }
-*/
 
 }
diff --git a/Swiften/LinkLocal/LinkLocalServiceBrowser.h b/Swiften/LinkLocal/LinkLocalServiceBrowser.h
index 10b12b7..5bd9bf0 100644
--- a/Swiften/LinkLocal/LinkLocalServiceBrowser.h
+++ b/Swiften/LinkLocal/LinkLocalServiceBrowser.h
@@ -1,36 +1,41 @@
 #pragma once
 
+#include <boost/signal.hpp>
 #include <boost/shared_ptr.hpp>
 #include <boost/optional.hpp>
 #include <map>
 #include <vector>
 
 #include "Swiften/Base/String.h"
-#include "Swiften/LinkLocal/LinkLocalService.h"
 #include "Swiften/LinkLocal/DNSSD/DNSSDQuerier.h"
+#include "Swiften/LinkLocal/DNSSD/DNSSDResolveServiceQuery.h"
 #include "Swiften/LinkLocal/DNSSD/DNSSDServiceID.h"
 
 namespace Swift {
-	class HostAddress;
+	//class HostAddress;
 
 	class LinkLocalServiceBrowser {
 		public:
 			LinkLocalServiceBrowser(boost::shared_ptr<DNSSDQuerier> querier);
+			~LinkLocalServiceBrowser();
 
-			std::vector<LinkLocalService> getServices() const;
+			/*std::vector<LinkLocalService> getServices() const;*/
 
 			boost::signal<void (const DNSSDServiceID&)> onServiceAdded;
 			boost::signal<void (const DNSSDServiceID&)> onServiceChanged;
 			boost::signal<void (const DNSSDServiceID&)> onServiceRemoved;
 
 		private:
-			//void handleServiceAdded(const DNSSDServiceID&);
-			//void handleServiceRemoved(const DNSSDServiceID&);
-			//void handleServiceResolved(const DNSSDServiceID& service, const DNSSDService::ResolveResult& result);
+			void handleServiceAdded(const DNSSDServiceID&);
+			void handleServiceRemoved(const DNSSDServiceID&);
+			void handleServiceResolved(const DNSSDServiceID& service, const boost::optional<DNSSDResolveServiceQuery::Result>& result);
 
 		private:
 			boost::shared_ptr<DNSSDQuerier> querier;
-			//typedef std::map<DNSSDServiceID, DNSSDService::ResolveResult> ServiceMap;
-			//ServiceMap services;
+			boost::shared_ptr<DNSSDBrowseQuery> browseQuery;
+			typedef std::map<DNSSDServiceID, boost::shared_ptr<DNSSDResolveServiceQuery> > ResolveQueryMap;
+			ResolveQueryMap resolveQueries;
+			typedef std::map<DNSSDServiceID, DNSSDResolveServiceQuery::Result> ServiceMap;
+			ServiceMap services;
 	};
 }
diff --git a/Swiften/LinkLocal/Makefile.inc b/Swiften/LinkLocal/Makefile.inc
index 0980194..ac3d2a2 100644
--- a/Swiften/LinkLocal/Makefile.inc
+++ b/Swiften/LinkLocal/Makefile.inc
@@ -1,13 +1,11 @@
 SWIFTEN_SOURCES += \
-	Swiften/LinkLocal/DNSSDServiceFactory.cpp \
+	Swiften/LinkLocal/LinkLocalServiceBrowser.cpp \
 	Swiften/LinkLocal/DNSSDService.cpp \
-	Swiften/LinkLocal/PlatformDNSSDServiceFactory.cpp \
 	Swiften/LinkLocal/LinkLocalRoster.cpp \
 	Swiften/LinkLocal/LinkLocalServiceInfo.cpp \
 	Swiften/LinkLocal/IncomingLinkLocalSession.cpp \
 	Swiften/LinkLocal/OutgoingLinkLocalSession.cpp \
 	Swiften/LinkLocal/LinkLocalConnector.cpp
-#Swiften/LinkLocal/LinkLocalServiceBrowser.cpp 
 
 ifeq ($(HAVE_BONJOUR),yes)
 SWIFTEN_SOURCES += \
diff --git a/Swiften/LinkLocal/PlatformDNSSDServiceFactory.cpp b/Swiften/LinkLocal/PlatformDNSSDServiceFactory.cpp
deleted file mode 100644
index df70506..0000000
--- a/Swiften/LinkLocal/PlatformDNSSDServiceFactory.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-#include "Swiften/LinkLocal/PlatformDNSSDServiceFactory.h"
-
-#include <cassert>
-
-#ifdef HAVE_SWIFTEN_CONFIG_H
-#include "Swiften/config.h"
-#endif
-#if defined(HAVE_AVAHI)
-#include "Swiften/LinkLocal/AvahiDNSSDService.h"
-#elif defined(HAVE_BONJOUR)
-#include "Swiften/LinkLocal/AppleDNSSDService.h"
-#endif
-
-namespace Swift {
-
-PlatformDNSSDServiceFactory::PlatformDNSSDServiceFactory() {
-}
-
-bool PlatformDNSSDServiceFactory::canCreate() const {
-#if defined(HAVE_AVAHI) || defined(HAVE_BONJOUR)
-	return true;
-#else
-	return false;
-#endif
-}
-
-boost::shared_ptr<DNSSDService> PlatformDNSSDServiceFactory::createDNSSDService() {
-#if defined(HAVE_AVAHI)
-	return boost::shared_ptr<DNSSDService>(new AvahiDNSSDService());
-#elif defined(HAVE_BONJOUR)
-  return boost::shared_ptr<DNSSDService>(new AppleDNSSDService());
-#else
-	assert(false);
-	return boost::shared_ptr<DNSSDService>();
-#endif
-}
-
-}
diff --git a/Swiften/LinkLocal/PlatformDNSSDServiceFactory.h b/Swiften/LinkLocal/PlatformDNSSDServiceFactory.h
deleted file mode 100644
index 9c4e4e6..0000000
--- a/Swiften/LinkLocal/PlatformDNSSDServiceFactory.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#pragma once
-
-#include "Swiften/LinkLocal/DNSSDServiceFactory.h"
-
-namespace Swift {
-	class PlatformDNSSDServiceFactory : public DNSSDServiceFactory {
-		public:
-			PlatformDNSSDServiceFactory();
-
-			bool canCreate() const;
-			virtual boost::shared_ptr<DNSSDService> createDNSSDService();
-	};
-}
-- 
cgit v0.10.2-6-g49f6


From 2833b8f09c9aef09004662a2a89eefbaee1e4247 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Sun, 26 Jul 2009 00:05:30 +0200
Subject: Implement LinkLocalService.


diff --git a/Swiften/LinkLocal/LinkLocalService.h b/Swiften/LinkLocal/LinkLocalService.h
index 2c62307..0c675a3 100644
--- a/Swiften/LinkLocal/LinkLocalService.h
+++ b/Swiften/LinkLocal/LinkLocalService.h
@@ -1,8 +1,8 @@
 #pragma once
 
 #include "Swiften/Base/String.h"
-#include "Swiften/Network/HostAddress.h"
 #include "Swiften/LinkLocal/DNSSD/DNSSDServiceID.h"
+#include "Swiften/LinkLocal/DNSSD/DNSSDResolveServiceQuery.h"
 #include "Swiften/LinkLocal/LinkLocalServiceInfo.h"
 
 namespace Swift {
@@ -10,7 +10,7 @@ namespace Swift {
 		public:
 			LinkLocalService(
 					const DNSSDServiceID& id,
-					const DNSSDService::ResolveResult& info) :
+					const DNSSDResolveServiceQuery::Result& info) :
 						id(id),
 						info(info) {}
 
@@ -36,6 +36,6 @@ namespace Swift {
 
 		private:
 			DNSSDServiceID id;
-			DNSSDService::ResolveResult info;
+			DNSSDResolveServiceQuery::Result info;
 	};
 }
diff --git a/Swiften/LinkLocal/LinkLocalServiceBrowser.cpp b/Swiften/LinkLocal/LinkLocalServiceBrowser.cpp
index 6634a0a..4e9c2de 100644
--- a/Swiften/LinkLocal/LinkLocalServiceBrowser.cpp
+++ b/Swiften/LinkLocal/LinkLocalServiceBrowser.cpp
@@ -20,7 +20,6 @@ LinkLocalServiceBrowser::~LinkLocalServiceBrowser() {
 	browseQuery->stopBrowsing();
 }
 
-/*
 std::vector<LinkLocalService> LinkLocalServiceBrowser::getServices() const {
 	std::vector<LinkLocalService> result;
 	for (ServiceMap::const_iterator i = services.begin(); i != services.end(); ++i) {
@@ -28,7 +27,6 @@ std::vector<LinkLocalService> LinkLocalServiceBrowser::getServices() const {
 	}
 	return result;
 }
-*/
 
 void LinkLocalServiceBrowser::handleServiceAdded(const DNSSDServiceID& service) {
 	boost::shared_ptr<DNSSDResolveServiceQuery> resolveQuery = querier->createResolveServiceQuery(service);
@@ -50,11 +48,7 @@ void LinkLocalServiceBrowser::handleServiceRemoved(const DNSSDServiceID& service
 }
 
 void LinkLocalServiceBrowser::handleServiceResolved(const DNSSDServiceID& service, const boost::optional<DNSSDResolveServiceQuery::Result>& result) {
-	if (!result) {
-		// TODO
-		std::cerr << "Error resolving" << std::endl;
-	}
-	else {
+	if (result) {
 		std::pair<ServiceMap::iterator, bool> r = services.insert(std::make_pair(service, *result));
 		if (r.second) {
 			onServiceAdded(service);
diff --git a/Swiften/LinkLocal/LinkLocalServiceBrowser.h b/Swiften/LinkLocal/LinkLocalServiceBrowser.h
index 5bd9bf0..7ec796a 100644
--- a/Swiften/LinkLocal/LinkLocalServiceBrowser.h
+++ b/Swiften/LinkLocal/LinkLocalServiceBrowser.h
@@ -10,16 +10,15 @@
 #include "Swiften/LinkLocal/DNSSD/DNSSDQuerier.h"
 #include "Swiften/LinkLocal/DNSSD/DNSSDResolveServiceQuery.h"
 #include "Swiften/LinkLocal/DNSSD/DNSSDServiceID.h"
+#include "Swiften/LinkLocal/LinkLocalService.h"
 
 namespace Swift {
-	//class HostAddress;
-
 	class LinkLocalServiceBrowser {
 		public:
 			LinkLocalServiceBrowser(boost::shared_ptr<DNSSDQuerier> querier);
 			~LinkLocalServiceBrowser();
 
-			/*std::vector<LinkLocalService> getServices() const;*/
+			std::vector<LinkLocalService> getServices() const;
 
 			boost::signal<void (const DNSSDServiceID&)> onServiceAdded;
 			boost::signal<void (const DNSSDServiceID&)> onServiceChanged;
-- 
cgit v0.10.2-6-g49f6


From 26d623d3cfd8937fb52acf76ef33d230f5010538 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Sun, 26 Jul 2009 10:21:20 +0200
Subject: Implement fake DNSSD querier.


diff --git a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourBrowseQuery.h b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourBrowseQuery.h
index 62d8606..8e3181e 100644
--- a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourBrowseQuery.h
+++ b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourBrowseQuery.h
@@ -14,14 +14,17 @@ namespace Swift {
 						&sdRef, 0, 0, "_presence._tcp", 0, 
 						&BonjourBrowseQuery::handleServiceDiscoveredStatic, this);
 				if (result != kDNSServiceErr_NoError) {
-					std::cout << "Error" << std::endl;
-					// TODO
+					sdRef = NULL;
 				}
 			}
 
 			void startBrowsing() {
-				assert(sdRef);
-				run();
+				if (!sdRef) {
+					MainEventLoop::postEvent(boost::bind(boost::ref(onError)), shared_from_this());
+				}
+				else {
+					run();
+				}
 			}
 
 			void stopBrowsing() {
@@ -35,7 +38,7 @@ namespace Swift {
 
 			void handleServiceDiscovered(DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *name, const char *type, const char *domain) {
 				if (errorCode != kDNSServiceErr_NoError) {
-					return;
+					MainEventLoop::postEvent(boost::bind(boost::ref(onError)), shared_from_this());
 				}
 				else {
 					DNSSDServiceID service(name, type, domain, interfaceIndex);
diff --git a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuerier.cpp b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuerier.cpp
index c065d4d..70fbc7c 100644
--- a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuerier.cpp
+++ b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuerier.cpp
@@ -22,7 +22,7 @@ BonjourQuerier::BonjourQuerier() : stopRequested(false), thread(0) {
 }
 
 BonjourQuerier::~BonjourQuerier() {
-	stop();
+	assert(!thread);
 }
 
 boost::shared_ptr<DNSSDBrowseQuery> BonjourQuerier::createBrowseQuery() {
@@ -64,18 +64,19 @@ void BonjourQuerier::interruptSelect() {
 }
 
 void BonjourQuerier::start() {
-	stop();
+	assert(!thread);
 	thread = new boost::thread(boost::bind(&BonjourQuerier::run, shared_from_this()));
 }
 
 void BonjourQuerier::stop() {
 	if (thread) {
 		stopRequested = true;
-		runningQueries.clear(); // TODO: Is this the right thing to do?
+		assert(runningQueries.empty());
 		runningQueriesAvailableEvent.notify_one();
 		interruptSelect();
 		thread->join();
 		delete thread;
+		thread = NULL;
 		stopRequested = false;
 	}
 }
diff --git a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourRegisterQuery.h b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourRegisterQuery.h
index 9c4db13..41e5831 100644
--- a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourRegisterQuery.h
+++ b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourRegisterQuery.h
@@ -18,13 +18,21 @@ namespace Swift {
 						txtRecord.getSize(), txtRecord.getData(), 
 						&BonjourRegisterQuery::handleServiceRegisteredStatic, this);
 				if (result != kDNSServiceErr_NoError) {
-					// TODO
-					std::cerr << "Error creating service registration" << std::endl;
+					sdRef = NULL;
 				}
 			}
 
 			void registerService() {
-				run();
+				if (sdRef) {
+					run();
+				}
+				else {
+					MainEventLoop::postEvent(boost::bind(boost::ref(onRegisterFinished), boost::optional<DNSSDServiceID>()), shared_from_this());
+				}
+			}
+
+			void unregisterService() {
+				stop();
 			}
 
 			void updateServiceInfo(const LinkLocalServiceInfo& info) {
diff --git a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourResolveHostnameQuery.h b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourResolveHostnameQuery.h
index 58c6588..6e2a852 100644
--- a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourResolveHostnameQuery.h
+++ b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourResolveHostnameQuery.h
@@ -19,13 +19,18 @@ namespace Swift {
 						hostname.getUTF8Data(), 
 						&BonjourResolveHostnameQuery::handleHostnameResolvedStatic, this);
 				if (result != kDNSServiceErr_NoError) {
-					MainEventLoop::postEvent(boost::bind(boost::ref(onHostnameResolved), boost::optional<HostAddress>()), shared_from_this());
+					sdRef = NULL;
 				}
 			}
 
 			//void DNSSDResolveHostnameQuery::run() {
 			void run() {
-				BonjourQuery::run();
+				if (sdRef) {
+					BonjourQuery::run();
+				}
+				else {
+					MainEventLoop::postEvent(boost::bind(boost::ref(onHostnameResolved), boost::optional<HostAddress>()), shared_from_this());
+				}
 			}
 
 		private:
diff --git a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourResolveServiceQuery.h b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourResolveServiceQuery.h
index 1ebd487..8b3f7ec 100644
--- a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourResolveServiceQuery.h
+++ b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourResolveServiceQuery.h
@@ -18,12 +18,17 @@ namespace Swift {
 						service.getDomain().getUTF8Data(), 
 						&BonjourResolveServiceQuery::handleServiceResolvedStatic, this);
 				if (result != kDNSServiceErr_NoError) {
-					MainEventLoop::postEvent(boost::bind(boost::ref(onServiceResolved), boost::optional<Result>()), shared_from_this());
+					sdRef = NULL;
 				}
 			}
 
 			void start() {
-				run();
+				if (sdRef) {
+					run();
+				}
+				else {
+					MainEventLoop::postEvent(boost::bind(boost::ref(onServiceResolved), boost::optional<Result>()), shared_from_this());
+				}
 			}
 
 			void stop() {
diff --git a/Swiften/LinkLocal/DNSSD/DNSSDBrowseQuery.h b/Swiften/LinkLocal/DNSSD/DNSSDBrowseQuery.h
index 86967ed..9b30858 100644
--- a/Swiften/LinkLocal/DNSSD/DNSSDBrowseQuery.h
+++ b/Swiften/LinkLocal/DNSSD/DNSSDBrowseQuery.h
@@ -14,5 +14,6 @@ namespace Swift {
 
 			boost::signal<void (const DNSSDServiceID&)> onServiceAdded;
 			boost::signal<void (const DNSSDServiceID&)> onServiceRemoved;
+			boost::signal<void ()> onError;
 	};
 }
diff --git a/Swiften/LinkLocal/DNSSD/DNSSDRegisterQuery.h b/Swiften/LinkLocal/DNSSD/DNSSDRegisterQuery.h
index a643880..627cc6b 100644
--- a/Swiften/LinkLocal/DNSSD/DNSSDRegisterQuery.h
+++ b/Swiften/LinkLocal/DNSSD/DNSSDRegisterQuery.h
@@ -13,6 +13,7 @@ namespace Swift {
 			virtual ~DNSSDRegisterQuery();
 
 			virtual void registerService() = 0;
+			virtual void unregisterService() = 0;
 			virtual void updateServiceInfo(const LinkLocalServiceInfo& info) = 0;
 
 			boost::signal<void (boost::optional<DNSSDServiceID>)> onRegisterFinished;
diff --git a/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDBrowseQuery.h b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDBrowseQuery.h
new file mode 100644
index 0000000..5a0b93b
--- /dev/null
+++ b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDBrowseQuery.h
@@ -0,0 +1,22 @@
+#pragma once
+
+#include "Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuery.h"
+#include "Swiften/LinkLocal/DNSSD/DNSSDBrowseQuery.h"
+
+namespace Swift {
+	class FakeDNSSDQuerier;
+
+	class FakeDNSSDBrowseQuery : public DNSSDBrowseQuery, public FakeDNSSDQuery {
+		public:	
+			FakeDNSSDBrowseQuery(boost::shared_ptr<FakeDNSSDQuerier> querier) : FakeDNSSDQuery(querier) {
+			}
+
+			void startBrowsing() {
+				run();
+			}
+
+			void stopBrowsing() {
+				finish();
+			}
+	};
+}
diff --git a/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.cpp b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.cpp
new file mode 100644
index 0000000..222500a
--- /dev/null
+++ b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.cpp
@@ -0,0 +1,92 @@
+#include "Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.h"
+
+#include <boost/bind.hpp>
+
+#include "Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDBrowseQuery.h"
+#include "Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDRegisterQuery.h"
+#include "Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDResolveServiceQuery.h"
+#include "Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDResolveHostnameQuery.h"
+#include "Swiften/EventLoop/MainEventLoop.h"
+
+namespace Swift {
+
+FakeDNSSDQuerier::FakeDNSSDQuerier() {
+}
+
+boost::shared_ptr<DNSSDBrowseQuery> FakeDNSSDQuerier::createBrowseQuery() {
+	return boost::shared_ptr<DNSSDBrowseQuery>(new FakeDNSSDBrowseQuery(shared_from_this()));
+}
+
+boost::shared_ptr<DNSSDRegisterQuery> FakeDNSSDQuerier::createRegisterQuery(const String& name, int port, const LinkLocalServiceInfo& info) {
+	return boost::shared_ptr<DNSSDRegisterQuery>(new FakeDNSSDRegisterQuery(name, port, info, shared_from_this()));
+}
+
+boost::shared_ptr<DNSSDResolveServiceQuery> FakeDNSSDQuerier::createResolveServiceQuery(const DNSSDServiceID& service) {
+	return boost::shared_ptr<DNSSDResolveServiceQuery>(new FakeDNSSDResolveServiceQuery(service, shared_from_this()));
+}
+
+boost::shared_ptr<DNSSDResolveHostnameQuery> FakeDNSSDQuerier::createResolveHostnameQuery(const String& hostname, int interfaceIndex) {
+	return boost::shared_ptr<DNSSDResolveHostnameQuery>(new FakeDNSSDResolveHostnameQuery(hostname, interfaceIndex, shared_from_this()));
+}
+
+void FakeDNSSDQuerier::addRunningQuery(boost::shared_ptr<FakeDNSSDQuery> query) {
+	runningQueries.push_back(query);
+	if (boost::shared_ptr<FakeDNSSDBrowseQuery> browseQuery = boost::dynamic_pointer_cast<FakeDNSSDBrowseQuery>(query)) {
+		foreach(const DNSSDServiceID& service, services) {
+			MainEventLoop::postEvent(boost::bind(boost::ref(browseQuery->onServiceAdded), service), shared_from_this());
+		}
+	}
+	else if (boost::shared_ptr<FakeDNSSDResolveServiceQuery> resolveQuery = boost::dynamic_pointer_cast<FakeDNSSDResolveServiceQuery>(query)) {
+		for(ServiceInfoMap::const_iterator i = serviceInfo.begin(); i != serviceInfo.end(); ++i) {
+			if (i->first == resolveQuery->service) {
+				MainEventLoop::postEvent(boost::bind(boost::ref(resolveQuery->onServiceResolved), i->second), shared_from_this());
+			}
+		}
+	}
+}
+
+void FakeDNSSDQuerier::removeRunningQuery(boost::shared_ptr<FakeDNSSDQuery> query) {
+	runningQueries.erase(std::remove(
+		runningQueries.begin(), runningQueries.end(), query), runningQueries.end());
+}
+
+void FakeDNSSDQuerier::addService(const DNSSDServiceID& id) {
+	services.insert(id);
+	foreach(const boost::shared_ptr<FakeDNSSDBrowseQuery>& query, getQueries<FakeDNSSDBrowseQuery>()) {
+		MainEventLoop::postEvent(boost::bind(boost::ref(query->onServiceAdded), id), shared_from_this());
+	}
+}
+
+void FakeDNSSDQuerier::removeService(const DNSSDServiceID& id) {
+	services.erase(id);
+	serviceInfo.erase(id);
+	foreach(const boost::shared_ptr<FakeDNSSDBrowseQuery>& query, getQueries<FakeDNSSDBrowseQuery>()) {
+		MainEventLoop::postEvent(boost::bind(boost::ref(query->onServiceRemoved), id), shared_from_this());
+	}
+}
+
+void FakeDNSSDQuerier::setServiceInfo(const DNSSDServiceID& id, const DNSSDResolveServiceQuery::Result& info) {
+	std::pair<ServiceInfoMap::iterator, bool> r = serviceInfo.insert(std::make_pair(id, info));
+	if (!r.second) {
+		r.first->second = info;
+	}
+	foreach(const boost::shared_ptr<FakeDNSSDResolveServiceQuery>& query, getQueries<FakeDNSSDResolveServiceQuery>()) {
+		if (query->service == id) {
+			MainEventLoop::postEvent(boost::bind(boost::ref(query->onServiceResolved), info), shared_from_this());
+		}
+	}
+}
+
+void FakeDNSSDQuerier::setBrowseError() {
+	foreach(const boost::shared_ptr<FakeDNSSDBrowseQuery>& query, getQueries<FakeDNSSDBrowseQuery>()) {
+		MainEventLoop::postEvent(boost::ref(query->onError), shared_from_this());
+	}
+}
+
+void FakeDNSSDQuerier::setRegisterError() {
+	foreach(const boost::shared_ptr<FakeDNSSDRegisterQuery>& query, getQueries<FakeDNSSDRegisterQuery>()) {
+		MainEventLoop::postEvent(boost::bind(boost::ref(query->onRegisterFinished), boost::optional<DNSSDServiceID>()), shared_from_this());
+	}
+}
+
+}
diff --git a/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.h b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.h
new file mode 100644
index 0000000..6c5f343
--- /dev/null
+++ b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.h
@@ -0,0 +1,61 @@
+#pragma once
+
+#include <boost/shared_ptr.hpp>
+#include <boost/enable_shared_from_this.hpp>
+#include <list>
+#include <set>
+
+#include "Swiften/Base/foreach.h"
+#include "Swiften/EventLoop/EventOwner.h"
+#include "Swiften/LinkLocal/DNSSD/DNSSDQuerier.h"
+#include "Swiften/LinkLocal/DNSSD/DNSSDResolveServiceQuery.h"
+
+namespace Swift {
+	class LinkLocalServiceInfo;
+	class FakeDNSSDQuery;
+	class FakeDNSSDBrowseQuery;
+
+	class FakeDNSSDQuerier : 
+			public DNSSDQuerier, 
+			public EventOwner,
+			public boost::enable_shared_from_this<FakeDNSSDQuerier> {
+		public:
+			FakeDNSSDQuerier();
+
+			boost::shared_ptr<DNSSDBrowseQuery> createBrowseQuery();
+			boost::shared_ptr<DNSSDRegisterQuery> createRegisterQuery(
+					const String& name, int port, const LinkLocalServiceInfo& info);
+			boost::shared_ptr<DNSSDResolveServiceQuery> createResolveServiceQuery(
+					const DNSSDServiceID&);
+			boost::shared_ptr<DNSSDResolveHostnameQuery> createResolveHostnameQuery(
+					const String& hostname, int interfaceIndex);
+
+			void addRunningQuery(boost::shared_ptr<FakeDNSSDQuery>);
+			void removeRunningQuery(boost::shared_ptr<FakeDNSSDQuery>);
+
+			void addService(const DNSSDServiceID& id);
+			void removeService(const DNSSDServiceID& id);
+			void setServiceInfo(const DNSSDServiceID& id, const DNSSDResolveServiceQuery::Result& info);
+
+			void setBrowseError();
+			void setRegisterError();
+
+		private:
+			template<typename T>
+			std::vector< boost::shared_ptr<T> > getQueries() const {
+				std::vector< boost::shared_ptr<T> > result;
+				foreach(const boost::shared_ptr<FakeDNSSDQuery>& query, runningQueries) {
+					if (boost::shared_ptr<T> resultQuery = boost::dynamic_pointer_cast<T>(query)) {
+						result.push_back(resultQuery);
+					}
+				}
+				return result;
+			}
+
+		private:
+			std::list< boost::shared_ptr<FakeDNSSDQuery> > runningQueries;
+			std::set<DNSSDServiceID> services;
+			typedef std::map<DNSSDServiceID,DNSSDResolveServiceQuery::Result> ServiceInfoMap;
+			ServiceInfoMap serviceInfo;
+	};
+}
diff --git a/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuery.cpp b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuery.cpp
new file mode 100644
index 0000000..ced7850
--- /dev/null
+++ b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuery.cpp
@@ -0,0 +1,20 @@
+#include "Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuery.h"
+#include "Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.h"
+
+namespace Swift {
+
+FakeDNSSDQuery::FakeDNSSDQuery(boost::shared_ptr<FakeDNSSDQuerier> querier) : querier(querier) {
+}
+
+FakeDNSSDQuery::~FakeDNSSDQuery() {
+}
+
+void FakeDNSSDQuery::run() {
+	querier->addRunningQuery(shared_from_this());
+}
+
+void FakeDNSSDQuery::finish() {
+	querier->removeRunningQuery(shared_from_this());
+}
+
+}
diff --git a/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuery.h b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuery.h
new file mode 100644
index 0000000..9fca1d4
--- /dev/null
+++ b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuery.h
@@ -0,0 +1,25 @@
+#pragma once
+
+#include <boost/shared_ptr.hpp>
+#include <boost/enable_shared_from_this.hpp>
+
+#include "Swiften/EventLoop/EventOwner.h"
+
+namespace Swift {
+	class FakeDNSSDQuerier;
+
+	class FakeDNSSDQuery : 
+			public EventOwner,
+			public boost::enable_shared_from_this<FakeDNSSDQuery> {
+		public:
+			FakeDNSSDQuery(boost::shared_ptr<FakeDNSSDQuerier>);
+			virtual ~FakeDNSSDQuery();
+			
+		protected:
+			void run();
+			void finish();
+		
+		protected:
+			boost::shared_ptr<FakeDNSSDQuerier> querier;
+	};
+}
diff --git a/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDRegisterQuery.h b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDRegisterQuery.h
new file mode 100644
index 0000000..b4646fd
--- /dev/null
+++ b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDRegisterQuery.h
@@ -0,0 +1,31 @@
+#pragma once
+
+#include "Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuery.h"
+#include "Swiften/LinkLocal/DNSSD/DNSSDRegisterQuery.h"
+#include "Swiften/LinkLocal/LinkLocalServiceInfo.h"
+#include "Swiften/Base/String.h"
+
+namespace Swift {
+	class FakeDNSSDQuerier;
+
+	class FakeDNSSDRegisterQuery : public DNSSDRegisterQuery, public FakeDNSSDQuery {
+		public:	
+			FakeDNSSDRegisterQuery(const String& name, int port, const LinkLocalServiceInfo& info, boost::shared_ptr<FakeDNSSDQuerier> querier) : FakeDNSSDQuery(querier), name(name), port(port), info(info) {
+			}
+
+			void registerService() {
+				run();
+			}
+
+			void updateServiceInfo(const LinkLocalServiceInfo&) {
+			}
+
+			void unregisterService() {
+				finish();
+			}
+
+			String name;
+			int port;
+			LinkLocalServiceInfo info;
+	};
+}
diff --git a/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDResolveHostnameQuery.h b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDResolveHostnameQuery.h
new file mode 100644
index 0000000..2ff84d3
--- /dev/null
+++ b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDResolveHostnameQuery.h
@@ -0,0 +1,25 @@
+#pragma once
+
+#include "Swiften/Base/String.h"
+#include "Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuery.h"
+#include "Swiften/LinkLocal/DNSSD/DNSSDResolveHostnameQuery.h"
+#include "Swiften/Network/HostAddress.h"
+
+#include <netinet/in.h>
+
+namespace Swift {
+	class FakeDNSSDQuerier;
+
+	class FakeDNSSDResolveHostnameQuery : public DNSSDResolveHostnameQuery, public FakeDNSSDQuery {
+		public:	
+			FakeDNSSDResolveHostnameQuery(const String& hostname, int interfaceIndex, boost::shared_ptr<FakeDNSSDQuerier> querier) : FakeDNSSDQuery(querier), hostname(hostname), interfaceIndex(interfaceIndex) {
+			}
+
+			void run() {
+				FakeDNSSDQuery::run();
+			}
+
+			String hostname;
+			int interfaceIndex;
+	};
+}
diff --git a/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDResolveServiceQuery.h b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDResolveServiceQuery.h
new file mode 100644
index 0000000..60d35e5
--- /dev/null
+++ b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDResolveServiceQuery.h
@@ -0,0 +1,25 @@
+#pragma once
+
+#include "Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuery.h"
+#include "Swiften/LinkLocal/DNSSD/DNSSDResolveServiceQuery.h"
+#include "Swiften/LinkLocal/LinkLocalServiceInfo.h"
+
+namespace Swift {
+	class FakeDNSSDQuerier;
+
+	class FakeDNSSDResolveServiceQuery : public DNSSDResolveServiceQuery, public FakeDNSSDQuery {
+		public:	
+			FakeDNSSDResolveServiceQuery(const DNSSDServiceID& service, boost::shared_ptr<FakeDNSSDQuerier> querier) : FakeDNSSDQuery(querier), service(service) {
+			}
+
+			void start() {
+				run();
+			}
+
+			void stop() {
+				finish();
+			}
+
+			DNSSDServiceID service;
+	};
+}
diff --git a/Swiften/LinkLocal/DNSSD/Fake/Makefile.inc b/Swiften/LinkLocal/DNSSD/Fake/Makefile.inc
new file mode 100644
index 0000000..316d061
--- /dev/null
+++ b/Swiften/LinkLocal/DNSSD/Fake/Makefile.inc
@@ -0,0 +1,3 @@
+SWIFTEN_SOURCES += \
+	Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuery.cpp \
+	Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.cpp
diff --git a/Swiften/LinkLocal/DNSSD/Makefile.inc b/Swiften/LinkLocal/DNSSD/Makefile.inc
index 8612fee..3d2c969 100644
--- a/Swiften/LinkLocal/DNSSD/Makefile.inc
+++ b/Swiften/LinkLocal/DNSSD/Makefile.inc
@@ -11,3 +11,5 @@ include Swiften/LinkLocal/DNSSD/Bonjour/Makefile.inc
 endif
 ifeq ($(HAVE_AVAHI),yes)
 endif
+
+include Swiften/LinkLocal/DNSSD/Fake/Makefile.inc
diff --git a/Swiften/LinkLocal/LinkLocalServiceBrowser.cpp b/Swiften/LinkLocal/LinkLocalServiceBrowser.cpp
index 4e9c2de..aed917a 100644
--- a/Swiften/LinkLocal/LinkLocalServiceBrowser.cpp
+++ b/Swiften/LinkLocal/LinkLocalServiceBrowser.cpp
@@ -7,17 +7,66 @@
 
 namespace Swift {
 
-LinkLocalServiceBrowser::LinkLocalServiceBrowser(boost::shared_ptr<DNSSDQuerier> querier) : querier(querier) {
+LinkLocalServiceBrowser::LinkLocalServiceBrowser(boost::shared_ptr<DNSSDQuerier> querier) : querier(querier), haveError(false) {
+}
+
+LinkLocalServiceBrowser::~LinkLocalServiceBrowser() {
+	assert(!isRunning());
+}
+
+
+void LinkLocalServiceBrowser::start() {
+	assert(!isRunning());
+	haveError = false;
 	browseQuery = querier->createBrowseQuery();
 	browseQuery->onServiceAdded.connect(
 			boost::bind(&LinkLocalServiceBrowser::handleServiceAdded, this, _1));
 	browseQuery->onServiceRemoved.connect(
 			boost::bind(&LinkLocalServiceBrowser::handleServiceRemoved, this, _1));
+	browseQuery->onError.connect(
+			boost::bind(&LinkLocalServiceBrowser::handleBrowseError, this));
 	browseQuery->startBrowsing();
 }
 
-LinkLocalServiceBrowser::~LinkLocalServiceBrowser() {
+void LinkLocalServiceBrowser::stop() {
+	assert(isRunning());
+	if (isRegistered()) {
+		unregisterService();
+	}
+	for (ResolveQueryMap::const_iterator i = resolveQueries.begin(); i != resolveQueries.end(); ++i) {
+		i->second->stop();
+	}
+	resolveQueries.clear();
+	services.clear();
 	browseQuery->stopBrowsing();
+	browseQuery.reset();
+	onStopped(haveError);
+}
+
+bool LinkLocalServiceBrowser::isRunning() const {
+	return browseQuery;
+}
+
+bool LinkLocalServiceBrowser::hasError() const {
+	return haveError;
+}
+
+bool LinkLocalServiceBrowser::isRegistered() const {
+	return registerQuery;
+}
+
+void LinkLocalServiceBrowser::registerService(const String& name, int port, const LinkLocalServiceInfo& info) {
+	assert(!registerQuery);
+	registerQuery = querier->createRegisterQuery(name, port, info);
+	registerQuery->onRegisterFinished.connect(
+		boost::bind(&LinkLocalServiceBrowser::handleRegisterFinished, this, _1));
+	registerQuery->registerService();
+}
+
+void LinkLocalServiceBrowser::unregisterService() {
+	assert(registerQuery);
+	registerQuery->unregisterService();
+	registerQuery.reset();
 }
 
 std::vector<LinkLocalService> LinkLocalServiceBrowser::getServices() const {
@@ -44,6 +93,7 @@ void LinkLocalServiceBrowser::handleServiceRemoved(const DNSSDServiceID& service
 	assert(i != resolveQueries.end());
 	i->second->stop();
 	resolveQueries.erase(i);
+	services.erase(service);
 	onServiceRemoved(service);
 }
 
@@ -60,4 +110,16 @@ void LinkLocalServiceBrowser::handleServiceResolved(const DNSSDServiceID& servic
 	}
 }
 
+void LinkLocalServiceBrowser::handleRegisterFinished(const boost::optional<DNSSDServiceID>& result) {
+	if (!result) {
+		haveError = true;
+		stop();
+	}
+}
+
+void LinkLocalServiceBrowser::handleBrowseError() {
+	haveError = true;
+	stop();
+}
+
 }
diff --git a/Swiften/LinkLocal/LinkLocalServiceBrowser.h b/Swiften/LinkLocal/LinkLocalServiceBrowser.h
index 7ec796a..33c9858 100644
--- a/Swiften/LinkLocal/LinkLocalServiceBrowser.h
+++ b/Swiften/LinkLocal/LinkLocalServiceBrowser.h
@@ -9,8 +9,10 @@
 #include "Swiften/Base/String.h"
 #include "Swiften/LinkLocal/DNSSD/DNSSDQuerier.h"
 #include "Swiften/LinkLocal/DNSSD/DNSSDResolveServiceQuery.h"
+#include "Swiften/LinkLocal/DNSSD/DNSSDRegisterQuery.h"
 #include "Swiften/LinkLocal/DNSSD/DNSSDServiceID.h"
 #include "Swiften/LinkLocal/LinkLocalService.h"
+#include "Swiften/LinkLocal/LinkLocalServiceInfo.h"
 
 namespace Swift {
 	class LinkLocalServiceBrowser {
@@ -18,23 +20,37 @@ namespace Swift {
 			LinkLocalServiceBrowser(boost::shared_ptr<DNSSDQuerier> querier);
 			~LinkLocalServiceBrowser();
 
+			void start();
+			void stop();
+			bool isRunning() const;
+			bool hasError() const;
+
+			void registerService(const String& name, int port, const LinkLocalServiceInfo& info = LinkLocalServiceInfo());
+			void unregisterService();
+			bool isRegistered() const;
+
 			std::vector<LinkLocalService> getServices() const;
 
 			boost::signal<void (const DNSSDServiceID&)> onServiceAdded;
 			boost::signal<void (const DNSSDServiceID&)> onServiceChanged;
 			boost::signal<void (const DNSSDServiceID&)> onServiceRemoved;
+			boost::signal<void (bool)> onStopped;
 
 		private:
 			void handleServiceAdded(const DNSSDServiceID&);
 			void handleServiceRemoved(const DNSSDServiceID&);
 			void handleServiceResolved(const DNSSDServiceID& service, const boost::optional<DNSSDResolveServiceQuery::Result>& result);
+			void handleRegisterFinished(const boost::optional<DNSSDServiceID>&);
+			void handleBrowseError();
 
 		private:
 			boost::shared_ptr<DNSSDQuerier> querier;
 			boost::shared_ptr<DNSSDBrowseQuery> browseQuery;
+			boost::shared_ptr<DNSSDRegisterQuery> registerQuery;
 			typedef std::map<DNSSDServiceID, boost::shared_ptr<DNSSDResolveServiceQuery> > ResolveQueryMap;
 			ResolveQueryMap resolveQueries;
 			typedef std::map<DNSSDServiceID, DNSSDResolveServiceQuery::Result> ServiceMap;
 			ServiceMap services;
+			bool haveError;
 	};
 }
diff --git a/Swiften/LinkLocal/UnitTest/LinkLocalServiceBrowserTest.cpp b/Swiften/LinkLocal/UnitTest/LinkLocalServiceBrowserTest.cpp
index 34f797c..7e2dd26 100644
--- a/Swiften/LinkLocal/UnitTest/LinkLocalServiceBrowserTest.cpp
+++ b/Swiften/LinkLocal/UnitTest/LinkLocalServiceBrowserTest.cpp
@@ -5,20 +5,26 @@
 
 #include "Swiften/LinkLocal/LinkLocalServiceBrowser.h"
 #include "Swiften/LinkLocal/LinkLocalService.h"
-#include "Swiften/LinkLocal/UnitTest/MockDNSSDService.h"
-#include "Swiften/LinkLocal/DNSSDService.h"
+#include "Swiften/LinkLocal/DNSSD/DNSSDServiceID.h"
+#include "Swiften/LinkLocal/DNSSD/DNSSDResolveServiceQuery.h"
+#include "Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.h"
 #include "Swiften/EventLoop/DummyEventLoop.h"
 
-// Test canCreate() == false
-
 using namespace Swift;
 
 class LinkLocalServiceBrowserTest : public CppUnit::TestFixture {
 		CPPUNIT_TEST_SUITE(LinkLocalServiceBrowserTest);
+		CPPUNIT_TEST(testConstructor);
+		CPPUNIT_TEST(testStart);
 		CPPUNIT_TEST(testServiceAdded);
 		CPPUNIT_TEST(testServiceAdded_NoServiceInfo);
 		CPPUNIT_TEST(testServiceChanged);
 		CPPUNIT_TEST(testServiceRemoved);
+		CPPUNIT_TEST(testError_BrowseErrorAfterStart);
+		CPPUNIT_TEST(testError_BrowseErrorAfterResolve);
+		CPPUNIT_TEST(testRegisterService);
+		CPPUNIT_TEST(testRegisterService_Error);
+		CPPUNIT_TEST(testRegisterService_Reregister);
 		CPPUNIT_TEST_SUITE_END();
 
 	public:
@@ -26,10 +32,10 @@ class LinkLocalServiceBrowserTest : public CppUnit::TestFixture {
 
 		void setUp() {
 			eventLoop = new DummyEventLoop();
-			dnsSDServiceFactory = new MockDNSSDServiceFactory();
-			testServiceID = new LinkLocalServiceID("foo", "bar.local");
-			testServiceInfo = new DNSSDService::ResolveResult("xmpp.bar.local", 1234, LinkLocalServiceInfo());
-			testServiceInfo2 = new DNSSDService::ResolveResult("xmpp.foo.local", 2345, LinkLocalServiceInfo());
+			querier = boost::shared_ptr<FakeDNSSDQuerier>(new FakeDNSSDQuerier());
+			testServiceID = new DNSSDServiceID("foo", "bar.local");
+			testServiceInfo = new DNSSDResolveServiceQuery::Result("_presence._tcp.bar.local", "xmpp.bar.local", 1234, LinkLocalServiceInfo());
+			testServiceInfo2 = new DNSSDResolveServiceQuery::Result("_presence.tcp.bar.local", "xmpp.foo.local", 2345, LinkLocalServiceInfo());
 		}
 
 		void tearDown() {
@@ -40,15 +46,33 @@ class LinkLocalServiceBrowserTest : public CppUnit::TestFixture {
 			delete testServiceInfo2;
 			delete testServiceInfo;
 			delete testServiceID;
-      delete dnsSDServiceFactory;
 			delete eventLoop;
 		}
 
+		void testConstructor() {
+			boost::shared_ptr<LinkLocalServiceBrowser> testling = createTestling();
+
+			CPPUNIT_ASSERT(!testling->isRunning());
+			CPPUNIT_ASSERT(!testling->hasError());
+		}
+
+		void testStart() {
+			boost::shared_ptr<LinkLocalServiceBrowser> testling = createTestling();
+			testling->start();
+
+			CPPUNIT_ASSERT(testling->isRunning());
+			CPPUNIT_ASSERT(!testling->hasError());
+
+			testling->stop();
+		}
+
 		void testServiceAdded() {
 			boost::shared_ptr<LinkLocalServiceBrowser> testling = createTestling();
+			testling->start();
+			eventLoop->processEvents();
 
-			dnsSDService()->setServiceInfo(*testServiceID,*testServiceInfo);
-			dnsSDService()->addService(*testServiceID);
+			querier->setServiceInfo(*testServiceID,*testServiceInfo);
+			querier->addService(*testServiceID);
 			eventLoop->processEvents();
 
 			CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(addedServices.size()));
@@ -60,26 +84,33 @@ class LinkLocalServiceBrowserTest : public CppUnit::TestFixture {
 			CPPUNIT_ASSERT(*testServiceID == services[0].getID());
 			CPPUNIT_ASSERT(testServiceInfo->port == services[0].getPort());
 			CPPUNIT_ASSERT(testServiceInfo->host == services[0].getHostname());
+
+			testling->stop();
 		}
 
 		void testServiceAdded_NoServiceInfo() {
 			boost::shared_ptr<LinkLocalServiceBrowser> testling = createTestling();
+			testling->start();
+			eventLoop->processEvents();
 
-			dnsSDService()->addService(*testServiceID);
+			querier->addService(*testServiceID);
 			eventLoop->processEvents();
 
 			CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(addedServices.size()));
 			std::vector<LinkLocalService> services = testling->getServices();
 			CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(services.size()));
+
+			testling->stop();
 		}
 
 		void testServiceChanged() {
 			boost::shared_ptr<LinkLocalServiceBrowser> testling = createTestling();
-			dnsSDService()->setServiceInfo(*testServiceID,*testServiceInfo);
-			dnsSDService()->addService(*testServiceID);
+			testling->start();
+			querier->setServiceInfo(*testServiceID,*testServiceInfo);
+			querier->addService(*testServiceID);
 			eventLoop->processEvents();
 
-			dnsSDService()->setServiceInfo(*testServiceID,*testServiceInfo2);
+			querier->setServiceInfo(*testServiceID,*testServiceInfo2);
 			eventLoop->processEvents();
 
 			CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(addedServices.size()));
@@ -91,31 +122,93 @@ class LinkLocalServiceBrowserTest : public CppUnit::TestFixture {
 			CPPUNIT_ASSERT(*testServiceID == services[0].getID());
 			CPPUNIT_ASSERT(testServiceInfo2->port == services[0].getPort());
 			CPPUNIT_ASSERT(testServiceInfo2->host == services[0].getHostname());
+
+			testling->stop();
 		}
 
 		void testServiceRemoved() {
 			boost::shared_ptr<LinkLocalServiceBrowser> testling = createTestling();
-			dnsSDService()->setServiceInfo(*testServiceID,*testServiceInfo);
-			dnsSDService()->addService(*testServiceID);
+			testling->start();
+			querier->setServiceInfo(*testServiceID,*testServiceInfo);
+			querier->addService(*testServiceID);
 			eventLoop->processEvents();
 
-			dnsSDService()->removeService(*testServiceID);
+			querier->removeService(*testServiceID);
 			eventLoop->processEvents();
-			dnsSDService()->setServiceInfo(*testServiceID,*testServiceInfo2);
+			querier->setServiceInfo(*testServiceID,*testServiceInfo2);
 			eventLoop->processEvents();
 
 			CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(addedServices.size()));
 			CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(changedServices.size()));
 			CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(removedServices.size()));
 			CPPUNIT_ASSERT(removedServices[0] == *testServiceID);
-			std::vector<LinkLocalService> services = testling->getServices();
-			CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(services.size()));
+			CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(testling->getServices().size()));
+
+			testling->stop();
+		}
+
+		void testError_BrowseErrorAfterStart() {
+			boost::shared_ptr<LinkLocalServiceBrowser> testling = createTestling();
+			testling->start();
+
+			querier->setBrowseError();
+			eventLoop->processEvents();
+
+			CPPUNIT_ASSERT(!testling->isRunning());
+			CPPUNIT_ASSERT(testling->hasError());
+		}
+
+		void testError_BrowseErrorAfterResolve() {
+			boost::shared_ptr<LinkLocalServiceBrowser> testling = createTestling();
+			testling->start();
+			querier->setServiceInfo(*testServiceID,*testServiceInfo);
+			querier->addService(*testServiceID);
+			eventLoop->processEvents();
+
+			querier->setBrowseError();
+			eventLoop->processEvents();
+			querier->setServiceInfo(*testServiceID,*testServiceInfo2);
+			eventLoop->processEvents();
+
+			CPPUNIT_ASSERT(!testling->isRunning());
+			CPPUNIT_ASSERT(testling->hasError());
+			CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(testling->getServices().size()));
+			CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(changedServices.size()));
+		}
+
+		void testRegisterService() {
+			boost::shared_ptr<LinkLocalServiceBrowser> testling = createTestling();
+			testling->start();
+			eventLoop->processEvents();
+
+			testling->stop();
+		}
+
+		void testRegisterService_Error() {
+			boost::shared_ptr<LinkLocalServiceBrowser> testling = createTestling();
+			testling->start();
+			testling->registerService("", 1234);
+			eventLoop->processEvents();
+
+			querier->setRegisterError();
+			eventLoop->processEvents();
+
+			CPPUNIT_ASSERT(!testling->isRunning());
+			CPPUNIT_ASSERT(testling->hasError());
+		}
+
+		void testRegisterService_Reregister() {
+			boost::shared_ptr<LinkLocalServiceBrowser> testling = createTestling();
+			testling->start();
+			eventLoop->processEvents();
+
+			testling->stop();
 		}
 
 	private:
 		boost::shared_ptr<LinkLocalServiceBrowser> createTestling() {
 			boost::shared_ptr<LinkLocalServiceBrowser> testling(
-					new LinkLocalServiceBrowser(dnsSDServiceFactory));
+					new LinkLocalServiceBrowser(querier));
 			testling->onServiceAdded.connect(boost::bind(
 					&LinkLocalServiceBrowserTest::handleServiceAdded, this, _1));
 			testling->onServiceChanged.connect(boost::bind(
@@ -125,32 +218,27 @@ class LinkLocalServiceBrowserTest : public CppUnit::TestFixture {
 			return testling;
 		}
 
-		void handleServiceAdded(const LinkLocalServiceID& service) {
+		void handleServiceAdded(const DNSSDServiceID& service) {
 			addedServices.push_back(service);
 		}
 
-		void handleServiceRemoved(const LinkLocalServiceID& service) {
+		void handleServiceRemoved(const DNSSDServiceID& service) {
 			removedServices.push_back(service);
 		}
 
-		void handleServiceChanged(const LinkLocalServiceID& service) {
+		void handleServiceChanged(const DNSSDServiceID& service) {
 			changedServices.push_back(service);
 		}
 
-    boost::shared_ptr<MockDNSSDService> dnsSDService() const {
-      CPPUNIT_ASSERT(dnsSDServiceFactory->services.size() > 0);
-      return dnsSDServiceFactory->services[0];
-    }
-
 	private:
 		DummyEventLoop* eventLoop;
-		MockDNSSDServiceFactory* dnsSDServiceFactory;
-		std::vector<LinkLocalServiceID> addedServices;
-		std::vector<LinkLocalServiceID> changedServices;
-		std::vector<LinkLocalServiceID> removedServices;
-		LinkLocalServiceID* testServiceID;
-		DNSSDService::ResolveResult* testServiceInfo;
-		DNSSDService::ResolveResult* testServiceInfo2;
+		boost::shared_ptr<FakeDNSSDQuerier> querier;
+		std::vector<DNSSDServiceID> addedServices;
+		std::vector<DNSSDServiceID> changedServices;
+		std::vector<DNSSDServiceID> removedServices;
+		DNSSDServiceID* testServiceID;
+		DNSSDResolveServiceQuery::Result* testServiceInfo;
+		DNSSDResolveServiceQuery::Result* testServiceInfo2;
 };
 
 CPPUNIT_TEST_SUITE_REGISTRATION(LinkLocalServiceBrowserTest);
diff --git a/Swiften/LinkLocal/UnitTest/Makefile.inc b/Swiften/LinkLocal/UnitTest/Makefile.inc
index abc1180..9640fa7 100644
--- a/Swiften/LinkLocal/UnitTest/Makefile.inc
+++ b/Swiften/LinkLocal/UnitTest/Makefile.inc
@@ -1,2 +1,3 @@
 UNITTEST_SOURCES += \
+	Swiften/LinkLocal/UnitTest/LinkLocalServiceBrowserTest.cpp \
 	Swiften/LinkLocal/UnitTest/LinkLocalServiceInfoTest.cpp
diff --git a/Swiften/LinkLocal/UnitTest/MockDNSSDService.h b/Swiften/LinkLocal/UnitTest/MockDNSSDService.h
deleted file mode 100644
index 69ac06d..0000000
--- a/Swiften/LinkLocal/UnitTest/MockDNSSDService.h
+++ /dev/null
@@ -1,97 +0,0 @@
-#pragma once
-
-#include <vector>
-#include <map>
-#include <boost/bind.hpp>
-
-#include "Swiften/EventLoop/MainEventLoop.h"
-#include "Swiften/LinkLocal/DNSSDService.h"
-#include "Swiften/LinkLocal/DNSSDServiceFactory.h"
-
-namespace Swift {
-	class MockDNSSDService : public DNSSDService {
-		public:
-			MockDNSSDService() {
-			}
-			
-			void start() {
-			}
-
-			void stop() {
-			}
-
-			virtual void registerService(const String&, int, const LinkLocalServiceInfo&) {
-				assert(false);
-			}
-
-			virtual void updateService(const LinkLocalServiceInfo&) {
-				assert(false);
-			}
-
-			virtual void unregisterService() {
-				assert(false);
-			}
-
-			virtual void startResolvingService(const LinkLocalServiceID& id) {
-				resolvingServices.push_back(id);
-				broadcastServiceInfo(id);
-			}
-
-			virtual void stopResolvingService(const LinkLocalServiceID& id) {
-				resolvingServices.erase(std::remove(resolvingServices.begin(), resolvingServices.end(), id), resolvingServices.end());
-			}
-			
-			virtual void resolveHostname(const String&, int) {
-				assert(false);
-			}
-
-			void addService(const LinkLocalServiceID& id) {
-				MainEventLoop::postEvent(boost::bind(boost::ref(onServiceAdded), id));
-			}
-
-			void removeService(const LinkLocalServiceID& id) {
-				serviceInfo.erase(id);
-				MainEventLoop::postEvent(boost::bind(boost::ref(onServiceRemoved), id));
-			}
-
-			void setServiceInfo(const LinkLocalServiceID& id, const DNSSDService::ResolveResult& info) {
-				std::pair<ServiceInfoMap::iterator, bool> r = serviceInfo.insert(std::make_pair(id, info));
-				if (!r.second) {
-					r.first->second = info;
-				}
-				broadcastServiceInfo(id);
-			}
-
-		private:
-			void broadcastServiceInfo(const LinkLocalServiceID& id) {
-				if (std::find(resolvingServices.begin(), resolvingServices.end(), id) != resolvingServices.end()) {
-					ServiceInfoMap::const_iterator i = serviceInfo.find(id);
-					if (i != serviceInfo.end()) {
-						MainEventLoop::postEvent(
-								boost::bind(boost::ref(onServiceResolved), id, i->second));
-					}
-				}
-			}
-
-		private:
-			typedef std::map<LinkLocalServiceID,DNSSDService::ResolveResult> ServiceInfoMap;
-			ServiceInfoMap serviceInfo;
-			std::vector<LinkLocalServiceID> resolvingServices;
-	};
-
-  class MockDNSSDServiceFactory : public DNSSDServiceFactory {
-    public:
-      boost::shared_ptr<DNSSDService> createDNSSDService() {
-        boost::shared_ptr<MockDNSSDService> result(new MockDNSSDService());   
-        services.push_back(result);
-        return result;
-      }
-
-      bool canCreate() const {
-        return true;
-      }
-
-      std::vector<boost::shared_ptr<MockDNSSDService> > services;
-  };
-
-}
-- 
cgit v0.10.2-6-g49f6


From e7ab68e8daf120d932d9eefc9053e9e064ca29af Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Sun, 26 Jul 2009 17:06:11 +0200
Subject: Make DNSSD independent of LinkLocalServiceInfo.


diff --git a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuerier.cpp b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuerier.cpp
index 70fbc7c..9c9e64e 100644
--- a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuerier.cpp
+++ b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuerier.cpp
@@ -29,7 +29,7 @@ boost::shared_ptr<DNSSDBrowseQuery> BonjourQuerier::createBrowseQuery() {
 	return boost::shared_ptr<DNSSDBrowseQuery>(new BonjourBrowseQuery(shared_from_this()));
 }
 
-boost::shared_ptr<DNSSDRegisterQuery> BonjourQuerier::createRegisterQuery(const String& name, int port, const LinkLocalServiceInfo& info) {
+boost::shared_ptr<DNSSDRegisterQuery> BonjourQuerier::createRegisterQuery(const String& name, int port, const ByteArray& info) {
 	return boost::shared_ptr<DNSSDRegisterQuery>(new BonjourRegisterQuery(name, port, info, shared_from_this()));
 }
 
diff --git a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuerier.h b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuerier.h
index 644a8d9..d12f94f 100644
--- a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuerier.h
+++ b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuerier.h
@@ -10,7 +10,7 @@
 #include "Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuery.h"
 
 namespace Swift {
-	class LinkLocalServiceInfo;
+	class ByteArray;
 
 	class BonjourQuerier : 
 			public DNSSDQuerier, 
@@ -21,7 +21,7 @@ namespace Swift {
 
 			boost::shared_ptr<DNSSDBrowseQuery> createBrowseQuery();
 			boost::shared_ptr<DNSSDRegisterQuery> createRegisterQuery(
-					const String& name, int port, const LinkLocalServiceInfo& info);
+					const String& name, int port, const ByteArray& info);
 			boost::shared_ptr<DNSSDResolveServiceQuery> createResolveServiceQuery(
 					const DNSSDServiceID&);
 			boost::shared_ptr<DNSSDResolveHostnameQuery> createResolveHostnameQuery(
diff --git a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourRegisterQuery.h b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourRegisterQuery.h
index 41e5831..c85b90f 100644
--- a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourRegisterQuery.h
+++ b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourRegisterQuery.h
@@ -2,7 +2,6 @@
 
 #include "Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuery.h"
 #include "Swiften/LinkLocal/DNSSD/DNSSDRegisterQuery.h"
-#include "Swiften/LinkLocal/LinkLocalServiceInfo.h"
 #include "Swiften/Base/ByteArray.h"
 #include "Swiften/EventLoop/MainEventLoop.h"
 
@@ -11,8 +10,7 @@ namespace Swift {
 
 	class BonjourRegisterQuery : public DNSSDRegisterQuery, public BonjourQuery {
 		public:	
-			BonjourRegisterQuery(const String& name, int port, const LinkLocalServiceInfo& info, boost::shared_ptr<BonjourQuerier> querier) : BonjourQuery(querier) {
-				ByteArray txtRecord = info.toTXTRecord();
+			BonjourRegisterQuery(const String& name, int port, const ByteArray& txtRecord, boost::shared_ptr<BonjourQuerier> querier) : BonjourQuery(querier) {
 				DNSServiceErrorType result = DNSServiceRegister(
 						&sdRef, 0, 0, name.getUTF8Data(), "_presence._tcp", NULL, NULL, port, 
 						txtRecord.getSize(), txtRecord.getData(), 
@@ -35,9 +33,8 @@ namespace Swift {
 				stop();
 			}
 
-			void updateServiceInfo(const LinkLocalServiceInfo& info) {
+			void updateServiceInfo(const ByteArray& txtRecord) {
 				boost::lock_guard<boost::mutex> lock(sdRefMutex);
-				ByteArray txtRecord = info.toTXTRecord();
 				DNSServiceUpdateRecord(sdRef, NULL, NULL, txtRecord.getSize(), txtRecord.getData(), 0);
 			}
 
diff --git a/Swiften/LinkLocal/DNSSD/DNSSDQuerier.h b/Swiften/LinkLocal/DNSSD/DNSSDQuerier.h
index 6c7b576..799bc0c 100644
--- a/Swiften/LinkLocal/DNSSD/DNSSDQuerier.h
+++ b/Swiften/LinkLocal/DNSSD/DNSSDQuerier.h
@@ -4,7 +4,7 @@
 
 namespace Swift {
 	class String;
-	class LinkLocalServiceInfo;
+	class ByteArray;
 	class DNSSDServiceID;
 	class DNSSDBrowseQuery;
 	class DNSSDRegisterQuery;
@@ -17,7 +17,7 @@ namespace Swift {
 
 			virtual boost::shared_ptr<DNSSDBrowseQuery> createBrowseQuery() = 0;
 			virtual boost::shared_ptr<DNSSDRegisterQuery> createRegisterQuery(
-					const String& name, int port, const LinkLocalServiceInfo& info) = 0;
+					const String& name, int port, const ByteArray& info) = 0;
 			virtual boost::shared_ptr<DNSSDResolveServiceQuery> createResolveServiceQuery(
 					const DNSSDServiceID&) = 0;
 			virtual boost::shared_ptr<DNSSDResolveHostnameQuery> createResolveHostnameQuery(
diff --git a/Swiften/LinkLocal/DNSSD/DNSSDRegisterQuery.h b/Swiften/LinkLocal/DNSSD/DNSSDRegisterQuery.h
index 627cc6b..4a04fa9 100644
--- a/Swiften/LinkLocal/DNSSD/DNSSDRegisterQuery.h
+++ b/Swiften/LinkLocal/DNSSD/DNSSDRegisterQuery.h
@@ -6,7 +6,7 @@
 #include "Swiften/LinkLocal/DNSSD/DNSSDServiceID.h"
 
 namespace Swift {
-	class LinkLocalServiceInfo;
+	class ByteArray;
 
 	class DNSSDRegisterQuery {
 		public:
@@ -14,7 +14,7 @@ namespace Swift {
 
 			virtual void registerService() = 0;
 			virtual void unregisterService() = 0;
-			virtual void updateServiceInfo(const LinkLocalServiceInfo& info) = 0;
+			virtual void updateServiceInfo(const ByteArray& info) = 0;
 
 			boost::signal<void (boost::optional<DNSSDServiceID>)> onRegisterFinished;
 	};
diff --git a/Swiften/LinkLocal/DNSSD/DNSSDResolveServiceQuery.h b/Swiften/LinkLocal/DNSSD/DNSSDResolveServiceQuery.h
index f79b537..217e396 100644
--- a/Swiften/LinkLocal/DNSSD/DNSSDResolveServiceQuery.h
+++ b/Swiften/LinkLocal/DNSSD/DNSSDResolveServiceQuery.h
@@ -4,19 +4,18 @@
 #include <boost/optional.hpp>
 
 #include "Swiften/LinkLocal/DNSSD/DNSSDServiceID.h"
-#include "Swiften/LinkLocal/LinkLocalServiceInfo.h"
+#include "Swiften/Base/ByteArray.h"
 
 namespace Swift {
 	class DNSSDResolveServiceQuery {
 		public:
 			struct Result {
-				Result(const String& fullName, const String& host, int port, 
-						const LinkLocalServiceInfo& info) : 
+				Result(const String& fullName, const String& host, int port, const ByteArray& info) : 
 							fullName(fullName), host(host), port(port), info(info) {}
 				String fullName;
 				String host;
 				int port;
-				LinkLocalServiceInfo info;
+				ByteArray info;
 			};
 
 			virtual ~DNSSDResolveServiceQuery();
diff --git a/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.cpp b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.cpp
index 222500a..88c7774 100644
--- a/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.cpp
+++ b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.cpp
@@ -17,7 +17,7 @@ boost::shared_ptr<DNSSDBrowseQuery> FakeDNSSDQuerier::createBrowseQuery() {
 	return boost::shared_ptr<DNSSDBrowseQuery>(new FakeDNSSDBrowseQuery(shared_from_this()));
 }
 
-boost::shared_ptr<DNSSDRegisterQuery> FakeDNSSDQuerier::createRegisterQuery(const String& name, int port, const LinkLocalServiceInfo& info) {
+boost::shared_ptr<DNSSDRegisterQuery> FakeDNSSDQuerier::createRegisterQuery(const String& name, int port, const ByteArray& info) {
 	return boost::shared_ptr<DNSSDRegisterQuery>(new FakeDNSSDRegisterQuery(name, port, info, shared_from_this()));
 }
 
diff --git a/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.h b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.h
index 6c5f343..43b717e 100644
--- a/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.h
+++ b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.h
@@ -11,7 +11,7 @@
 #include "Swiften/LinkLocal/DNSSD/DNSSDResolveServiceQuery.h"
 
 namespace Swift {
-	class LinkLocalServiceInfo;
+	class ByteArray;
 	class FakeDNSSDQuery;
 	class FakeDNSSDBrowseQuery;
 
@@ -24,7 +24,7 @@ namespace Swift {
 
 			boost::shared_ptr<DNSSDBrowseQuery> createBrowseQuery();
 			boost::shared_ptr<DNSSDRegisterQuery> createRegisterQuery(
-					const String& name, int port, const LinkLocalServiceInfo& info);
+					const String& name, int port, const ByteArray& info);
 			boost::shared_ptr<DNSSDResolveServiceQuery> createResolveServiceQuery(
 					const DNSSDServiceID&);
 			boost::shared_ptr<DNSSDResolveHostnameQuery> createResolveHostnameQuery(
diff --git a/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDRegisterQuery.h b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDRegisterQuery.h
index b4646fd..82ec623 100644
--- a/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDRegisterQuery.h
+++ b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDRegisterQuery.h
@@ -2,7 +2,7 @@
 
 #include "Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuery.h"
 #include "Swiften/LinkLocal/DNSSD/DNSSDRegisterQuery.h"
-#include "Swiften/LinkLocal/LinkLocalServiceInfo.h"
+#include "Swiften/Base/ByteArray.h"
 #include "Swiften/Base/String.h"
 
 namespace Swift {
@@ -10,14 +10,15 @@ namespace Swift {
 
 	class FakeDNSSDRegisterQuery : public DNSSDRegisterQuery, public FakeDNSSDQuery {
 		public:	
-			FakeDNSSDRegisterQuery(const String& name, int port, const LinkLocalServiceInfo& info, boost::shared_ptr<FakeDNSSDQuerier> querier) : FakeDNSSDQuery(querier), name(name), port(port), info(info) {
+			FakeDNSSDRegisterQuery(const String& name, int port, const ByteArray& info, boost::shared_ptr<FakeDNSSDQuerier> querier) : FakeDNSSDQuery(querier), name(name), port(port), info(info) {
 			}
 
 			void registerService() {
 				run();
 			}
 
-			void updateServiceInfo(const LinkLocalServiceInfo&) {
+			void updateServiceInfo(const ByteArray& i) {
+				info = i;
 			}
 
 			void unregisterService() {
@@ -26,6 +27,6 @@ namespace Swift {
 
 			String name;
 			int port;
-			LinkLocalServiceInfo info;
+			ByteArray info;
 	};
 }
diff --git a/Swiften/LinkLocal/LinkLocalService.h b/Swiften/LinkLocal/LinkLocalService.h
index 0c675a3..37f2130 100644
--- a/Swiften/LinkLocal/LinkLocalService.h
+++ b/Swiften/LinkLocal/LinkLocalService.h
@@ -30,8 +30,8 @@ namespace Swift {
 				return info.host;
 			}
 
-			const LinkLocalServiceInfo& getInfo() const {
-				return info.info;
+			LinkLocalServiceInfo getInfo() const {
+				return LinkLocalServiceInfo::createFromTXTRecord(info.info);
 			}
 
 		private:
diff --git a/Swiften/LinkLocal/LinkLocalServiceBrowser.cpp b/Swiften/LinkLocal/LinkLocalServiceBrowser.cpp
index aed917a..265acc1 100644
--- a/Swiften/LinkLocal/LinkLocalServiceBrowser.cpp
+++ b/Swiften/LinkLocal/LinkLocalServiceBrowser.cpp
@@ -57,7 +57,7 @@ bool LinkLocalServiceBrowser::isRegistered() const {
 
 void LinkLocalServiceBrowser::registerService(const String& name, int port, const LinkLocalServiceInfo& info) {
 	assert(!registerQuery);
-	registerQuery = querier->createRegisterQuery(name, port, info);
+	registerQuery = querier->createRegisterQuery(name, port, info.toTXTRecord());
 	registerQuery->onRegisterFinished.connect(
 		boost::bind(&LinkLocalServiceBrowser::handleRegisterFinished, this, _1));
 	registerQuery->registerService();
diff --git a/Swiften/LinkLocal/UnitTest/LinkLocalServiceBrowserTest.cpp b/Swiften/LinkLocal/UnitTest/LinkLocalServiceBrowserTest.cpp
index 7e2dd26..ab42834 100644
--- a/Swiften/LinkLocal/UnitTest/LinkLocalServiceBrowserTest.cpp
+++ b/Swiften/LinkLocal/UnitTest/LinkLocalServiceBrowserTest.cpp
@@ -34,8 +34,8 @@ class LinkLocalServiceBrowserTest : public CppUnit::TestFixture {
 			eventLoop = new DummyEventLoop();
 			querier = boost::shared_ptr<FakeDNSSDQuerier>(new FakeDNSSDQuerier());
 			testServiceID = new DNSSDServiceID("foo", "bar.local");
-			testServiceInfo = new DNSSDResolveServiceQuery::Result("_presence._tcp.bar.local", "xmpp.bar.local", 1234, LinkLocalServiceInfo());
-			testServiceInfo2 = new DNSSDResolveServiceQuery::Result("_presence.tcp.bar.local", "xmpp.foo.local", 2345, LinkLocalServiceInfo());
+			testServiceInfo = new DNSSDResolveServiceQuery::Result("_presence._tcp.bar.local", "xmpp.bar.local", 1234, LinkLocalServiceInfo().toTXTRecord());
+			testServiceInfo2 = new DNSSDResolveServiceQuery::Result("_presence.tcp.bar.local", "xmpp.foo.local", 2345, LinkLocalServiceInfo().toTXTRecord());
 		}
 
 		void tearDown() {
-- 
cgit v0.10.2-6-g49f6


From 81ea0a6b0ea85c55c2f166b69da652aaab2ef79a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Sun, 26 Jul 2009 17:23:28 +0200
Subject: Test LinkLocal service registration.


diff --git a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourBrowseQuery.h b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourBrowseQuery.h
index 8e3181e..be0c921 100644
--- a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourBrowseQuery.h
+++ b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourBrowseQuery.h
@@ -41,7 +41,7 @@ namespace Swift {
 					MainEventLoop::postEvent(boost::bind(boost::ref(onError)), shared_from_this());
 				}
 				else {
-					DNSSDServiceID service(name, type, domain, interfaceIndex);
+					DNSSDServiceID service(name, domain, type, interfaceIndex);
 					if (flags & kDNSServiceFlagsAdd) {
 						MainEventLoop::postEvent(boost::bind(boost::ref(onServiceAdded), service), shared_from_this());
 					}
diff --git a/Swiften/LinkLocal/DNSSD/DNSSDServiceID.h b/Swiften/LinkLocal/DNSSD/DNSSDServiceID.h
index b1986d3..5243662 100644
--- a/Swiften/LinkLocal/DNSSD/DNSSDServiceID.h
+++ b/Swiften/LinkLocal/DNSSD/DNSSDServiceID.h
@@ -9,31 +9,31 @@ namespace Swift {
 
 			DNSSDServiceID(
 				const String& name, 
-				const String& type, 
-				const String& domain = PresenceServiceType, 
+				const String& domain, 
+				const String& type = PresenceServiceType, 
 				int networkInterface = 0) : 
 					name(name), 
-					type(type), 
 					domain(domain), 
+					type(type), 
 					networkInterface(networkInterface) {
 			}
 
 			bool operator==(const DNSSDServiceID& o) const {
-				return name == o.name && type == o.type && domain == o.domain && (networkInterface != 0 && o.networkInterface != 0 ? networkInterface == o.networkInterface : true);
+				return name == o.name && domain == o.domain && type == o.type && (networkInterface != 0 && o.networkInterface != 0 ? networkInterface == o.networkInterface : true);
 			}
 
 			bool operator<(const DNSSDServiceID& o) const {
 				if (o.name == name) {
-					if (o.type == type) {
-						if (o.domain == domain) {
+					if (o.domain == domain) {
+						if (o.type == type) {
 							return networkInterface < o.networkInterface;
 						}
 						else {
-							return domain < o.domain;
+							return type < o.type;
 						}
 					}
 					else {
-						return type < o.type;
+						return domain < o.domain;
 					}
 				}
 				else {
@@ -45,22 +45,22 @@ namespace Swift {
 				return name;
 			}
 
-			const String& getType() const {
-				return type;
-			}
-
 			const String& getDomain() const {
 				return domain;
 			}
 
+			const String& getType() const {
+				return type;
+			}
+
 			int getNetworkInterfaceID() const {
 				return networkInterface;
 			}
 
 		private:
 			String name;
-			String type;
 			String domain;
+			String type;
 			int networkInterface;
 	};
 }
diff --git a/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.cpp b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.cpp
index 88c7774..5079192 100644
--- a/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.cpp
+++ b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.cpp
@@ -10,7 +10,7 @@
 
 namespace Swift {
 
-FakeDNSSDQuerier::FakeDNSSDQuerier() {
+FakeDNSSDQuerier::FakeDNSSDQuerier(const String& domain) : domain(domain) {
 }
 
 boost::shared_ptr<DNSSDBrowseQuery> FakeDNSSDQuerier::createBrowseQuery() {
@@ -43,6 +43,10 @@ void FakeDNSSDQuerier::addRunningQuery(boost::shared_ptr<FakeDNSSDQuery> query)
 			}
 		}
 	}
+	else if (boost::shared_ptr<FakeDNSSDRegisterQuery> registerQuery = boost::dynamic_pointer_cast<FakeDNSSDRegisterQuery>(query)) {
+		DNSSDServiceID service(registerQuery->name, domain);
+		MainEventLoop::postEvent(boost::bind(boost::ref(registerQuery->onRegisterFinished), service), shared_from_this());
+	}
 }
 
 void FakeDNSSDQuerier::removeRunningQuery(boost::shared_ptr<FakeDNSSDQuery> query) {
@@ -77,6 +81,15 @@ void FakeDNSSDQuerier::setServiceInfo(const DNSSDServiceID& id, const DNSSDResol
 	}
 }
 
+bool FakeDNSSDQuerier::isServiceRegistered(const String& name, int port, const ByteArray& info) {
+	foreach(const boost::shared_ptr<FakeDNSSDRegisterQuery>& query, getQueries<FakeDNSSDRegisterQuery>()) {
+		if (query->name == name && query->port == port && query->info == info) {
+			return true;
+		}
+	}
+	return false;
+}
+
 void FakeDNSSDQuerier::setBrowseError() {
 	foreach(const boost::shared_ptr<FakeDNSSDBrowseQuery>& query, getQueries<FakeDNSSDBrowseQuery>()) {
 		MainEventLoop::postEvent(boost::ref(query->onError), shared_from_this());
diff --git a/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.h b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.h
index 43b717e..f2ec17b 100644
--- a/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.h
+++ b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.h
@@ -20,7 +20,7 @@ namespace Swift {
 			public EventOwner,
 			public boost::enable_shared_from_this<FakeDNSSDQuerier> {
 		public:
-			FakeDNSSDQuerier();
+			FakeDNSSDQuerier(const String& domain);
 
 			boost::shared_ptr<DNSSDBrowseQuery> createBrowseQuery();
 			boost::shared_ptr<DNSSDRegisterQuery> createRegisterQuery(
@@ -36,6 +36,7 @@ namespace Swift {
 			void addService(const DNSSDServiceID& id);
 			void removeService(const DNSSDServiceID& id);
 			void setServiceInfo(const DNSSDServiceID& id, const DNSSDResolveServiceQuery::Result& info);
+			bool isServiceRegistered(const String& name, int port, const ByteArray& info);
 
 			void setBrowseError();
 			void setRegisterError();
@@ -53,6 +54,7 @@ namespace Swift {
 			}
 
 		private:
+			String domain;
 			std::list< boost::shared_ptr<FakeDNSSDQuery> > runningQueries;
 			std::set<DNSSDServiceID> services;
 			typedef std::map<DNSSDServiceID,DNSSDResolveServiceQuery::Result> ServiceInfoMap;
diff --git a/Swiften/LinkLocal/LinkLocalServiceBrowser.cpp b/Swiften/LinkLocal/LinkLocalServiceBrowser.cpp
index 265acc1..f7c5478 100644
--- a/Swiften/LinkLocal/LinkLocalServiceBrowser.cpp
+++ b/Swiften/LinkLocal/LinkLocalServiceBrowser.cpp
@@ -11,7 +11,9 @@ LinkLocalServiceBrowser::LinkLocalServiceBrowser(boost::shared_ptr<DNSSDQuerier>
 }
 
 LinkLocalServiceBrowser::~LinkLocalServiceBrowser() {
-	assert(!isRunning());
+	if (isRunning()) {
+		std::cerr << "WARNING: LinkLocalServiceBrowser still running on destruction" << std::endl;
+	}
 }
 
 
@@ -67,6 +69,7 @@ void LinkLocalServiceBrowser::unregisterService() {
 	assert(registerQuery);
 	registerQuery->unregisterService();
 	registerQuery.reset();
+	selfService.reset();
 }
 
 std::vector<LinkLocalService> LinkLocalServiceBrowser::getServices() const {
@@ -78,6 +81,9 @@ std::vector<LinkLocalService> LinkLocalServiceBrowser::getServices() const {
 }
 
 void LinkLocalServiceBrowser::handleServiceAdded(const DNSSDServiceID& service) {
+	if (selfService && service == *selfService) {
+		return;
+	}
 	boost::shared_ptr<DNSSDResolveServiceQuery> resolveQuery = querier->createResolveServiceQuery(service);
 	resolveQuery->onServiceResolved.connect(
 		boost::bind(&LinkLocalServiceBrowser::handleServiceResolved, this, service, _1));
@@ -89,6 +95,9 @@ void LinkLocalServiceBrowser::handleServiceAdded(const DNSSDServiceID& service)
 }
 
 void LinkLocalServiceBrowser::handleServiceRemoved(const DNSSDServiceID& service) {
+	if (selfService && service == *selfService) {
+		return;
+	}
 	ResolveQueryMap::iterator i = resolveQueries.find(service);
 	assert(i != resolveQueries.end());
 	i->second->stop();
@@ -111,7 +120,10 @@ void LinkLocalServiceBrowser::handleServiceResolved(const DNSSDServiceID& servic
 }
 
 void LinkLocalServiceBrowser::handleRegisterFinished(const boost::optional<DNSSDServiceID>& result) {
-	if (!result) {
+	if (result) {
+		selfService = result;
+	}
+	else {
 		haveError = true;
 		stop();
 	}
diff --git a/Swiften/LinkLocal/LinkLocalServiceBrowser.h b/Swiften/LinkLocal/LinkLocalServiceBrowser.h
index 33c9858..dcdd576 100644
--- a/Swiften/LinkLocal/LinkLocalServiceBrowser.h
+++ b/Swiften/LinkLocal/LinkLocalServiceBrowser.h
@@ -45,6 +45,7 @@ namespace Swift {
 
 		private:
 			boost::shared_ptr<DNSSDQuerier> querier;
+			boost::optional<DNSSDServiceID> selfService;
 			boost::shared_ptr<DNSSDBrowseQuery> browseQuery;
 			boost::shared_ptr<DNSSDRegisterQuery> registerQuery;
 			typedef std::map<DNSSDServiceID, boost::shared_ptr<DNSSDResolveServiceQuery> > ResolveQueryMap;
diff --git a/Swiften/LinkLocal/UnitTest/LinkLocalServiceBrowserTest.cpp b/Swiften/LinkLocal/UnitTest/LinkLocalServiceBrowserTest.cpp
index ab42834..4b66398 100644
--- a/Swiften/LinkLocal/UnitTest/LinkLocalServiceBrowserTest.cpp
+++ b/Swiften/LinkLocal/UnitTest/LinkLocalServiceBrowserTest.cpp
@@ -18,6 +18,8 @@ class LinkLocalServiceBrowserTest : public CppUnit::TestFixture {
 		CPPUNIT_TEST(testStart);
 		CPPUNIT_TEST(testServiceAdded);
 		CPPUNIT_TEST(testServiceAdded_NoServiceInfo);
+		CPPUNIT_TEST(testServiceAdded_RegisteredService);
+		CPPUNIT_TEST(testServiceAdded_UnregisteredService);
 		CPPUNIT_TEST(testServiceChanged);
 		CPPUNIT_TEST(testServiceRemoved);
 		CPPUNIT_TEST(testError_BrowseErrorAfterStart);
@@ -32,10 +34,14 @@ class LinkLocalServiceBrowserTest : public CppUnit::TestFixture {
 
 		void setUp() {
 			eventLoop = new DummyEventLoop();
-			querier = boost::shared_ptr<FakeDNSSDQuerier>(new FakeDNSSDQuerier());
+			querier = boost::shared_ptr<FakeDNSSDQuerier>(new FakeDNSSDQuerier("wonderland.lit"));
+			aliceServiceID = new DNSSDServiceID("alice", "wonderland.lit");
+			aliceServiceInfo = new DNSSDResolveServiceQuery::Result("_presence._tcp.wonderland.lit", "xmpp.wonderland.lit", 1234, LinkLocalServiceInfo().toTXTRecord());
 			testServiceID = new DNSSDServiceID("foo", "bar.local");
 			testServiceInfo = new DNSSDResolveServiceQuery::Result("_presence._tcp.bar.local", "xmpp.bar.local", 1234, LinkLocalServiceInfo().toTXTRecord());
 			testServiceInfo2 = new DNSSDResolveServiceQuery::Result("_presence.tcp.bar.local", "xmpp.foo.local", 2345, LinkLocalServiceInfo().toTXTRecord());
+			errorStopReceived = false;
+			normalStopReceived = false;
 		}
 
 		void tearDown() {
@@ -97,8 +103,50 @@ class LinkLocalServiceBrowserTest : public CppUnit::TestFixture {
 			eventLoop->processEvents();
 
 			CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(addedServices.size()));
+			CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(testling->getServices().size()));
+
+			testling->stop();
+		}
+
+		void testServiceAdded_RegisteredService() {
+			boost::shared_ptr<LinkLocalServiceBrowser> testling = createTestling();
+			testling->start();
+			eventLoop->processEvents();
+
+			testling->registerService("alice", 1234, LinkLocalServiceInfo());
+			eventLoop->processEvents();
+			querier->setServiceInfo(*aliceServiceID, *aliceServiceInfo);
+			querier->addService(*aliceServiceID);
+			eventLoop->processEvents();
+
+			CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(addedServices.size()));
+			CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(testling->getServices().size()));
+
+			testling->stop();
+		}
+
+		void testServiceAdded_UnregisteredService() {
+			boost::shared_ptr<LinkLocalServiceBrowser> testling = createTestling();
+			testling->start();
+			eventLoop->processEvents();
+			testling->registerService("alice", 1234, LinkLocalServiceInfo());
+			eventLoop->processEvents();
+			testling->unregisterService();
+			eventLoop->processEvents();
+
+			querier->setServiceInfo(*aliceServiceID, *aliceServiceInfo);
+			querier->addService(*aliceServiceID);
+			eventLoop->processEvents();
+
+			CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(addedServices.size()));
+			CPPUNIT_ASSERT(addedServices[0] == *aliceServiceID);
+			CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(changedServices.size()));
+			CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(removedServices.size()));
 			std::vector<LinkLocalService> services = testling->getServices();
-			CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(services.size()));
+			CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(services.size()));
+			CPPUNIT_ASSERT(*aliceServiceID == services[0].getID());
+			CPPUNIT_ASSERT(aliceServiceInfo->port == services[0].getPort());
+			CPPUNIT_ASSERT(aliceServiceInfo->host == services[0].getHostname());
 
 			testling->stop();
 		}
@@ -156,6 +204,7 @@ class LinkLocalServiceBrowserTest : public CppUnit::TestFixture {
 
 			CPPUNIT_ASSERT(!testling->isRunning());
 			CPPUNIT_ASSERT(testling->hasError());
+			CPPUNIT_ASSERT(errorStopReceived);
 		}
 
 		void testError_BrowseErrorAfterResolve() {
@@ -174,6 +223,7 @@ class LinkLocalServiceBrowserTest : public CppUnit::TestFixture {
 			CPPUNIT_ASSERT(testling->hasError());
 			CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(testling->getServices().size()));
 			CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(changedServices.size()));
+			CPPUNIT_ASSERT(errorStopReceived);
 		}
 
 		void testRegisterService() {
@@ -181,13 +231,21 @@ class LinkLocalServiceBrowserTest : public CppUnit::TestFixture {
 			testling->start();
 			eventLoop->processEvents();
 
+			LinkLocalServiceInfo info;
+			info.setFirstName("Foo");
+			testling->registerService("foo@bar", 1234, info);
+			eventLoop->processEvents();
+
+			CPPUNIT_ASSERT(querier->isServiceRegistered("foo@bar", 1234, info.toTXTRecord()));
+
 			testling->stop();
 		}
 
 		void testRegisterService_Error() {
 			boost::shared_ptr<LinkLocalServiceBrowser> testling = createTestling();
 			testling->start();
-			testling->registerService("", 1234);
+			LinkLocalServiceInfo info;
+			testling->registerService("foo@bar", 1234, info);
 			eventLoop->processEvents();
 
 			querier->setRegisterError();
@@ -195,12 +253,26 @@ class LinkLocalServiceBrowserTest : public CppUnit::TestFixture {
 
 			CPPUNIT_ASSERT(!testling->isRunning());
 			CPPUNIT_ASSERT(testling->hasError());
+			CPPUNIT_ASSERT(errorStopReceived);
+			CPPUNIT_ASSERT(!querier->isServiceRegistered("foo@bar", 1234, info.toTXTRecord()));
 		}
 
 		void testRegisterService_Reregister() {
 			boost::shared_ptr<LinkLocalServiceBrowser> testling = createTestling();
 			testling->start();
 			eventLoop->processEvents();
+			LinkLocalServiceInfo info;
+			info.setFirstName("Foo");
+			testling->registerService("foo@bar", 1234, info);
+			eventLoop->processEvents();
+			testling->unregisterService();
+			eventLoop->processEvents();
+
+			info.setFirstName("Bar");
+			testling->registerService("bar@baz", 3456, info);
+			eventLoop->processEvents();
+
+			CPPUNIT_ASSERT(querier->isServiceRegistered("bar@baz", 3456, info.toTXTRecord()));
 
 			testling->stop();
 		}
@@ -215,6 +287,8 @@ class LinkLocalServiceBrowserTest : public CppUnit::TestFixture {
 					&LinkLocalServiceBrowserTest::handleServiceChanged, this, _1));
 			testling->onServiceRemoved.connect(boost::bind(
 					&LinkLocalServiceBrowserTest::handleServiceRemoved, this, _1));
+			testling->onStopped.connect(boost::bind(
+					&LinkLocalServiceBrowserTest::handleStopped, this, _1));
 			return testling;
 		}
 
@@ -230,15 +304,30 @@ class LinkLocalServiceBrowserTest : public CppUnit::TestFixture {
 			changedServices.push_back(service);
 		}
 
+		void handleStopped(bool error) {
+			CPPUNIT_ASSERT(!errorStopReceived);
+			CPPUNIT_ASSERT(!normalStopReceived);
+			if (error) {
+				errorStopReceived = true;
+			}
+			else {
+				normalStopReceived = true;
+			}
+		}
+
 	private:
 		DummyEventLoop* eventLoop;
 		boost::shared_ptr<FakeDNSSDQuerier> querier;
 		std::vector<DNSSDServiceID> addedServices;
 		std::vector<DNSSDServiceID> changedServices;
 		std::vector<DNSSDServiceID> removedServices;
+		DNSSDServiceID* aliceServiceID;
+		DNSSDResolveServiceQuery::Result* aliceServiceInfo;
 		DNSSDServiceID* testServiceID;
 		DNSSDResolveServiceQuery::Result* testServiceInfo;
 		DNSSDResolveServiceQuery::Result* testServiceInfo2;
+		bool errorStopReceived;
+		bool normalStopReceived;
 };
 
 CPPUNIT_TEST_SUITE_REGISTRATION(LinkLocalServiceBrowserTest);
-- 
cgit v0.10.2-6-g49f6


From 4e2cb67ac26ca338a4bd7676683186f543903c5a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Sun, 26 Jul 2009 22:52:45 +0200
Subject: Fix bonjour compilation.


diff --git a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourRegisterQuery.h b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourRegisterQuery.h
index c85b90f..34d5742 100644
--- a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourRegisterQuery.h
+++ b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourRegisterQuery.h
@@ -30,7 +30,7 @@ namespace Swift {
 			}
 
 			void unregisterService() {
-				stop();
+				finish();
 			}
 
 			void updateServiceInfo(const ByteArray& txtRecord) {
diff --git a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourResolveServiceQuery.h b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourResolveServiceQuery.h
index 8b3f7ec..d16ca5b 100644
--- a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourResolveServiceQuery.h
+++ b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourResolveServiceQuery.h
@@ -49,8 +49,7 @@ namespace Swift {
 							boost::bind(
 								boost::ref(onServiceResolved), 
 								Result(String(fullName), String(host), port, 
-									LinkLocalServiceInfo::createFromTXTRecord(
-										ByteArray(reinterpret_cast<const char*>(txtRecord), txtLen)))), 
+									ByteArray(reinterpret_cast<const char*>(txtRecord), txtLen))), 
 							shared_from_this());
 				}
 			}
-- 
cgit v0.10.2-6-g49f6


From 644bcda4cb795944cc5d5df53b3c0392450239df Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Mon, 27 Jul 2009 20:32:51 +0200
Subject: Improve LinkLocalServiceInfo unit test.


diff --git a/Slimber/Server.cpp b/Slimber/Server.cpp
index c3c3d22..39f4233 100644
--- a/Slimber/Server.cpp
+++ b/Slimber/Server.cpp
@@ -69,7 +69,7 @@ void Server::handleNewLinkLocalConnection(boost::shared_ptr<Connection> connecti
 	registerLinkLocalSession(session);
 }
 
-void Server::handleServiceRegistered(const LinkLocalServiceID& service) {
+void Server::handleServiceRegistered(const DNSSDServiceID& service) {
 	std::cout << "Service registered " << service.getName() << " " << service.getType() << " " << service.getDomain() << std::endl;
 	selfJID_ = JID(service.getName());
 }
diff --git a/Slimber/Server.h b/Slimber/Server.h
index b40f576..9167106 100644
--- a/Slimber/Server.h
+++ b/Slimber/Server.h
@@ -33,7 +33,7 @@ namespace Swift {
 		private:
 			void handleNewClientConnection(boost::shared_ptr<Connection> c);
 			void handleNewLinkLocalConnection(boost::shared_ptr<Connection> connection);
-			void handleServiceRegistered(const LinkLocalServiceID& service);
+			void handleServiceRegistered(const DNSSDServiceID& service);
 			void handleSessionStarted();
 			void handleSessionFinished(boost::shared_ptr<ServerFromClientSession>);
 			void handleLinkLocalSessionFinished(boost::shared_ptr<Session> session);
diff --git a/Swiften/LinkLocal/DNSSD/DNSSDServiceID.cpp b/Swiften/LinkLocal/DNSSD/DNSSDServiceID.cpp
index 06a5b81..b360ee5 100644
--- a/Swiften/LinkLocal/DNSSD/DNSSDServiceID.cpp
+++ b/Swiften/LinkLocal/DNSSD/DNSSDServiceID.cpp
@@ -2,6 +2,6 @@
 
 namespace Swift {
 
-const String DNSSDServiceID::PresenceServiceType = String("_presence._tcp");
+const char* DNSSDServiceID::PresenceServiceType = "_presence._tcp";
 
 }
diff --git a/Swiften/LinkLocal/DNSSD/DNSSDServiceID.h b/Swiften/LinkLocal/DNSSD/DNSSDServiceID.h
index 5243662..ba7828b 100644
--- a/Swiften/LinkLocal/DNSSD/DNSSDServiceID.h
+++ b/Swiften/LinkLocal/DNSSD/DNSSDServiceID.h
@@ -5,7 +5,7 @@
 namespace Swift {
 	class DNSSDServiceID {
 		public:
-			static const String PresenceServiceType;
+			static const char* PresenceServiceType;
 
 			DNSSDServiceID(
 				const String& name, 
diff --git a/Swiften/LinkLocal/UnitTest/LinkLocalServiceBrowserTest.cpp b/Swiften/LinkLocal/UnitTest/LinkLocalServiceBrowserTest.cpp
index 4b66398..e9501cb 100644
--- a/Swiften/LinkLocal/UnitTest/LinkLocalServiceBrowserTest.cpp
+++ b/Swiften/LinkLocal/UnitTest/LinkLocalServiceBrowserTest.cpp
@@ -49,6 +49,8 @@ class LinkLocalServiceBrowserTest : public CppUnit::TestFixture {
 			removedServices.clear();
 			changedServices.clear();
 
+			delete aliceServiceID;
+			delete aliceServiceInfo;
 			delete testServiceInfo2;
 			delete testServiceInfo;
 			delete testServiceID;
diff --git a/Swiften/LinkLocal/UnitTest/LinkLocalServiceInfoTest.cpp b/Swiften/LinkLocal/UnitTest/LinkLocalServiceInfoTest.cpp
index b850f14..68f191a 100644
--- a/Swiften/LinkLocal/UnitTest/LinkLocalServiceInfoTest.cpp
+++ b/Swiften/LinkLocal/UnitTest/LinkLocalServiceInfoTest.cpp
@@ -10,6 +10,7 @@ class LinkLocalServiceInfoTest : public CppUnit::TestFixture {
 		CPPUNIT_TEST(testGetTXTRecord);
 		CPPUNIT_TEST(testCreateFromTXTRecord);
 		CPPUNIT_TEST(testCreateFromTXTRecord_InvalidSize);
+		CPPUNIT_TEST(testGetTXTRecordCreateFromTXTRecord_RoundTrip);
 		CPPUNIT_TEST_SUITE_END();
 
 	public:
@@ -37,6 +38,28 @@ class LinkLocalServiceInfoTest : public CppUnit::TestFixture {
 
 			CPPUNIT_ASSERT_EQUAL(String("a"), info.getLastName());
 		}
+
+		void testGetTXTRecordCreateFromTXTRecord_RoundTrip() {
+			LinkLocalServiceInfo info;
+			info.setFirstName("Remko");
+			info.setLastName("Tron\xc3\xe7on");
+			info.setEMail("remko-email@swift.im");
+			info.setJID(JID("remko-jid@swift.im"));
+			info.setMessage("I'm busy");
+			info.setNick("el-tramo");
+			info.setStatus(LinkLocalServiceInfo::DND);
+			info.setPort(1234);
+
+			LinkLocalServiceInfo info2 = LinkLocalServiceInfo::createFromTXTRecord(info.toTXTRecord());
+			CPPUNIT_ASSERT_EQUAL(info.getFirstName(), info2.getFirstName());
+			CPPUNIT_ASSERT_EQUAL(info.getLastName(), info2.getLastName());
+			CPPUNIT_ASSERT_EQUAL(info.getEMail(), info2.getEMail());
+			CPPUNIT_ASSERT_EQUAL(info.getJID(), info2.getJID());
+			CPPUNIT_ASSERT_EQUAL(info.getMessage(), info2.getMessage());
+			CPPUNIT_ASSERT_EQUAL(info.getNick(), info2.getNick());
+			CPPUNIT_ASSERT(info.getStatus() == info2.getStatus());
+			CPPUNIT_ASSERT(info.getPort() == info2.getPort());
+		}
 };
 
 CPPUNIT_TEST_SUITE_REGISTRATION(LinkLocalServiceInfoTest);
-- 
cgit v0.10.2-6-g49f6


From 4b809245dd6a1236dda99ab780485599434a419a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Mon, 27 Jul 2009 20:33:30 +0200
Subject: Add beginnings of AvahiQuerier.


diff --git a/Swiften/LinkLocal/DNSSD/Avahi/AvahiQuerier.cpp b/Swiften/LinkLocal/DNSSD/Avahi/AvahiQuerier.cpp
new file mode 100644
index 0000000..55ccede
--- /dev/null
+++ b/Swiften/LinkLocal/DNSSD/Avahi/AvahiQuerier.cpp
@@ -0,0 +1,59 @@
+#include "Swiften/LinkLocal/DNSSD/Avahi/AvahiQuerier.h"
+
+#include <iostream>
+
+//#include "Swiften/LinkLocal/DNSSD/Avahi/AvahiBrowseQuery.h"
+//#include "Swiften/LinkLocal/DNSSD/Avahi/AvahiRegisterQuery.h"
+//#include "Swiften/LinkLocal/DNSSD/Avahi/AvahiResolveServiceQuery.h"
+//#include "Swiften/LinkLocal/DNSSD/Avahi/AvahiResolveHostnameQuery.h"
+//#include "Swiften/Base/foreach.h"
+
+namespace Swift {
+
+AvahiQuerier::AvahiQuerier() : client(NULL), threadedPoll(NULL) {
+}
+
+AvahiQuerier::~AvahiQuerier() {
+}
+
+boost::shared_ptr<DNSSDBrowseQuery> AvahiQuerier::createBrowseQuery() {
+	//return boost::shared_ptr<DNSSDBrowseQuery>(new AvahiBrowseQuery(shared_from_this()));
+}
+
+boost::shared_ptr<DNSSDRegisterQuery> AvahiQuerier::createRegisterQuery(const String& name, int port, const ByteArray& info) {
+	//return boost::shared_ptr<DNSSDRegisterQuery>(new AvahiRegisterQuery(name, port, info, shared_from_this()));
+}
+
+boost::shared_ptr<DNSSDResolveServiceQuery> AvahiQuerier::createResolveServiceQuery(const DNSSDServiceID& service) {
+	//return boost::shared_ptr<DNSSDResolveServiceQuery>(new AvahiResolveServiceQuery(service, shared_from_this()));
+}
+
+boost::shared_ptr<DNSSDResolveHostnameQuery> AvahiQuerier::createResolveHostnameQuery(const String& hostname, int interfaceIndex) {
+	//return boost::shared_ptr<DNSSDResolveHostnameQuery>(new AvahiResolveHostnameQuery(hostname, interfaceIndex, shared_from_this()));
+}
+
+void AvahiQuerier::start() {
+	assert(!threadedPoll);
+	threadedPoll = avahi_threaded_poll_new();
+	int error;
+	assert(!client);
+	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;
+	}
+	avahi_threaded_poll_start(threadedPoll);
+}
+
+void AvahiQuerier::stop() {
+	assert(threadedPoll);
+	avahi_threaded_poll_stop(threadedPoll);
+	assert(client);
+	avahi_client_free(client);
+	avahi_threaded_poll_free(threadedPoll);
+}
+
+}
diff --git a/Swiften/LinkLocal/DNSSD/Avahi/AvahiQuerier.h b/Swiften/LinkLocal/DNSSD/Avahi/AvahiQuerier.h
new file mode 100644
index 0000000..ca45384
--- /dev/null
+++ b/Swiften/LinkLocal/DNSSD/Avahi/AvahiQuerier.h
@@ -0,0 +1,39 @@
+#pragma once
+
+#include <boost/shared_ptr.hpp>
+#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/LinkLocal/DNSSD/DNSSDQuerier.h"
+
+namespace Swift {
+	class ByteArray;
+
+	class AvahiQuerier : 
+			public DNSSDQuerier, 
+			public boost::enable_shared_from_this<AvahiQuerier> {
+		public:
+			AvahiQuerier();
+			~AvahiQuerier();
+
+			boost::shared_ptr<DNSSDBrowseQuery> createBrowseQuery();
+			boost::shared_ptr<DNSSDRegisterQuery> createRegisterQuery(
+					const String& name, int port, const ByteArray& info);
+			boost::shared_ptr<DNSSDResolveServiceQuery> createResolveServiceQuery(
+					const DNSSDServiceID&);
+			boost::shared_ptr<DNSSDResolveHostnameQuery> createResolveHostnameQuery(
+					const String& hostname, int interfaceIndex);
+
+			void start();
+			void stop();
+
+		private:
+			AvahiClient* client;
+			AvahiThreadedPoll* threadedPoll;
+	};
+}
diff --git a/Swiften/LinkLocal/DNSSD/Avahi/Makefile.inc b/Swiften/LinkLocal/DNSSD/Avahi/Makefile.inc
new file mode 100644
index 0000000..6150dc1
--- /dev/null
+++ b/Swiften/LinkLocal/DNSSD/Avahi/Makefile.inc
@@ -0,0 +1,2 @@
+SWIFTEN_SOURCES += \
+	Swiften/LinkLocal/DNSSD/Avahi/AvahiQuerier.cpp
diff --git a/Swiften/LinkLocal/DNSSD/Makefile.inc b/Swiften/LinkLocal/DNSSD/Makefile.inc
index 3d2c969..f6997ef 100644
--- a/Swiften/LinkLocal/DNSSD/Makefile.inc
+++ b/Swiften/LinkLocal/DNSSD/Makefile.inc
@@ -10,6 +10,7 @@ ifeq ($(HAVE_BONJOUR),yes)
 include Swiften/LinkLocal/DNSSD/Bonjour/Makefile.inc
 endif
 ifeq ($(HAVE_AVAHI),yes)
+include Swiften/LinkLocal/DNSSD/Avahi/Makefile.inc
 endif
 
 include Swiften/LinkLocal/DNSSD/Fake/Makefile.inc
-- 
cgit v0.10.2-6-g49f6


From b145bde2b103b0e688eef6300d34668431c5ad04 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Wed, 29 Jul 2009 22:18:02 +0200
Subject: Created LinkLocalPresenceManager.


diff --git a/Slimber/CLI/main.cpp b/Slimber/CLI/main.cpp
index 8b70625..7ebdb0f 100644
--- a/Slimber/CLI/main.cpp
+++ b/Slimber/CLI/main.cpp
@@ -10,6 +10,7 @@
 #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"
 #include "Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuerier.h"
@@ -22,10 +23,8 @@ int main() {
 	SimpleEventLoop eventLoop;
 	boost::shared_ptr<BonjourQuerier> querier(new BonjourQuerier());
 	querier->start();
-	boost::shared_ptr<DNSSDBrowseQuery> query = querier->createBrowseQuery();
-	query->startBrowsing();
-	boost::shared_ptr<DNSSDRegisterQuery> query2 = querier->createRegisterQuery("remko", 1234, LinkLocalServiceInfo());
-	query2->registerService();
+	LinkLocalServiceBrowser browser(querier);
+	browser.start();
 
 /*
 	boost::shared_ptr<DNSSDService> dnsSDService;
diff --git a/Slimber/LinkLocalPresenceManager.cpp b/Slimber/LinkLocalPresenceManager.cpp
new file mode 100644
index 0000000..b964786
--- /dev/null
+++ b/Slimber/LinkLocalPresenceManager.cpp
@@ -0,0 +1,98 @@
+#include "Slimber/LinkLocalPresenceManager.h"
+
+#include <boost/bind.hpp>
+
+#include "Swiften/Base/foreach.h"
+#include "Swiften/LinkLocal/LinkLocalServiceBrowser.h"
+#include "Swiften/Elements/RosterPayload.h"
+#include "Swiften/Elements/Presence.h"
+
+namespace Swift {
+
+LinkLocalPresenceManager::LinkLocalPresenceManager(LinkLocalServiceBrowser* browser) : browser(browser) {
+	browser->onServiceAdded.connect(
+			boost::bind(&LinkLocalPresenceManager::handleServiceAdded, this, _1));
+	browser->onServiceChanged.connect(
+			boost::bind(&LinkLocalPresenceManager::handleServiceChanged, this, _1));
+	browser->onServiceRemoved.connect(
+			boost::bind(&LinkLocalPresenceManager::handleServiceRemoved, this, _1));
+}
+
+void LinkLocalPresenceManager::handleServiceAdded(const LinkLocalService& service) {
+	boost::shared_ptr<RosterPayload> roster(new RosterPayload());
+	roster->addItem(getRosterItem(service));
+	onRosterChanged(roster);
+	onPresenceChanged(getPresence(service));
+}
+
+void LinkLocalPresenceManager::handleServiceChanged(const LinkLocalService& service) {
+	onPresenceChanged(getPresence(service));
+}
+
+void LinkLocalPresenceManager::handleServiceRemoved(const LinkLocalService& service) {
+	boost::shared_ptr<RosterPayload> roster(new RosterPayload());
+	roster->addItem(RosterItemPayload(getJIDForService(service), "", RosterItemPayload::Remove));
+	onRosterChanged(roster);
+}
+
+boost::shared_ptr<RosterPayload> LinkLocalPresenceManager::getRoster() const {
+	boost::shared_ptr<RosterPayload> roster(new RosterPayload());
+	foreach(const LinkLocalService& service, browser->getServices()) {
+		roster->addItem(getRosterItem(service));
+	}
+	return roster;
+}
+
+std::vector<boost::shared_ptr<Presence> > LinkLocalPresenceManager::getAllPresence() const {
+	std::vector<boost::shared_ptr<Presence> > result;
+	foreach(const LinkLocalService& service, browser->getServices()) {
+		result.push_back(getPresence(service));
+	}
+	return result;
+}
+
+RosterItemPayload LinkLocalPresenceManager::getRosterItem(const LinkLocalService& service) const {
+ return RosterItemPayload(getJIDForService(service), getRosterName(service), RosterItemPayload::Both);
+}
+
+String LinkLocalPresenceManager::getRosterName(const LinkLocalService& service) const {
+	LinkLocalServiceInfo info = service.getInfo();
+	if (!info.getNick().isEmpty()) {
+		return info.getNick();
+	}
+	else if (!info.getFirstName().isEmpty()) {
+		String result = info.getFirstName();
+		if (!info.getLastName().isEmpty()) {
+			result += " " + info.getLastName();
+		}
+		return result;
+	}
+	else if (!info.getLastName().isEmpty()) {
+		return info.getLastName();
+	}
+	return "";
+}
+
+JID LinkLocalPresenceManager::getJIDForService(const LinkLocalService& service) const {
+	return JID(service.getName());
+}
+
+boost::shared_ptr<Presence> LinkLocalPresenceManager::getPresence(const LinkLocalService& service) const {
+	boost::shared_ptr<Presence> presence(new Presence());
+	presence->setFrom(getJIDForService(service));
+	switch (service.getInfo().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(service.getInfo().getMessage());
+	return presence;
+}
+
+}
diff --git a/Slimber/LinkLocalPresenceManager.h b/Slimber/LinkLocalPresenceManager.h
new file mode 100644
index 0000000..2af2313
--- /dev/null
+++ b/Slimber/LinkLocalPresenceManager.h
@@ -0,0 +1,39 @@
+#pragma once
+
+#include <boost/shared_ptr.hpp>
+#include <boost/signal.hpp>
+
+#include "Swiften/Elements/RosterItemPayload.h"
+#include "Swiften/Base/String.h"
+#include "Swiften/JID/JID.h"
+
+namespace Swift {
+	class LinkLocalService;
+	class LinkLocalServiceBrowser;
+	class RosterPayload;
+	class Presence;
+
+	class LinkLocalPresenceManager {
+		public:
+			LinkLocalPresenceManager(LinkLocalServiceBrowser*);
+
+			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;
+
+		private:
+			void handleServiceAdded(const LinkLocalService&);
+			void handleServiceChanged(const LinkLocalService&);
+			void handleServiceRemoved(const LinkLocalService&);
+
+			RosterItemPayload getRosterItem(const LinkLocalService& service) const;
+			String getRosterName(const LinkLocalService& service) const;
+			JID getJIDForService(const LinkLocalService& service) const;
+			boost::shared_ptr<Presence> getPresence(const LinkLocalService& service) const;
+
+		private:
+			LinkLocalServiceBrowser* browser;
+	};
+}
diff --git a/Slimber/Makefile.inc b/Slimber/Makefile.inc
index fea164f..16fcb8f 100644
--- a/Slimber/Makefile.inc
+++ b/Slimber/Makefile.inc
@@ -1,14 +1,16 @@
 SLIMBER_TARGET = Slimber/Slimber.a
 SLIMBER_SOURCES = \
+	Slimber/LinkLocalPresenceManager.cpp \
 	Slimber/FileVCardCollection.cpp \
 	Slimber/VCardCollection.cpp \
 	Slimber/Server.cpp
 SLIMBER_OBJECTS = \
 	$(SLIMBER_SOURCES:.cpp=.o)
 
-DEPS += \
-	$(SLIMBER_SOURCES:.cpp=.dep) \
+DEPS += $(SLIMBER_SOURCES:.cpp=.dep)
+UNITTEST_LIBS += $(SLIMBER_TARGET)
 
+include Slimber/UnitTest/Makefile.inc
 include Slimber/CLI/Makefile.inc
 ifeq ($(MACOSX),1)
 include Slimber/Cocoa/Makefile.inc
diff --git a/Slimber/UnitTest/LinkLocalPresenceManagerTest.cpp b/Slimber/UnitTest/LinkLocalPresenceManagerTest.cpp
new file mode 100644
index 0000000..a1ecdf8
--- /dev/null
+++ b/Slimber/UnitTest/LinkLocalPresenceManagerTest.cpp
@@ -0,0 +1,224 @@
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+#include <boost/bind.hpp>
+#include <map>
+
+#include "Swiften/Elements/Presence.h"
+#include "Swiften/Elements/RosterPayload.h"
+#include "Swiften/Elements/RosterItemPayload.h"
+#include "Slimber/LinkLocalPresenceManager.h"
+#include "Swiften/LinkLocal/LinkLocalServiceInfo.h"
+#include "Swiften/LinkLocal/LinkLocalServiceBrowser.h"
+#include "Swiften/LinkLocal/DNSSD/DNSSDServiceID.h"
+#include "Swiften/LinkLocal/DNSSD/DNSSDResolveServiceQuery.h"
+#include "Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.h"
+#include "Swiften/EventLoop/DummyEventLoop.h"
+
+using namespace Swift;
+
+class LinkLocalPresenceManagerTest : public CppUnit::TestFixture {
+		CPPUNIT_TEST_SUITE(LinkLocalPresenceManagerTest);
+		CPPUNIT_TEST(testServiceAdded);
+		CPPUNIT_TEST(testServiceRemoved);
+		CPPUNIT_TEST(testServiceChanged);
+		CPPUNIT_TEST(testGetRoster);
+		CPPUNIT_TEST(testGetAllPresence);
+		CPPUNIT_TEST(testGetRoster_InfoWithNick);
+		CPPUNIT_TEST(testGetRoster_InfoWithFirstName);
+		CPPUNIT_TEST(testGetRoster_InfoWithLastName);
+		CPPUNIT_TEST(testGetRoster_InfoWithFirstAndLastName);
+		CPPUNIT_TEST(testGetRoster_NoInfo);
+		CPPUNIT_TEST_SUITE_END();
+
+	public:
+		LinkLocalPresenceManagerTest() {}
+
+		void setUp() {
+			eventLoop = new DummyEventLoop();
+			querier = boost::shared_ptr<FakeDNSSDQuerier>(new FakeDNSSDQuerier("wonderland.lit"));
+			browser = new LinkLocalServiceBrowser(querier);
+			browser->start();
+		}
+
+		void tearDown() {
+			browser->stop();
+			delete browser;
+			delete eventLoop;
+		}
+
+		void testServiceAdded() {
+			std::auto_ptr<LinkLocalPresenceManager> testling(createTestling());
+
+			addService("alice@wonderland", "Alice");
+
+			CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(rosterChanges.size()));
+			CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(rosterChanges[0]->getItems().size()));
+			boost::optional<RosterItemPayload> item = rosterChanges[0]->getItem(JID("alice@wonderland"));
+			CPPUNIT_ASSERT(item);
+			CPPUNIT_ASSERT_EQUAL(String("Alice"), item->getName());
+			CPPUNIT_ASSERT_EQUAL(RosterItemPayload::Both, item->getSubscription());
+			CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(presenceChanges.size()));
+			CPPUNIT_ASSERT(StatusShow::Online == presenceChanges[0]->getShow());
+			CPPUNIT_ASSERT(JID("alice@wonderland") == presenceChanges[0]->getFrom());
+		}
+
+		void testServiceRemoved() {
+			std::auto_ptr<LinkLocalPresenceManager> testling(createTestling());
+
+			addService("alice@wonderland");
+			removeService("alice@wonderland");
+
+			CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(rosterChanges.size()));
+			CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(rosterChanges[1]->getItems().size()));
+			boost::optional<RosterItemPayload> item = rosterChanges[1]->getItem(JID("alice@wonderland"));
+			CPPUNIT_ASSERT(item);
+			CPPUNIT_ASSERT_EQUAL(RosterItemPayload::Remove, item->getSubscription());
+		}
+
+		void testServiceChanged() {
+			std::auto_ptr<LinkLocalPresenceManager> testling(createTestling());
+
+			addService("alice@wonderland");
+			updateServicePresence("alice@wonderland", LinkLocalServiceInfo::Away, "I'm Away");
+
+			CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(rosterChanges.size()));
+			CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(presenceChanges.size()));
+			CPPUNIT_ASSERT(StatusShow::Away == presenceChanges[1]->getShow());
+			CPPUNIT_ASSERT(JID("alice@wonderland") == presenceChanges[1]->getFrom());
+			CPPUNIT_ASSERT_EQUAL(String("I'm Away"), presenceChanges[1]->getStatus());
+		}
+
+		void testGetAllPresence() {
+			std::auto_ptr<LinkLocalPresenceManager> testling(createTestling());
+
+			addService("alice@wonderland");
+			addService("rabbit@teaparty");
+			updateServicePresence("rabbit@teaparty", LinkLocalServiceInfo::Away, "Partying");
+			
+			std::vector<boost::shared_ptr<Presence> > presences = testling->getAllPresence();
+			CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(presences.size()));
+			// The order doesn't matter
+			CPPUNIT_ASSERT(JID("rabbit@teaparty") == presences[0]->getFrom());
+			CPPUNIT_ASSERT(StatusShow::Away == presences[0]->getShow());
+			CPPUNIT_ASSERT(JID("alice@wonderland") == presences[1]->getFrom());
+			CPPUNIT_ASSERT(StatusShow::Online == presences[1]->getShow());
+		}
+
+		void testGetRoster() {
+			std::auto_ptr<LinkLocalPresenceManager> testling(createTestling());
+
+			addService("alice@wonderland", "Alice");
+			addService("rabbit@teaparty", "Rabbit");
+
+			boost::shared_ptr<RosterPayload> roster = testling->getRoster();
+			CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(roster->getItems().size()));
+			boost::optional<RosterItemPayload> item;
+			item = roster->getItem(JID("alice@wonderland"));
+			CPPUNIT_ASSERT(item);
+			CPPUNIT_ASSERT_EQUAL(String("Alice"), item->getName());
+			CPPUNIT_ASSERT_EQUAL(RosterItemPayload::Both, item->getSubscription());
+			item = roster->getItem(JID("rabbit@teaparty"));
+			CPPUNIT_ASSERT(item);
+			CPPUNIT_ASSERT_EQUAL(String("Rabbit"), item->getName());
+			CPPUNIT_ASSERT_EQUAL(RosterItemPayload::Both, item->getSubscription());
+		}
+
+		void testGetRoster_InfoWithNick() {
+			std::auto_ptr<LinkLocalPresenceManager> testling(createTestling());
+
+			addService("alice@wonderland", "Alice", "Alice In", "Wonderland");
+
+			boost::optional<RosterItemPayload> item = testling->getRoster()->getItem(JID("alice@wonderland"));
+			CPPUNIT_ASSERT_EQUAL(String("Alice"), item->getName());
+		}
+
+		void testGetRoster_InfoWithFirstName() {
+			std::auto_ptr<LinkLocalPresenceManager> testling(createTestling());
+
+			addService("alice@wonderland", "", "Alice In", "");
+
+			boost::optional<RosterItemPayload> item = testling->getRoster()->getItem(JID("alice@wonderland"));
+			CPPUNIT_ASSERT_EQUAL(String("Alice In"), item->getName());
+		}
+
+		void testGetRoster_InfoWithLastName() {
+			std::auto_ptr<LinkLocalPresenceManager> testling(createTestling());
+
+			addService("alice@wonderland", "", "", "Wonderland");
+
+			boost::optional<RosterItemPayload> item = testling->getRoster()->getItem(JID("alice@wonderland"));
+			CPPUNIT_ASSERT_EQUAL(String("Wonderland"), item->getName());
+		}
+
+		void testGetRoster_InfoWithFirstAndLastName() {
+			std::auto_ptr<LinkLocalPresenceManager> testling(createTestling());
+
+			addService("alice@wonderland", "", "Alice In", "Wonderland");
+
+			boost::optional<RosterItemPayload> item = testling->getRoster()->getItem(JID("alice@wonderland"));
+			CPPUNIT_ASSERT_EQUAL(String("Alice In Wonderland"), item->getName());
+		}
+
+		void testGetRoster_NoInfo() {
+			std::auto_ptr<LinkLocalPresenceManager> testling(createTestling());
+
+			addService("alice@wonderland");
+
+			boost::optional<RosterItemPayload> item = testling->getRoster()->getItem(JID("alice@wonderland"));
+			CPPUNIT_ASSERT_EQUAL(String(""), item->getName());
+		}
+
+	private:
+		std::auto_ptr<LinkLocalPresenceManager> createTestling() {
+			std::auto_ptr<LinkLocalPresenceManager> testling(
+					new LinkLocalPresenceManager(browser));
+			testling->onRosterChanged.connect(boost::bind(
+					&LinkLocalPresenceManagerTest::handleRosterChanged, this, _1));
+			testling->onPresenceChanged.connect(boost::bind(
+					&LinkLocalPresenceManagerTest::handlePresenceChanged, this, _1));
+			return testling;
+		}
+
+		void addService(const String& name, const String& nickName = String(), const String& firstName = String(), const String& lastName = String()) {
+			DNSSDServiceID service(name, "local.");
+			LinkLocalServiceInfo info;
+			info.setFirstName(firstName);
+			info.setLastName(lastName);
+			info.setNick(nickName);
+			querier->setServiceInfo(service, DNSSDResolveServiceQuery::Result(name + "._presence._tcp.local", "rabbithole.local", 1234, info.toTXTRecord()));
+			querier->addService(service);
+			eventLoop->processEvents();
+		}
+
+		void removeService(const String& name) {
+			DNSSDServiceID service(name, "local.");
+			querier->removeService(DNSSDServiceID(name, "local."));
+			eventLoop->processEvents();
+		}
+
+		void updateServicePresence(const String& name, LinkLocalServiceInfo::Status status, const String& message) {
+			DNSSDServiceID service(name, "local.");
+			LinkLocalServiceInfo info;
+			info.setStatus(status);
+			info.setMessage(message);
+			querier->setServiceInfo(service, DNSSDResolveServiceQuery::Result(name + "._presence._tcp.local", "rabbithole.local", 1234, info.toTXTRecord()));
+			eventLoop->processEvents();
+		}
+
+		void handleRosterChanged(boost::shared_ptr<RosterPayload> payload) {
+			rosterChanges.push_back(payload);
+		}
+
+		void handlePresenceChanged(boost::shared_ptr<Presence> presence) {
+			presenceChanges.push_back(presence);
+		}
+
+	private:
+		DummyEventLoop* eventLoop;
+		boost::shared_ptr<FakeDNSSDQuerier> querier;
+		LinkLocalServiceBrowser* browser;
+		std::vector< boost::shared_ptr<RosterPayload> > rosterChanges;
+		std::vector< boost::shared_ptr<Presence> > presenceChanges;
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(LinkLocalPresenceManagerTest);
diff --git a/Slimber/UnitTest/Makefile.inc b/Slimber/UnitTest/Makefile.inc
new file mode 100644
index 0000000..f2c4db8
--- /dev/null
+++ b/Slimber/UnitTest/Makefile.inc
@@ -0,0 +1,2 @@
+UNITTEST_SOURCES += \
+	Slimber/UnitTest/LinkLocalPresenceManagerTest.cpp
diff --git a/Swiften/Elements/RosterPayload.cpp b/Swiften/Elements/RosterPayload.cpp
index 6d39264..8e2fd87 100644
--- a/Swiften/Elements/RosterPayload.cpp
+++ b/Swiften/Elements/RosterPayload.cpp
@@ -7,7 +7,7 @@ boost::optional<RosterItemPayload> RosterPayload::getItem(const JID& jid) const
 	foreach(const RosterItemPayload& item, items_) {
     // FIXME: MSVC rejects this. Find out why.
 		//if (item.getJID() == jid) {
-    if (item.getJID().compare(jid, JID::WithResource)) {
+    if (item.getJID().equals(jid, JID::WithResource)) {
 			return boost::optional<RosterItemPayload>(item);
 		}
 	}
diff --git a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourBrowseQuery.h b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourBrowseQuery.h
index be0c921..c605175 100644
--- a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourBrowseQuery.h
+++ b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourBrowseQuery.h
@@ -41,6 +41,7 @@ namespace Swift {
 					MainEventLoop::postEvent(boost::bind(boost::ref(onError)), shared_from_this());
 				}
 				else {
+					std::cout << "Discovered service: name:" << name << " domain:" << domain << " type: " << type << std::endl;
 					DNSSDServiceID service(name, domain, type, interfaceIndex);
 					if (flags & kDNSServiceFlagsAdd) {
 						MainEventLoop::postEvent(boost::bind(boost::ref(onServiceAdded), service), shared_from_this());
diff --git a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourResolveServiceQuery.h b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourResolveServiceQuery.h
index d16ca5b..886b87b 100644
--- a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourResolveServiceQuery.h
+++ b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourResolveServiceQuery.h
@@ -45,6 +45,7 @@ namespace Swift {
 					MainEventLoop::postEvent(boost::bind(boost::ref(onServiceResolved), boost::optional<Result>()), shared_from_this());
 				}
 				else {
+					std::cout << "Service resolved: name:" << fullName << " host:" << host << " port:" << port << std::endl;
 					MainEventLoop::postEvent(
 							boost::bind(
 								boost::ref(onServiceResolved), 
diff --git a/Swiften/LinkLocal/LinkLocalServiceBrowser.cpp b/Swiften/LinkLocal/LinkLocalServiceBrowser.cpp
index f7c5478..f65cd7a 100644
--- a/Swiften/LinkLocal/LinkLocalServiceBrowser.cpp
+++ b/Swiften/LinkLocal/LinkLocalServiceBrowser.cpp
@@ -102,19 +102,22 @@ void LinkLocalServiceBrowser::handleServiceRemoved(const DNSSDServiceID& service
 	assert(i != resolveQueries.end());
 	i->second->stop();
 	resolveQueries.erase(i);
-	services.erase(service);
-	onServiceRemoved(service);
+	ServiceMap::iterator j = services.find(service);
+	assert(j != services.end());
+	LinkLocalService linkLocalService(j->first, j->second);
+	services.erase(j);
+	onServiceRemoved(linkLocalService);
 }
 
 void LinkLocalServiceBrowser::handleServiceResolved(const DNSSDServiceID& service, const boost::optional<DNSSDResolveServiceQuery::Result>& result) {
 	if (result) {
 		std::pair<ServiceMap::iterator, bool> r = services.insert(std::make_pair(service, *result));
 		if (r.second) {
-			onServiceAdded(service);
+			onServiceAdded(LinkLocalService(r.first->first, r.first->second));
 		}
 		else {
 			r.first->second = *result;
-			onServiceChanged(service);
+			onServiceChanged(LinkLocalService(r.first->first, r.first->second));
 		}
 	}
 }
diff --git a/Swiften/LinkLocal/LinkLocalServiceBrowser.h b/Swiften/LinkLocal/LinkLocalServiceBrowser.h
index dcdd576..a6623b1 100644
--- a/Swiften/LinkLocal/LinkLocalServiceBrowser.h
+++ b/Swiften/LinkLocal/LinkLocalServiceBrowser.h
@@ -31,9 +31,9 @@ namespace Swift {
 
 			std::vector<LinkLocalService> getServices() const;
 
-			boost::signal<void (const DNSSDServiceID&)> onServiceAdded;
-			boost::signal<void (const DNSSDServiceID&)> onServiceChanged;
-			boost::signal<void (const DNSSDServiceID&)> onServiceRemoved;
+			boost::signal<void (const LinkLocalService&)> onServiceAdded;
+			boost::signal<void (const LinkLocalService&)> onServiceChanged;
+			boost::signal<void (const LinkLocalService&)> onServiceRemoved;
 			boost::signal<void (bool)> onStopped;
 
 		private:
diff --git a/Swiften/LinkLocal/UnitTest/LinkLocalServiceBrowserTest.cpp b/Swiften/LinkLocal/UnitTest/LinkLocalServiceBrowserTest.cpp
index e9501cb..6e4d3b4 100644
--- a/Swiften/LinkLocal/UnitTest/LinkLocalServiceBrowserTest.cpp
+++ b/Swiften/LinkLocal/UnitTest/LinkLocalServiceBrowserTest.cpp
@@ -84,7 +84,7 @@ class LinkLocalServiceBrowserTest : public CppUnit::TestFixture {
 			eventLoop->processEvents();
 
 			CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(addedServices.size()));
-			CPPUNIT_ASSERT(addedServices[0] == *testServiceID);
+			CPPUNIT_ASSERT(addedServices[0].getID() == *testServiceID);
 			CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(changedServices.size()));
 			CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(removedServices.size()));
 			std::vector<LinkLocalService> services = testling->getServices();
@@ -141,7 +141,7 @@ class LinkLocalServiceBrowserTest : public CppUnit::TestFixture {
 			eventLoop->processEvents();
 
 			CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(addedServices.size()));
-			CPPUNIT_ASSERT(addedServices[0] == *aliceServiceID);
+			CPPUNIT_ASSERT(addedServices[0].getID() == *aliceServiceID);
 			CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(changedServices.size()));
 			CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(removedServices.size()));
 			std::vector<LinkLocalService> services = testling->getServices();
@@ -166,7 +166,7 @@ class LinkLocalServiceBrowserTest : public CppUnit::TestFixture {
 			CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(addedServices.size()));
 			CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(changedServices.size()));
 			CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(removedServices.size()));
-			CPPUNIT_ASSERT(changedServices[0] == *testServiceID);
+			CPPUNIT_ASSERT(changedServices[0].getID() == *testServiceID);
 			std::vector<LinkLocalService> services = testling->getServices();
 			CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(services.size()));
 			CPPUNIT_ASSERT(*testServiceID == services[0].getID());
@@ -191,7 +191,7 @@ class LinkLocalServiceBrowserTest : public CppUnit::TestFixture {
 			CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(addedServices.size()));
 			CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(changedServices.size()));
 			CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(removedServices.size()));
-			CPPUNIT_ASSERT(removedServices[0] == *testServiceID);
+			CPPUNIT_ASSERT(removedServices[0].getID() == *testServiceID);
 			CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(testling->getServices().size()));
 
 			testling->stop();
@@ -294,15 +294,15 @@ class LinkLocalServiceBrowserTest : public CppUnit::TestFixture {
 			return testling;
 		}
 
-		void handleServiceAdded(const DNSSDServiceID& service) {
+		void handleServiceAdded(const LinkLocalService& service) {
 			addedServices.push_back(service);
 		}
 
-		void handleServiceRemoved(const DNSSDServiceID& service) {
+		void handleServiceRemoved(const LinkLocalService& service) {
 			removedServices.push_back(service);
 		}
 
-		void handleServiceChanged(const DNSSDServiceID& service) {
+		void handleServiceChanged(const LinkLocalService& service) {
 			changedServices.push_back(service);
 		}
 
@@ -320,9 +320,9 @@ class LinkLocalServiceBrowserTest : public CppUnit::TestFixture {
 	private:
 		DummyEventLoop* eventLoop;
 		boost::shared_ptr<FakeDNSSDQuerier> querier;
-		std::vector<DNSSDServiceID> addedServices;
-		std::vector<DNSSDServiceID> changedServices;
-		std::vector<DNSSDServiceID> removedServices;
+		std::vector<LinkLocalService> addedServices;
+		std::vector<LinkLocalService> changedServices;
+		std::vector<LinkLocalService> removedServices;
 		DNSSDServiceID* aliceServiceID;
 		DNSSDResolveServiceQuery::Result* aliceServiceInfo;
 		DNSSDServiceID* testServiceID;
-- 
cgit v0.10.2-6-g49f6


From be2db74cad9f1d0359741beecdef2aed63e0ad2b 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:11:19 +0200
Subject: Proide a description for LinkLocalServices.


diff --git a/Swiften/LinkLocal/LinkLocalService.cpp b/Swiften/LinkLocal/LinkLocalService.cpp
new file mode 100644
index 0000000..f567a63
--- /dev/null
+++ b/Swiften/LinkLocal/LinkLocalService.cpp
@@ -0,0 +1,23 @@
+#include "Swiften/LinkLocal/LinkLocalService.h"
+
+namespace Swift {
+
+String LinkLocalService::getDescription() const {
+	LinkLocalServiceInfo info = getInfo();
+	if (!info.getNick().isEmpty()) {
+		return info.getNick();
+	}
+	else if (!info.getFirstName().isEmpty()) {
+		String result = info.getFirstName();
+		if (!info.getLastName().isEmpty()) {
+			result += " " + info.getLastName();
+		}
+		return result;
+	}
+	else if (!info.getLastName().isEmpty()) {
+		return info.getLastName();
+	}
+	return getName();
+}
+
+}
diff --git a/Swiften/LinkLocal/LinkLocalService.h b/Swiften/LinkLocal/LinkLocalService.h
index 37f2130..f7e9e3c 100644
--- a/Swiften/LinkLocal/LinkLocalService.h
+++ b/Swiften/LinkLocal/LinkLocalService.h
@@ -34,6 +34,8 @@ namespace Swift {
 				return LinkLocalServiceInfo::createFromTXTRecord(info.info);
 			}
 
+			String getDescription() const;
+
 		private:
 			DNSSDServiceID id;
 			DNSSDResolveServiceQuery::Result info;
diff --git a/Swiften/LinkLocal/Makefile.inc b/Swiften/LinkLocal/Makefile.inc
index ac3d2a2..3738789 100644
--- a/Swiften/LinkLocal/Makefile.inc
+++ b/Swiften/LinkLocal/Makefile.inc
@@ -1,6 +1,7 @@
 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 \
diff --git a/Swiften/LinkLocal/UnitTest/LinkLocalServiceInfoTest.cpp b/Swiften/LinkLocal/UnitTest/LinkLocalServiceInfoTest.cpp
index 68f191a..b5d7ef5 100644
--- a/Swiften/LinkLocal/UnitTest/LinkLocalServiceInfoTest.cpp
+++ b/Swiften/LinkLocal/UnitTest/LinkLocalServiceInfoTest.cpp
@@ -14,8 +14,6 @@ class LinkLocalServiceInfoTest : public CppUnit::TestFixture {
 		CPPUNIT_TEST_SUITE_END();
 
 	public:
-		LinkLocalServiceInfoTest() {}
-
 		void testGetTXTRecord() {
 			LinkLocalServiceInfo info;
 			info.setFirstName("Remko");
diff --git a/Swiften/LinkLocal/UnitTest/LinkLocalServiceTest.cpp b/Swiften/LinkLocal/UnitTest/LinkLocalServiceTest.cpp
new file mode 100644
index 0000000..69ec718
--- /dev/null
+++ b/Swiften/LinkLocal/UnitTest/LinkLocalServiceTest.cpp
@@ -0,0 +1,62 @@
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+
+#include "Swiften/LinkLocal/LinkLocalService.h"
+
+using namespace Swift;
+
+class LinkLocalServiceTest : public CppUnit::TestFixture {
+		CPPUNIT_TEST_SUITE(LinkLocalServiceTest);
+		CPPUNIT_TEST(testGetDescription_WithNick);
+		CPPUNIT_TEST(testGetDescription_WithFirstName);
+		CPPUNIT_TEST(testGetDescription_WithLastName);
+		CPPUNIT_TEST(testGetDescription_WithFirstAndLastName);
+		CPPUNIT_TEST(testGetDescription_NoInfo);
+		CPPUNIT_TEST_SUITE_END();
+
+	public:
+		void testGetDescription_WithNick() {
+			LinkLocalService testling = createService("alice@wonderland", "Alice", "Alice In", "Wonderland");
+
+			CPPUNIT_ASSERT_EQUAL(String("Alice"), testling.getDescription());
+		}
+
+		void testGetDescription_WithFirstName() {
+			LinkLocalService testling = createService("alice@wonderland", "", "Alice In");
+
+			CPPUNIT_ASSERT_EQUAL(String("Alice In"), testling.getDescription());
+		}
+
+		void testGetDescription_WithLastName() {
+			LinkLocalService testling = createService("alice@wonderland", "", "", "Wonderland");
+
+			CPPUNIT_ASSERT_EQUAL(String("Wonderland"), testling.getDescription());
+		}
+
+		void testGetDescription_WithFirstAndLastName() {
+			LinkLocalService testling = createService("alice@wonderland", "", "Alice In", "Wonderland");
+
+			CPPUNIT_ASSERT_EQUAL(String("Alice In Wonderland"), testling.getDescription());
+		}
+
+		void testGetDescription_NoInfo() {
+			LinkLocalService testling = createService("alice@wonderland");
+
+			CPPUNIT_ASSERT_EQUAL(String("alice@wonderland"), testling.getDescription());
+		}
+	
+	private:
+		LinkLocalService createService(const String& name, const String& nickName = String(), const String& firstName = String(), const String& lastName = String()) {
+			DNSSDServiceID service(name, "local.");
+			LinkLocalServiceInfo info;
+			info.setFirstName(firstName);
+			info.setLastName(lastName);
+			info.setNick(nickName);
+			return LinkLocalService(service, 
+					DNSSDResolveServiceQuery::Result(
+						name + "._presence._tcp.local", "rabbithole.local", 1234, 
+						info.toTXTRecord()));
+		}
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(LinkLocalServiceTest);
diff --git a/Swiften/LinkLocal/UnitTest/Makefile.inc b/Swiften/LinkLocal/UnitTest/Makefile.inc
index 9640fa7..e5f1bf0 100644
--- a/Swiften/LinkLocal/UnitTest/Makefile.inc
+++ b/Swiften/LinkLocal/UnitTest/Makefile.inc
@@ -1,3 +1,4 @@
 UNITTEST_SOURCES += \
+	Swiften/LinkLocal/UnitTest/LinkLocalServiceTest.cpp \
 	Swiften/LinkLocal/UnitTest/LinkLocalServiceBrowserTest.cpp \
 	Swiften/LinkLocal/UnitTest/LinkLocalServiceInfoTest.cpp
-- 
cgit v0.10.2-6-g49f6


From f1938c7096f2ab77fb438d285f1eadb094010b0a 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:22 +0200
Subject: Remove unnecessary test constructor.


diff --git a/QA/UnitTest/template/FooTest.cpp b/QA/UnitTest/template/FooTest.cpp
index b6b9abf..9657360 100644
--- a/QA/UnitTest/template/FooTest.cpp
+++ b/QA/UnitTest/template/FooTest.cpp
@@ -9,8 +9,6 @@ class FooTest : public CppUnit::TestFixture {
 		CPPUNIT_TEST_SUITE_END();
 
 	public:
-		FooTest() {}
-
 		void setUp() {
 		}
 
-- 
cgit v0.10.2-6-g49f6


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


From ba113b63e5ee8e76638ae8f02f7220fb1b8fcdce Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Fri, 31 Jul 2009 00:14:58 +0200
Subject: Remove assertion that is triggered on unregister().


diff --git a/Swiften/LinkLocal/LinkLocalServiceBrowser.cpp b/Swiften/LinkLocal/LinkLocalServiceBrowser.cpp
index b24d8f0..061bf2c 100644
--- a/Swiften/LinkLocal/LinkLocalServiceBrowser.cpp
+++ b/Swiften/LinkLocal/LinkLocalServiceBrowser.cpp
@@ -100,11 +100,12 @@ void LinkLocalServiceBrowser::handleServiceAdded(const DNSSDServiceID& service)
 }
 
 void LinkLocalServiceBrowser::handleServiceRemoved(const DNSSDServiceID& service) {
-	if (selfService && service == *selfService) {
+	ResolveQueryMap::iterator i = resolveQueries.find(service);
+	if (i == resolveQueries.end()) {
+		// Can happen after an unregister(), when getting the old 'self' 
+		// service remove notification.
 		return;
 	}
-	ResolveQueryMap::iterator i = resolveQueries.find(service);
-	assert(i != resolveQueries.end());
 	i->second->stop();
 	resolveQueries.erase(i);
 	ServiceMap::iterator j = services.find(service);
-- 
cgit v0.10.2-6-g49f6


From 387a3193b648f40f499895c0c03b982c2f8d1263 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Fri, 31 Jul 2009 00:25:50 +0200
Subject: Added unit test that triggers the assertion on self service removal.


diff --git a/Swiften/LinkLocal/UnitTest/LinkLocalServiceBrowserTest.cpp b/Swiften/LinkLocal/UnitTest/LinkLocalServiceBrowserTest.cpp
index 76117c0..9f91269 100644
--- a/Swiften/LinkLocal/UnitTest/LinkLocalServiceBrowserTest.cpp
+++ b/Swiften/LinkLocal/UnitTest/LinkLocalServiceBrowserTest.cpp
@@ -22,6 +22,7 @@ class LinkLocalServiceBrowserTest : public CppUnit::TestFixture {
 		CPPUNIT_TEST(testServiceAdded_UnregisteredService);
 		CPPUNIT_TEST(testServiceChanged);
 		CPPUNIT_TEST(testServiceRemoved);
+		CPPUNIT_TEST(testServiceRemoved_UnregisteredService);
 		CPPUNIT_TEST(testError_BrowseErrorAfterStart);
 		CPPUNIT_TEST(testError_BrowseErrorAfterResolve);
 		CPPUNIT_TEST(testRegisterService);
@@ -154,6 +155,23 @@ class LinkLocalServiceBrowserTest : public CppUnit::TestFixture {
 			testling->stop();
 		}
 
+		void testServiceRemoved_UnregisteredService() {
+			boost::shared_ptr<LinkLocalServiceBrowser> testling = createTestling();
+			testling->start();
+			eventLoop->processEvents();
+			testling->registerService("alice", 1234, LinkLocalServiceInfo());
+			eventLoop->processEvents();
+			testling->unregisterService();
+			eventLoop->processEvents();
+
+			querier->removeService(*aliceServiceID);
+			eventLoop->processEvents();
+
+			CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(removedServices.size()));
+
+			testling->stop();
+		}
+
 		void testServiceChanged() {
 			boost::shared_ptr<LinkLocalServiceBrowser> testling = createTestling();
 			testling->start();
-- 
cgit v0.10.2-6-g49f6


From 1dc80e3835c85a47291d91fd82c0f2f2617aa591 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Fri, 31 Jul 2009 18:34:32 +0200
Subject: Re-enable accidentally disabled XMLParser tests.


diff --git a/Swiften/Parser/UnitTest/XMLParserTest.cpp b/Swiften/Parser/UnitTest/XMLParserTest.cpp
index a26b31b..6a42d0d 100644
--- a/Swiften/Parser/UnitTest/XMLParserTest.cpp
+++ b/Swiften/Parser/UnitTest/XMLParserTest.cpp
@@ -2,7 +2,7 @@
 #include <cppunit/extensions/TestFactoryRegistry.h>
 #include <vector>
 
-#ifdef HAVE_CONFIG_H
+#ifdef HAVE_SWIFTEN_CONFIG_H
 #include "Swiften/config.h"
 #endif
 #include "Swiften/Base/String.h"
@@ -17,10 +17,10 @@
 using namespace Swift;
 
 template <typename ParserType>
-class XMLParserTest : public CppUnit::TestFixture
-{
+class XMLParserTest : public CppUnit::TestFixture {
 		CPPUNIT_TEST_SUITE(XMLParserTest);
 		CPPUNIT_TEST(testParse_NestedElements);
+		CPPUNIT_TEST(testParse_ElementInNamespacedElement);
 		CPPUNIT_TEST(testParse_CharacterData);
 		CPPUNIT_TEST(testParse_NamespacePrefix);
 		CPPUNIT_TEST(testParse_UnhandledXML);
@@ -30,8 +30,6 @@ class XMLParserTest : public CppUnit::TestFixture
 		CPPUNIT_TEST_SUITE_END();
 
 	public:
-		XMLParserTest() {}
-
 		void testParse_NestedElements() {
 			ParserType testling(&client_);
 
@@ -46,17 +44,51 @@ class XMLParserTest : public CppUnit::TestFixture
 			CPPUNIT_ASSERT_EQUAL(String("iq"), client_.events[0].data);
 			CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), client_.events[0].attributes.size());
 			CPPUNIT_ASSERT_EQUAL(String("get"), client_.events[0].attributes["type"]);
+			CPPUNIT_ASSERT_EQUAL(String(), client_.events[0].ns);
 
 			CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[1].type);
 			CPPUNIT_ASSERT_EQUAL(String("query"), client_.events[1].data);
-			CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), client_.events[1].attributes.size());
-			CPPUNIT_ASSERT_EQUAL(String("jabber:iq:version"), client_.events[1].attributes["xmlns"]);
+			CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), client_.events[1].attributes.size());
+			CPPUNIT_ASSERT_EQUAL(String("jabber:iq:version"), client_.events[1].ns);
 
 			CPPUNIT_ASSERT_EQUAL(Client::EndElement, client_.events[2].type);
 			CPPUNIT_ASSERT_EQUAL(String("query"), client_.events[2].data);
+			CPPUNIT_ASSERT_EQUAL(String("jabber:iq:version"), client_.events[2].ns);
 
 			CPPUNIT_ASSERT_EQUAL(Client::EndElement, client_.events[3].type);
 			CPPUNIT_ASSERT_EQUAL(String("iq"), client_.events[3].data);
+			CPPUNIT_ASSERT_EQUAL(String(), client_.events[3].ns);
+		}
+
+		void testParse_ElementInNamespacedElement() {
+			ParserType testling(&client_);
+
+			CPPUNIT_ASSERT(testling.parse(
+				"<query xmlns='jabber:iq:version'>"
+          "<name>Swift</name>"
+				"</query>"));
+
+			CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(5), client_.events.size());
+
+			CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[0].type);
+			CPPUNIT_ASSERT_EQUAL(String("query"), client_.events[0].data);
+			CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), client_.events[0].attributes.size());
+			CPPUNIT_ASSERT_EQUAL(String("jabber:iq:version"), client_.events[0].ns);
+
+			CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[1].type);
+			CPPUNIT_ASSERT_EQUAL(String("name"), client_.events[1].data);
+			CPPUNIT_ASSERT_EQUAL(String("jabber:iq:version"), client_.events[1].ns);
+
+			CPPUNIT_ASSERT_EQUAL(Client::CharacterData, client_.events[2].type);
+			CPPUNIT_ASSERT_EQUAL(String("Swift"), client_.events[2].data);
+
+			CPPUNIT_ASSERT_EQUAL(Client::EndElement, client_.events[3].type);
+			CPPUNIT_ASSERT_EQUAL(String("name"), client_.events[3].data);
+			CPPUNIT_ASSERT_EQUAL(String("jabber:iq:version"), client_.events[3].ns);
+
+			CPPUNIT_ASSERT_EQUAL(Client::EndElement, client_.events[4].type);
+			CPPUNIT_ASSERT_EQUAL(String("query"), client_.events[4].data);
+			CPPUNIT_ASSERT_EQUAL(String("jabber:iq:version"), client_.events[4].ns);
 		}
 
 		void testParse_CharacterData() {
@@ -96,16 +128,20 @@ class XMLParserTest : public CppUnit::TestFixture
 			CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(4), client_.events.size());
 
 			CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[0].type);
-			CPPUNIT_ASSERT_EQUAL(String("p:x"), client_.events[0].data);
+			CPPUNIT_ASSERT_EQUAL(String("x"), client_.events[0].data);
+			CPPUNIT_ASSERT_EQUAL(String("bla"), client_.events[0].ns);
 
 			CPPUNIT_ASSERT_EQUAL(Client::StartElement, client_.events[1].type);
-			CPPUNIT_ASSERT_EQUAL(String("p:y"), client_.events[1].data);
+			CPPUNIT_ASSERT_EQUAL(String("y"), client_.events[1].data);
+			CPPUNIT_ASSERT_EQUAL(String("bla"), client_.events[1].ns);
 
 			CPPUNIT_ASSERT_EQUAL(Client::EndElement, client_.events[2].type);
-			CPPUNIT_ASSERT_EQUAL(String("p:y"), client_.events[2].data);
+			CPPUNIT_ASSERT_EQUAL(String("y"), client_.events[2].data);
+			CPPUNIT_ASSERT_EQUAL(String("bla"), client_.events[2].ns);
 
 			CPPUNIT_ASSERT_EQUAL(Client::EndElement, client_.events[3].type);
-			CPPUNIT_ASSERT_EQUAL(String("p:x"), client_.events[3].data);
+			CPPUNIT_ASSERT_EQUAL(String("x"), client_.events[3].data);
+			CPPUNIT_ASSERT_EQUAL(String("bla"), client_.events[3].ns);
 		}
 
 		void testParse_UnhandledXML() {
@@ -158,24 +194,26 @@ class XMLParserTest : public CppUnit::TestFixture
 					Event(
 							Type type, 
 							const String& data, 
+              const String& ns,
 							const AttributeMap& attributes)
-								: type(type), data(data), attributes(attributes) {}
-					Event(Type type, const String& data)
-								: type(type), data(data) {}
+								: type(type), data(data), ns(ns), attributes(attributes) {}
+					Event(Type type, const String& data, const String& ns = String())
+								: type(type), data(data), ns(ns) {}
 
 					Type type;
 					String data;
+          String ns;
 					AttributeMap attributes;
 				};
 
 				Client() {}
 
-				virtual void handleStartElement(const String& element, const AttributeMap& attributes) {
-					events.push_back(Event(StartElement, element, attributes));
+				virtual void handleStartElement(const String& element, const String& ns, const AttributeMap& attributes) {
+					events.push_back(Event(StartElement, element, ns, attributes));
 				}
 
-				virtual void handleEndElement(const String& element) {
-					events.push_back(Event(EndElement, element));
+				virtual void handleEndElement(const String& element, const String& ns) {
+					events.push_back(Event(EndElement, element, ns));
 				}
 
 				virtual void handleCharacterData(const String& data) {
-- 
cgit v0.10.2-6-g49f6


From 7d03474e499e9d357c2d69e2333ba5dd0dc03fd4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Fri, 31 Jul 2009 18:34:49 +0200
Subject: ExpatParser: Fix invalid handleEndElement()


diff --git a/Swiften/Parser/ExpatParser.cpp b/Swiften/Parser/ExpatParser.cpp
index 6d23c93..6f7ff86 100644
--- a/Swiften/Parser/ExpatParser.cpp
+++ b/Swiften/Parser/ExpatParser.cpp
@@ -32,6 +32,10 @@ static void handleStartElement(void* client, const XML_Char* name, const XML_Cha
 
 static void handleEndElement(void* client, const XML_Char* name) {
 	std::pair<String,String> nsTagPair = String(name).getSplittedAtFirst(NAMESPACE_SEPARATOR);
+	if (nsTagPair.second == "") {
+		nsTagPair.second = nsTagPair.first;
+		nsTagPair.first = "";
+	}
 	static_cast<XMLParserClient*>(client)->handleEndElement(nsTagPair.second, nsTagPair.first);
 }
 
-- 
cgit v0.10.2-6-g49f6


From d0f250d26bd1bdb405b2232159e7f84741d13e52 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Fri, 31 Jul 2009 18:35:29 +0200
Subject: Add Slimber to coverage tests.


diff --git a/tools/coverage/FilterLCovData.py b/tools/coverage/FilterLCovData.py
index b1dd74e..8d56a7f 100755
--- a/tools/coverage/FilterLCovData.py
+++ b/tools/coverage/FilterLCovData.py
@@ -1,9 +1,15 @@
 #!/usr/bin/env python
 
+# TODO: Add uncovered non-ignored files
+
 import sys, re, os.path
 
 assert(len(sys.argv) == 2)
 
+def isIgnored(file) :
+  return (find.find("/Swiften/") == -1 and find.find("/Slimber/") == -1 and find.find("/Swift/") == -1) or (find.find("/UnitTest/") != -1 or find.find("/QA/") != -1)
+  
+
 output = []
 inputFile = open(sys.argv[1])
 inIgnoredFile = False
@@ -12,7 +18,7 @@ for line in inputFile.readlines() :
     if line == "end_of_record\n" :
       inIgnoredFile = False
   else :
-    if line.startswith("SF:") and (line.find("/Swiften/") == -1 or line.find("/UnitTest/") != -1 or line.find("/QA/") != -1 or line.find("/3rdParty/") != -1):
+    if line.startswith("SF:") and isIgnored(line) :
       inIgnoredFile = True
     else :
       m = re.match("SF:(.*)", line)
diff --git a/tools/coverage/GenerateCoverageResults.sh b/tools/coverage/GenerateCoverageResults.sh
index 75efaa9..f006e4b 100755
--- a/tools/coverage/GenerateCoverageResults.sh
+++ b/tools/coverage/GenerateCoverageResults.sh
@@ -31,6 +31,7 @@ $LCOVDIR/lcov --zerocounters --directory $SOURCE_DIR
 # All tests
 make -C $SOURCE_DIR test
 $LCOVDIR/lcov --capture --directory $SOURCE_DIR -b $SOURCE_DIR --output-file $OUTPUT_DIR/all.info --test-name all
+cp $OUTPUT_DIR/all.info $OUTPUT_DIR/all.info.orig
 $SCRIPT_DIR/FilterLCovData.py $OUTPUT_DIR/all.info
 
 # Generate HTML
-- 
cgit v0.10.2-6-g49f6


From aa60aa80d2d170a536c246ef6c221f92de7dd8ed Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Fri, 31 Jul 2009 18:38:15 +0200
Subject: Adapt LinkLocalConnector to new LinkLocal infrastructure.


diff --git a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourResolveHostnameQuery.h b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourResolveHostnameQuery.h
index 6e2a852..7b5f19a 100644
--- a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourResolveHostnameQuery.h
+++ b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourResolveHostnameQuery.h
@@ -12,7 +12,7 @@ namespace Swift {
 	class BonjourQuerier;
 
 	class BonjourResolveHostnameQuery : public DNSSDResolveHostnameQuery, public BonjourQuery {
-		public:	
+		public: 
 			BonjourResolveHostnameQuery(const String& hostname, int interfaceIndex, boost::shared_ptr<BonjourQuerier> querier) : BonjourQuery(querier) {
 				DNSServiceErrorType result = DNSServiceGetAddrInfo(
 						&sdRef, 0, interfaceIndex, kDNSServiceProtocol_IPv4, 
@@ -33,6 +33,10 @@ namespace Swift {
 				}
 			}
 
+			void finish() {
+				BonjourQuery::finish();
+			}
+
 		private:
 			static void handleHostnameResolvedStatic(DNSServiceRef, DNSServiceFlags, uint32_t, DNSServiceErrorType errorCode, const char*, const struct sockaddr *address, uint32_t, void *context) {
 				static_cast<BonjourResolveHostnameQuery*>(context)->handleHostnameResolved(errorCode, address);
diff --git a/Swiften/LinkLocal/DNSSD/DNSSDResolveHostnameQuery.h b/Swiften/LinkLocal/DNSSD/DNSSDResolveHostnameQuery.h
index a2e218c..1b9f291 100644
--- a/Swiften/LinkLocal/DNSSD/DNSSDResolveHostnameQuery.h
+++ b/Swiften/LinkLocal/DNSSD/DNSSDResolveHostnameQuery.h
@@ -11,6 +11,7 @@ namespace Swift {
 			virtual ~DNSSDResolveHostnameQuery();
 
 			virtual void run() = 0;
+			virtual void finish() = 0;
 
 			boost::signal<void (const boost::optional<HostAddress>&)> onHostnameResolved;
 	};
diff --git a/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDResolveHostnameQuery.h b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDResolveHostnameQuery.h
index 2ff84d3..1f9d7f1 100644
--- a/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDResolveHostnameQuery.h
+++ b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDResolveHostnameQuery.h
@@ -19,6 +19,10 @@ namespace Swift {
 				FakeDNSSDQuery::run();
 			}
 
+			void finish() {
+				FakeDNSSDQuery::finish();
+			}
+
 			String hostname;
 			int interfaceIndex;
 	};
diff --git a/Swiften/LinkLocal/LinkLocalConnector.cpp b/Swiften/LinkLocal/LinkLocalConnector.cpp
index 28107ed..18b5d6a 100644
--- a/Swiften/LinkLocal/LinkLocalConnector.cpp
+++ b/Swiften/LinkLocal/LinkLocalConnector.cpp
@@ -7,52 +7,53 @@
 #include "Swiften/Network/HostAddress.h"
 #include "Swiften/Network/HostAddressPort.h"
 #include "Swiften/LinkLocal/DNSSD/DNSSDQuerier.h"
+#include "Swiften/LinkLocal/DNSSD/DNSSDResolveHostnameQuery.h"
 
 namespace Swift {
 
 LinkLocalConnector::LinkLocalConnector(
 		const JID& remoteJID,
 		const String& hostname,
+		int interfaceIndex,
 		int port,
 		boost::shared_ptr<DNSSDQuerier> querier,
 		boost::shared_ptr<Connection> connection) : 
-			remoteJID_(remoteJID),
-			hostname_(hostname),
-			port_(port),
-			querier_(querier),
-			connection_(connection),
-			resolving_(false) {
+			remoteJID(remoteJID),
+			hostname(hostname),
+			interfaceIndex(interfaceIndex),
+			port(port),
+			querier(querier),
+			connection(connection) {
 }
 
 void LinkLocalConnector::connect() {
-	resolving_ = true;
-	//querier_->onHostnameResolved.connect(boost::bind(&LinkLocalConnector::handleHostnameResolved, boost::dynamic_pointer_cast<LinkLocalConnector>(shared_from_this()), _1, _2));
-	//querier_->resolveHostname(hostname_);
+	resolveQuery = querier->createResolveHostnameQuery(hostname, interfaceIndex);
+	resolveQuery->onHostnameResolved.connect(boost::bind(
+			&LinkLocalConnector::handleHostnameResolved, 
+			boost::dynamic_pointer_cast<LinkLocalConnector>(shared_from_this()), 
+			_1));
+	resolveQuery->run();
 }
 
-/*
-void LinkLocalConnector::handleHostnameResolved(const String& hostname, const boost::optional<HostAddress>& address) {
-	if (resolving_) {
-		if (hostname == hostname_) {
-			resolving_ = false;
-			if (address) {
-				connection_->onConnectFinished.connect(boost::bind(boost::ref(onConnectFinished), _1));
-				connection_->connect(HostAddressPort(*address, port_));
-			}
-			else {
-				onConnectFinished(false);
-			}
-		}
+void LinkLocalConnector::handleHostnameResolved(const boost::optional<HostAddress>& address) {
+	if (address) {
+		resolveQuery->finish();
+		resolveQuery.reset();
+		connection->onConnectFinished.connect(
+				boost::bind(boost::ref(onConnectFinished), _1));
+		connection->connect(HostAddressPort(*address, port));
+	}
+	else {
+		onConnectFinished(false);
 	}
 }
-*/
 
 void LinkLocalConnector::handleConnected(bool error) {
 	onConnectFinished(error);
 }
 
 void LinkLocalConnector::queueElement(boost::shared_ptr<Element> element) {
-	queuedElements_.push_back(element);
+	queuedElements.push_back(element);
 }
 
 
diff --git a/Swiften/LinkLocal/LinkLocalConnector.h b/Swiften/LinkLocal/LinkLocalConnector.h
index 2ddb5b8..134656c 100644
--- a/Swiften/LinkLocal/LinkLocalConnector.h
+++ b/Swiften/LinkLocal/LinkLocalConnector.h
@@ -16,44 +16,47 @@ namespace Swift {
 	class PayloadParserFactoryCollection;
 	class PayloadSerializerCollection;
 	class DNSSDQuerier;
+	class DNSSDResolveHostnameQuery;
 
 	class LinkLocalConnector : public boost::enable_shared_from_this<LinkLocalConnector> {
 		public:
 			LinkLocalConnector(
 					const JID& remoteJID,
 					const String& hostname,
+					int interfaceIndex,
 					int port,
 					boost::shared_ptr<DNSSDQuerier> querier,
 					boost::shared_ptr<Connection> connection);
 
 			const JID& getRemoteJID() const {
-				return remoteJID_;
+				return remoteJID;
 			}
 
 			void connect();
 			void queueElement(boost::shared_ptr<Element> element);
 
 			const std::vector<boost::shared_ptr<Element> >& getQueuedElements() const {
-				return queuedElements_;
+				return queuedElements;
 			}
 
 			boost::shared_ptr<Connection> getConnection() const {
-				return connection_;
+				return connection;
 			}
 
 			boost::signal<void (bool)> onConnectFinished;
 
 		private:
-			//void handleHostnameResolved(const String& hostname, const boost::optional<HostAddress>& address);
+			void handleHostnameResolved(const boost::optional<HostAddress>& address);
 			void handleConnected(bool error);
 
 		private:
-			JID remoteJID_;
-			String hostname_;
-			int port_;
-			boost::shared_ptr<DNSSDQuerier> querier_;
-			boost::shared_ptr<Connection> connection_;
-			bool resolving_;
-			std::vector<boost::shared_ptr<Element> > queuedElements_;
+			JID remoteJID;
+			String hostname;
+			int interfaceIndex;
+			int port;
+			boost::shared_ptr<DNSSDQuerier> querier;
+			boost::shared_ptr<DNSSDResolveHostnameQuery> resolveQuery;
+			boost::shared_ptr<Connection> connection;
+			std::vector<boost::shared_ptr<Element> > queuedElements;
 	};
 }
-- 
cgit v0.10.2-6-g49f6