From 4457bc810a326de8d7895b3f2ff36ade5f1ae1a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be> Date: Sat, 18 Jul 2009 21:04:32 +0200 Subject: Implement incoming linklocal connections. diff --git a/Nim/main.cpp b/Nim/main.cpp index 8166534..15c41c7 100644 --- a/Nim/main.cpp +++ b/Nim/main.cpp @@ -2,6 +2,7 @@ #include <boost/bind.hpp> #include <boost/shared_ptr.hpp> +#include "Swiften/Network/BoostConnectionFactory.h" #include "Swiften/Elements/IQ.h" #include "Swiften/Elements/Presence.h" #include "Swiften/Elements/RosterPayload.h" @@ -17,6 +18,9 @@ #include "Swiften/Elements/Stanza.h" #include "Swiften/LinkLocal/LinkLocalServiceInfo.h" #include "Swiften/LinkLocal/LinkLocalRoster.h" +#include "Swiften/LinkLocal/LinkLocalSession.h" +#include "Swiften/LinkLocal/OutgoingLinkLocalSession.h" +#include "Swiften/LinkLocal/IncomingLinkLocalSession.h" #include "Swiften/LinkLocal/DNSSDService.h" #include "Swiften/LinkLocal/AppleDNSSDService.h" #include "Swiften/Network/ConnectionServer.h" @@ -42,7 +46,7 @@ class DummyUserRegistry : public UserRegistry { class Server { public: - Server(int clientConnectionPort, int linkLocalConnectionPort) : dnsSDServiceRegistered_(false), rosterRequested_(false), clientConnectionPort_(clientConnectionPort), linkLocalConnectionPort_(linkLocalConnectionPort) { + Server(int clientConnectionPort, int linkLocalConnectionPort) : boostConnectionFactory_(&boostIOServiceThread_.getIOService()), 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(); @@ -53,7 +57,6 @@ class Server { dnsSDService_ = boost::shared_ptr<AppleDNSSDService>(new AppleDNSSDService()); 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)); @@ -71,20 +74,40 @@ class Server { serverFromClientSession_->start(); } - void handleNewLinkLocalConnection(boost::shared_ptr<Connection>) { - std::cout << "Incoming link local connection" << std::endl; + 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<LinkLocalSession> session) { + std::cout << "Link local session from " << session->getRemoteJID() << " ended" << std::endl; + linkLocalSessions_.erase(std::remove(linkLocalSessions_.begin(), linkLocalSessions_.end(), session), linkLocalSessions_.end()); + } + + void handleLinkLocalStanzaReceived(boost::shared_ptr<Stanza> stanza, boost::shared_ptr<LinkLocalSession> session) { + JID fromJID = session->getRemoteJID(); + if (!linkLocalRoster_->hasItem(fromJID)) { + return; // TODO: Queue + } + stanza->setFrom(fromJID); + serverFromClientSession_->sendStanza(stanza); + } + void unregisterService() { if (dnsSDServiceRegistered_) { dnsSDServiceRegistered_ = false; @@ -141,6 +164,47 @@ class Server { } } } + else { + JID toJID = stanza->getTo(); + boost::shared_ptr<LinkLocalSession> outgoingSession = + getLinkLocalSessionForJID(toJID); + if (outgoingSession) { + outgoingSession->sendStanza(stanza); + } + else { + if (linkLocalRoster_->hasItem(toJID)) { + boost::shared_ptr<OutgoingLinkLocalSession> outgoingSession( + new OutgoingLinkLocalSession( + selfJID_, toJID, linkLocalRoster_->getHostname(toJID), + dnsSDService_, + &payloadParserFactories_, &payloadSerializers_, + &boostConnectionFactory_)); + registerLinkLocalSession(outgoingSession); + outgoingSession->sendStanza(stanza); + } + else { + session->sendStanza(IQ::createError( + stanza->getFrom(), stanza->getID(), + Error::RecipientUnavailable, Error::Wait)); + } + } + } + } + + void registerLinkLocalSession(boost::shared_ptr<LinkLocalSession> session) { + session->onSessionFinished.connect(boost::bind(&Server::handleLinkLocalSessionFinished, this, session)); + session->onStanzaReceived.connect(boost::bind(&Server::handleLinkLocalStanzaReceived, this, _1, session)); + linkLocalSessions_.push_back(session); + session->start(); + } + + boost::shared_ptr<LinkLocalSession> getLinkLocalSessionForJID(const JID& jid) { + foreach(const boost::shared_ptr<LinkLocalSession> session, linkLocalSessions_) { + if (session->getRemoteJID() == jid) { + return session; + } + } + return boost::shared_ptr<LinkLocalSession>(); } void handleRosterChanged(boost::shared_ptr<RosterPayload> roster) { @@ -186,18 +250,22 @@ class Server { private: IDGenerator idGenerator_; BoostIOServiceThread boostIOServiceThread_; + BoostConnectionFactory boostConnectionFactory_; DummyUserRegistry userRegistry_; boost::shared_ptr<AppleDNSSDService> 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<LinkLocalSession> > linkLocalSessions_; + std::vector< boost::shared_ptr<Stanza> > queuedOutgoingStanzas_; FullPayloadParserFactoryCollection payloadParserFactories_; FullPayloadSerializerCollection payloadSerializers_; bool dnsSDServiceRegistered_; bool rosterRequested_; int clientConnectionPort_; int linkLocalConnectionPort_; + JID selfJID_; }; int main() { diff --git a/Swiften/Base/String.h b/Swiften/Base/String.h index 0da2e39..247a8a3 100644 --- a/Swiften/Base/String.h +++ b/Swiften/Base/String.h @@ -87,6 +87,11 @@ namespace Swift { return *this; } + String& operator=(const String& o) { + data_ = o.data_; + return *this; + } + friend bool operator>(const String& a, const String& b) { return a.data_ > b.data_; } diff --git a/Swiften/Client/Session.cpp b/Swiften/Client/Session.cpp index 2f0e076..6c2a873 100644 --- a/Swiften/Client/Session.cpp +++ b/Swiften/Client/Session.cpp @@ -3,6 +3,7 @@ #include <boost/bind.hpp> #include "Swiften/Network/ConnectionFactory.h" +#include "Swiften/Elements/ProtocolHeader.h" #include "Swiften/StreamStack/StreamStack.h" #include "Swiften/StreamStack/ConnectionLayer.h" #include "Swiften/StreamStack/XMPPLayer.h" @@ -61,7 +62,9 @@ void Session::handleConnected() { } void Session::sendStreamHeader() { - xmppLayer_->writeHeader(jid_.getDomain()); + ProtocolHeader header; + header.setTo(jid_.getDomain()); + xmppLayer_->writeHeader(header); } void Session::initializeStreamStack() { diff --git a/Swiften/Client/UnitTest/SessionTest.cpp b/Swiften/Client/UnitTest/SessionTest.cpp index 45c0996..a11ddde 100644 --- a/Swiften/Client/UnitTest/SessionTest.cpp +++ b/Swiften/Client/UnitTest/SessionTest.cpp @@ -11,6 +11,7 @@ #include "Swiften/StreamStack/TLSLayer.h" #include "Swiften/StreamStack/StreamStack.h" #include "Swiften/StreamStack/WhitespacePingLayer.h" +#include "Swiften/Elements/ProtocolHeader.h" #include "Swiften/Elements/StreamFeatures.h" #include "Swiften/Elements/Element.h" #include "Swiften/Elements/Error.h" @@ -486,6 +487,7 @@ class SessionTest : public CppUnit::TestFixture { assert(false); } + void connect(const HostAddressPort&) { assert(false); } void connect(const String& domain) { if (fail_) { MainEventLoop::postEvent(boost::bind(boost::ref(onDisconnected), Connection::ConnectionError)); @@ -513,8 +515,8 @@ class SessionTest : public CppUnit::TestFixture { parser_ = new XMPPParser(this, &payloadParserFactories_); } - void handleStreamStart(const String&, const String& to, const String&) { - CPPUNIT_ASSERT_EQUAL(domain_, to); + void handleStreamStart(const ProtocolHeader& header) { + CPPUNIT_ASSERT_EQUAL(domain_, header.getTo()); handleEvent(Event::StreamStartEvent); } @@ -548,7 +550,11 @@ class SessionTest : public CppUnit::TestFixture { String serializeEvent(const Event& event) { switch (event.type) { case Event::StreamStartEvent: - return serializer_.serializeHeader("", domain_, ""); + { + ProtocolHeader header; + header.setTo(domain_); + return serializer_.serializeHeader(header); + } case Event::ElementEvent: return serializer_.serializeElement(event.element); case Event::StreamEndEvent: diff --git a/Swiften/Elements/ProtocolHeader.h b/Swiften/Elements/ProtocolHeader.h new file mode 100644 index 0000000..da64811 --- /dev/null +++ b/Swiften/Elements/ProtocolHeader.h @@ -0,0 +1,36 @@ +#pragma once + +#include "Swiften/Base/String.h" + +namespace Swift { + class ProtocolHeader { + public: + ProtocolHeader() : version("1.0") {} + + const String& getTo() const { return to; } + void setTo(const String& a) { + to = a; + } + + const String& getFrom() const { return from; } + void setFrom(const String& a) { + from = a; + } + + const String& getVersion() const { return version; } + void setVersion(const String& a) { + version = a; + } + + const String& getID() const { return id; } + void setID(const String& a) { + id = a; + } + + private: + String to; + String from; + String id; + String version; + }; +} diff --git a/Swiften/LinkLocal/AppleDNSSDService.cpp b/Swiften/LinkLocal/AppleDNSSDService.cpp index d4befd1..521c584 100644 --- a/Swiften/LinkLocal/AppleDNSSDService.cpp +++ b/Swiften/LinkLocal/AppleDNSSDService.cpp @@ -98,7 +98,6 @@ void AppleDNSSDService::stopResolvingService(const Service& service) { void AppleDNSSDService::resolveHostname(const String& hostname, int interfaceIndex) { boost::lock_guard<boost::mutex> lock(sdRefsMutex); - std::cout << "Resolve " << hostname << std::endl; DNSServiceRef hostnameResolveSDRef; DNSServiceErrorType result = DNSServiceGetAddrInfo(&hostnameResolveSDRef, 0, interfaceIndex, kDNSServiceProtocol_IPv4, hostname.getUTF8Data(), &AppleDNSSDService::handleHostnameResolvedGlobal, this); @@ -159,7 +158,6 @@ 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); @@ -193,7 +191,6 @@ 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 @@ -211,7 +208,6 @@ void AppleDNSSDService::doStart() { resolveSDRefs.clear(); for (HostnameSDRefs::const_iterator i = hostnameResolveSDRefs.begin(); i != hostnameResolveSDRefs.end(); ++i) { - std::cout << "Removing hostnameResolve" << std::endl; DNSServiceRefDeallocate(*i); } hostnameResolveSDRefs.clear(); diff --git a/Swiften/LinkLocal/IncomingLinkLocalSession.cpp b/Swiften/LinkLocal/IncomingLinkLocalSession.cpp new file mode 100644 index 0000000..db4b007 --- /dev/null +++ b/Swiften/LinkLocal/IncomingLinkLocalSession.cpp @@ -0,0 +1,69 @@ +#include "Swiften/LinkLocal/IncomingLinkLocalSession.h" + +#include <boost/bind.hpp> + +#include "Swiften/Elements/ProtocolHeader.h" +#include "Swiften/Network/Connection.h" +#include "Swiften/StreamStack/StreamStack.h" +#include "Swiften/StreamStack/ConnectionLayer.h" +#include "Swiften/StreamStack/XMPPLayer.h" +#include "Swiften/Elements/StreamFeatures.h" +#include "Swiften/Elements/IQ.h" +#include "Swiften/SASL/PLAINMessage.h" + +namespace Swift { + +IncomingLinkLocalSession::IncomingLinkLocalSession( + const JID& localJID, + boost::shared_ptr<Connection> connection, + PayloadParserFactoryCollection* payloadParserFactories, + PayloadSerializerCollection* payloadSerializers) : + LinkLocalSession( + localJID, + connection, + payloadParserFactories, + payloadSerializers) { +} + +void IncomingLinkLocalSession::start() { + initializeStreamStack(); +} + +void IncomingLinkLocalSession::handleStreamStart(const ProtocolHeader& incomingHeader) { + remoteJID_ = JID(incomingHeader.getFrom()); + if (!remoteJID_.isValid()) { + finishSession(); + return; + } + ProtocolHeader header; + header.setFrom(getLocalJID()); + getXMPPLayer()->writeHeader(header); + + if (incomingHeader.getVersion() == "1.0") { + getXMPPLayer()->writeElement(boost::shared_ptr<StreamFeatures>(new StreamFeatures())); + } + else { + setInitialized(); + } +} + +void IncomingLinkLocalSession::handleElement(boost::shared_ptr<Element> element) { + boost::shared_ptr<Stanza> stanza = boost::dynamic_pointer_cast<Stanza>(element); + // If we get our first stanza before streamfeatures, our session is implicitly + // initialized + if (stanza && !isInitialized()) { + setInitialized(); + } + + if (isInitialized()) { + if (stanza) { + onStanzaReceived(stanza); + } + else { + std::cerr << "Received unexpected element" << std::endl; + } + } +} + + +} diff --git a/Swiften/LinkLocal/IncomingLinkLocalSession.h b/Swiften/LinkLocal/IncomingLinkLocalSession.h new file mode 100644 index 0000000..d4fa91a --- /dev/null +++ b/Swiften/LinkLocal/IncomingLinkLocalSession.h @@ -0,0 +1,39 @@ +#pragma once + +#include <boost/shared_ptr.hpp> +#include <boost/signal.hpp> + +#include "Swiften/LinkLocal/LinkLocalSession.h" +#include "Swiften/JID/JID.h" +#include "Swiften/Network/Connection.h" + +namespace Swift { + class ProtocolHeader; + class String; + class Element; + class PayloadParserFactoryCollection; + class PayloadSerializerCollection; + + class IncomingLinkLocalSession : public LinkLocalSession { + public: + IncomingLinkLocalSession( + const JID& localJID, + boost::shared_ptr<Connection> connection, + PayloadParserFactoryCollection* payloadParserFactories, + PayloadSerializerCollection* payloadSerializers); + + const JID& getRemoteJID() const { + return remoteJID_; + } + + void start(); + + private: + void handleElement(boost::shared_ptr<Element>); + void handleStreamStart(const ProtocolHeader&); + + private: + bool initialized_; + JID remoteJID_; + }; +} diff --git a/Swiften/LinkLocal/LinkLocalRoster.cpp b/Swiften/LinkLocal/LinkLocalRoster.cpp index 89bfa55..6809377 100644 --- a/Swiften/LinkLocal/LinkLocalRoster.cpp +++ b/Swiften/LinkLocal/LinkLocalRoster.cpp @@ -77,6 +77,7 @@ void LinkLocalRoster::handleServiceAdded(const DNSSDService::Service& service) { if (selfService && *selfService == service) { return; } + std::cout << "Service added: " << service.name << std::endl; dnsSDService->startResolvingService(service); } @@ -93,7 +94,7 @@ void LinkLocalRoster::handleServiceRemoved(const DNSSDService::Service& service) void LinkLocalRoster::handleServiceResolved(const DNSSDService::Service& service, const DNSSDService::ResolveResult& result) { services.insert(std::make_pair(service, result)); - dnsSDService->resolveHostname(result.host); + std::cout << "Service resolved: " << service.name << std::endl; boost::shared_ptr<RosterPayload> roster(new RosterPayload()); roster->addItem(getRosterItem(service, result)); @@ -109,4 +110,22 @@ void LinkLocalRoster::handleStopped(bool error) { std::cout << "DNSSDService stopped: " << error << std::endl; } +bool LinkLocalRoster::hasItem(const JID& j) const { + for(ServiceMap::const_iterator i = services.begin(); i != services.end(); ++i) { + if (getJIDForService(i->first) == j) { + return true; + } + } + return false; +} + +String LinkLocalRoster::getHostname(const JID& j) const { + for(ServiceMap::const_iterator i = services.begin(); i != services.end(); ++i) { + if (getJIDForService(i->first) == j) { + return i->second.host; + } + } + return ""; +} + } diff --git a/Swiften/LinkLocal/LinkLocalRoster.h b/Swiften/LinkLocal/LinkLocalRoster.h index 33dd455..bd774f4 100644 --- a/Swiften/LinkLocal/LinkLocalRoster.h +++ b/Swiften/LinkLocal/LinkLocalRoster.h @@ -23,6 +23,9 @@ namespace Swift { boost::signal<void (boost::shared_ptr<RosterPayload>)> onRosterChanged; boost::signal<void (boost::shared_ptr<Presence>)> onPresenceChanged; + bool hasItem(const JID&) const; + String getHostname(const JID&) const; + private: RosterItemPayload getRosterItem(const DNSSDService::Service& service, const DNSSDService::ResolveResult& info) const; String getRosterName(const DNSSDService::Service& service, const DNSSDService::ResolveResult& info) const; diff --git a/Swiften/LinkLocal/LinkLocalSession.cpp b/Swiften/LinkLocal/LinkLocalSession.cpp new file mode 100644 index 0000000..a308686 --- /dev/null +++ b/Swiften/LinkLocal/LinkLocalSession.cpp @@ -0,0 +1,59 @@ +#include "Swiften/LinkLocal/LinkLocalSession.h" + +#include <boost/bind.hpp> + +#include "Swiften/StreamStack/XMPPLayer.h" +#include "Swiften/StreamStack/StreamStack.h" + +namespace Swift { + +LinkLocalSession::LinkLocalSession( + const JID& localJID, + boost::shared_ptr<Connection> connection, + PayloadParserFactoryCollection* payloadParserFactories, + PayloadSerializerCollection* payloadSerializers) : + localJID(localJID), + payloadParserFactories(payloadParserFactories), + payloadSerializers(payloadSerializers), + connection(connection), + initialized(false) { +} + +LinkLocalSession::~LinkLocalSession() { + delete streamStack; +} + +void LinkLocalSession::initializeStreamStack() { + assert(connection); + xmppLayer = boost::shared_ptr<XMPPLayer>( + new XMPPLayer(payloadParserFactories, payloadSerializers)); + xmppLayer->onStreamStart.connect( + boost::bind(&LinkLocalSession::handleStreamStart, this, _1)); + xmppLayer->onElement.connect( + boost::bind(&LinkLocalSession::handleElement, this, _1)); + //xmppLayer->onError.connect( + // boost::bind(&LinkLocalSession::setError, this, XMLError)); + connection->onDisconnected.connect( + boost::bind(&LinkLocalSession::handleDisconnected, shared_from_this(), _1)); + connectionLayer = boost::shared_ptr<ConnectionLayer>(new ConnectionLayer(connection)); + streamStack = new StreamStack(xmppLayer, connectionLayer); +} + +void LinkLocalSession::finishSession() { + connection->disconnect(); +} + +void LinkLocalSession::sendStanza(boost::shared_ptr<Stanza> stanza) { + xmppLayer->writeElement(stanza); +} + +void LinkLocalSession::handleDisconnected(const boost::optional<Connection::Error>&) { + onSessionFinished(); +} + +void LinkLocalSession::setInitialized() { + initialized = true; + onSessionStarted(); +} + +} diff --git a/Swiften/LinkLocal/LinkLocalSession.h b/Swiften/LinkLocal/LinkLocalSession.h new file mode 100644 index 0000000..9a7ac13 --- /dev/null +++ b/Swiften/LinkLocal/LinkLocalSession.h @@ -0,0 +1,82 @@ +#pragma once + +#include <boost/shared_ptr.hpp> +#include <boost/signal.hpp> +#include <boost/enable_shared_from_this.hpp> + +#include "Swiften/JID/JID.h" +#include "Swiften/Elements/Element.h" +#include "Swiften/Network/Connection.h" +#include "Swiften/StreamStack/ConnectionLayer.h" + +namespace Swift { + class ProtocolHeader; + class StreamStack; + class JID; + class Stanza; + class ByteArray; + class PayloadParserFactoryCollection; + class PayloadSerializerCollection; + class XMPPLayer; + + class LinkLocalSession : + public boost::enable_shared_from_this<LinkLocalSession> { + public: + LinkLocalSession( + const JID& localJID, + boost::shared_ptr<Connection> connection, + PayloadParserFactoryCollection* payloadParserFactories, + PayloadSerializerCollection* payloadSerializers); + virtual ~LinkLocalSession(); + + void finishSession(); + + // TODO: Make non-virtual when OutgoingSession is fixed + virtual void sendStanza(boost::shared_ptr<Stanza>); + + virtual const JID& getRemoteJID() const = 0; + + virtual void start() = 0; + + boost::signal<void (boost::shared_ptr<Stanza>)> onStanzaReceived; + boost::signal<void ()> onSessionFinished; + boost::signal<void ()> onSessionStarted; + boost::signal<void (const ByteArray&)> onDataWritten; + boost::signal<void (const ByteArray&)> onDataRead; + + protected: + void initializeStreamStack(); + + const JID& getLocalJID() const { + return localJID; + } + + boost::shared_ptr<XMPPLayer> getXMPPLayer() const { + return xmppLayer; + } + + // TODO: Remove later + void setConnection(boost::shared_ptr<Connection> c) { + connection = c; + } + + virtual void handleElement(boost::shared_ptr<Element>) = 0; + virtual void handleStreamStart(const ProtocolHeader&) = 0; + + void setInitialized(); + bool isInitialized() const { return initialized; } + + private: + void handleDisconnected(const boost::optional<Connection::Error>& error); + + private: + JID localJID; + PayloadParserFactoryCollection* payloadParserFactories; + PayloadSerializerCollection* payloadSerializers; + boost::shared_ptr<Connection> connection; + boost::shared_ptr<XMPPLayer> xmppLayer; + boost::shared_ptr<ConnectionLayer> connectionLayer; + StreamStack* streamStack; + bool initialized; + }; +} diff --git a/Swiften/LinkLocal/Makefile.inc b/Swiften/LinkLocal/Makefile.inc index 683447c..1d29844 100644 --- a/Swiften/LinkLocal/Makefile.inc +++ b/Swiften/LinkLocal/Makefile.inc @@ -1,7 +1,10 @@ SWIFTEN_SOURCES += \ Swiften/LinkLocal/DNSSDService.cpp \ Swiften/LinkLocal/LinkLocalRoster.cpp \ - Swiften/LinkLocal/LinkLocalServiceInfo.cpp + Swiften/LinkLocal/LinkLocalServiceInfo.cpp \ + Swiften/LinkLocal/IncomingLinkLocalSession.cpp \ + Swiften/LinkLocal/OutgoingLinkLocalSession.cpp \ + Swiften/LinkLocal/LinkLocalSession.cpp ifeq ($(MACOSX),1) diff --git a/Swiften/LinkLocal/OutgoingLinkLocalSession.cpp b/Swiften/LinkLocal/OutgoingLinkLocalSession.cpp new file mode 100644 index 0000000..57f3154 --- /dev/null +++ b/Swiften/LinkLocal/OutgoingLinkLocalSession.cpp @@ -0,0 +1,74 @@ +#include "Swiften/LinkLocal/OutgoingLinkLocalSession.h" + +#include <boost/bind.hpp> + +#include "Swiften/Elements/ProtocolHeader.h" +#include "Swiften/Network/Connection.h" +#include "Swiften/StreamStack/StreamStack.h" +#include "Swiften/LinkLocal/DNSSDService.h" +#include "Swiften/StreamStack/ConnectionLayer.h" +#include "Swiften/StreamStack/XMPPLayer.h" +#include "Swiften/Elements/StreamFeatures.h" +#include "Swiften/Elements/IQ.h" +#include "Swiften/SASL/PLAINMessage.h" + +namespace Swift { + +OutgoingLinkLocalSession::OutgoingLinkLocalSession( + const JID& localJID, + const JID& remoteJID, + const String& hostname, + boost::shared_ptr<DNSSDService> resolver, + PayloadParserFactoryCollection* payloadParserFactories, + PayloadSerializerCollection* payloadSerializers, + ConnectionFactory* connectionFactory) : + LinkLocalSession( + localJID, + boost::shared_ptr<Connection>(), + payloadParserFactories, + payloadSerializers), + resolving_(false), + remoteJID_(remoteJID), + hostname_(hostname), + resolver_(resolver), + connectionFactory_(connectionFactory) { +} + +void OutgoingLinkLocalSession::start() { + resolving_ = true; + //resolver_->onHostnameResolved.connect(boost::bind(&OutgoingLinkLocalSession::handleHostnameResolved, this, _1, _2)); +} + +#if 0 +void OutgoingLinkLocalSession::handleHostnameResolved(const String& hostname, const HostAddress&) { + if (resolving_) { + if (hostname == hostname_) { + boost::shared_ptr<Connection> connection = connectionFactory_->createConnection(); + connection->onConnected.connect(boost::bind(&Session::handleConnected, shared_from_this())); + connection->onDisconnected.connect(boost::bind(&Session::handleDisconnected, shared_from_this(), _1)); + connection_->connect(jid_.getDomain()); + resolving_ = false; + boost:: + } + } +} +#endif + +void OutgoingLinkLocalSession::handleStreamStart(const ProtocolHeader&) { + ProtocolHeader header; + header.setFrom(getLocalJID()); + getXMPPLayer()->writeHeader(header); + setInitialized(); +} + +void OutgoingLinkLocalSession::handleElement(boost::shared_ptr<Element> element) { + if (isInitialized()) { + boost::shared_ptr<Stanza> stanza = boost::dynamic_pointer_cast<Stanza>(element); + if (stanza) { + onStanzaReceived(stanza); + } + } +} + + +} diff --git a/Swiften/LinkLocal/OutgoingLinkLocalSession.h b/Swiften/LinkLocal/OutgoingLinkLocalSession.h new file mode 100644 index 0000000..ae1e86b --- /dev/null +++ b/Swiften/LinkLocal/OutgoingLinkLocalSession.h @@ -0,0 +1,48 @@ +#pragma once + +#include <boost/shared_ptr.hpp> +#include <boost/signal.hpp> +#include <boost/enable_shared_from_this.hpp> + +#include "Swiften/LinkLocal/LinkLocalSession.h" +#include "Swiften/JID/JID.h" + +namespace Swift { + class ConnectionFactory; + class HostAddress; + class String; + class Element; + class PayloadParserFactoryCollection; + class PayloadSerializerCollection; + class DNSSDService; + + class OutgoingLinkLocalSession : public LinkLocalSession, public boost::enable_shared_from_this<OutgoingLinkLocalSession> { + public: + OutgoingLinkLocalSession( + const JID& localJID, + const JID& remoteJID, + const String& hostname, + boost::shared_ptr<DNSSDService> resolver, + PayloadParserFactoryCollection* payloadParserFactories, + PayloadSerializerCollection* payloadSerializers, + ConnectionFactory* connectionFactory); + + const JID& getRemoteJID() const { + return remoteJID_; + } + + void start(); + + private: + void handleElement(boost::shared_ptr<Element>); + void handleStreamStart(const ProtocolHeader&); + //void handleHostnameResolved(const String& hostname, const HostAddress& address); + + private: + bool resolving_; + JID remoteJID_; + String hostname_; + boost::shared_ptr<DNSSDService> resolver_; + ConnectionFactory* connectionFactory_; + }; +} diff --git a/Swiften/Network/BoostConnection.cpp b/Swiften/Network/BoostConnection.cpp index d374221..b064c7a 100644 --- a/Swiften/Network/BoostConnection.cpp +++ b/Swiften/Network/BoostConnection.cpp @@ -51,18 +51,21 @@ void BoostConnection::listen() { void BoostConnection::connect(const String& domain) { DomainNameResolver resolver; try { - HostAddressPort addressPort = resolver.resolve(domain.getUTF8String()); - boost::asio::ip::tcp::endpoint endpoint( - boost::asio::ip::address::from_string(addressPort.getAddress().toString()), addressPort.getPort()); - socket_.async_connect( - endpoint, - boost::bind(&BoostConnection::handleConnectFinished, shared_from_this(), boost::asio::placeholders::error)); + connect(resolver.resolve(domain.getUTF8String())); } catch (const DomainNameResolveException& e) { onDisconnected(DomainNameResolveError); } } +void BoostConnection::connect(const HostAddressPort& addressPort) { + boost::asio::ip::tcp::endpoint endpoint( + boost::asio::ip::address::from_string(addressPort.getAddress().toString()), addressPort.getPort()); + socket_.async_connect( + endpoint, + boost::bind(&BoostConnection::handleConnectFinished, shared_from_this(), boost::asio::placeholders::error)); +} + void BoostConnection::disconnect() { //MainEventLoop::removeEventsFromOwner(shared_from_this()); socket_.close(); diff --git a/Swiften/Network/BoostConnection.h b/Swiften/Network/BoostConnection.h index 76b6588..0ed6874 100644 --- a/Swiften/Network/BoostConnection.h +++ b/Swiften/Network/BoostConnection.h @@ -21,6 +21,7 @@ namespace Swift { virtual void listen(); virtual void connect(const String& domain); + virtual void connect(const HostAddressPort& address); virtual void disconnect(); virtual void write(const ByteArray& data); diff --git a/Swiften/Network/Connection.h b/Swiften/Network/Connection.h index c34c21d..25f9a16 100644 --- a/Swiften/Network/Connection.h +++ b/Swiften/Network/Connection.h @@ -1,5 +1,4 @@ -#ifndef SWIFTEN_CONNECTION_H -#define SWIFTEN_CONNECTION_H +#pragma once #include <boost/signals.hpp> @@ -7,6 +6,8 @@ #include "Swiften/Base/String.h" namespace Swift { + class HostAddressPort; + class Connection { public: enum Error { @@ -20,6 +21,7 @@ namespace Swift { virtual ~Connection() {} virtual void listen() = 0; + virtual void connect(const HostAddressPort& address) = 0; virtual void connect(const String& domain) = 0; virtual void disconnect() = 0; virtual void write(const ByteArray& data) = 0; @@ -30,5 +32,3 @@ namespace Swift { boost::signal<void (const ByteArray&)> onDataRead; }; } - -#endif diff --git a/Swiften/Parser/UnitTest/XMPPParserTest.cpp b/Swiften/Parser/UnitTest/XMPPParserTest.cpp index a8b805e..ecdd565 100644 --- a/Swiften/Parser/UnitTest/XMPPParserTest.cpp +++ b/Swiften/Parser/UnitTest/XMPPParserTest.cpp @@ -2,6 +2,7 @@ #include <cppunit/extensions/TestFactoryRegistry.h> #include <vector> +#include "Swiften/Elements/ProtocolHeader.h" #include "Swiften/Base/String.h" #include "Swiften/Parser/XMPPParser.h" #include "Swiften/Parser/ElementParser.h" @@ -165,8 +166,8 @@ class XMPPParserTest : public CppUnit::TestFixture Client() {} - void handleStreamStart(const String& from, const String& to, const String& id) { - events.push_back(Event(StreamStart, from, to, id)); + void handleStreamStart(const ProtocolHeader& header) { + events.push_back(Event(StreamStart, header.getFrom(), header.getTo(), header.getID())); } void handleElement(boost::shared_ptr<Element> element) { diff --git a/Swiften/Parser/XMPPParser.cpp b/Swiften/Parser/XMPPParser.cpp index 0f04cca..f97bed8 100644 --- a/Swiften/Parser/XMPPParser.cpp +++ b/Swiften/Parser/XMPPParser.cpp @@ -3,6 +3,7 @@ #include <iostream> #include <cassert> +#include "Swiften/Elements/ProtocolHeader.h" #include "Swiften/Base/String.h" #include "Swiften/Parser/XMLParser.h" #include "Swiften/Parser/PlatformXMLParserFactory.h" @@ -54,7 +55,12 @@ bool XMPPParser::parse(const String& data) { void XMPPParser::handleStartElement(const String& element, const String& ns, const AttributeMap& attributes) { if (!inStream()) { if (element == "stream" && ns == "http://etherx.jabber.org/streams") { - client_->handleStreamStart(attributes.getAttribute("from"), attributes.getAttribute("to"), attributes.getAttribute("id")); + ProtocolHeader header; + header.setFrom(attributes.getAttribute("from")); + header.setTo(attributes.getAttribute("to")); + header.setID(attributes.getAttribute("id")); + header.setVersion(attributes.getAttribute("version")); + client_->handleStreamStart(header); } else { parseErrorOccurred_ = true; diff --git a/Swiften/Parser/XMPPParserClient.h b/Swiften/Parser/XMPPParserClient.h index fb81df8..b8f8e46 100644 --- a/Swiften/Parser/XMPPParserClient.h +++ b/Swiften/Parser/XMPPParserClient.h @@ -1,5 +1,4 @@ -#ifndef SWIFTEN_XMPPPARSERCLIENT_H -#define SWIFTEN_XMPPPARSERCLIENT_H +#pragma once #include <boost/shared_ptr.hpp> @@ -7,15 +6,14 @@ namespace Swift { class String; + class ProtocolHeader; class XMPPParserClient { public: virtual ~XMPPParserClient(); - virtual void handleStreamStart(const String& from, const String& to, const String& id) = 0; + virtual void handleStreamStart(const ProtocolHeader&) = 0; virtual void handleElement(boost::shared_ptr<Element>) = 0; virtual void handleStreamEnd() = 0; }; } - -#endif diff --git a/Swiften/Serializer/XMPPSerializer.cpp b/Swiften/Serializer/XMPPSerializer.cpp index 6139586..660bb37 100644 --- a/Swiften/Serializer/XMPPSerializer.cpp +++ b/Swiften/Serializer/XMPPSerializer.cpp @@ -3,6 +3,7 @@ #include <boost/bind.hpp> #include <iostream> +#include "Swiften/Elements/ProtocolHeader.h" #include "Swiften/Base/foreach.h" #include "Swiften/Serializer/CompressRequestSerializer.h" #include "Swiften/Serializer/CompressFailureSerializer.h" @@ -34,16 +35,19 @@ XMPPSerializer::XMPPSerializer(PayloadSerializerCollection* payloadSerializers) serializers_.push_back(boost::shared_ptr<ElementSerializer>(new StreamFeaturesSerializer())); } -String XMPPSerializer::serializeHeader(const String& from, const String& to, const String& id) const { - String result = "<?xml version=\"1.0\"?><stream:stream xmlns=\"jabber:client\" xmlns:stream=\"http://etherx.jabber.org/streams\" version=\"1.0\""; - if (!from.isEmpty()) { - result += " from=\"" + from + "\""; +String XMPPSerializer::serializeHeader(const ProtocolHeader& header) const { + String result = "<?xml version=\"1.0\"?><stream:stream xmlns=\"jabber:client\" xmlns:stream=\"http://etherx.jabber.org/streams\""; + if (!header.getFrom().isEmpty()) { + result += " from=\"" + header.getFrom() + "\""; } - if (!to.isEmpty()) { - result += " to=\"" + to + "\""; + if (!header.getTo().isEmpty()) { + result += " to=\"" + header.getTo() + "\""; } - if (!id.isEmpty()) { - result += " id=\"" + id + "\""; + if (!header.getID().isEmpty()) { + result += " id=\"" + header.getID() + "\""; + } + if (!header.getVersion().isEmpty()) { + result += " version=\"" + header.getVersion() + "\""; } result += ">"; return result; diff --git a/Swiften/Serializer/XMPPSerializer.h b/Swiften/Serializer/XMPPSerializer.h index f77e14b..38ba3ff 100644 --- a/Swiften/Serializer/XMPPSerializer.h +++ b/Swiften/Serializer/XMPPSerializer.h @@ -1,5 +1,4 @@ -#ifndef SWIFTEN_XMPPSERIALIZER_H -#define SWIFTEN_XMPPSERIALIZER_H +#pragma once #include <boost/shared_ptr.hpp> #include <vector> @@ -11,12 +10,13 @@ namespace Swift { class PayloadSerializerCollection; class CompressRequestSerializer; + class ProtocolHeader; class XMPPSerializer { public: XMPPSerializer(PayloadSerializerCollection*); - String serializeHeader(const String& from, const String& to, const String& id = "") const; + String serializeHeader(const ProtocolHeader&) const; String serializeElement(boost::shared_ptr<Element> stanza) const; String serializeFooter() const; @@ -24,5 +24,3 @@ namespace Swift { std::vector< boost::shared_ptr<ElementSerializer> > serializers_; }; } - -#endif diff --git a/Swiften/Server/ServerFromClientSession.cpp b/Swiften/Server/ServerFromClientSession.cpp index 9a3cf83..45df3be 100644 --- a/Swiften/Server/ServerFromClientSession.cpp +++ b/Swiften/Server/ServerFromClientSession.cpp @@ -2,6 +2,7 @@ #include <boost/bind.hpp> +#include "Swiften/Elements/ProtocolHeader.h" #include "Swiften/Server/UserRegistry.h" #include "Swiften/Network/Connection.h" #include "Swiften/StreamStack/StreamStack.h" @@ -42,7 +43,7 @@ ServerFromClientSession::~ServerFromClientSession() { void ServerFromClientSession::start() { xmppLayer_->onStreamStart.connect( - boost::bind(&ServerFromClientSession::handleStreamStart, this, _2)); + boost::bind(&ServerFromClientSession::handleStreamStart, this, _1)); xmppLayer_->onElement.connect( boost::bind(&ServerFromClientSession::handleElement, this, _1)); //xmppLayer_->onError.connect( @@ -99,9 +100,12 @@ void ServerFromClientSession::handleElement(boost::shared_ptr<Element> element) } } -void ServerFromClientSession::handleStreamStart(const String& domain) { - domain_ = JID("", domain); - xmppLayer_->writeHeader(domain, id_); +void ServerFromClientSession::handleStreamStart(const ProtocolHeader& incomingHeader) { + domain_ = JID("", incomingHeader.getTo()); + ProtocolHeader header; + header.setFrom(incomingHeader.getTo()); + header.setID(id_); + xmppLayer_->writeHeader(header); boost::shared_ptr<StreamFeatures> features(new StreamFeatures()); if (!authenticated_) { diff --git a/Swiften/Server/ServerFromClientSession.h b/Swiften/Server/ServerFromClientSession.h index e7df99d..733c428 100644 --- a/Swiften/Server/ServerFromClientSession.h +++ b/Swiften/Server/ServerFromClientSession.h @@ -9,6 +9,7 @@ #include "Swiften/Network/Connection.h" namespace Swift { + class ProtocolHeader; class Element; class Stanza; class PayloadParserFactoryCollection; @@ -51,7 +52,7 @@ namespace Swift { private: void handleDisconnected(const boost::optional<Connection::Error>& error); void handleElement(boost::shared_ptr<Element>); - void handleStreamStart(const String& domain); + void handleStreamStart(const ProtocolHeader& header); private: String id_; diff --git a/Swiften/StreamStack/UnitTest/XMPPLayerTest.cpp b/Swiften/StreamStack/UnitTest/XMPPLayerTest.cpp index f60c370..e284ba9 100644 --- a/Swiften/StreamStack/UnitTest/XMPPLayerTest.cpp +++ b/Swiften/StreamStack/UnitTest/XMPPLayerTest.cpp @@ -3,6 +3,7 @@ #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> +#include "Swiften/Elements/ProtocolHeader.h" #include "Swiften/Elements/Presence.h" #include "Swiften/Base/ByteArray.h" #include "Swiften/StreamStack/XMPPLayer.h" @@ -68,9 +69,11 @@ class XMPPLayerTest : public CppUnit::TestFixture void testWriteHeader() { testling_->onWriteData.connect(boost::bind(&XMPPLayerTest::handleWriteData, this, _1)); - testling_->writeHeader("example.com"); + ProtocolHeader header; + header.setTo("example.com"); + testling_->writeHeader(header); - CPPUNIT_ASSERT_EQUAL(String("<?xml version=\"1.0\"?><stream:stream xmlns=\"jabber:client\" xmlns:stream=\"http://etherx.jabber.org/streams\" version=\"1.0\" to=\"example.com\">"), dataReceived_); + CPPUNIT_ASSERT_EQUAL(String("<?xml version=\"1.0\"?><stream:stream xmlns=\"jabber:client\" xmlns:stream=\"http://etherx.jabber.org/streams\" to=\"example.com\" version=\"1.0\">"), dataReceived_); } void testWriteElement() { diff --git a/Swiften/StreamStack/XMPPLayer.cpp b/Swiften/StreamStack/XMPPLayer.cpp index 73d763a..b87cb4a 100644 --- a/Swiften/StreamStack/XMPPLayer.cpp +++ b/Swiften/StreamStack/XMPPLayer.cpp @@ -1,6 +1,7 @@ #include "Swiften/StreamStack/XMPPLayer.h" #include "Swiften/Parser/XMPPParser.h" #include "Swiften/Serializer/XMPPSerializer.h" +#include "Swiften/Elements/ProtocolHeader.h" namespace Swift { @@ -20,12 +21,8 @@ XMPPLayer::~XMPPLayer() { delete xmppParser_; } -void XMPPLayer::writeHeader(const String& to) { - onWriteData(ByteArray(xmppSerializer_->serializeHeader("", to))); -} - -void XMPPLayer::writeHeader(const String& from, const String& id) { - onWriteData(ByteArray(xmppSerializer_->serializeHeader(from, "", id))); +void XMPPLayer::writeHeader(const ProtocolHeader& header) { + onWriteData(ByteArray(xmppSerializer_->serializeHeader(header))); } void XMPPLayer::writeFooter() { @@ -60,8 +57,8 @@ void XMPPLayer::doResetParser() { resetParserAfterParse_ = false; } -void XMPPLayer::handleStreamStart(const String& from, const String& to, const String& id) { - onStreamStart(from, to, id); +void XMPPLayer::handleStreamStart(const ProtocolHeader& header) { + onStreamStart(header); } void XMPPLayer::handleElement(boost::shared_ptr<Element> stanza) { diff --git a/Swiften/StreamStack/XMPPLayer.h b/Swiften/StreamStack/XMPPLayer.h index 7437112..7974811 100644 --- a/Swiften/StreamStack/XMPPLayer.h +++ b/Swiften/StreamStack/XMPPLayer.h @@ -1,5 +1,4 @@ -#ifndef SWIFTEN_XMPPLAYER_H -#define SWIFTEN_XMPPLAYER_H +#pragma once #include <boost/shared_ptr.hpp> #include <boost/signal.hpp> @@ -10,6 +9,7 @@ #include "Swiften/Parser/XMPPParserClient.h" namespace Swift { + class ProtocolHeader; class XMPPParser; class PayloadParserFactoryCollection; class XMPPSerializer; @@ -22,8 +22,7 @@ namespace Swift { PayloadSerializerCollection* payloadSerializers); ~XMPPLayer(); - void writeHeader(const String& from, const String& id); - void writeHeader(const String& to); + void writeHeader(const ProtocolHeader& header); void writeFooter(); void writeElement(boost::shared_ptr<Element>); void writeData(const String& data); @@ -32,14 +31,14 @@ namespace Swift { void resetParser(); public: - boost::signal<void (const String& /* from */, const String& /* to */ , const String& /* id */)> onStreamStart; + boost::signal<void (const ProtocolHeader&)> onStreamStart; boost::signal<void (boost::shared_ptr<Element>)> onElement; boost::signal<void (const ByteArray&)> onWriteData; boost::signal<void (const ByteArray&)> onDataRead; boost::signal<void ()> onError; private: - void handleStreamStart(const String&, const String&, const String&); + void handleStreamStart(const ProtocolHeader&); void handleElement(boost::shared_ptr<Element>); void handleStreamEnd(); @@ -54,5 +53,3 @@ namespace Swift { bool inParser_; }; } - -#endif -- cgit v0.10.2-6-g49f6