From a5afa80ca54da1b72078b3e508de1d80cceb0c90 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Thu, 16 Jul 2009 18:46:22 +0200
Subject: Created Swiften/LinkLocal module.


diff --git a/Nim/main.cpp b/Nim/main.cpp
index 52755ae..2709bb1 100644
--- a/Nim/main.cpp
+++ b/Nim/main.cpp
@@ -1,85 +1,111 @@
-#include <dns_sd.h>
-#include <iostream>
-#include <sys/socket.h>
+#include <string>
+#include <boost/bind.hpp>
+#include <boost/shared_ptr.hpp>
 
-#include "Swiften/Network/HostAddress.h"
+#include "Swiften/Elements/IQ.h"
+#include "Swiften/Elements/RosterPayload.h"
+#include "Swiften/Elements/VCard.h"
+#include "Swiften/Server/UserRegistry.h"
+#include "Swiften/JID/JID.h"
+#include "Swiften/Base/String.h"
+#include "Swiften/Server/UserRegistry.h"
+#include "Swiften/Base/IDGenerator.h"
+#include "Swiften/EventLoop/MainEventLoop.h"
+#include "Swiften/EventLoop/SimpleEventLoop.h"
+#include "Swiften/EventLoop/EventOwner.h"
+#include "Swiften/Elements/Stanza.h"
+#include "Swiften/LinkLocal/LinkLocalRoster.h"
+#include "Swiften/LinkLocal/DNSSDService.h"
+#include "Swiften/LinkLocal/AppleDNSSDService.h"
+#include "Swiften/Network/ConnectionServer.h"
+#include "Swiften/Network/BoostConnection.h"
+#include "Swiften/Network/BoostIOServiceThread.h"
+#include "Swiften/Network/BoostConnectionServer.h"
+#include "Swiften/Server/ServerFromClientSession.h"
+#include "Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.h"
+#include "Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h"
 
 using namespace Swift;
 
-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;
-} 
+class DummyUserRegistry : public UserRegistry {
+	public:
+		DummyUserRegistry() {
+		}
 
-int main(int argc, char* argv[]) {
-	fd_set fdSet;
-	DNSServiceErrorType result;
+		virtual bool isValidUserPassword(const JID&, const String&) const {
+			return true;
+		}
+};
 
-	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);
+class Server {
+	public:
+		Server() {
+			serverFromClientConnectionServer_ = boost::shared_ptr<BoostConnectionServer>(new BoostConnectionServer(5224, &boostIOServiceThread_.getIOService()));
+			serverFromClientConnectionServer_->onNewConnection.connect(boost::bind(&Server::handleNewConnection, this, _1));
+			serverFromClientConnectionServer_->start();
 
-	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);
-		FD_SET(browseSocket, &fdSet);
-		select(browseSocket+1, &fdSet, &fdSet, &fdSet, 0);
-		DNSServiceProcessResult(browseSDRef);
-	//}
+			dnsSDService_ = boost::shared_ptr<AppleDNSSDService>(new AppleDNSSDService());
+			linkLocalRoster_ = boost::shared_ptr<LinkLocalRoster>(new LinkLocalRoster(dnsSDService_));
+			dnsSDService_->start();
+			// dnsSDService_->publish
+		}
 
+	private:
+		void handleNewConnection(boost::shared_ptr<Connection> c) {
+			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->onSessionFinished.connect(boost::bind(&Server::handleSessionFinished, this, session));
+		}
 
-	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 resolveSocket = DNSServiceRefSockFD(resolveSDRef);
-	//while(true) {
-		FD_ZERO(&fdSet);
-		FD_SET(resolveSocket, &fdSet);
-		select(resolveSocket+1, &fdSet, &fdSet, &fdSet, 0);
-		DNSServiceProcessResult(resolveSDRef);
-	//}
+		void handleSessionFinished(ServerFromClientSession* session) {
+			serverFromClientSessions_.erase(std::remove(serverFromClientSessions_.begin(), serverFromClientSessions_.end(), session), serverFromClientSessions_.end());
+			delete session;
+		}
 
+		void handleStanzaReceived(boost::shared_ptr<Stanza> stanza, ServerFromClientSession* session) {
+			stanza->setFrom(session->getJID());
+			if (!stanza->getTo().isValid()) {
+				stanza->setTo(JID(session->getDomain()));
+			}
+			if (!stanza->getTo().isValid() || stanza->getTo() == session->getDomain() || stanza->getTo() == session->getJID().toBare()) {
+				if (boost::shared_ptr<IQ> iq = boost::dynamic_pointer_cast<IQ>(stanza)) {
+					if (iq->getPayload<RosterPayload>()) {
+						session->sendStanza(IQ::createResult(iq->getFrom(), iq->getID(), boost::shared_ptr<RosterPayload>(new RosterPayload())));
+					}
+					if (iq->getPayload<VCard>()) {
+						if (iq->getType() == IQ::Get) {
+							boost::shared_ptr<VCard> vcard(new VCard());
+							vcard->setNickname(iq->getFrom().getNode());
+							session->sendStanza(IQ::createResult(iq->getFrom(), iq->getID(), vcard));
+						}
+						else {
+							session->sendStanza(IQ::createError(iq->getFrom(), iq->getID(), Error::Forbidden, Error::Cancel));
+						}
+					}
+					else {
+						session->sendStanza(IQ::createError(iq->getFrom(), iq->getID(), Error::FeatureNotImplemented, Error::Cancel));
+					}
+				}
+			}
+		}
 
-	DNSServiceRef addressSDRef;
-	result = DNSServiceGetAddrInfo(&addressSDRef, 0, 6, kDNSServiceProtocol_IPv4, "Micro.local.", handleAddressInfoReceived, 0);
-	if (result != kDNSServiceErr_NoError) {
-		std::cerr << "Error 4" << std::endl;
-	}
-	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);
-	//}
+	private:
+		IDGenerator idGenerator_;
+		BoostIOServiceThread boostIOServiceThread_;
+		DummyUserRegistry userRegistry_;
+		boost::shared_ptr<AppleDNSSDService> dnsSDService_;
+		boost::shared_ptr<LinkLocalRoster> linkLocalRoster_;
+		boost::shared_ptr<BoostConnectionServer> serverFromClientConnectionServer_;
+		std::vector<ServerFromClientSession*> serverFromClientSessions_;
+		FullPayloadParserFactoryCollection payloadParserFactories_;
+		FullPayloadSerializerCollection payloadSerializers_;
+};
 
-	// DNSServiceRefDeallocate
-	
+int main() {
+	SimpleEventLoop eventLoop;
+	Server server;
+	eventLoop.run();
 	return 0;
 }
diff --git a/Swiften/LinkLocal/AppleDNSSDService.cpp b/Swiften/LinkLocal/AppleDNSSDService.cpp
new file mode 100644
index 0000000..b68b09e
--- /dev/null
+++ b/Swiften/LinkLocal/AppleDNSSDService.cpp
@@ -0,0 +1,116 @@
+#include "Swiften/LinkLocal/AppleDNSSDService.h"
+
+#include <dns_sd.h>
+#include <iostream>
+#include <sys/socket.h>
+
+namespace Swift {
+
+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;
+	} 
+}
+
+
+AppleDNSSDService::AppleDNSSDService() : thread(0), stopRequested(false) {
+}
+
+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::stop() {
+	if (thread) {
+		stopRequested = true;
+		thread->join();
+		delete thread;
+		stopRequested = false;
+	}
+}
+
+void AppleDNSSDService::doStart() {
+	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);
+			FD_SET(browseSocket, &fdSet);
+			select(browseSocket+1, &fdSet, &fdSet, &fdSet, 0);
+			DNSServiceProcessResult(browseSDRef);
+		//}
+
+
+		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 resolveSocket = DNSServiceRefSockFD(resolveSDRef);
+		//while(true) {
+			FD_ZERO(&fdSet);
+			FD_SET(resolveSocket, &fdSet);
+			select(resolveSocket+1, &fdSet, &fdSet, &fdSet, 0);
+			DNSServiceProcessResult(resolveSDRef);
+		//}
+
+
+		DNSServiceRef addressSDRef;
+		result = DNSServiceGetAddrInfo(&addressSDRef, 0, 6, kDNSServiceProtocol_IPv4, "Micro.local.", handleAddressInfoReceived, 0);
+		if (result != kDNSServiceErr_NoError) {
+			std::cerr << "Error 4" << std::endl;
+		}
+		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);
+		//}
+
+		// DNSServiceRefDeallocate
+
+	}
+}
+
+}
diff --git a/Swiften/LinkLocal/AppleDNSSDService.h b/Swiften/LinkLocal/AppleDNSSDService.h
new file mode 100644
index 0000000..e6bedf7
--- /dev/null
+++ b/Swiften/LinkLocal/AppleDNSSDService.h
@@ -0,0 +1,26 @@
+#pragma once
+
+#include <boost/enable_shared_from_this.hpp>
+#include <boost/thread.hpp>
+
+#include "Swiften/LinkLocal/DNSSDService.h"
+#include "Swiften/EventLoop/EventOwner.h"
+
+namespace Swift {
+	class AppleDNSSDService : public DNSSDService, public EventOwner, public boost::enable_shared_from_this<AppleDNSSDService> {
+		public:
+			AppleDNSSDService();
+			~AppleDNSSDService();
+
+			virtual void publishService(const std::map<String,String> properties);
+			virtual void start();
+			virtual void stop();
+
+		private:
+			void doStart();
+
+		private:
+			boost::thread* thread;
+			bool stopRequested;
+	};
+}
diff --git a/Swiften/LinkLocal/DNSSDService.cpp b/Swiften/LinkLocal/DNSSDService.cpp
new file mode 100644
index 0000000..9545981
--- /dev/null
+++ b/Swiften/LinkLocal/DNSSDService.cpp
@@ -0,0 +1,8 @@
+#include "Swiften/LinkLocal/DNSSDService.h"
+
+namespace Swift {
+
+DNSSDService::~DNSSDService() {
+}
+
+}
diff --git a/Swiften/LinkLocal/DNSSDService.h b/Swiften/LinkLocal/DNSSDService.h
new file mode 100644
index 0000000..0899ffd
--- /dev/null
+++ b/Swiften/LinkLocal/DNSSDService.h
@@ -0,0 +1,27 @@
+#pragma once
+
+#include <boost/signal.hpp>
+#include <map>
+
+#include "Swiften/Base/String.h"
+
+namespace Swift {
+	class DNSSDService {
+		public:
+			struct DiscoveredService {
+				String name;
+				String type;
+				String domain;
+				int networkInterface;
+			};
+
+			virtual ~DNSSDService();
+
+			virtual void publishService(const std::map<String,String> properties) = 0;
+			virtual void start() = 0;
+
+			boost::signal<void (const DiscoveredService&)> onServiceAdded;
+			boost::signal<void (const DiscoveredService&)> onServiceRemoved;
+			boost::signal<void ()> onServiceRegistered;
+	};
+}
diff --git a/Swiften/LinkLocal/LinkLocalRoster.cpp b/Swiften/LinkLocal/LinkLocalRoster.cpp
new file mode 100644
index 0000000..6773d51
--- /dev/null
+++ b/Swiften/LinkLocal/LinkLocalRoster.cpp
@@ -0,0 +1,21 @@
+#include <boost/bind.hpp>
+#include <iostream>
+
+#include "Swiften/LinkLocal/LinkLocalRoster.h"
+
+namespace Swift {
+
+LinkLocalRoster::LinkLocalRoster(boost::shared_ptr<DNSSDService> service) : dnsSDService(service) {
+	service->onServiceAdded.connect(boost::bind(&LinkLocalRoster::handleServiceAdded, this, _1));
+	service->onServiceRemoved.connect(boost::bind(&LinkLocalRoster::handleServiceRemoved, this, _1));
+}
+
+void LinkLocalRoster::handleServiceAdded(const DNSSDService::DiscoveredService& service) {
+	std::cout << "Service added " << service.name << " " << service.type << " " << service.domain << std::endl;
+}
+
+void LinkLocalRoster::handleServiceRemoved(const DNSSDService::DiscoveredService& 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
new file mode 100644
index 0000000..625bf8b
--- /dev/null
+++ b/Swiften/LinkLocal/LinkLocalRoster.h
@@ -0,0 +1,19 @@
+#pragma once
+
+#include <boost/shared_ptr.hpp>
+
+#include "Swiften/LinkLocal/DNSSDService.h"
+
+namespace Swift {
+	class LinkLocalRoster {
+		public:
+			LinkLocalRoster(boost::shared_ptr<DNSSDService> service);
+
+		private:
+			void handleServiceAdded(const DNSSDService::DiscoveredService&);
+			void handleServiceRemoved(const DNSSDService::DiscoveredService&);
+
+		private:
+			boost::shared_ptr<DNSSDService> dnsSDService;
+	};
+}
diff --git a/Swiften/LinkLocal/Makefile.inc b/Swiften/LinkLocal/Makefile.inc
new file mode 100644
index 0000000..54315da
--- /dev/null
+++ b/Swiften/LinkLocal/Makefile.inc
@@ -0,0 +1,9 @@
+SWIFTEN_SOURCES += \
+	Swiften/LinkLocal/DNSSDService.cpp \
+	Swiften/LinkLocal/LinkLocalRoster.cpp
+
+
+ifeq ($(MACOSX),1)
+SWIFTEN_SOURCES += \
+	Swiften/LinkLocal/AppleDNSSDService.cpp
+endif
diff --git a/Swiften/Makefile.inc b/Swiften/Makefile.inc
index 6e47259..6fa2df8 100644
--- a/Swiften/Makefile.inc
+++ b/Swiften/Makefile.inc
@@ -22,6 +22,7 @@ include Swiften/Notifier/Makefile.inc
 include Swiften/History/Makefile.inc
 include Swiften/Avatars/Makefile.inc
 include Swiften/Server/Makefile.inc
+include Swiften/LinkLocal/Makefile.inc
 
 CPPFLAGS += $(SQLITE_CPPFLAGS)
 
-- 
cgit v0.10.2-6-g49f6