summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'Swiften/LinkLocal')
-rw-r--r--Swiften/LinkLocal/AppleDNSSDService.cpp184
-rw-r--r--Swiften/LinkLocal/AppleDNSSDService.h16
-rw-r--r--Swiften/LinkLocal/DNSSDService.h13
-rw-r--r--Swiften/LinkLocal/LinkLocalRoster.cpp4
-rw-r--r--Swiften/LinkLocal/LinkLocalRoster.h4
5 files changed, 149 insertions, 72 deletions
diff --git a/Swiften/LinkLocal/AppleDNSSDService.cpp b/Swiften/LinkLocal/AppleDNSSDService.cpp
index b68b09e..3b71f74 100644
--- a/Swiften/LinkLocal/AppleDNSSDService.cpp
+++ b/Swiften/LinkLocal/AppleDNSSDService.cpp
@@ -1,48 +1,74 @@
#include "Swiften/LinkLocal/AppleDNSSDService.h"
-#include <dns_sd.h>
+#include <algorithm>
+#include <unistd.h>
#include <iostream>
#include <sys/socket.h>
+#include "Swiften/EventLoop/MainEventLoop.h"
+
namespace Swift {
+#if 0
namespace {
- void handleServiceRegistered(DNSServiceRef sdRef, DNSServiceFlags flags, DNSServiceErrorType errorCode, const char *name, const char *regtype, const char *domain, void *context ) {
- std::cerr << "Service registered " << name << " " << regtype << " " << domain << std::endl;
- }
-
- void handleServiceDiscovered(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *serviceName, const char *regtype, const char *replyDomain, void *context ) {
- std::cerr << "Service discovered " << interfaceIndex << " " << serviceName << " " << regtype << " " << replyDomain << " " << flags << std::endl;
- }
-
void handleServiceResolved( 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 ) {
std::cerr << "Service resolved " << fullname << " " << hosttarget << " " << port << " " << txtLen << " " << /*std::string((const char*) txtRecord, txtLen) <<*/ std::endl;
}
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;
+ //std::cerr << "Address received " << HostAddress((const unsigned char*) address->sa_data, 4).toString() << std::endl;
}
}
+/*
+ result = DNSServiceResolve(&resolveSDRef, 0, 6, "Remko@Micro", "_presence._tcp.", "local.", handleServiceResolved , 0);
+ result = DNSServiceGetAddrInfo(&addressSDRef, 0, 6, kDNSServiceProtocol_IPv4, "Micro.local.", handleAddressInfoReceived, 0);
+ */
+#endif
+
-AppleDNSSDService::AppleDNSSDService() : thread(0), stopRequested(false) {
+AppleDNSSDService::AppleDNSSDService() : thread(0), stopRequested(false), browseSDRef(0), registerSDRef(0) {
+ int fds[2];
+ int result = pipe(fds);
+ assert(result == 0);
+ interruptSelectReadSocket = fds[0];
+ interruptSelectWriteSocket = fds[1];
}
AppleDNSSDService::~AppleDNSSDService() {
stop();
}
-void AppleDNSSDService::publishService(const std::map<String,String>) {
-}
-
void AppleDNSSDService::start() {
assert(!thread);
thread = new boost::thread(boost::bind(&AppleDNSSDService::doStart, shared_from_this()));
}
+void AppleDNSSDService::registerService(const String& name, int port, const std::map<String,String>&) {
+ // TODO: Use properties
+ boost::lock_guard<boost::mutex> lock(sdRefsMutex);
+
+ assert(!registerSDRef);
+ DNSServiceErrorType result = DNSServiceRegister(&registerSDRef, 0, 0, name.getUTF8Data(), "_presence._tcp", NULL, NULL, port, 0, NULL, &AppleDNSSDService::handleServiceRegisteredGlobal, this);
+ interruptSelect();
+ if (result != kDNSServiceErr_NoError) {
+ onError();
+ }
+}
+
+void AppleDNSSDService::unregisterService() {
+ boost::lock_guard<boost::mutex> lock(sdRefsMutex);
+
+ assert(registerSDRef);
+ interruptSelect();
+ DNSServiceRefDeallocate(registerSDRef);
+ registerSDRef = NULL;
+}
+
void AppleDNSSDService::stop() {
if (thread) {
stopRequested = true;
+ interruptSelect();
thread->join();
delete thread;
stopRequested = false;
@@ -50,66 +76,100 @@ void AppleDNSSDService::stop() {
}
void AppleDNSSDService::doStart() {
- while (!stopRequested) {
+ // 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;
+ }
+ // Run the main loop
+ while (!stopRequested) {
fd_set fdSet;
- DNSServiceErrorType result;
-
- DNSServiceRef registerSDRef;
- result = DNSServiceRegister(&registerSDRef, 0, 0, "eemi", "_presence._tcp", NULL, NULL, 5269, 0, NULL, handleServiceRegistered, NULL);
- if (result != kDNSServiceErr_NoError) {
- std::cerr << "Error 1" << std::endl;
- }
- int registerSocket = DNSServiceRefSockFD(registerSDRef);
FD_ZERO(&fdSet);
- FD_SET(registerSocket, &fdSet);
- select(registerSocket+1, &fdSet, &fdSet, &fdSet, 0);
- DNSServiceProcessResult(registerSDRef);
-
- DNSServiceRef browseSDRef;
- result = DNSServiceBrowse(&browseSDRef, 0, 0, "_presence._tcp", 0, handleServiceDiscovered , 0);
- if (result != kDNSServiceErr_NoError) {
- std::cerr << "Error 2" << std::endl;
- }
- int browseSocket = DNSServiceRefSockFD(browseSDRef);
- //while(true) {
- FD_ZERO(&fdSet);
+ int maxSocket = 0;
+
+ {
+ boost::lock_guard<boost::mutex> lock(sdRefsMutex);
+
+ // Browsing
+ int browseSocket = DNSServiceRefSockFD(browseSDRef);
+ maxSocket = browseSocket;
FD_SET(browseSocket, &fdSet);
- select(browseSocket+1, &fdSet, &fdSet, &fdSet, 0);
- DNSServiceProcessResult(browseSDRef);
- //}
+ // Registration
+ if (registerSDRef) {
+ int registerSocket = DNSServiceRefSockFD(registerSDRef);
+ maxSocket = std::max(maxSocket, registerSocket);
+ FD_SET(registerSocket, &fdSet);
+ }
+ }
- DNSServiceRef resolveSDRef;
- result = DNSServiceResolve(&resolveSDRef, 0, 6, "Remko@Micro", "_presence._tcp.", "local.", handleServiceResolved , 0);
- if (result != kDNSServiceErr_NoError) {
- std::cerr << "Error 3" << std::endl;
+ int selectResult = select(maxSocket+1, &fdSet, NULL, NULL, 0);
+
+ {
+ boost::lock_guard<boost::mutex> lock(sdRefsMutex);
+
+ if (selectResult == -1) {
+ MainEventLoop::postEvent(boost::ref(onError), shared_from_this());
+ return;
+ }
+ if (selectResult == 0) {
+ continue;
+ }
+ if (FD_ISSET(DNSServiceRefSockFD(browseSDRef), &fdSet)) {
+ DNSServiceProcessResult(browseSDRef);
+ }
+ if (registerSDRef && FD_ISSET(DNSServiceRefSockFD(registerSDRef), &fdSet)) {
+ DNSServiceProcessResult(registerSDRef);
+ }
}
- int resolveSocket = DNSServiceRefSockFD(resolveSDRef);
- //while(true) {
- FD_ZERO(&fdSet);
- FD_SET(resolveSocket, &fdSet);
- select(resolveSocket+1, &fdSet, &fdSet, &fdSet, 0);
- DNSServiceProcessResult(resolveSDRef);
- //}
+ }
+ if (registerSDRef) {
+ DNSServiceRefDeallocate(registerSDRef);
+ registerSDRef = NULL;
+ }
- DNSServiceRef addressSDRef;
- result = DNSServiceGetAddrInfo(&addressSDRef, 0, 6, kDNSServiceProtocol_IPv4, "Micro.local.", handleAddressInfoReceived, 0);
- if (result != kDNSServiceErr_NoError) {
- std::cerr << "Error 4" << std::endl;
+ DNSServiceRefDeallocate(browseSDRef);
+ browseSDRef = NULL;
+}
+
+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) {
+ MainEventLoop::postEvent(boost::ref(onError), shared_from_this());
+ }
+ else {
+ Service service(serviceName, regtype, replyDomain, interfaceIndex);
+ if (flags & kDNSServiceFlagsAdd) {
+ MainEventLoop::postEvent(boost::bind(boost::ref(onServiceAdded), service), shared_from_this());
}
- int addressSocket = DNSServiceRefSockFD(addressSDRef);
- //while(true) {
- std::cout << "GetAddrInfo2" << std::endl;
- FD_ZERO(&fdSet);
- FD_SET(addressSocket, &fdSet);
- select(addressSocket+1, &fdSet, &fdSet, &fdSet, 0);
- DNSServiceProcessResult(addressSDRef);
- //}
+ else {
+ MainEventLoop::postEvent(boost::bind(boost::ref(onServiceRemoved), service), shared_from_this());
+ }
+ }
+}
- // DNSServiceRefDeallocate
+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) {
+ MainEventLoop::postEvent(boost::ref(onError), shared_from_this());
+ }
+ else {
+ MainEventLoop::postEvent(boost::bind(boost::ref(onServiceRegistered), Service(name, regtype, domain, 0)), shared_from_this());
}
}
diff --git a/Swiften/LinkLocal/AppleDNSSDService.h b/Swiften/LinkLocal/AppleDNSSDService.h
index e6bedf7..3607ce0 100644
--- a/Swiften/LinkLocal/AppleDNSSDService.h
+++ b/Swiften/LinkLocal/AppleDNSSDService.h
@@ -2,6 +2,8 @@
#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/EventLoop/EventOwner.h"
@@ -12,15 +14,27 @@ namespace Swift {
AppleDNSSDService();
~AppleDNSSDService();
- virtual void publishService(const std::map<String,String> properties);
+ virtual void registerService(const String& name, int port, const std::map<String,String>& properties);
+ virtual void unregisterService();
virtual void start();
virtual void stop();
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 *);
private:
boost::thread* thread;
bool stopRequested;
+ int interruptSelectReadSocket;
+ int interruptSelectWriteSocket;
+ boost::mutex sdRefsMutex;
+ DNSServiceRef browseSDRef;
+ DNSServiceRef registerSDRef;
};
}
diff --git a/Swiften/LinkLocal/DNSSDService.h b/Swiften/LinkLocal/DNSSDService.h
index 0899ffd..3437c58 100644
--- a/Swiften/LinkLocal/DNSSDService.h
+++ b/Swiften/LinkLocal/DNSSDService.h
@@ -8,7 +8,8 @@
namespace Swift {
class DNSSDService {
public:
- struct DiscoveredService {
+ struct Service {
+ Service(const String& name, const String& type, const String& domain, int networkInterface) : name(name), type(type), domain(domain), networkInterface(networkInterface) {}
String name;
String type;
String domain;
@@ -17,11 +18,13 @@ namespace Swift {
virtual ~DNSSDService();
- virtual void publishService(const std::map<String,String> properties) = 0;
+ virtual void registerService(const String& name, int port, const std::map<String,String>& properties) = 0;
+ virtual void unregisterService() = 0;
virtual void start() = 0;
- boost::signal<void (const DiscoveredService&)> onServiceAdded;
- boost::signal<void (const DiscoveredService&)> onServiceRemoved;
- boost::signal<void ()> onServiceRegistered;
+ boost::signal<void (const Service&)> onServiceAdded;
+ boost::signal<void (const Service&)> onServiceRemoved;
+ boost::signal<void (const Service&)> onServiceRegistered;
+ boost::signal<void ()> onError;
};
}
diff --git a/Swiften/LinkLocal/LinkLocalRoster.cpp b/Swiften/LinkLocal/LinkLocalRoster.cpp
index 6773d51..9f7e4ad 100644
--- a/Swiften/LinkLocal/LinkLocalRoster.cpp
+++ b/Swiften/LinkLocal/LinkLocalRoster.cpp
@@ -10,11 +10,11 @@ LinkLocalRoster::LinkLocalRoster(boost::shared_ptr<DNSSDService> service) : dnsS
service->onServiceRemoved.connect(boost::bind(&LinkLocalRoster::handleServiceRemoved, this, _1));
}
-void LinkLocalRoster::handleServiceAdded(const DNSSDService::DiscoveredService& service) {
+void LinkLocalRoster::handleServiceAdded(const DNSSDService::Service& service) {
std::cout << "Service added " << service.name << " " << service.type << " " << service.domain << std::endl;
}
-void LinkLocalRoster::handleServiceRemoved(const DNSSDService::DiscoveredService& service) {
+void LinkLocalRoster::handleServiceRemoved(const DNSSDService::Service& service) {
std::cout << "Service removed " << service.name << " " << service.type << " " << service.domain << std::endl;
}
diff --git a/Swiften/LinkLocal/LinkLocalRoster.h b/Swiften/LinkLocal/LinkLocalRoster.h
index 625bf8b..5b66b84 100644
--- a/Swiften/LinkLocal/LinkLocalRoster.h
+++ b/Swiften/LinkLocal/LinkLocalRoster.h
@@ -10,8 +10,8 @@ namespace Swift {
LinkLocalRoster(boost::shared_ptr<DNSSDService> service);
private:
- void handleServiceAdded(const DNSSDService::DiscoveredService&);
- void handleServiceRemoved(const DNSSDService::DiscoveredService&);
+ void handleServiceAdded(const DNSSDService::Service&);
+ void handleServiceRemoved(const DNSSDService::Service&);
private:
boost::shared_ptr<DNSSDService> dnsSDService;