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