diff options
| author | Remko Tronçon <git@el-tramo.be> | 2009-07-20 10:02:41 (GMT) | 
|---|---|---|
| committer | Remko Tronçon <git@el-tramo.be> | 2009-07-20 10:04:14 (GMT) | 
| commit | 6c181e11f30cfb58688f327326a03f268ee3790a (patch) | |
| tree | b987c7b9052dc3adeeae170e0e6432dc3b98fb44 | |
| parent | 4a34df5d9861041aa7c984b55d2df13d7cb0e7d1 (diff) | |
| download | swift-6c181e11f30cfb58688f327326a03f268ee3790a.zip swift-6c181e11f30cfb58688f327326a03f268ee3790a.tar.bz2 | |
Move Slimber server out of main.
| -rw-r--r-- | Slimber/.gitignore | 2 | ||||
| -rw-r--r-- | Slimber/Makefile.inc | 1 | ||||
| -rw-r--r-- | Slimber/Server.cpp | 279 | ||||
| -rw-r--r-- | Slimber/Server.h | 76 | ||||
| -rw-r--r-- | Slimber/main.cpp | 338 | 
5 files changed, 367 insertions, 329 deletions
| diff --git a/Slimber/.gitignore b/Slimber/.gitignore index 6bb3f86..f7293e8 100644 --- a/Slimber/.gitignore +++ b/Slimber/.gitignore @@ -1 +1 @@ -nim +slimber diff --git a/Slimber/Makefile.inc b/Slimber/Makefile.inc index 904bc83..86692b3 100644 --- a/Slimber/Makefile.inc +++ b/Slimber/Makefile.inc @@ -1,5 +1,6 @@  SLIMBER_TARGET = Slimber/slimber  SLIMBER_SOURCES = \ +	Slimber/Server.cpp \  	Slimber/main.cpp  SLIMBER_OBJECTS = \  	$(SLIMBER_SOURCES:.cpp=.o) diff --git a/Slimber/Server.cpp b/Slimber/Server.cpp new file mode 100644 index 0000000..e84659a --- /dev/null +++ b/Slimber/Server.cpp @@ -0,0 +1,279 @@ +#include "Slimber/Server.h" + +#include <string> +#include <boost/bind.hpp> + +#include "Swiften/Session/SessionTracer.h" +#include "Swiften/Elements/IQ.h" +#include "Swiften/Elements/VCard.h" +#include "Swiften/Server/UserRegistry.h" +#include "Swiften/Base/String.h" +#include "Swiften/LinkLocal/LinkLocalServiceInfo.h" +#include "Swiften/LinkLocal/LinkLocalRoster.h" +#include "Swiften/LinkLocal/OutgoingLinkLocalSession.h" +#include "Swiften/LinkLocal/IncomingLinkLocalSession.h" +#include "Swiften/Network/ConnectionServer.h" +#include "Swiften/Server/ServerFromClientSession.h" + +namespace Swift { + +Server::Server(int clientConnectionPort, int linkLocalConnectionPort, boost::shared_ptr<DNSSDService> dnsSDService) :  +		dnsSDServiceRegistered_(false),  +		rosterRequested_(false),  +		clientConnectionPort_(clientConnectionPort),  +		linkLocalConnectionPort_(linkLocalConnectionPort), +		dnsSDService_(dnsSDService) { +	serverFromClientConnectionServer_ =  +			boost::shared_ptr<BoostConnectionServer>(new BoostConnectionServer( +					clientConnectionPort, &boostIOServiceThread_.getIOService())); +	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_->onServiceRegistered.connect +			(boost::bind(&Server::handleServiceRegistered, this, _1)); +	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(); +} + +void Server::handleNewClientConnection(boost::shared_ptr<Connection> c) { +	if (serverFromClientSession_) { +		c->disconnect(); +	} +	serverFromClientSession_ = boost::shared_ptr<ServerFromClientSession>(new ServerFromClientSession(idGenerator_.generateID(), c, &payloadParserFactories_, &payloadSerializers_, &userRegistry_)); +	serverFromClientSession_->onElementReceived.connect(boost::bind(&Server::handleElementReceived, this, _1, serverFromClientSession_)); +	serverFromClientSession_->onSessionFinished.connect(boost::bind(&Server::handleSessionFinished, this, serverFromClientSession_)); +	tracers_.push_back(boost::shared_ptr<SessionTracer>(new SessionTracer(serverFromClientSession_))); +	serverFromClientSession_->startSession(); +} + +void Server::handleNewLinkLocalConnection(boost::shared_ptr<Connection> connection) { +	boost::shared_ptr<IncomingLinkLocalSession> session( +			new IncomingLinkLocalSession( +				selfJID_, connection,  +				&payloadParserFactories_, &payloadSerializers_)); +	registerLinkLocalSession(session); +} + +void Server::handleServiceRegistered(const DNSSDService::Service& service) { +	std::cout << "Service registered " << service.name << " " << service.type << " " << service.domain << std::endl; +	selfJID_ = JID(service.name); +} + +void Server::handleSessionFinished(boost::shared_ptr<ServerFromClientSession>) { +	serverFromClientSession_.reset(); +	unregisterService(); +	selfJID_ = JID(); +	rosterRequested_ = false; +} + +void Server::handleLinkLocalSessionFinished(boost::shared_ptr<Session> session) { +	std::cout << "Link local session from " << session->getRemoteJID() << " ended" << std::endl; +	linkLocalSessions_.erase(std::remove(linkLocalSessions_.begin(), linkLocalSessions_.end(), session), linkLocalSessions_.end()); +} + +void Server::handleLinkLocalElementReceived(boost::shared_ptr<Element> element, boost::shared_ptr<Session> session) { +	if (boost::shared_ptr<Stanza> stanza = boost::dynamic_pointer_cast<Stanza>(element)) { +		JID fromJID = session->getRemoteJID(); +		if (!linkLocalRoster_->hasItem(fromJID)) { +			return; // TODO: Queue +		} +		stanza->setFrom(fromJID); +		serverFromClientSession_->sendElement(stanza); +	} +} + +void Server::unregisterService() { +	if (dnsSDServiceRegistered_) { +		dnsSDServiceRegistered_ = false; +		dnsSDService_->unregisterService(); +	} +} + +void Server::handleElementReceived(boost::shared_ptr<Element> element, boost::shared_ptr<ServerFromClientSession> session) { +	boost::shared_ptr<Stanza> stanza = boost::dynamic_pointer_cast<Stanza>(element); +	if (!stanza) { +		return; +	} + +	stanza->setFrom(session->getRemoteJID()); +	if (!stanza->getTo().isValid()) { +		stanza->setTo(session->getLocalJID()); +	} + +	if (boost::shared_ptr<Presence> presence = boost::dynamic_pointer_cast<Presence>(stanza)) { +		if (presence->getType() == Presence::Available) { +			if (!dnsSDServiceRegistered_) { +				dnsSDServiceRegistered_ = true; +				dnsSDService_->registerService(session->getRemoteJID().toBare().toString(), linkLocalConnectionPort_, getLinkLocalServiceInfo(presence)); +			} +			else { +				dnsSDService_->updateService(getLinkLocalServiceInfo(presence)); +			} +		} +		else { +			unregisterService(); +		} +	} +	else if (!stanza->getTo().isValid() || stanza->getTo() == session->getLocalJID() || stanza->getTo() == session->getRemoteJID().toBare()) { +		if (boost::shared_ptr<IQ> iq = boost::dynamic_pointer_cast<IQ>(stanza)) { +			if (iq->getPayload<RosterPayload>()) { +				if (iq->getType() == IQ::Get) { +					session->sendElement(IQ::createResult(iq->getFrom(), iq->getID(), linkLocalRoster_->getRoster())); +					rosterRequested_ = true; +					foreach(const boost::shared_ptr<Presence> presence, linkLocalRoster_->getAllPresence()) { +						session->sendElement(presence); +					} +				} +				else { +					session->sendElement(IQ::createError(iq->getFrom(), iq->getID(), Error::Forbidden, Error::Cancel)); +				} +			} +			if (iq->getPayload<VCard>()) { +				if (iq->getType() == IQ::Get) { +					boost::shared_ptr<VCard> vcard(new VCard()); +					vcard->setNickname(iq->getFrom().getNode()); +					session->sendElement(IQ::createResult(iq->getFrom(), iq->getID(), vcard)); +				} +				else { +					session->sendElement(IQ::createError(iq->getFrom(), iq->getID(), Error::Forbidden, Error::Cancel)); +				} +			} +			else { +				session->sendElement(IQ::createError(iq->getFrom(), iq->getID(), Error::FeatureNotImplemented, Error::Cancel)); +			} +		} +	} +	else { +		JID toJID = stanza->getTo(); +		boost::shared_ptr<Session> outgoingSession =  +				getLinkLocalSessionForJID(toJID); +		if (outgoingSession) { +			outgoingSession->sendElement(stanza); +		} +		else { +			if (linkLocalRoster_->hasItem(toJID)) { +				boost::shared_ptr<LinkLocalConnector> connector = +					getLinkLocalConnectorForJID(toJID); +				if (!connector) { +					connector = boost::shared_ptr<LinkLocalConnector>( +							new LinkLocalConnector( +								toJID,  +								linkLocalRoster_->getHostname(toJID),  +								linkLocalRoster_->getPort(toJID),  +								dnsSDService_, +								boost::shared_ptr<BoostConnection>(new BoostConnection(&boostIOServiceThread_.getIOService())))); +					connector->onConnectFinished.connect( +							boost::bind(&Server::handleConnectFinished, this, connector, _1)); +					connectors_.push_back(connector); +					connector->connect(); +				} +				connector->queueElement(element); +			} +			else { +				session->sendElement(IQ::createError( +						stanza->getFrom(), stanza->getID(),  +						Error::RecipientUnavailable, Error::Wait)); +			} +		} +	} +} + +void Server::handleConnectFinished(boost::shared_ptr<LinkLocalConnector> connector, bool error) { +	if (error) { +		std::cerr << "Error connecting" << std::endl; +		// TODO: Send back queued stanzas +	} +	else { +		boost::shared_ptr<OutgoingLinkLocalSession> outgoingSession( +				new OutgoingLinkLocalSession( +					selfJID_, connector->getRemoteJID(), connector->getConnection(), +					&payloadParserFactories_, &payloadSerializers_)); +		foreach(const boost::shared_ptr<Element> element, connector->getQueuedElements()) { +			outgoingSession->queueElement(element); +		} +		registerLinkLocalSession(outgoingSession); +	} +	connectors_.erase(std::remove(connectors_.begin(), connectors_.end(), connector), connectors_.end()); +} + + +void Server::registerLinkLocalSession(boost::shared_ptr<Session> session) { +	session->onSessionFinished.connect(boost::bind(&Server::handleLinkLocalSessionFinished, this, session)); +	session->onElementReceived.connect(boost::bind(&Server::handleLinkLocalElementReceived, this, _1, session)); +	linkLocalSessions_.push_back(session); +	tracers_.push_back(boost::shared_ptr<SessionTracer>(new SessionTracer(session))); +	session->startSession(); +} + +boost::shared_ptr<Session> Server::getLinkLocalSessionForJID(const JID& jid) { +	foreach(const boost::shared_ptr<Session> session, linkLocalSessions_) { +		if (session->getRemoteJID() == jid) { +			return session; +		} +	} +	return boost::shared_ptr<Session>(); +} + +boost::shared_ptr<LinkLocalConnector> Server::getLinkLocalConnectorForJID(const JID& jid) { +	foreach(const boost::shared_ptr<LinkLocalConnector> connector, connectors_) { +		if (connector->getRemoteJID() == jid) { +			return connector; +		} +	} +	return boost::shared_ptr<LinkLocalConnector>(); +} + +void Server::handleRosterChanged(boost::shared_ptr<RosterPayload> roster) { +	if (rosterRequested_) { +		boost::shared_ptr<IQ> iq = IQ::createRequest(IQ::Set, serverFromClientSession_->getRemoteJID(), idGenerator_.generateID(), roster); +		iq->setFrom(serverFromClientSession_->getRemoteJID().toBare()); +		serverFromClientSession_->sendElement(iq); +	} +} + +void Server::handlePresenceChanged(boost::shared_ptr<Presence> presence) { +	if (rosterRequested_) { +		serverFromClientSession_->sendElement(presence); +	} +} + +LinkLocalServiceInfo Server::getLinkLocalServiceInfo(boost::shared_ptr<Presence> presence) { +	LinkLocalServiceInfo info; +	info.setFirstName("Remko"); +	info.setLastName("Tron\xc3\xa7on"); +	info.setEMail("email@example.com"); +	info.setJID(JID("jid@example.com")); +	info.setMessage(presence->getStatus()); +	info.setNick("Remko"); +	switch (presence->getShow()) { +		case StatusShow::Online:  +		case StatusShow::None:  +		case StatusShow::FFC:  +			info.setStatus(LinkLocalServiceInfo::Available); +			break; +		case StatusShow::Away:  +		case StatusShow::XA:  +			info.setStatus(LinkLocalServiceInfo::Away); +			break; +		case StatusShow::DND:  +			info.setStatus(LinkLocalServiceInfo::DND); +			break; +	} +	info.setPort(linkLocalConnectionPort_); +	return info; +} + +} diff --git a/Slimber/Server.h b/Slimber/Server.h new file mode 100644 index 0000000..573e3d9 --- /dev/null +++ b/Slimber/Server.h @@ -0,0 +1,76 @@ +#pragma once + +#include <boost/shared_ptr.hpp> +#include <vector> + +#include "Swiften/Network/BoostConnection.h" +#include "Swiften/Network/BoostIOServiceThread.h" +#include "Swiften/Network/BoostConnectionServer.h" +#include "Swiften/Server/UserRegistry.h" +#include "Swiften/Base/IDGenerator.h" +#include "Swiften/Network/Connection.h" +#include "Swiften/LinkLocal/DNSSDService.h" +#include "Swiften/LinkLocal/LinkLocalRoster.h" +#include "Swiften/Session/SessionTracer.h" +#include "Swiften/Server/ServerFromClientSession.h" +#include "Swiften/Elements/Element.h" +#include "Swiften/LinkLocal/LinkLocalConnector.h" +#include "Swiften/JID/JID.h" +#include "Swiften/Elements/Presence.h" +#include "Swiften/Elements/RosterPayload.h" +#include "Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.h" +#include "Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h" + +namespace Swift { +	class Server { +		public: +			Server(int clientConnectionPort, int linkLocalConnectionPort, boost::shared_ptr<DNSSDService> dnsSDService); + +		private: +			void handleNewClientConnection(boost::shared_ptr<Connection> c); +			void handleNewLinkLocalConnection(boost::shared_ptr<Connection> connection); +			void handleServiceRegistered(const DNSSDService::Service& service); +			void handleSessionFinished(boost::shared_ptr<ServerFromClientSession>); +			void handleLinkLocalSessionFinished(boost::shared_ptr<Session> session); +			void handleLinkLocalElementReceived(boost::shared_ptr<Element> element, boost::shared_ptr<Session> session); +			void unregisterService(); +			void handleElementReceived(boost::shared_ptr<Element> element, boost::shared_ptr<ServerFromClientSession> session); +			void handleConnectFinished(boost::shared_ptr<LinkLocalConnector> connector, bool error); +			void registerLinkLocalSession(boost::shared_ptr<Session> session); +			boost::shared_ptr<Session> getLinkLocalSessionForJID(const JID& jid); +			boost::shared_ptr<LinkLocalConnector> getLinkLocalConnectorForJID(const JID& jid); +			void handleRosterChanged(boost::shared_ptr<RosterPayload> roster); +			void handlePresenceChanged(boost::shared_ptr<Presence> presence); +			LinkLocalServiceInfo getLinkLocalServiceInfo(boost::shared_ptr<Presence> presence); + +		private: +			class DummyUserRegistry : public UserRegistry { +				public: +					DummyUserRegistry() {} + +					virtual bool isValidUserPassword(const JID&, const String&) const { +						return true; +					} +			}; + +		private: +			IDGenerator idGenerator_; +			BoostIOServiceThread boostIOServiceThread_; +			DummyUserRegistry userRegistry_; +			bool dnsSDServiceRegistered_; +			bool rosterRequested_; +			int clientConnectionPort_; +			int linkLocalConnectionPort_; +			boost::shared_ptr<DNSSDService> dnsSDService_; +			boost::shared_ptr<LinkLocalRoster> linkLocalRoster_; +			boost::shared_ptr<BoostConnectionServer> serverFromClientConnectionServer_; +			boost::shared_ptr<ServerFromClientSession> serverFromClientSession_; +			boost::shared_ptr<BoostConnectionServer> serverFromNetworkConnectionServer_; +			std::vector< boost::shared_ptr<SessionTracer> > tracers_; +			std::vector< boost::shared_ptr<Session> > linkLocalSessions_; +			std::vector< boost::shared_ptr<LinkLocalConnector> > connectors_; +			FullPayloadParserFactoryCollection payloadParserFactories_; +			FullPayloadSerializerCollection payloadSerializers_; +			JID selfJID_; +	}; +} diff --git a/Slimber/main.cpp b/Slimber/main.cpp index a048312..31ae15a 100644 --- a/Slimber/main.cpp +++ b/Slimber/main.cpp @@ -1,348 +1,30 @@  #include <string>  #include <boost/bind.hpp> -#include <boost/shared_ptr.hpp>  #include "Swiften/Base/Platform.h" -#include "Swiften/Session/SessionTracer.h" -#include "Swiften/Network/BoostConnectionFactory.h" -#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" -#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/Element.h" -#include "Swiften/LinkLocal/LinkLocalConnector.h" -#include "Swiften/LinkLocal/LinkLocalServiceInfo.h" -#include "Swiften/LinkLocal/LinkLocalRoster.h" -#include "Swiften/LinkLocal/OutgoingLinkLocalSession.h" -#include "Swiften/LinkLocal/IncomingLinkLocalSession.h" -#include "Swiften/LinkLocal/DNSSDService.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" -  #if defined(SWIFTEN_PLATFORM_MACOSX) || defined(SWIFTEN_PLATFORM_WINDOWS)  #include "Swiften/LinkLocal/AppleDNSSDService.h"  #else  #include "Swiften/LinkLocal/AvahiDNSSDService.h"  #endif +#include "Slimber/Server.h" +#include "Swiften/EventLoop/SimpleEventLoop.h"  using namespace Swift; +int main() { +	SimpleEventLoop eventLoop; -class DummyUserRegistry : public UserRegistry { -	public: -		DummyUserRegistry() { -		} - -		virtual bool isValidUserPassword(const JID&, const String&) const { -			return true; -		} -}; - -class Server { -	public: -		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::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(); - +	boost::shared_ptr<DNSSDService> dnsSDService;  #if defined(SWIFTEN_PLATFORM_MACOSX) || defined(SWIFTEN_PLATFORM_WINDOWS) -			dnsSDService_ = boost::shared_ptr<AppleDNSSDService>( -					new AppleDNSSDService()); +	dnsSDService = boost::shared_ptr<AppleDNSSDService>( +			new AppleDNSSDService());  #else -			dnsSDService_ = boost::shared_ptr<AvahiDNSSDService>( -					new AvahiDNSSDService()); +	dnsSDService = boost::shared_ptr<AvahiDNSSDService>( +			new AvahiDNSSDService());  #endif -			dnsSDService_->onServiceRegistered.connect -					(boost::bind(&Server::handleServiceRegistered, this, _1)); -			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 handleNewClientConnection(boost::shared_ptr<Connection> c) { -			if (serverFromClientSession_) { -				c->disconnect(); -			} -			serverFromClientSession_ = boost::shared_ptr<ServerFromClientSession>(new ServerFromClientSession(idGenerator_.generateID(), c, &payloadParserFactories_, &payloadSerializers_, &userRegistry_)); -			serverFromClientSession_->onElementReceived.connect(boost::bind(&Server::handleElementReceived, this, _1, serverFromClientSession_)); -			serverFromClientSession_->onSessionFinished.connect(boost::bind(&Server::handleSessionFinished, this, serverFromClientSession_)); -			tracers_.push_back(boost::shared_ptr<SessionTracer>(new SessionTracer(serverFromClientSession_))); -			serverFromClientSession_->startSession(); -		} - -		void handleNewLinkLocalConnection(boost::shared_ptr<Connection> connection) { -			boost::shared_ptr<IncomingLinkLocalSession> session( -					new IncomingLinkLocalSession( -						selfJID_, connection,  -						&payloadParserFactories_, &payloadSerializers_)); -			registerLinkLocalSession(session); -		} -		 -		void handleServiceRegistered(const DNSSDService::Service& service) { -			std::cout << "Service registered " << service.name << " " << service.type << " " << service.domain << std::endl; -			selfJID_ = JID(service.name); -		} - -		void handleSessionFinished(boost::shared_ptr<ServerFromClientSession>) { -			serverFromClientSession_.reset(); -			unregisterService(); -			selfJID_ = JID(); -			rosterRequested_ = false; -		} - -		void handleLinkLocalSessionFinished(boost::shared_ptr<Session> session) { -			std::cout << "Link local session from " << session->getRemoteJID() << " ended" << std::endl; -			linkLocalSessions_.erase(std::remove(linkLocalSessions_.begin(), linkLocalSessions_.end(), session), linkLocalSessions_.end()); -		} - -		void handleLinkLocalElementReceived(boost::shared_ptr<Element> element, boost::shared_ptr<Session> session) { -			if (boost::shared_ptr<Stanza> stanza = boost::dynamic_pointer_cast<Stanza>(element)) { -				JID fromJID = session->getRemoteJID(); -				if (!linkLocalRoster_->hasItem(fromJID)) { -					return; // TODO: Queue -				} -				stanza->setFrom(fromJID); -				serverFromClientSession_->sendElement(stanza); -			} -		} - -		void unregisterService() { -			if (dnsSDServiceRegistered_) { -				dnsSDServiceRegistered_ = false; -				dnsSDService_->unregisterService(); -			} -		} -		void handleElementReceived(boost::shared_ptr<Element> element, boost::shared_ptr<ServerFromClientSession> session) { -			boost::shared_ptr<Stanza> stanza = boost::dynamic_pointer_cast<Stanza>(element); -			if (!stanza) { -				return; -			} - -			stanza->setFrom(session->getRemoteJID()); -			if (!stanza->getTo().isValid()) { -				stanza->setTo(session->getLocalJID()); -			} - -			if (boost::shared_ptr<Presence> presence = boost::dynamic_pointer_cast<Presence>(stanza)) { -				if (presence->getType() == Presence::Available) { -					if (!dnsSDServiceRegistered_) { -						dnsSDServiceRegistered_ = true; -						dnsSDService_->registerService(session->getRemoteJID().toBare().toString(), linkLocalConnectionPort_, getLinkLocalServiceInfo(presence)); -					} -					else { -						dnsSDService_->updateService(getLinkLocalServiceInfo(presence)); -					} -				} -				else { -					unregisterService(); -				} -			} -			else if (!stanza->getTo().isValid() || stanza->getTo() == session->getLocalJID() || stanza->getTo() == session->getRemoteJID().toBare()) { -				if (boost::shared_ptr<IQ> iq = boost::dynamic_pointer_cast<IQ>(stanza)) { -					if (iq->getPayload<RosterPayload>()) { -						if (iq->getType() == IQ::Get) { -							session->sendElement(IQ::createResult(iq->getFrom(), iq->getID(), linkLocalRoster_->getRoster())); -							rosterRequested_ = true; -							foreach(const boost::shared_ptr<Presence> presence, linkLocalRoster_->getAllPresence()) { -								session->sendElement(presence); -							} -						} -						else { -							session->sendElement(IQ::createError(iq->getFrom(), iq->getID(), Error::Forbidden, Error::Cancel)); -						} -					} -					if (iq->getPayload<VCard>()) { -						if (iq->getType() == IQ::Get) { -							boost::shared_ptr<VCard> vcard(new VCard()); -							vcard->setNickname(iq->getFrom().getNode()); -							session->sendElement(IQ::createResult(iq->getFrom(), iq->getID(), vcard)); -						} -						else { -							session->sendElement(IQ::createError(iq->getFrom(), iq->getID(), Error::Forbidden, Error::Cancel)); -						} -					} -					else { -						session->sendElement(IQ::createError(iq->getFrom(), iq->getID(), Error::FeatureNotImplemented, Error::Cancel)); -					} -				} -			} -			else { -				JID toJID = stanza->getTo(); -				boost::shared_ptr<Session> outgoingSession =  -						getLinkLocalSessionForJID(toJID); -				if (outgoingSession) { -					outgoingSession->sendElement(stanza); -				} -				else { -					if (linkLocalRoster_->hasItem(toJID)) { -						boost::shared_ptr<LinkLocalConnector> connector = -							getLinkLocalConnectorForJID(toJID); -						if (!connector) { -							connector = boost::shared_ptr<LinkLocalConnector>( -									new LinkLocalConnector( -										toJID,  -										linkLocalRoster_->getHostname(toJID),  -										linkLocalRoster_->getPort(toJID),  -										dnsSDService_, -										boost::shared_ptr<BoostConnection>(new BoostConnection(&boostIOServiceThread_.getIOService())))); -							connector->onConnectFinished.connect( -									boost::bind(&Server::handleConnectFinished, this, connector, _1)); -							connectors_.push_back(connector); -							connector->connect(); -						} -						connector->queueElement(element); -					} -					else { -						session->sendElement(IQ::createError( -								stanza->getFrom(), stanza->getID(),  -								Error::RecipientUnavailable, Error::Wait)); -					} -				} -			} -		} - -		void handleConnectFinished(boost::shared_ptr<LinkLocalConnector> connector, bool error) { -			if (error) { -				std::cerr << "Error connecting" << std::endl; -				// TODO: Send back queued stanzas -			} -			else { -				boost::shared_ptr<OutgoingLinkLocalSession> outgoingSession( -						new OutgoingLinkLocalSession( -							selfJID_, connector->getRemoteJID(), connector->getConnection(), -							&payloadParserFactories_, &payloadSerializers_)); -				foreach(const boost::shared_ptr<Element> element, connector->getQueuedElements()) { -					outgoingSession->queueElement(element); -				} -				registerLinkLocalSession(outgoingSession); -			} -			connectors_.erase(std::remove(connectors_.begin(), connectors_.end(), connector), connectors_.end()); -		} - - -		void registerLinkLocalSession(boost::shared_ptr<Session> session) { -			session->onSessionFinished.connect(boost::bind(&Server::handleLinkLocalSessionFinished, this, session)); -			session->onElementReceived.connect(boost::bind(&Server::handleLinkLocalElementReceived, this, _1, session)); -			linkLocalSessions_.push_back(session); -			tracers_.push_back(boost::shared_ptr<SessionTracer>(new SessionTracer(session))); -			session->startSession(); -		} - -		boost::shared_ptr<Session> getLinkLocalSessionForJID(const JID& jid) { -			foreach(const boost::shared_ptr<Session> session, linkLocalSessions_) { -				if (session->getRemoteJID() == jid) { -					return session; -				} -			} -			return boost::shared_ptr<Session>(); -		} - -		boost::shared_ptr<LinkLocalConnector> getLinkLocalConnectorForJID(const JID& jid) { -			foreach(const boost::shared_ptr<LinkLocalConnector> connector, connectors_) { -				if (connector->getRemoteJID() == jid) { -					return connector; -				} -			} -			return boost::shared_ptr<LinkLocalConnector>(); -		} - -		void handleRosterChanged(boost::shared_ptr<RosterPayload> roster) { -			if (rosterRequested_) { -				boost::shared_ptr<IQ> iq = IQ::createRequest(IQ::Set, serverFromClientSession_->getRemoteJID(), idGenerator_.generateID(), roster); -				iq->setFrom(serverFromClientSession_->getRemoteJID().toBare()); -				serverFromClientSession_->sendElement(iq); -			} -		} - -		void handlePresenceChanged(boost::shared_ptr<Presence> presence) { -			if (rosterRequested_) { -				serverFromClientSession_->sendElement(presence); -			} -		} - -		LinkLocalServiceInfo getLinkLocalServiceInfo(boost::shared_ptr<Presence> presence) { -			LinkLocalServiceInfo info; -			info.setFirstName("Remko"); -			info.setLastName("Tron\xc3\xa7on"); -			info.setEMail("email@example.com"); -			info.setJID(JID("jid@example.com")); -			info.setMessage(presence->getStatus()); -			info.setNick("Remko"); -			switch (presence->getShow()) { -				case StatusShow::Online:  -				case StatusShow::None:  -				case StatusShow::FFC:  -					info.setStatus(LinkLocalServiceInfo::Available); -					break; -				case StatusShow::Away:  -				case StatusShow::XA:  -					info.setStatus(LinkLocalServiceInfo::Away); -					break; -				case StatusShow::DND:  -					info.setStatus(LinkLocalServiceInfo::DND); -					break; -			} -			info.setPort(linkLocalConnectionPort_); -			return info; -		} - -	private: -		IDGenerator idGenerator_; -		BoostIOServiceThread boostIOServiceThread_; -		DummyUserRegistry userRegistry_; -		boost::shared_ptr<DNSSDService> dnsSDService_; -		boost::shared_ptr<LinkLocalRoster> linkLocalRoster_; -		boost::shared_ptr<BoostConnectionServer> serverFromClientConnectionServer_; -		boost::shared_ptr<ServerFromClientSession> serverFromClientSession_; -		boost::shared_ptr<BoostConnectionServer> serverFromNetworkConnectionServer_; -		std::vector< boost::shared_ptr<SessionTracer> > tracers_; -		std::vector< boost::shared_ptr<Session> > linkLocalSessions_; -		std::vector< boost::shared_ptr<LinkLocalConnector> > connectors_; -		FullPayloadParserFactoryCollection payloadParserFactories_; -		FullPayloadSerializerCollection payloadSerializers_; -		bool dnsSDServiceRegistered_; -		bool rosterRequested_; -		int clientConnectionPort_; -		int linkLocalConnectionPort_; -		JID selfJID_; -}; - -int main() { -	SimpleEventLoop eventLoop; -	Server server(5222, 5562); +	Server server(5222, 5562, dnsSDService);  	eventLoop.run();  	return 0;  } | 
 Swift
 Swift