From 70e454fd02597c9a71ed89356a572e48256f8349 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Remko=20Tron=C3=A7on?= Date: Sat, 18 Jul 2009 16:10:19 +0200 Subject: Implement roster<->linklocal bridge. 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 #include #include #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(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(new BoostConnectionServer(linkLocalConnectionPort, &boostIOServiceThread_.getIOService())); + serverFromNetworkConnectionServer_->onNewConnection.connect(boost::bind(&Server::handleNewLinkLocalConnection, this, _1)); + serverFromNetworkConnectionServer_->start(); + dnsSDService_ = boost::shared_ptr(new AppleDNSSDService()); linkLocalRoster_ = boost::shared_ptr(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 c) { - boost::shared_ptr 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 c) { + if (serverFromClientSession_) { + c->disconnect(); + } + serverFromClientSession_ = boost::shared_ptr(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) { + std::cout << "Incoming link local connection" << std::endl; } void handleSessionStarted(boost::shared_ptr session) { @@ -82,13 +97,13 @@ class Server { std::cout << "Service registered " << service.name << " " << service.type << " " << service.domain << std::endl; } - void handleSessionFinished(boost::shared_ptr 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_.reset(); + + std::cout << "Service unregistered" << std::endl; + dnsSDServiceRegistered_ = false; + rosterRequested_ = false; + dnsSDService_->unregisterService(); } void handleStanzaReceived(boost::shared_ptr stanza, boost::shared_ptr 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 = boost::dynamic_pointer_cast(stanza)) { if (iq->getPayload()) { - session->sendStanza(IQ::createResult(iq->getFrom(), iq->getID(), boost::shared_ptr(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, linkLocalRoster_->getAllPresence()) { + session->sendStanza(presence); + } + } + else { + session->sendStanza(IQ::createError(iq->getFrom(), iq->getID(), Error::Forbidden, Error::Cancel)); + } } if (iq->getPayload()) { if (iq->getType() == IQ::Get) { @@ -118,6 +142,20 @@ class Server { } } + void handleRosterChanged(boost::shared_ptr roster) { + if (rosterRequested_) { + boost::shared_ptr iq = IQ::createRequest(IQ::Set, serverFromClientSession_->getJID(), idGenerator_.generateID(), roster); + iq->setFrom(serverFromClientSession_->getJID().toBare()); + serverFromClientSession_->sendStanza(iq); + } + } + + void handlePresenceChanged(boost::shared_ptr presence) { + if (rosterRequested_) { + serverFromClientSession_->sendStanza(presence); + } + } + private: IDGenerator idGenerator_; BoostIOServiceThread boostIOServiceThread_; @@ -125,10 +163,12 @@ class Server { boost::shared_ptr dnsSDService_; boost::shared_ptr linkLocalRoster_; boost::shared_ptr serverFromClientConnectionServer_; - std::vector< boost::shared_ptr > serverFromClientSessions_; + boost::shared_ptr serverFromClientSession_; + boost::shared_ptr 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 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 LinkLocalRoster::getRoster() const { + boost::shared_ptr 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 > LinkLocalRoster::getAllPresence() const { + std::vector > 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 LinkLocalRoster::getPresence(const DNSSDService::Service& service, const DNSSDService::ResolveResult& resolveResult) const { + boost::shared_ptr 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 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& 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 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 #include +#include +#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 service); + boost::shared_ptr getRoster() const; + std::vector > getAllPresence() const; + + boost::signal)> onRosterChanged; + boost::signal)> 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 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& address); private: boost::shared_ptr dnsSDService; boost::optional selfService; + typedef std::map ServiceMap; + ServiceMap services; }; } -- cgit v0.10.2-6-g49f6