From 4052a822acd9da9dab6a8e2343c6170fb08dd8d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Remko=20Tron=C3=A7on?= Date: Sat, 18 Jul 2009 16:48:20 +0200 Subject: Implement outgoing presence bridge. diff --git a/Nim/main.cpp b/Nim/main.cpp index 024ecd1..8166534 100644 --- a/Nim/main.cpp +++ b/Nim/main.cpp @@ -1,5 +1,3 @@ -// TODO: Prohibit multiple logins - #include #include #include @@ -54,6 +52,8 @@ class Server { serverFromNetworkConnectionServer_->start(); dnsSDService_ = boost::shared_ptr(new AppleDNSSDService()); + dnsSDService_->onServiceRegistered.connect(boost::bind(&Server::handleServiceRegistered, this, _1)); + 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)); @@ -67,7 +67,6 @@ class Server { } 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(); } @@ -76,34 +75,21 @@ class Server { std::cout << "Incoming link local connection" << std::endl; } - void handleSessionStarted(boost::shared_ptr session) { - if (!dnsSDServiceRegistered_) { - dnsSDServiceRegistered_ = true; - dnsSDService_->onServiceRegistered.connect(boost::bind(&Server::handleServiceRegistered, this, _1)); - LinkLocalServiceInfo info; - info.setFirstName("Remko"); - info.setLastName("Tron\xc3\xa7on"); - info.setEMail("email@example.com"); - info.setJID(JID("jid@example.com")); - info.setMessage("I'm not Here"); - info.setNick("Remko"); - info.setStatus(LinkLocalServiceInfo::Away); - info.setPort(linkLocalConnectionPort_); - dnsSDService_->registerService(session->getJID().toBare().toString(), linkLocalConnectionPort_, info); - } - } - void handleServiceRegistered(const DNSSDService::Service& service) { std::cout << "Service registered " << service.name << " " << service.type << " " << service.domain << std::endl; } void handleSessionFinished(boost::shared_ptr) { serverFromClientSession_.reset(); - - std::cout << "Service unregistered" << std::endl; - dnsSDServiceRegistered_ = false; + unregisterService(); rosterRequested_ = false; - dnsSDService_->unregisterService(); + } + + void unregisterService() { + if (dnsSDServiceRegistered_) { + dnsSDServiceRegistered_ = false; + dnsSDService_->unregisterService(); + } } void handleStanzaReceived(boost::shared_ptr stanza, boost::shared_ptr session) { @@ -111,7 +97,22 @@ class Server { if (!stanza->getTo().isValid()) { stanza->setTo(JID(session->getDomain())); } - if (!stanza->getTo().isValid() || stanza->getTo() == session->getDomain() || stanza->getTo() == session->getJID().toBare()) { + + if (boost::shared_ptr presence = boost::dynamic_pointer_cast(stanza)) { + if (presence->getType() == Presence::Available) { + if (!dnsSDServiceRegistered_) { + dnsSDServiceRegistered_ = true; + dnsSDService_->registerService(session->getJID().toBare().toString(), linkLocalConnectionPort_, getLinkLocalServiceInfo(presence)); + } + else { + dnsSDService_->updateService(getLinkLocalServiceInfo(presence)); + } + } + else { + unregisterService(); + } + } + else 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()) { if (iq->getType() == IQ::Get) { @@ -156,6 +157,32 @@ class Server { } } + LinkLocalServiceInfo getLinkLocalServiceInfo(boost::shared_ptr 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_; diff --git a/Swiften/LinkLocal/AppleDNSSDService.cpp b/Swiften/LinkLocal/AppleDNSSDService.cpp index 18cdcb0..d4befd1 100644 --- a/Swiften/LinkLocal/AppleDNSSDService.cpp +++ b/Swiften/LinkLocal/AppleDNSSDService.cpp @@ -55,6 +55,13 @@ void AppleDNSSDService::registerService(const String& name, int port, const Link interruptSelect(); } +void AppleDNSSDService::updateService(const LinkLocalServiceInfo& info) { + boost::lock_guard lock(sdRefsMutex); + assert(registerSDRef); + ByteArray txtRecord = info.toTXTRecord(); + DNSServiceUpdateRecord(registerSDRef, NULL, NULL, txtRecord.getSize(), txtRecord.getData(), 0); +} + void AppleDNSSDService::unregisterService() { boost::lock_guard lock(sdRefsMutex); @@ -91,6 +98,7 @@ void AppleDNSSDService::stopResolvingService(const Service& service) { void AppleDNSSDService::resolveHostname(const String& hostname, int interfaceIndex) { boost::lock_guard lock(sdRefsMutex); + std::cout << "Resolve " << hostname << std::endl; DNSServiceRef hostnameResolveSDRef; DNSServiceErrorType result = DNSServiceGetAddrInfo(&hostnameResolveSDRef, 0, interfaceIndex, kDNSServiceProtocol_IPv4, hostname.getUTF8Data(), &AppleDNSSDService::handleHostnameResolvedGlobal, this); @@ -110,11 +118,14 @@ void AppleDNSSDService::doStart() { onStarted(); // Listen for new services - assert(!browseSDRef); - DNSServiceErrorType result = DNSServiceBrowse(&browseSDRef, 0, 0, "_presence._tcp", 0, &AppleDNSSDService::handleServiceDiscoveredGlobal , this); - if (result != kDNSServiceErr_NoError) { - std::cerr << "Error creating browse query" << std::endl; - haveError = true; + { + boost::lock_guard lock(sdRefsMutex); + assert(!browseSDRef); + DNSServiceErrorType result = DNSServiceBrowse(&browseSDRef, 0, 0, "_presence._tcp", 0, &AppleDNSSDService::handleServiceDiscoveredGlobal , this); + if (result != kDNSServiceErr_NoError) { + std::cerr << "Error creating browse query" << std::endl; + haveError = true; + } } // Run the main loop @@ -148,6 +159,7 @@ void AppleDNSSDService::doStart() { // Hostname resolving for (HostnameSDRefs::const_iterator i = hostnameResolveSDRefs.begin(); i != hostnameResolveSDRefs.end(); ++i) { + std::cout << "Adding ostname resolve " << std::endl; int hostnameResolveSocket = DNSServiceRefSockFD(*i); maxSocket = std::max(maxSocket, hostnameResolveSocket); FD_SET(hostnameResolveSocket, &fdSet); @@ -181,6 +193,7 @@ void AppleDNSSDService::doStart() { for (HostnameSDRefs::const_iterator i = hostnameResolveSDRefs.begin(); i != hostnameResolveSDRefs.end(); ++i) { if (FD_ISSET(DNSServiceRefSockFD(*i), &fdSet)) { DNSServiceProcessResult(*i); + std::cout << "Removing hostnameResolve" << std::endl; hostnameResolveSDRefs.erase(std::remove(hostnameResolveSDRefs.begin(), hostnameResolveSDRefs.end(), *i), hostnameResolveSDRefs.end()); DNSServiceRefDeallocate(*i); break; // Stop the loop, because we removed an element @@ -189,23 +202,28 @@ void AppleDNSSDService::doStart() { } } - for (ServiceSDRefMap::const_iterator i = resolveSDRefs.begin(); i != resolveSDRefs.end(); ++i) { - DNSServiceRefDeallocate(i->second); - } - resolveSDRefs.clear(); + { + boost::lock_guard lock(sdRefsMutex); - for (HostnameSDRefs::const_iterator i = hostnameResolveSDRefs.begin(); i != hostnameResolveSDRefs.end(); ++i) { - DNSServiceRefDeallocate(*i); - } - hostnameResolveSDRefs.clear(); + for (ServiceSDRefMap::const_iterator i = resolveSDRefs.begin(); i != resolveSDRefs.end(); ++i) { + DNSServiceRefDeallocate(i->second); + } + resolveSDRefs.clear(); - if (registerSDRef) { - DNSServiceRefDeallocate(registerSDRef); - registerSDRef = NULL; - } + for (HostnameSDRefs::const_iterator i = hostnameResolveSDRefs.begin(); i != hostnameResolveSDRefs.end(); ++i) { + std::cout << "Removing hostnameResolve" << std::endl; + DNSServiceRefDeallocate(*i); + } + hostnameResolveSDRefs.clear(); + + if (registerSDRef) { + DNSServiceRefDeallocate(registerSDRef); + registerSDRef = NULL; + } - DNSServiceRefDeallocate(browseSDRef); - browseSDRef = NULL; + DNSServiceRefDeallocate(browseSDRef); + browseSDRef = NULL; + } MainEventLoop::postEvent(boost::bind(boost::ref(onStopped), haveError), shared_from_this()); } diff --git a/Swiften/LinkLocal/AppleDNSSDService.h b/Swiften/LinkLocal/AppleDNSSDService.h index cdeafed..fe4a648 100644 --- a/Swiften/LinkLocal/AppleDNSSDService.h +++ b/Swiften/LinkLocal/AppleDNSSDService.h @@ -18,6 +18,7 @@ namespace Swift { virtual void stop(); virtual void registerService(const String& name, int port, const LinkLocalServiceInfo&); + virtual void updateService(const LinkLocalServiceInfo&); virtual void unregisterService(); virtual void startResolvingService(const Service&); diff --git a/Swiften/LinkLocal/DNSSDService.h b/Swiften/LinkLocal/DNSSDService.h index 3dd8c7b..9689352 100644 --- a/Swiften/LinkLocal/DNSSDService.h +++ b/Swiften/LinkLocal/DNSSDService.h @@ -55,6 +55,7 @@ namespace Swift { virtual void stop() = 0; virtual void registerService(const String& name, int port, const LinkLocalServiceInfo&) = 0; + virtual void updateService(const LinkLocalServiceInfo&) = 0; virtual void unregisterService() = 0; virtual void startResolvingService(const Service&) = 0; diff --git a/Swiften/LinkLocal/LinkLocalRoster.cpp b/Swiften/LinkLocal/LinkLocalRoster.cpp index aedea77..89bfa55 100644 --- a/Swiften/LinkLocal/LinkLocalRoster.cpp +++ b/Swiften/LinkLocal/LinkLocalRoster.cpp @@ -81,6 +81,9 @@ void LinkLocalRoster::handleServiceAdded(const DNSSDService::Service& service) { } void LinkLocalRoster::handleServiceRemoved(const DNSSDService::Service& service) { + if (selfService && *selfService == service) { + return; + } dnsSDService->stopResolvingService(service); services.erase(service); boost::shared_ptr roster(new RosterPayload()); -- cgit v0.10.2-6-g49f6