summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRemko Tronçon <git@el-tramo.be>2009-07-20 10:02:41 (GMT)
committerRemko Tronçon <git@el-tramo.be>2009-07-20 10:04:14 (GMT)
commit6c181e11f30cfb58688f327326a03f268ee3790a (patch)
treeb987c7b9052dc3adeeae170e0e6432dc3b98fb44
parent4a34df5d9861041aa7c984b55d2df13d7cb0e7d1 (diff)
downloadswift-contrib-6c181e11f30cfb58688f327326a03f268ee3790a.zip
swift-contrib-6c181e11f30cfb58688f327326a03f268ee3790a.tar.bz2
Move Slimber server out of main.
-rw-r--r--Slimber/.gitignore2
-rw-r--r--Slimber/Makefile.inc1
-rw-r--r--Slimber/Server.cpp279
-rw-r--r--Slimber/Server.h76
-rw-r--r--Slimber/main.cpp338
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;
}