diff options
| author | Remko Tronçon <git@el-tramo.be> | 2009-07-18 14:10:19 (GMT) | 
|---|---|---|
| committer | Remko Tronçon <git@el-tramo.be> | 2009-07-18 14:10:19 (GMT) | 
| commit | 70e454fd02597c9a71ed89356a572e48256f8349 (patch) | |
| tree | 7f567453cde7ed7c95c1424e8693ce9cacb7f624 | |
| parent | 7388443bda19877980e368a0654b55097db0bda7 (diff) | |
| download | swift-70e454fd02597c9a71ed89356a572e48256f8349.zip swift-70e454fd02597c9a71ed89356a572e48256f8349.tar.bz2 | |
Implement roster<->linklocal bridge.
| -rw-r--r-- | Nim/main.cpp | 76 | ||||
| -rw-r--r-- | Swiften/LinkLocal/LinkLocalRoster.cpp | 81 | ||||
| -rw-r--r-- | Swiften/LinkLocal/LinkLocalRoster.h | 19 | 
3 files changed, 144 insertions, 32 deletions
| diff --git a/Nim/main.cpp b/Nim/main.cpp index 390bc6c..024ecd1 100644 --- a/Nim/main.cpp +++ b/Nim/main.cpp @@ -1,8 +1,11 @@ +// TODO: Prohibit multiple logins +  #include <string>  #include <boost/bind.hpp>  #include <boost/shared_ptr.hpp>  #include "Swiften/Elements/IQ.h" +#include "Swiften/Elements/Presence.h"  #include "Swiften/Elements/RosterPayload.h"  #include "Swiften/Elements/VCard.h"  #include "Swiften/Server/UserRegistry.h" @@ -41,24 +44,36 @@ class DummyUserRegistry : public UserRegistry {  class Server {  	public: -		Server(int clientConnectionPort, int linkLocalConnectionPort) : dnsSDServiceRegistered_(false), clientConnectionPort_(clientConnectionPort), linkLocalConnectionPort_(linkLocalConnectionPort) { +		Server(int clientConnectionPort, int linkLocalConnectionPort) : dnsSDServiceRegistered_(false), rosterRequested_(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_->onNewConnection.connect(boost::bind(&Server::handleNewClientConnection, this, _1));  			serverFromClientConnectionServer_->start(); +			serverFromNetworkConnectionServer_ = boost::shared_ptr<BoostConnectionServer>(new BoostConnectionServer(linkLocalConnectionPort, &boostIOServiceThread_.getIOService())); +			serverFromNetworkConnectionServer_->onNewConnection.connect(boost::bind(&Server::handleNewLinkLocalConnection, this, _1)); +			serverFromNetworkConnectionServer_->start(); +  			dnsSDService_ = boost::shared_ptr<AppleDNSSDService>(new AppleDNSSDService());  			linkLocalRoster_ = boost::shared_ptr<LinkLocalRoster>(new LinkLocalRoster(dnsSDService_)); +			linkLocalRoster_->onRosterChanged.connect(boost::bind(&Server::handleRosterChanged, this, _1)); +			linkLocalRoster_->onPresenceChanged.connect(boost::bind(&Server::handlePresenceChanged, this, _1));  			dnsSDService_->start();  		}  	private: -		void handleNewConnection(boost::shared_ptr<Connection> c) { -			boost::shared_ptr<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)); -			session->start(); +		void handleNewClientConnection(boost::shared_ptr<Connection> c) { +			if (serverFromClientSession_) { +				c->disconnect(); +			} +			serverFromClientSession_ = boost::shared_ptr<ServerFromClientSession>(new ServerFromClientSession(idGenerator_.generateID(), c, &payloadParserFactories_, &payloadSerializers_, &userRegistry_)); +			serverFromClientSession_->onStanzaReceived.connect(boost::bind(&Server::handleStanzaReceived, this, _1, serverFromClientSession_)); +			serverFromClientSession_->onSessionStarted.connect(boost::bind(&Server::handleSessionStarted, this, serverFromClientSession_)); +			serverFromClientSession_->onSessionFinished.connect(boost::bind(&Server::handleSessionFinished, this, serverFromClientSession_)); +			serverFromClientSession_->start(); +		} + +		void handleNewLinkLocalConnection(boost::shared_ptr<Connection>) { +			std::cout << "Incoming link local connection" << std::endl;  		}  		void handleSessionStarted(boost::shared_ptr<ServerFromClientSession> session) { @@ -82,13 +97,13 @@ class Server {  			std::cout << "Service registered " << service.name << " " << service.type << " " << service.domain << std::endl;  		} -		void handleSessionFinished(boost::shared_ptr<ServerFromClientSession> session) { -			serverFromClientSessions_.erase(std::remove(serverFromClientSessions_.begin(), serverFromClientSessions_.end(), session), serverFromClientSessions_.end()); -			if (serverFromClientSessions_.empty()) { -				std::cout << "Service unregistered" << std::endl; -				dnsSDServiceRegistered_ = false; -				dnsSDService_->unregisterService(); -			} +		void handleSessionFinished(boost::shared_ptr<ServerFromClientSession>) { +			serverFromClientSession_.reset(); + +			std::cout << "Service unregistered" << std::endl; +			dnsSDServiceRegistered_ = false; +			rosterRequested_ = false; +			dnsSDService_->unregisterService();  		}  		void handleStanzaReceived(boost::shared_ptr<Stanza> stanza, boost::shared_ptr<ServerFromClientSession> session) { @@ -99,7 +114,16 @@ class Server {  			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->getType() == IQ::Get) { +							session->sendStanza(IQ::createResult(iq->getFrom(), iq->getID(), linkLocalRoster_->getRoster())); +							rosterRequested_ = true; +							foreach(const boost::shared_ptr<Presence> presence, linkLocalRoster_->getAllPresence()) { +								session->sendStanza(presence); +							} +						} +						else { +							session->sendStanza(IQ::createError(iq->getFrom(), iq->getID(), Error::Forbidden, Error::Cancel)); +						}  					}  					if (iq->getPayload<VCard>()) {  						if (iq->getType() == IQ::Get) { @@ -118,6 +142,20 @@ class Server {  			}  		} +		void handleRosterChanged(boost::shared_ptr<RosterPayload> roster) { +			if (rosterRequested_) { +				boost::shared_ptr<IQ> iq = IQ::createRequest(IQ::Set, serverFromClientSession_->getJID(), idGenerator_.generateID(), roster); +				iq->setFrom(serverFromClientSession_->getJID().toBare()); +				serverFromClientSession_->sendStanza(iq); +			} +		} + +		void handlePresenceChanged(boost::shared_ptr<Presence> presence) { +			if (rosterRequested_) { +				serverFromClientSession_->sendStanza(presence); +			} +		} +  	private:  		IDGenerator idGenerator_;  		BoostIOServiceThread boostIOServiceThread_; @@ -125,10 +163,12 @@ class Server {  		boost::shared_ptr<AppleDNSSDService> dnsSDService_;  		boost::shared_ptr<LinkLocalRoster> linkLocalRoster_;  		boost::shared_ptr<BoostConnectionServer> serverFromClientConnectionServer_; -		std::vector< boost::shared_ptr<ServerFromClientSession> > serverFromClientSessions_; +		boost::shared_ptr<ServerFromClientSession> serverFromClientSession_; +		boost::shared_ptr<BoostConnectionServer> serverFromNetworkConnectionServer_;  		FullPayloadParserFactoryCollection payloadParserFactories_;  		FullPayloadSerializerCollection payloadSerializers_;  		bool dnsSDServiceRegistered_; +		bool rosterRequested_;  		int clientConnectionPort_;  		int linkLocalConnectionPort_;  }; diff --git a/Swiften/LinkLocal/LinkLocalRoster.cpp b/Swiften/LinkLocal/LinkLocalRoster.cpp index feec7b7..aedea77 100644 --- a/Swiften/LinkLocal/LinkLocalRoster.cpp +++ b/Swiften/LinkLocal/LinkLocalRoster.cpp @@ -12,37 +12,92 @@ LinkLocalRoster::LinkLocalRoster(boost::shared_ptr<DNSSDService> service) : dnsS  	dnsSDService->onServiceAdded.connect(boost::bind(&LinkLocalRoster::handleServiceAdded, this, _1));  	dnsSDService->onServiceRemoved.connect(boost::bind(&LinkLocalRoster::handleServiceRemoved, this, _1));  	dnsSDService->onServiceResolved.connect(boost::bind(&LinkLocalRoster::handleServiceResolved, this, _1, _2)); -	dnsSDService->onHostnameResolved.connect(boost::bind(&LinkLocalRoster::handleHostnameResolved, this, _1, _2)); +} + +boost::shared_ptr<RosterPayload> LinkLocalRoster::getRoster() const { +	boost::shared_ptr<RosterPayload> roster(new RosterPayload()); +	for(ServiceMap::const_iterator i = services.begin(); i != services.end(); ++i) { +		roster->addItem(getRosterItem(i->first, i->second)); +	} +	return roster; +} + +std::vector<boost::shared_ptr<Presence> > LinkLocalRoster::getAllPresence() const { +	std::vector<boost::shared_ptr<Presence> > result; +	for(ServiceMap::const_iterator i = services.begin(); i != services.end(); ++i) { +		result.push_back(getPresence(i->first, i->second)); +	} +	return result; +} + +RosterItemPayload LinkLocalRoster::getRosterItem(const DNSSDService::Service& service, const DNSSDService::ResolveResult& resolveResult) const { + return RosterItemPayload(getJIDForService(service), getRosterName(service, resolveResult), RosterItemPayload::Both); +} + +String LinkLocalRoster::getRosterName(const DNSSDService::Service& service, const DNSSDService::ResolveResult& resolveResult) const { +	if (!resolveResult.info.getNick().isEmpty()) { +		return resolveResult.info.getNick(); +	} +	else if (!resolveResult.info.getFirstName().isEmpty()) { +		String result = resolveResult.info.getFirstName(); +		if (!resolveResult.info.getLastName().isEmpty()) { +			result += " " + resolveResult.info.getLastName(); +		} +		return result; +	} +	else if (!resolveResult.info.getLastName().isEmpty()) { +		return resolveResult.info.getLastName(); +	} +	return service.name; +} + +JID LinkLocalRoster::getJIDForService(const DNSSDService::Service& service) const { +	return JID(service.name); +} + +boost::shared_ptr<Presence> LinkLocalRoster::getPresence(const DNSSDService::Service& service, const DNSSDService::ResolveResult& resolveResult) const { +	boost::shared_ptr<Presence> presence(new Presence()); +	presence->setFrom(getJIDForService(service)); +	switch (resolveResult.info.getStatus()) { +		case LinkLocalServiceInfo::Available: +			presence->setShow(StatusShow::Online); +			break; +		case LinkLocalServiceInfo::Away: +			presence->setShow(StatusShow::Away); +			break; +		case LinkLocalServiceInfo::DND: +			presence->setShow(StatusShow::DND); +			break; +	} +	presence->setStatus(resolveResult.info.getMessage()); +	return presence;  }  void LinkLocalRoster::handleServiceAdded(const DNSSDService::Service& service) {  	if (selfService && *selfService == service) {  		return;  	} -	std::cout << "Service added " << service.name << " " << service.type << " " << service.domain << std::endl;  	dnsSDService->startResolvingService(service);  }  void LinkLocalRoster::handleServiceRemoved(const DNSSDService::Service& service) { -	std::cout << "Service removed " << service.name << " " << service.type << " " << service.domain << std::endl;  	dnsSDService->stopResolvingService(service); +	services.erase(service); +	boost::shared_ptr<RosterPayload> roster(new RosterPayload()); +	roster->addItem(RosterItemPayload(getJIDForService(service), "", RosterItemPayload::Remove)); +	onRosterChanged(roster);  }  void LinkLocalRoster::handleServiceResolved(const DNSSDService::Service& service, const DNSSDService::ResolveResult& result) { -	std::cout << "Service resolved: " << service.name << "->" << result.host << " " << result.port << " " << result.info.getLastName() << std::endl; +	services.insert(std::make_pair(service, result));  	dnsSDService->resolveHostname(result.host); -} -void LinkLocalRoster::handleHostnameResolved(const String& hostname, const boost::optional<HostAddress>& address) { -	if (address) { -		std::cout << "Address resolved: " << hostname << " " << address->toString() << std::endl; -	} -	else { -		std::cout << "Unable to resolve address for " << hostname << std::endl; -	} +	boost::shared_ptr<RosterPayload> roster(new RosterPayload()); +	roster->addItem(getRosterItem(service, result)); +	onRosterChanged(roster); +	onPresenceChanged(getPresence(service, result));  } -  void LinkLocalRoster::handleServiceRegistered(const DNSSDService::Service& service) {  	selfService = service;  } diff --git a/Swiften/LinkLocal/LinkLocalRoster.h b/Swiften/LinkLocal/LinkLocalRoster.h index 321bd96..33dd455 100644 --- a/Swiften/LinkLocal/LinkLocalRoster.h +++ b/Swiften/LinkLocal/LinkLocalRoster.h @@ -2,8 +2,13 @@  #include <boost/shared_ptr.hpp>  #include <boost/optional.hpp> +#include <set> +#include "Swiften/Base/String.h" +#include "Swiften/JID/JID.h"  #include "Swiften/LinkLocal/DNSSDService.h" +#include "Swiften/Elements/RosterPayload.h" +#include "Swiften/Elements/Presence.h"  namespace Swift {  	class HostAddress; @@ -12,16 +17,28 @@ namespace Swift {  		public:  			LinkLocalRoster(boost::shared_ptr<DNSSDService> service); +			boost::shared_ptr<RosterPayload> getRoster() const; +			std::vector<boost::shared_ptr<Presence> > getAllPresence() const; + +			boost::signal<void (boost::shared_ptr<RosterPayload>)> onRosterChanged; +			boost::signal<void (boost::shared_ptr<Presence>)> onPresenceChanged; +  		private: +			RosterItemPayload getRosterItem(const DNSSDService::Service& service, const DNSSDService::ResolveResult& info) const; +			String getRosterName(const DNSSDService::Service& service, const DNSSDService::ResolveResult& info) const; +			JID getJIDForService(const DNSSDService::Service& service) const; +			boost::shared_ptr<Presence> getPresence(const DNSSDService::Service& service, const DNSSDService::ResolveResult& info) const; +  			void handleStopped(bool);  			void handleServiceRegistered(const DNSSDService::Service& service);  			void handleServiceAdded(const DNSSDService::Service&);  			void handleServiceRemoved(const DNSSDService::Service&);  			void handleServiceResolved(const DNSSDService::Service& service, const DNSSDService::ResolveResult& result); -			void handleHostnameResolved(const String& hostname, const boost::optional<HostAddress>& address);  		private:  			boost::shared_ptr<DNSSDService> dnsSDService;  			boost::optional<DNSSDService::Service> selfService; +			typedef std::map<DNSSDService::Service, DNSSDService::ResolveResult> ServiceMap; +			ServiceMap services;  	};  } | 
 Swift
 Swift