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