summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRemko Tronçon <git@el-tramo.be>2009-07-18 10:17:45 (GMT)
committerRemko Tronçon <git@el-tramo.be>2009-07-18 11:54:02 (GMT)
commit7388443bda19877980e368a0654b55097db0bda7 (patch)
treec9ccbedfa94cecf4a6e2188e1cdb5420e3e97c3a
parent633c82407e47ec2ba7a92cef9c5b30a24a93fc68 (diff)
downloadswift-7388443bda19877980e368a0654b55097db0bda7.zip
swift-7388443bda19877980e368a0654b55097db0bda7.tar.bz2
Add DNS-SD hostname resolving.
-rw-r--r--Swiften/LinkLocal/AppleDNSSDService.cpp144
-rw-r--r--Swiften/LinkLocal/AppleDNSSDService.h15
-rw-r--r--Swiften/LinkLocal/DNSSDService.h14
-rw-r--r--Swiften/LinkLocal/LinkLocalRoster.cpp21
-rw-r--r--Swiften/LinkLocal/LinkLocalRoster.h8
5 files changed, 145 insertions, 57 deletions
diff --git a/Swiften/LinkLocal/AppleDNSSDService.cpp b/Swiften/LinkLocal/AppleDNSSDService.cpp
index abf8548..18cdcb0 100644
--- a/Swiften/LinkLocal/AppleDNSSDService.cpp
+++ b/Swiften/LinkLocal/AppleDNSSDService.cpp
@@ -4,30 +4,21 @@
#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 {
-#if 0
-namespace {
- void handleAddressInfoReceived ( DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *hostname, const struct sockaddr *address, uint32_t ttl, void *context ) {
- //std::cerr << "Address received " << HostAddress((const unsigned char*) address->sa_data, 4).toString() << std::endl;
- }
-}
-
-/*
- result = DNSServiceGetAddrInfo(&addressSDRef, 0, 6, kDNSServiceProtocol_IPv4, "Micro.local.", handleAddressInfoReceived, 0);
- */
-#endif
-
-
-AppleDNSSDService::AppleDNSSDService() : thread(0), stopRequested(false), browseSDRef(0), registerSDRef(0) {
+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];
}
@@ -36,10 +27,20 @@ AppleDNSSDService::~AppleDNSSDService() {
}
void AppleDNSSDService::start() {
- assert(!thread);
+ 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);
@@ -47,7 +48,8 @@ void AppleDNSSDService::registerService(const String& name, int port, const Link
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) {
- onError();
+ std::cerr << "Error creating service registration" << std::endl;
+ haveError = true;
}
interruptSelect();
@@ -57,10 +59,8 @@ void AppleDNSSDService::unregisterService() {
boost::lock_guard<boost::mutex> lock(sdRefsMutex);
assert(registerSDRef);
- DNSServiceRefDeallocate(registerSDRef);
+ DNSServiceRefDeallocate(registerSDRef); // Interrupts select()
registerSDRef = NULL;
-
- interruptSelect();
}
void AppleDNSSDService::startResolvingService(const Service& service) {
@@ -69,11 +69,13 @@ void AppleDNSSDService::startResolvingService(const Service& service) {
DNSServiceRef resolveSDRef;
DNSServiceErrorType result = DNSServiceResolve(&resolveSDRef, 0, service.networkInterface, service.name.getUTF8Data(), service.type.getUTF8Data(), service.domain.getUTF8Data(), &AppleDNSSDService::handleServiceResolvedGlobal, this);
if (result != kDNSServiceErr_NoError) {
- onError();
+ std::cerr << "Error creating service resolve query" << std::endl;
+ haveError = true;
+ }
+ else {
+ bool isNew = resolveSDRefs.insert(std::make_pair(service, resolveSDRef)).second;
+ assert(isNew);
}
-
- bool isNew = resolveSDRefs.insert(std::make_pair(service, resolveSDRef)).second;
- assert(isNew);
interruptSelect();
}
@@ -83,33 +85,40 @@ void AppleDNSSDService::stopResolvingService(const Service& service) {
ServiceSDRefMap::iterator i = resolveSDRefs.find(service);
assert(i != resolveSDRefs.end());
- DNSServiceRefDeallocate(i->second);
+ DNSServiceRefDeallocate(i->second); // Interrupts select()
resolveSDRefs.erase(i);
-
- interruptSelect();
}
-void AppleDNSSDService::stop() {
- if (thread) {
- stopRequested = true;
- interruptSelect();
- thread->join();
- delete thread;
- stopRequested = false;
+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
assert(!browseSDRef);
DNSServiceErrorType result = DNSServiceBrowse(&browseSDRef, 0, 0, "_presence._tcp", 0, &AppleDNSSDService::handleServiceDiscoveredGlobal , this);
if (result != kDNSServiceErr_NoError) {
- MainEventLoop::postEvent(boost::ref(onError), shared_from_this());
- return;
+ std::cerr << "Error creating browse query" << std::endl;
+ haveError = true;
}
// Run the main loop
- while (!stopRequested) {
+ while (!haveError && !stopRequested) {
fd_set fdSet;
FD_ZERO(&fdSet);
int maxSocket = interruptSelectReadSocket;
@@ -130,24 +139,32 @@ void AppleDNSSDService::doStart() {
FD_SET(registerSocket, &fdSet);
}
- // Resolving
+ // 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 == -1) {
- MainEventLoop::postEvent(boost::ref(onError), shared_from_this());
- return;
- }
- if (selectResult == 0) {
+ if (selectResult <= 0) {
continue;
}
if (FD_ISSET(DNSServiceRefSockFD(browseSDRef), &fdSet)) {
@@ -161,9 +178,27 @@ void AppleDNSSDService::doStart() {
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
+ }
+ }
}
}
+ 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;
@@ -171,6 +206,8 @@ void AppleDNSSDService::doStart() {
DNSServiceRefDeallocate(browseSDRef);
browseSDRef = NULL;
+
+ MainEventLoop::postEvent(boost::bind(boost::ref(onStopped), haveError), shared_from_this());
}
void AppleDNSSDService::interruptSelect() {
@@ -184,7 +221,7 @@ void AppleDNSSDService::handleServiceDiscoveredGlobal(DNSServiceRef sdRef, DNSSe
void AppleDNSSDService::handleServiceDiscovered(DNSServiceRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *serviceName, const char *regtype, const char *replyDomain) {
if (errorCode != kDNSServiceErr_NoError) {
- MainEventLoop::postEvent(boost::ref(onError), shared_from_this());
+ return;
}
else {
Service service(serviceName, regtype, replyDomain, interfaceIndex);
@@ -203,7 +240,8 @@ void AppleDNSSDService::handleServiceRegisteredGlobal(DNSServiceRef sdRef, DNSSe
void AppleDNSSDService::handleServiceRegistered(DNSServiceRef, DNSServiceFlags, DNSServiceErrorType errorCode, const char *name, const char *regtype, const char *domain) {
if (errorCode != kDNSServiceErr_NoError) {
- MainEventLoop::postEvent(boost::ref(onError), shared_from_this());
+ std::cerr << "Error registering service" << std::endl;
+ haveError = true;
}
else {
MainEventLoop::postEvent(boost::bind(boost::ref(onServiceRegistered), Service(name, regtype, domain, 0)), shared_from_this());
@@ -228,5 +266,21 @@ void AppleDNSSDService::handleServiceResolved(DNSServiceRef sdRef, DNSServiceFla
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
index bf6b4aa..cdeafed 100644
--- a/Swiften/LinkLocal/AppleDNSSDService.h
+++ b/Swiften/LinkLocal/AppleDNSSDService.h
@@ -14,12 +14,16 @@ namespace Swift {
AppleDNSSDService();
~AppleDNSSDService();
+ virtual void start();
+ virtual void stop();
+
virtual void registerService(const String& name, int port, const LinkLocalServiceInfo&);
+ virtual void unregisterService();
+
virtual void startResolvingService(const Service&);
virtual void stopResolvingService(const Service&);
- virtual void unregisterService();
- virtual void start();
- virtual void stop();
+
+ virtual void resolveHostname(const String& hostname, int interfaceIndex = 0);
private:
void doStart();
@@ -31,10 +35,13 @@ namespace Swift {
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;
@@ -42,5 +49,7 @@ namespace Swift {
DNSServiceRef registerSDRef;
typedef std::map<Service, DNSServiceRef> ServiceSDRefMap;
ServiceSDRefMap resolveSDRefs;
+ typedef std::vector<DNSServiceRef> HostnameSDRefs;
+ HostnameSDRefs hostnameResolveSDRefs;
};
}
diff --git a/Swiften/LinkLocal/DNSSDService.h b/Swiften/LinkLocal/DNSSDService.h
index 6a9425f..3dd8c7b 100644
--- a/Swiften/LinkLocal/DNSSDService.h
+++ b/Swiften/LinkLocal/DNSSDService.h
@@ -8,6 +8,7 @@
namespace Swift {
class LinkLocalServiceInfo;
+ class HostAddress;
class DNSSDService {
public:
@@ -50,16 +51,23 @@ namespace Swift {
virtual ~DNSSDService();
+ virtual void start() = 0;
+ virtual void stop() = 0;
+
virtual void registerService(const String& name, int port, const LinkLocalServiceInfo&) = 0;
+ virtual void unregisterService() = 0;
+
virtual void startResolvingService(const Service&) = 0;
virtual void stopResolvingService(const Service&) = 0;
- virtual void unregisterService() = 0;
- virtual void start() = 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 ()> onError;
+ boost::signal<void (const String&, const boost::optional<HostAddress>&)> onHostnameResolved;
};
}
diff --git a/Swiften/LinkLocal/LinkLocalRoster.cpp b/Swiften/LinkLocal/LinkLocalRoster.cpp
index fde52a9..feec7b7 100644
--- a/Swiften/LinkLocal/LinkLocalRoster.cpp
+++ b/Swiften/LinkLocal/LinkLocalRoster.cpp
@@ -2,15 +2,17 @@
#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));
- dnsSDService->onError.connect(boost::bind(&LinkLocalRoster::handleDNSSDError, this));
- dnsSDService->onServiceRegistered.connect(boost::bind(&LinkLocalRoster::handleServiceRegistered, this, _1));
+ dnsSDService->onHostnameResolved.connect(boost::bind(&LinkLocalRoster::handleHostnameResolved, this, _1, _2));
}
void LinkLocalRoster::handleServiceAdded(const DNSSDService::Service& service) {
@@ -28,14 +30,25 @@ void LinkLocalRoster::handleServiceRemoved(const DNSSDService::Service& service)
void LinkLocalRoster::handleServiceResolved(const DNSSDService::Service& service, const DNSSDService::ResolveResult& result) {
std::cout << "Service resolved: " << service.name << "->" << result.host << " " << result.port << " " << result.info.getLastName() << std::endl;
+ dnsSDService->resolveHostname(result.host);
}
+void LinkLocalRoster::handleHostnameResolved(const String& hostname, const boost::optional<HostAddress>& address) {
+ if (address) {
+ std::cout << "Address resolved: " << hostname << " " << address->toString() << std::endl;
+ }
+ else {
+ std::cout << "Unable to resolve address for " << hostname << std::endl;
+ }
+}
+
+
void LinkLocalRoster::handleServiceRegistered(const DNSSDService::Service& service) {
selfService = service;
}
-void LinkLocalRoster::handleDNSSDError() {
- std::cout << "DNSSD Error" << std::endl;
+void LinkLocalRoster::handleStopped(bool error) {
+ std::cout << "DNSSDService stopped: " << error << std::endl;
}
}
diff --git a/Swiften/LinkLocal/LinkLocalRoster.h b/Swiften/LinkLocal/LinkLocalRoster.h
index 3cc8d55..321bd96 100644
--- a/Swiften/LinkLocal/LinkLocalRoster.h
+++ b/Swiften/LinkLocal/LinkLocalRoster.h
@@ -1,20 +1,24 @@
#pragma once
#include <boost/shared_ptr.hpp>
+#include <boost/optional.hpp>
#include "Swiften/LinkLocal/DNSSDService.h"
namespace Swift {
+ class HostAddress;
+
class LinkLocalRoster {
public:
LinkLocalRoster(boost::shared_ptr<DNSSDService> service);
private:
+ 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 handleDNSSDError();
- void handleServiceRegistered(const DNSSDService::Service& service);
+ void handleHostnameResolved(const String& hostname, const boost::optional<HostAddress>& address);
private:
boost::shared_ptr<DNSSDService> dnsSDService;