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