diff options
22 files changed, 551 insertions, 151 deletions
| diff --git a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourBrowseQuery.h b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourBrowseQuery.h index 62d8606..8e3181e 100644 --- a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourBrowseQuery.h +++ b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourBrowseQuery.h @@ -14,14 +14,17 @@ namespace Swift {  						&sdRef, 0, 0, "_presence._tcp", 0,   						&BonjourBrowseQuery::handleServiceDiscoveredStatic, this);  				if (result != kDNSServiceErr_NoError) { -					std::cout << "Error" << std::endl; -					// TODO +					sdRef = NULL;  				}  			}  			void startBrowsing() { -				assert(sdRef); -				run(); +				if (!sdRef) { +					MainEventLoop::postEvent(boost::bind(boost::ref(onError)), shared_from_this()); +				} +				else { +					run(); +				}  			}  			void stopBrowsing() { @@ -35,7 +38,7 @@ namespace Swift {  			void handleServiceDiscovered(DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *name, const char *type, const char *domain) {  				if (errorCode != kDNSServiceErr_NoError) { -					return; +					MainEventLoop::postEvent(boost::bind(boost::ref(onError)), shared_from_this());  				}  				else {  					DNSSDServiceID service(name, type, domain, interfaceIndex); diff --git a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuerier.cpp b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuerier.cpp index c065d4d..70fbc7c 100644 --- a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuerier.cpp +++ b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourQuerier.cpp @@ -22,7 +22,7 @@ BonjourQuerier::BonjourQuerier() : stopRequested(false), thread(0) {  }  BonjourQuerier::~BonjourQuerier() { -	stop(); +	assert(!thread);  }  boost::shared_ptr<DNSSDBrowseQuery> BonjourQuerier::createBrowseQuery() { @@ -64,18 +64,19 @@ void BonjourQuerier::interruptSelect() {  }  void BonjourQuerier::start() { -	stop(); +	assert(!thread);  	thread = new boost::thread(boost::bind(&BonjourQuerier::run, shared_from_this()));  }  void BonjourQuerier::stop() {  	if (thread) {  		stopRequested = true; -		runningQueries.clear(); // TODO: Is this the right thing to do? +		assert(runningQueries.empty());  		runningQueriesAvailableEvent.notify_one();  		interruptSelect();  		thread->join();  		delete thread; +		thread = NULL;  		stopRequested = false;  	}  } diff --git a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourRegisterQuery.h b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourRegisterQuery.h index 9c4db13..41e5831 100644 --- a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourRegisterQuery.h +++ b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourRegisterQuery.h @@ -18,13 +18,21 @@ namespace Swift {  						txtRecord.getSize(), txtRecord.getData(),   						&BonjourRegisterQuery::handleServiceRegisteredStatic, this);  				if (result != kDNSServiceErr_NoError) { -					// TODO -					std::cerr << "Error creating service registration" << std::endl; +					sdRef = NULL;  				}  			}  			void registerService() { -				run(); +				if (sdRef) { +					run(); +				} +				else { +					MainEventLoop::postEvent(boost::bind(boost::ref(onRegisterFinished), boost::optional<DNSSDServiceID>()), shared_from_this()); +				} +			} + +			void unregisterService() { +				stop();  			}  			void updateServiceInfo(const LinkLocalServiceInfo& info) { diff --git a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourResolveHostnameQuery.h b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourResolveHostnameQuery.h index 58c6588..6e2a852 100644 --- a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourResolveHostnameQuery.h +++ b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourResolveHostnameQuery.h @@ -19,13 +19,18 @@ namespace Swift {  						hostname.getUTF8Data(),   						&BonjourResolveHostnameQuery::handleHostnameResolvedStatic, this);  				if (result != kDNSServiceErr_NoError) { -					MainEventLoop::postEvent(boost::bind(boost::ref(onHostnameResolved), boost::optional<HostAddress>()), shared_from_this()); +					sdRef = NULL;  				}  			}  			//void DNSSDResolveHostnameQuery::run() {  			void run() { -				BonjourQuery::run(); +				if (sdRef) { +					BonjourQuery::run(); +				} +				else { +					MainEventLoop::postEvent(boost::bind(boost::ref(onHostnameResolved), boost::optional<HostAddress>()), shared_from_this()); +				}  			}  		private: diff --git a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourResolveServiceQuery.h b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourResolveServiceQuery.h index 1ebd487..8b3f7ec 100644 --- a/Swiften/LinkLocal/DNSSD/Bonjour/BonjourResolveServiceQuery.h +++ b/Swiften/LinkLocal/DNSSD/Bonjour/BonjourResolveServiceQuery.h @@ -18,12 +18,17 @@ namespace Swift {  						service.getDomain().getUTF8Data(),   						&BonjourResolveServiceQuery::handleServiceResolvedStatic, this);  				if (result != kDNSServiceErr_NoError) { -					MainEventLoop::postEvent(boost::bind(boost::ref(onServiceResolved), boost::optional<Result>()), shared_from_this()); +					sdRef = NULL;  				}  			}  			void start() { -				run(); +				if (sdRef) { +					run(); +				} +				else { +					MainEventLoop::postEvent(boost::bind(boost::ref(onServiceResolved), boost::optional<Result>()), shared_from_this()); +				}  			}  			void stop() { diff --git a/Swiften/LinkLocal/DNSSD/DNSSDBrowseQuery.h b/Swiften/LinkLocal/DNSSD/DNSSDBrowseQuery.h index 86967ed..9b30858 100644 --- a/Swiften/LinkLocal/DNSSD/DNSSDBrowseQuery.h +++ b/Swiften/LinkLocal/DNSSD/DNSSDBrowseQuery.h @@ -14,5 +14,6 @@ namespace Swift {  			boost::signal<void (const DNSSDServiceID&)> onServiceAdded;  			boost::signal<void (const DNSSDServiceID&)> onServiceRemoved; +			boost::signal<void ()> onError;  	};  } diff --git a/Swiften/LinkLocal/DNSSD/DNSSDRegisterQuery.h b/Swiften/LinkLocal/DNSSD/DNSSDRegisterQuery.h index a643880..627cc6b 100644 --- a/Swiften/LinkLocal/DNSSD/DNSSDRegisterQuery.h +++ b/Swiften/LinkLocal/DNSSD/DNSSDRegisterQuery.h @@ -13,6 +13,7 @@ namespace Swift {  			virtual ~DNSSDRegisterQuery();  			virtual void registerService() = 0; +			virtual void unregisterService() = 0;  			virtual void updateServiceInfo(const LinkLocalServiceInfo& info) = 0;  			boost::signal<void (boost::optional<DNSSDServiceID>)> onRegisterFinished; diff --git a/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDBrowseQuery.h b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDBrowseQuery.h new file mode 100644 index 0000000..5a0b93b --- /dev/null +++ b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDBrowseQuery.h @@ -0,0 +1,22 @@ +#pragma once + +#include "Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuery.h" +#include "Swiften/LinkLocal/DNSSD/DNSSDBrowseQuery.h" + +namespace Swift { +	class FakeDNSSDQuerier; + +	class FakeDNSSDBrowseQuery : public DNSSDBrowseQuery, public FakeDNSSDQuery { +		public:	 +			FakeDNSSDBrowseQuery(boost::shared_ptr<FakeDNSSDQuerier> querier) : FakeDNSSDQuery(querier) { +			} + +			void startBrowsing() { +				run(); +			} + +			void stopBrowsing() { +				finish(); +			} +	}; +} diff --git a/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.cpp b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.cpp new file mode 100644 index 0000000..222500a --- /dev/null +++ b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.cpp @@ -0,0 +1,92 @@ +#include "Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.h" + +#include <boost/bind.hpp> + +#include "Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDBrowseQuery.h" +#include "Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDRegisterQuery.h" +#include "Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDResolveServiceQuery.h" +#include "Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDResolveHostnameQuery.h" +#include "Swiften/EventLoop/MainEventLoop.h" + +namespace Swift { + +FakeDNSSDQuerier::FakeDNSSDQuerier() { +} + +boost::shared_ptr<DNSSDBrowseQuery> FakeDNSSDQuerier::createBrowseQuery() { +	return boost::shared_ptr<DNSSDBrowseQuery>(new FakeDNSSDBrowseQuery(shared_from_this())); +} + +boost::shared_ptr<DNSSDRegisterQuery> FakeDNSSDQuerier::createRegisterQuery(const String& name, int port, const LinkLocalServiceInfo& info) { +	return boost::shared_ptr<DNSSDRegisterQuery>(new FakeDNSSDRegisterQuery(name, port, info, shared_from_this())); +} + +boost::shared_ptr<DNSSDResolveServiceQuery> FakeDNSSDQuerier::createResolveServiceQuery(const DNSSDServiceID& service) { +	return boost::shared_ptr<DNSSDResolveServiceQuery>(new FakeDNSSDResolveServiceQuery(service, shared_from_this())); +} + +boost::shared_ptr<DNSSDResolveHostnameQuery> FakeDNSSDQuerier::createResolveHostnameQuery(const String& hostname, int interfaceIndex) { +	return boost::shared_ptr<DNSSDResolveHostnameQuery>(new FakeDNSSDResolveHostnameQuery(hostname, interfaceIndex, shared_from_this())); +} + +void FakeDNSSDQuerier::addRunningQuery(boost::shared_ptr<FakeDNSSDQuery> query) { +	runningQueries.push_back(query); +	if (boost::shared_ptr<FakeDNSSDBrowseQuery> browseQuery = boost::dynamic_pointer_cast<FakeDNSSDBrowseQuery>(query)) { +		foreach(const DNSSDServiceID& service, services) { +			MainEventLoop::postEvent(boost::bind(boost::ref(browseQuery->onServiceAdded), service), shared_from_this()); +		} +	} +	else if (boost::shared_ptr<FakeDNSSDResolveServiceQuery> resolveQuery = boost::dynamic_pointer_cast<FakeDNSSDResolveServiceQuery>(query)) { +		for(ServiceInfoMap::const_iterator i = serviceInfo.begin(); i != serviceInfo.end(); ++i) { +			if (i->first == resolveQuery->service) { +				MainEventLoop::postEvent(boost::bind(boost::ref(resolveQuery->onServiceResolved), i->second), shared_from_this()); +			} +		} +	} +} + +void FakeDNSSDQuerier::removeRunningQuery(boost::shared_ptr<FakeDNSSDQuery> query) { +	runningQueries.erase(std::remove( +		runningQueries.begin(), runningQueries.end(), query), runningQueries.end()); +} + +void FakeDNSSDQuerier::addService(const DNSSDServiceID& id) { +	services.insert(id); +	foreach(const boost::shared_ptr<FakeDNSSDBrowseQuery>& query, getQueries<FakeDNSSDBrowseQuery>()) { +		MainEventLoop::postEvent(boost::bind(boost::ref(query->onServiceAdded), id), shared_from_this()); +	} +} + +void FakeDNSSDQuerier::removeService(const DNSSDServiceID& id) { +	services.erase(id); +	serviceInfo.erase(id); +	foreach(const boost::shared_ptr<FakeDNSSDBrowseQuery>& query, getQueries<FakeDNSSDBrowseQuery>()) { +		MainEventLoop::postEvent(boost::bind(boost::ref(query->onServiceRemoved), id), shared_from_this()); +	} +} + +void FakeDNSSDQuerier::setServiceInfo(const DNSSDServiceID& id, const DNSSDResolveServiceQuery::Result& info) { +	std::pair<ServiceInfoMap::iterator, bool> r = serviceInfo.insert(std::make_pair(id, info)); +	if (!r.second) { +		r.first->second = info; +	} +	foreach(const boost::shared_ptr<FakeDNSSDResolveServiceQuery>& query, getQueries<FakeDNSSDResolveServiceQuery>()) { +		if (query->service == id) { +			MainEventLoop::postEvent(boost::bind(boost::ref(query->onServiceResolved), info), shared_from_this()); +		} +	} +} + +void FakeDNSSDQuerier::setBrowseError() { +	foreach(const boost::shared_ptr<FakeDNSSDBrowseQuery>& query, getQueries<FakeDNSSDBrowseQuery>()) { +		MainEventLoop::postEvent(boost::ref(query->onError), shared_from_this()); +	} +} + +void FakeDNSSDQuerier::setRegisterError() { +	foreach(const boost::shared_ptr<FakeDNSSDRegisterQuery>& query, getQueries<FakeDNSSDRegisterQuery>()) { +		MainEventLoop::postEvent(boost::bind(boost::ref(query->onRegisterFinished), boost::optional<DNSSDServiceID>()), shared_from_this()); +	} +} + +} diff --git a/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.h b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.h new file mode 100644 index 0000000..6c5f343 --- /dev/null +++ b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.h @@ -0,0 +1,61 @@ +#pragma once + +#include <boost/shared_ptr.hpp> +#include <boost/enable_shared_from_this.hpp> +#include <list> +#include <set> + +#include "Swiften/Base/foreach.h" +#include "Swiften/EventLoop/EventOwner.h" +#include "Swiften/LinkLocal/DNSSD/DNSSDQuerier.h" +#include "Swiften/LinkLocal/DNSSD/DNSSDResolveServiceQuery.h" + +namespace Swift { +	class LinkLocalServiceInfo; +	class FakeDNSSDQuery; +	class FakeDNSSDBrowseQuery; + +	class FakeDNSSDQuerier :  +			public DNSSDQuerier,  +			public EventOwner, +			public boost::enable_shared_from_this<FakeDNSSDQuerier> { +		public: +			FakeDNSSDQuerier(); + +			boost::shared_ptr<DNSSDBrowseQuery> createBrowseQuery(); +			boost::shared_ptr<DNSSDRegisterQuery> createRegisterQuery( +					const String& name, int port, const LinkLocalServiceInfo& info); +			boost::shared_ptr<DNSSDResolveServiceQuery> createResolveServiceQuery( +					const DNSSDServiceID&); +			boost::shared_ptr<DNSSDResolveHostnameQuery> createResolveHostnameQuery( +					const String& hostname, int interfaceIndex); + +			void addRunningQuery(boost::shared_ptr<FakeDNSSDQuery>); +			void removeRunningQuery(boost::shared_ptr<FakeDNSSDQuery>); + +			void addService(const DNSSDServiceID& id); +			void removeService(const DNSSDServiceID& id); +			void setServiceInfo(const DNSSDServiceID& id, const DNSSDResolveServiceQuery::Result& info); + +			void setBrowseError(); +			void setRegisterError(); + +		private: +			template<typename T> +			std::vector< boost::shared_ptr<T> > getQueries() const { +				std::vector< boost::shared_ptr<T> > result; +				foreach(const boost::shared_ptr<FakeDNSSDQuery>& query, runningQueries) { +					if (boost::shared_ptr<T> resultQuery = boost::dynamic_pointer_cast<T>(query)) { +						result.push_back(resultQuery); +					} +				} +				return result; +			} + +		private: +			std::list< boost::shared_ptr<FakeDNSSDQuery> > runningQueries; +			std::set<DNSSDServiceID> services; +			typedef std::map<DNSSDServiceID,DNSSDResolveServiceQuery::Result> ServiceInfoMap; +			ServiceInfoMap serviceInfo; +	}; +} diff --git a/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuery.cpp b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuery.cpp new file mode 100644 index 0000000..ced7850 --- /dev/null +++ b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuery.cpp @@ -0,0 +1,20 @@ +#include "Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuery.h" +#include "Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.h" + +namespace Swift { + +FakeDNSSDQuery::FakeDNSSDQuery(boost::shared_ptr<FakeDNSSDQuerier> querier) : querier(querier) { +} + +FakeDNSSDQuery::~FakeDNSSDQuery() { +} + +void FakeDNSSDQuery::run() { +	querier->addRunningQuery(shared_from_this()); +} + +void FakeDNSSDQuery::finish() { +	querier->removeRunningQuery(shared_from_this()); +} + +} diff --git a/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuery.h b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuery.h new file mode 100644 index 0000000..9fca1d4 --- /dev/null +++ b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuery.h @@ -0,0 +1,25 @@ +#pragma once + +#include <boost/shared_ptr.hpp> +#include <boost/enable_shared_from_this.hpp> + +#include "Swiften/EventLoop/EventOwner.h" + +namespace Swift { +	class FakeDNSSDQuerier; + +	class FakeDNSSDQuery :  +			public EventOwner, +			public boost::enable_shared_from_this<FakeDNSSDQuery> { +		public: +			FakeDNSSDQuery(boost::shared_ptr<FakeDNSSDQuerier>); +			virtual ~FakeDNSSDQuery(); +			 +		protected: +			void run(); +			void finish(); +		 +		protected: +			boost::shared_ptr<FakeDNSSDQuerier> querier; +	}; +} diff --git a/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDRegisterQuery.h b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDRegisterQuery.h new file mode 100644 index 0000000..b4646fd --- /dev/null +++ b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDRegisterQuery.h @@ -0,0 +1,31 @@ +#pragma once + +#include "Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuery.h" +#include "Swiften/LinkLocal/DNSSD/DNSSDRegisterQuery.h" +#include "Swiften/LinkLocal/LinkLocalServiceInfo.h" +#include "Swiften/Base/String.h" + +namespace Swift { +	class FakeDNSSDQuerier; + +	class FakeDNSSDRegisterQuery : public DNSSDRegisterQuery, public FakeDNSSDQuery { +		public:	 +			FakeDNSSDRegisterQuery(const String& name, int port, const LinkLocalServiceInfo& info, boost::shared_ptr<FakeDNSSDQuerier> querier) : FakeDNSSDQuery(querier), name(name), port(port), info(info) { +			} + +			void registerService() { +				run(); +			} + +			void updateServiceInfo(const LinkLocalServiceInfo&) { +			} + +			void unregisterService() { +				finish(); +			} + +			String name; +			int port; +			LinkLocalServiceInfo info; +	}; +} diff --git a/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDResolveHostnameQuery.h b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDResolveHostnameQuery.h new file mode 100644 index 0000000..2ff84d3 --- /dev/null +++ b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDResolveHostnameQuery.h @@ -0,0 +1,25 @@ +#pragma once + +#include "Swiften/Base/String.h" +#include "Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuery.h" +#include "Swiften/LinkLocal/DNSSD/DNSSDResolveHostnameQuery.h" +#include "Swiften/Network/HostAddress.h" + +#include <netinet/in.h> + +namespace Swift { +	class FakeDNSSDQuerier; + +	class FakeDNSSDResolveHostnameQuery : public DNSSDResolveHostnameQuery, public FakeDNSSDQuery { +		public:	 +			FakeDNSSDResolveHostnameQuery(const String& hostname, int interfaceIndex, boost::shared_ptr<FakeDNSSDQuerier> querier) : FakeDNSSDQuery(querier), hostname(hostname), interfaceIndex(interfaceIndex) { +			} + +			void run() { +				FakeDNSSDQuery::run(); +			} + +			String hostname; +			int interfaceIndex; +	}; +} diff --git a/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDResolveServiceQuery.h b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDResolveServiceQuery.h new file mode 100644 index 0000000..60d35e5 --- /dev/null +++ b/Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDResolveServiceQuery.h @@ -0,0 +1,25 @@ +#pragma once + +#include "Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuery.h" +#include "Swiften/LinkLocal/DNSSD/DNSSDResolveServiceQuery.h" +#include "Swiften/LinkLocal/LinkLocalServiceInfo.h" + +namespace Swift { +	class FakeDNSSDQuerier; + +	class FakeDNSSDResolveServiceQuery : public DNSSDResolveServiceQuery, public FakeDNSSDQuery { +		public:	 +			FakeDNSSDResolveServiceQuery(const DNSSDServiceID& service, boost::shared_ptr<FakeDNSSDQuerier> querier) : FakeDNSSDQuery(querier), service(service) { +			} + +			void start() { +				run(); +			} + +			void stop() { +				finish(); +			} + +			DNSSDServiceID service; +	}; +} diff --git a/Swiften/LinkLocal/DNSSD/Fake/Makefile.inc b/Swiften/LinkLocal/DNSSD/Fake/Makefile.inc new file mode 100644 index 0000000..316d061 --- /dev/null +++ b/Swiften/LinkLocal/DNSSD/Fake/Makefile.inc @@ -0,0 +1,3 @@ +SWIFTEN_SOURCES += \ +	Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuery.cpp \ +	Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.cpp diff --git a/Swiften/LinkLocal/DNSSD/Makefile.inc b/Swiften/LinkLocal/DNSSD/Makefile.inc index 8612fee..3d2c969 100644 --- a/Swiften/LinkLocal/DNSSD/Makefile.inc +++ b/Swiften/LinkLocal/DNSSD/Makefile.inc @@ -11,3 +11,5 @@ include Swiften/LinkLocal/DNSSD/Bonjour/Makefile.inc  endif  ifeq ($(HAVE_AVAHI),yes)  endif + +include Swiften/LinkLocal/DNSSD/Fake/Makefile.inc diff --git a/Swiften/LinkLocal/LinkLocalServiceBrowser.cpp b/Swiften/LinkLocal/LinkLocalServiceBrowser.cpp index 4e9c2de..aed917a 100644 --- a/Swiften/LinkLocal/LinkLocalServiceBrowser.cpp +++ b/Swiften/LinkLocal/LinkLocalServiceBrowser.cpp @@ -7,17 +7,66 @@  namespace Swift { -LinkLocalServiceBrowser::LinkLocalServiceBrowser(boost::shared_ptr<DNSSDQuerier> querier) : querier(querier) { +LinkLocalServiceBrowser::LinkLocalServiceBrowser(boost::shared_ptr<DNSSDQuerier> querier) : querier(querier), haveError(false) { +} + +LinkLocalServiceBrowser::~LinkLocalServiceBrowser() { +	assert(!isRunning()); +} + + +void LinkLocalServiceBrowser::start() { +	assert(!isRunning()); +	haveError = false;  	browseQuery = querier->createBrowseQuery();  	browseQuery->onServiceAdded.connect(  			boost::bind(&LinkLocalServiceBrowser::handleServiceAdded, this, _1));  	browseQuery->onServiceRemoved.connect(  			boost::bind(&LinkLocalServiceBrowser::handleServiceRemoved, this, _1)); +	browseQuery->onError.connect( +			boost::bind(&LinkLocalServiceBrowser::handleBrowseError, this));  	browseQuery->startBrowsing();  } -LinkLocalServiceBrowser::~LinkLocalServiceBrowser() { +void LinkLocalServiceBrowser::stop() { +	assert(isRunning()); +	if (isRegistered()) { +		unregisterService(); +	} +	for (ResolveQueryMap::const_iterator i = resolveQueries.begin(); i != resolveQueries.end(); ++i) { +		i->second->stop(); +	} +	resolveQueries.clear(); +	services.clear();  	browseQuery->stopBrowsing(); +	browseQuery.reset(); +	onStopped(haveError); +} + +bool LinkLocalServiceBrowser::isRunning() const { +	return browseQuery; +} + +bool LinkLocalServiceBrowser::hasError() const { +	return haveError; +} + +bool LinkLocalServiceBrowser::isRegistered() const { +	return registerQuery; +} + +void LinkLocalServiceBrowser::registerService(const String& name, int port, const LinkLocalServiceInfo& info) { +	assert(!registerQuery); +	registerQuery = querier->createRegisterQuery(name, port, info); +	registerQuery->onRegisterFinished.connect( +		boost::bind(&LinkLocalServiceBrowser::handleRegisterFinished, this, _1)); +	registerQuery->registerService(); +} + +void LinkLocalServiceBrowser::unregisterService() { +	assert(registerQuery); +	registerQuery->unregisterService(); +	registerQuery.reset();  }  std::vector<LinkLocalService> LinkLocalServiceBrowser::getServices() const { @@ -44,6 +93,7 @@ void LinkLocalServiceBrowser::handleServiceRemoved(const DNSSDServiceID& service  	assert(i != resolveQueries.end());  	i->second->stop();  	resolveQueries.erase(i); +	services.erase(service);  	onServiceRemoved(service);  } @@ -60,4 +110,16 @@ void LinkLocalServiceBrowser::handleServiceResolved(const DNSSDServiceID& servic  	}  } +void LinkLocalServiceBrowser::handleRegisterFinished(const boost::optional<DNSSDServiceID>& result) { +	if (!result) { +		haveError = true; +		stop(); +	} +} + +void LinkLocalServiceBrowser::handleBrowseError() { +	haveError = true; +	stop(); +} +  } diff --git a/Swiften/LinkLocal/LinkLocalServiceBrowser.h b/Swiften/LinkLocal/LinkLocalServiceBrowser.h index 7ec796a..33c9858 100644 --- a/Swiften/LinkLocal/LinkLocalServiceBrowser.h +++ b/Swiften/LinkLocal/LinkLocalServiceBrowser.h @@ -9,8 +9,10 @@  #include "Swiften/Base/String.h"  #include "Swiften/LinkLocal/DNSSD/DNSSDQuerier.h"  #include "Swiften/LinkLocal/DNSSD/DNSSDResolveServiceQuery.h" +#include "Swiften/LinkLocal/DNSSD/DNSSDRegisterQuery.h"  #include "Swiften/LinkLocal/DNSSD/DNSSDServiceID.h"  #include "Swiften/LinkLocal/LinkLocalService.h" +#include "Swiften/LinkLocal/LinkLocalServiceInfo.h"  namespace Swift {  	class LinkLocalServiceBrowser { @@ -18,23 +20,37 @@ namespace Swift {  			LinkLocalServiceBrowser(boost::shared_ptr<DNSSDQuerier> querier);  			~LinkLocalServiceBrowser(); +			void start(); +			void stop(); +			bool isRunning() const; +			bool hasError() const; + +			void registerService(const String& name, int port, const LinkLocalServiceInfo& info = LinkLocalServiceInfo()); +			void unregisterService(); +			bool isRegistered() const; +  			std::vector<LinkLocalService> getServices() const;  			boost::signal<void (const DNSSDServiceID&)> onServiceAdded;  			boost::signal<void (const DNSSDServiceID&)> onServiceChanged;  			boost::signal<void (const DNSSDServiceID&)> onServiceRemoved; +			boost::signal<void (bool)> onStopped;  		private:  			void handleServiceAdded(const DNSSDServiceID&);  			void handleServiceRemoved(const DNSSDServiceID&);  			void handleServiceResolved(const DNSSDServiceID& service, const boost::optional<DNSSDResolveServiceQuery::Result>& result); +			void handleRegisterFinished(const boost::optional<DNSSDServiceID>&); +			void handleBrowseError();  		private:  			boost::shared_ptr<DNSSDQuerier> querier;  			boost::shared_ptr<DNSSDBrowseQuery> browseQuery; +			boost::shared_ptr<DNSSDRegisterQuery> registerQuery;  			typedef std::map<DNSSDServiceID, boost::shared_ptr<DNSSDResolveServiceQuery> > ResolveQueryMap;  			ResolveQueryMap resolveQueries;  			typedef std::map<DNSSDServiceID, DNSSDResolveServiceQuery::Result> ServiceMap;  			ServiceMap services; +			bool haveError;  	};  } diff --git a/Swiften/LinkLocal/UnitTest/LinkLocalServiceBrowserTest.cpp b/Swiften/LinkLocal/UnitTest/LinkLocalServiceBrowserTest.cpp index 34f797c..7e2dd26 100644 --- a/Swiften/LinkLocal/UnitTest/LinkLocalServiceBrowserTest.cpp +++ b/Swiften/LinkLocal/UnitTest/LinkLocalServiceBrowserTest.cpp @@ -5,20 +5,26 @@  #include "Swiften/LinkLocal/LinkLocalServiceBrowser.h"  #include "Swiften/LinkLocal/LinkLocalService.h" -#include "Swiften/LinkLocal/UnitTest/MockDNSSDService.h" -#include "Swiften/LinkLocal/DNSSDService.h" +#include "Swiften/LinkLocal/DNSSD/DNSSDServiceID.h" +#include "Swiften/LinkLocal/DNSSD/DNSSDResolveServiceQuery.h" +#include "Swiften/LinkLocal/DNSSD/Fake/FakeDNSSDQuerier.h"  #include "Swiften/EventLoop/DummyEventLoop.h" -// Test canCreate() == false -  using namespace Swift;  class LinkLocalServiceBrowserTest : public CppUnit::TestFixture {  		CPPUNIT_TEST_SUITE(LinkLocalServiceBrowserTest); +		CPPUNIT_TEST(testConstructor); +		CPPUNIT_TEST(testStart);  		CPPUNIT_TEST(testServiceAdded);  		CPPUNIT_TEST(testServiceAdded_NoServiceInfo);  		CPPUNIT_TEST(testServiceChanged);  		CPPUNIT_TEST(testServiceRemoved); +		CPPUNIT_TEST(testError_BrowseErrorAfterStart); +		CPPUNIT_TEST(testError_BrowseErrorAfterResolve); +		CPPUNIT_TEST(testRegisterService); +		CPPUNIT_TEST(testRegisterService_Error); +		CPPUNIT_TEST(testRegisterService_Reregister);  		CPPUNIT_TEST_SUITE_END();  	public: @@ -26,10 +32,10 @@ class LinkLocalServiceBrowserTest : public CppUnit::TestFixture {  		void setUp() {  			eventLoop = new DummyEventLoop(); -			dnsSDServiceFactory = new MockDNSSDServiceFactory(); -			testServiceID = new LinkLocalServiceID("foo", "bar.local"); -			testServiceInfo = new DNSSDService::ResolveResult("xmpp.bar.local", 1234, LinkLocalServiceInfo()); -			testServiceInfo2 = new DNSSDService::ResolveResult("xmpp.foo.local", 2345, LinkLocalServiceInfo()); +			querier = boost::shared_ptr<FakeDNSSDQuerier>(new FakeDNSSDQuerier()); +			testServiceID = new DNSSDServiceID("foo", "bar.local"); +			testServiceInfo = new DNSSDResolveServiceQuery::Result("_presence._tcp.bar.local", "xmpp.bar.local", 1234, LinkLocalServiceInfo()); +			testServiceInfo2 = new DNSSDResolveServiceQuery::Result("_presence.tcp.bar.local", "xmpp.foo.local", 2345, LinkLocalServiceInfo());  		}  		void tearDown() { @@ -40,15 +46,33 @@ class LinkLocalServiceBrowserTest : public CppUnit::TestFixture {  			delete testServiceInfo2;  			delete testServiceInfo;  			delete testServiceID; -      delete dnsSDServiceFactory;  			delete eventLoop;  		} +		void testConstructor() { +			boost::shared_ptr<LinkLocalServiceBrowser> testling = createTestling(); + +			CPPUNIT_ASSERT(!testling->isRunning()); +			CPPUNIT_ASSERT(!testling->hasError()); +		} + +		void testStart() { +			boost::shared_ptr<LinkLocalServiceBrowser> testling = createTestling(); +			testling->start(); + +			CPPUNIT_ASSERT(testling->isRunning()); +			CPPUNIT_ASSERT(!testling->hasError()); + +			testling->stop(); +		} +  		void testServiceAdded() {  			boost::shared_ptr<LinkLocalServiceBrowser> testling = createTestling(); +			testling->start(); +			eventLoop->processEvents(); -			dnsSDService()->setServiceInfo(*testServiceID,*testServiceInfo); -			dnsSDService()->addService(*testServiceID); +			querier->setServiceInfo(*testServiceID,*testServiceInfo); +			querier->addService(*testServiceID);  			eventLoop->processEvents();  			CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(addedServices.size())); @@ -60,26 +84,33 @@ class LinkLocalServiceBrowserTest : public CppUnit::TestFixture {  			CPPUNIT_ASSERT(*testServiceID == services[0].getID());  			CPPUNIT_ASSERT(testServiceInfo->port == services[0].getPort());  			CPPUNIT_ASSERT(testServiceInfo->host == services[0].getHostname()); + +			testling->stop();  		}  		void testServiceAdded_NoServiceInfo() {  			boost::shared_ptr<LinkLocalServiceBrowser> testling = createTestling(); +			testling->start(); +			eventLoop->processEvents(); -			dnsSDService()->addService(*testServiceID); +			querier->addService(*testServiceID);  			eventLoop->processEvents();  			CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(addedServices.size()));  			std::vector<LinkLocalService> services = testling->getServices();  			CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(services.size())); + +			testling->stop();  		}  		void testServiceChanged() {  			boost::shared_ptr<LinkLocalServiceBrowser> testling = createTestling(); -			dnsSDService()->setServiceInfo(*testServiceID,*testServiceInfo); -			dnsSDService()->addService(*testServiceID); +			testling->start(); +			querier->setServiceInfo(*testServiceID,*testServiceInfo); +			querier->addService(*testServiceID);  			eventLoop->processEvents(); -			dnsSDService()->setServiceInfo(*testServiceID,*testServiceInfo2); +			querier->setServiceInfo(*testServiceID,*testServiceInfo2);  			eventLoop->processEvents();  			CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(addedServices.size())); @@ -91,31 +122,93 @@ class LinkLocalServiceBrowserTest : public CppUnit::TestFixture {  			CPPUNIT_ASSERT(*testServiceID == services[0].getID());  			CPPUNIT_ASSERT(testServiceInfo2->port == services[0].getPort());  			CPPUNIT_ASSERT(testServiceInfo2->host == services[0].getHostname()); + +			testling->stop();  		}  		void testServiceRemoved() {  			boost::shared_ptr<LinkLocalServiceBrowser> testling = createTestling(); -			dnsSDService()->setServiceInfo(*testServiceID,*testServiceInfo); -			dnsSDService()->addService(*testServiceID); +			testling->start(); +			querier->setServiceInfo(*testServiceID,*testServiceInfo); +			querier->addService(*testServiceID);  			eventLoop->processEvents(); -			dnsSDService()->removeService(*testServiceID); +			querier->removeService(*testServiceID);  			eventLoop->processEvents(); -			dnsSDService()->setServiceInfo(*testServiceID,*testServiceInfo2); +			querier->setServiceInfo(*testServiceID,*testServiceInfo2);  			eventLoop->processEvents();  			CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(addedServices.size()));  			CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(changedServices.size()));  			CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(removedServices.size()));  			CPPUNIT_ASSERT(removedServices[0] == *testServiceID); -			std::vector<LinkLocalService> services = testling->getServices(); -			CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(services.size())); +			CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(testling->getServices().size())); + +			testling->stop(); +		} + +		void testError_BrowseErrorAfterStart() { +			boost::shared_ptr<LinkLocalServiceBrowser> testling = createTestling(); +			testling->start(); + +			querier->setBrowseError(); +			eventLoop->processEvents(); + +			CPPUNIT_ASSERT(!testling->isRunning()); +			CPPUNIT_ASSERT(testling->hasError()); +		} + +		void testError_BrowseErrorAfterResolve() { +			boost::shared_ptr<LinkLocalServiceBrowser> testling = createTestling(); +			testling->start(); +			querier->setServiceInfo(*testServiceID,*testServiceInfo); +			querier->addService(*testServiceID); +			eventLoop->processEvents(); + +			querier->setBrowseError(); +			eventLoop->processEvents(); +			querier->setServiceInfo(*testServiceID,*testServiceInfo2); +			eventLoop->processEvents(); + +			CPPUNIT_ASSERT(!testling->isRunning()); +			CPPUNIT_ASSERT(testling->hasError()); +			CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(testling->getServices().size())); +			CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(changedServices.size())); +		} + +		void testRegisterService() { +			boost::shared_ptr<LinkLocalServiceBrowser> testling = createTestling(); +			testling->start(); +			eventLoop->processEvents(); + +			testling->stop(); +		} + +		void testRegisterService_Error() { +			boost::shared_ptr<LinkLocalServiceBrowser> testling = createTestling(); +			testling->start(); +			testling->registerService("", 1234); +			eventLoop->processEvents(); + +			querier->setRegisterError(); +			eventLoop->processEvents(); + +			CPPUNIT_ASSERT(!testling->isRunning()); +			CPPUNIT_ASSERT(testling->hasError()); +		} + +		void testRegisterService_Reregister() { +			boost::shared_ptr<LinkLocalServiceBrowser> testling = createTestling(); +			testling->start(); +			eventLoop->processEvents(); + +			testling->stop();  		}  	private:  		boost::shared_ptr<LinkLocalServiceBrowser> createTestling() {  			boost::shared_ptr<LinkLocalServiceBrowser> testling( -					new LinkLocalServiceBrowser(dnsSDServiceFactory)); +					new LinkLocalServiceBrowser(querier));  			testling->onServiceAdded.connect(boost::bind(  					&LinkLocalServiceBrowserTest::handleServiceAdded, this, _1));  			testling->onServiceChanged.connect(boost::bind( @@ -125,32 +218,27 @@ class LinkLocalServiceBrowserTest : public CppUnit::TestFixture {  			return testling;  		} -		void handleServiceAdded(const LinkLocalServiceID& service) { +		void handleServiceAdded(const DNSSDServiceID& service) {  			addedServices.push_back(service);  		} -		void handleServiceRemoved(const LinkLocalServiceID& service) { +		void handleServiceRemoved(const DNSSDServiceID& service) {  			removedServices.push_back(service);  		} -		void handleServiceChanged(const LinkLocalServiceID& service) { +		void handleServiceChanged(const DNSSDServiceID& service) {  			changedServices.push_back(service);  		} -    boost::shared_ptr<MockDNSSDService> dnsSDService() const { -      CPPUNIT_ASSERT(dnsSDServiceFactory->services.size() > 0); -      return dnsSDServiceFactory->services[0]; -    } -  	private:  		DummyEventLoop* eventLoop; -		MockDNSSDServiceFactory* dnsSDServiceFactory; -		std::vector<LinkLocalServiceID> addedServices; -		std::vector<LinkLocalServiceID> changedServices; -		std::vector<LinkLocalServiceID> removedServices; -		LinkLocalServiceID* testServiceID; -		DNSSDService::ResolveResult* testServiceInfo; -		DNSSDService::ResolveResult* testServiceInfo2; +		boost::shared_ptr<FakeDNSSDQuerier> querier; +		std::vector<DNSSDServiceID> addedServices; +		std::vector<DNSSDServiceID> changedServices; +		std::vector<DNSSDServiceID> removedServices; +		DNSSDServiceID* testServiceID; +		DNSSDResolveServiceQuery::Result* testServiceInfo; +		DNSSDResolveServiceQuery::Result* testServiceInfo2;  };  CPPUNIT_TEST_SUITE_REGISTRATION(LinkLocalServiceBrowserTest); diff --git a/Swiften/LinkLocal/UnitTest/Makefile.inc b/Swiften/LinkLocal/UnitTest/Makefile.inc index abc1180..9640fa7 100644 --- a/Swiften/LinkLocal/UnitTest/Makefile.inc +++ b/Swiften/LinkLocal/UnitTest/Makefile.inc @@ -1,2 +1,3 @@  UNITTEST_SOURCES += \ +	Swiften/LinkLocal/UnitTest/LinkLocalServiceBrowserTest.cpp \  	Swiften/LinkLocal/UnitTest/LinkLocalServiceInfoTest.cpp diff --git a/Swiften/LinkLocal/UnitTest/MockDNSSDService.h b/Swiften/LinkLocal/UnitTest/MockDNSSDService.h deleted file mode 100644 index 69ac06d..0000000 --- a/Swiften/LinkLocal/UnitTest/MockDNSSDService.h +++ /dev/null @@ -1,97 +0,0 @@ -#pragma once - -#include <vector> -#include <map> -#include <boost/bind.hpp> - -#include "Swiften/EventLoop/MainEventLoop.h" -#include "Swiften/LinkLocal/DNSSDService.h" -#include "Swiften/LinkLocal/DNSSDServiceFactory.h" - -namespace Swift { -	class MockDNSSDService : public DNSSDService { -		public: -			MockDNSSDService() { -			} -			 -			void start() { -			} - -			void stop() { -			} - -			virtual void registerService(const String&, int, const LinkLocalServiceInfo&) { -				assert(false); -			} - -			virtual void updateService(const LinkLocalServiceInfo&) { -				assert(false); -			} - -			virtual void unregisterService() { -				assert(false); -			} - -			virtual void startResolvingService(const LinkLocalServiceID& id) { -				resolvingServices.push_back(id); -				broadcastServiceInfo(id); -			} - -			virtual void stopResolvingService(const LinkLocalServiceID& id) { -				resolvingServices.erase(std::remove(resolvingServices.begin(), resolvingServices.end(), id), resolvingServices.end()); -			} -			 -			virtual void resolveHostname(const String&, int) { -				assert(false); -			} - -			void addService(const LinkLocalServiceID& id) { -				MainEventLoop::postEvent(boost::bind(boost::ref(onServiceAdded), id)); -			} - -			void removeService(const LinkLocalServiceID& id) { -				serviceInfo.erase(id); -				MainEventLoop::postEvent(boost::bind(boost::ref(onServiceRemoved), id)); -			} - -			void setServiceInfo(const LinkLocalServiceID& id, const DNSSDService::ResolveResult& info) { -				std::pair<ServiceInfoMap::iterator, bool> r = serviceInfo.insert(std::make_pair(id, info)); -				if (!r.second) { -					r.first->second = info; -				} -				broadcastServiceInfo(id); -			} - -		private: -			void broadcastServiceInfo(const LinkLocalServiceID& id) { -				if (std::find(resolvingServices.begin(), resolvingServices.end(), id) != resolvingServices.end()) { -					ServiceInfoMap::const_iterator i = serviceInfo.find(id); -					if (i != serviceInfo.end()) { -						MainEventLoop::postEvent( -								boost::bind(boost::ref(onServiceResolved), id, i->second)); -					} -				} -			} - -		private: -			typedef std::map<LinkLocalServiceID,DNSSDService::ResolveResult> ServiceInfoMap; -			ServiceInfoMap serviceInfo; -			std::vector<LinkLocalServiceID> resolvingServices; -	}; - -  class MockDNSSDServiceFactory : public DNSSDServiceFactory { -    public: -      boost::shared_ptr<DNSSDService> createDNSSDService() { -        boost::shared_ptr<MockDNSSDService> result(new MockDNSSDService());    -        services.push_back(result); -        return result; -      } - -      bool canCreate() const { -        return true; -      } - -      std::vector<boost::shared_ptr<MockDNSSDService> > services; -  }; - -} | 
 Swift
 Swift