diff options
| -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; | 
 Swift
 Swift