diff options
author | Remko Tronçon <git@el-tramo.be> | 2009-07-16 20:06:28 (GMT) |
---|---|---|
committer | Remko Tronçon <git@el-tramo.be> | 2009-07-16 20:06:28 (GMT) |
commit | 2c954f7e9464b8fdd970eed829e2ba632e8979d8 (patch) | |
tree | 2e15a454cb395e77bd4af858311fdc046d0cc2bd | |
parent | a5afa80ca54da1b72078b3e508de1d80cceb0c90 (diff) | |
download | swift-contrib-2c954f7e9464b8fdd970eed829e2ba632e8979d8.zip swift-contrib-2c954f7e9464b8fdd970eed829e2ba632e8979d8.tar.bz2 |
Implemented AppleDNSSDService registration & browsing.
-rw-r--r-- | Nim/main.cpp | 27 | ||||
-rw-r--r-- | Swiften/LinkLocal/AppleDNSSDService.cpp | 184 | ||||
-rw-r--r-- | Swiften/LinkLocal/AppleDNSSDService.h | 16 | ||||
-rw-r--r-- | Swiften/LinkLocal/DNSSDService.h | 13 | ||||
-rw-r--r-- | Swiften/LinkLocal/LinkLocalRoster.cpp | 4 | ||||
-rw-r--r-- | Swiften/LinkLocal/LinkLocalRoster.h | 4 | ||||
-rw-r--r-- | Swiften/Server/ServerFromClientSession.cpp | 1 | ||||
-rw-r--r-- | Swiften/Server/ServerFromClientSession.h | 1 |
8 files changed, 174 insertions, 76 deletions
diff --git a/Nim/main.cpp b/Nim/main.cpp index 2709bb1..607cc80 100644 --- a/Nim/main.cpp +++ b/Nim/main.cpp @@ -40,15 +40,14 @@ class DummyUserRegistry : public UserRegistry { class Server { public: - Server() { - serverFromClientConnectionServer_ = boost::shared_ptr<BoostConnectionServer>(new BoostConnectionServer(5224, &boostIOServiceThread_.getIOService())); + Server(int clientConnectionPort, int linkLocalConnectionPort) : dnsSDServiceRegistered_(false), clientConnectionPort_(clientConnectionPort), linkLocalConnectionPort_(linkLocalConnectionPort) { + serverFromClientConnectionServer_ = boost::shared_ptr<BoostConnectionServer>(new BoostConnectionServer(clientConnectionPort, &boostIOServiceThread_.getIOService())); serverFromClientConnectionServer_->onNewConnection.connect(boost::bind(&Server::handleNewConnection, this, _1)); serverFromClientConnectionServer_->start(); dnsSDService_ = boost::shared_ptr<AppleDNSSDService>(new AppleDNSSDService()); linkLocalRoster_ = boost::shared_ptr<LinkLocalRoster>(new LinkLocalRoster(dnsSDService_)); dnsSDService_->start(); - // dnsSDService_->publish } private: @@ -56,12 +55,29 @@ class Server { ServerFromClientSession* session = new ServerFromClientSession(idGenerator_.generateID(), c, &payloadParserFactories_, &payloadSerializers_, &userRegistry_); serverFromClientSessions_.push_back(session); session->onStanzaReceived.connect(boost::bind(&Server::handleStanzaReceived, this, _1, session)); + session->onSessionStarted.connect(boost::bind(&Server::handleSessionStarted, this, session)); session->onSessionFinished.connect(boost::bind(&Server::handleSessionFinished, this, session)); } + + void handleSessionStarted(ServerFromClientSession* session) { + if (!dnsSDServiceRegistered_) { + dnsSDServiceRegistered_ = true; + dnsSDService_->onServiceRegistered.connect(boost::bind(&Server::handleServiceRegistered, this, _1)); + dnsSDService_->registerService(session->getJID().toBare().toString(), linkLocalConnectionPort_, std::map<String,String>()); + } + } + + void handleServiceRegistered(const DNSSDService::Service& service) { + std::cout << "Service registered " << service.name << " " << service.type << " " << service.domain << std::endl; + } void handleSessionFinished(ServerFromClientSession* session) { serverFromClientSessions_.erase(std::remove(serverFromClientSessions_.begin(), serverFromClientSessions_.end(), session), serverFromClientSessions_.end()); delete session; + if (serverFromClientSessions_.empty()) { + dnsSDServiceRegistered_ = false; + dnsSDService_->unregisterService(); + } } void handleStanzaReceived(boost::shared_ptr<Stanza> stanza, ServerFromClientSession* session) { @@ -101,11 +117,14 @@ class Server { std::vector<ServerFromClientSession*> serverFromClientSessions_; FullPayloadParserFactoryCollection payloadParserFactories_; FullPayloadSerializerCollection payloadSerializers_; + bool dnsSDServiceRegistered_; + int clientConnectionPort_; + int linkLocalConnectionPort_; }; int main() { SimpleEventLoop eventLoop; - Server server; + Server server(5222, 5562); eventLoop.run(); return 0; } 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(®isterSDRef, 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(®isterSDRef, 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; diff --git a/Swiften/Server/ServerFromClientSession.cpp b/Swiften/Server/ServerFromClientSession.cpp index 67067c5..fe4388e 100644 --- a/Swiften/Server/ServerFromClientSession.cpp +++ b/Swiften/Server/ServerFromClientSession.cpp @@ -89,6 +89,7 @@ void ServerFromClientSession::handleElement(boost::shared_ptr<Element> element) else if (iq->getPayload<StartSession>()) { initialized_ = true; xmppLayer_->writeElement(IQ::createResult(jid_, iq->getID())); + onSessionStarted(); } } } diff --git a/Swiften/Server/ServerFromClientSession.h b/Swiften/Server/ServerFromClientSession.h index 62e89ef..0110d5d 100644 --- a/Swiften/Server/ServerFromClientSession.h +++ b/Swiften/Server/ServerFromClientSession.h @@ -40,6 +40,7 @@ namespace Swift { boost::signal<void (boost::shared_ptr<Stanza>)> onStanzaReceived; boost::signal<void ()> onSessionFinished; + boost::signal<void ()> onSessionStarted; boost::signal<void (const ByteArray&)> onDataWritten; boost::signal<void (const ByteArray&)> onDataRead; |