summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTobias Markmann <tm@ayena.de>2015-01-09 16:39:11 (GMT)
committerSwift Review <review@swift.im>2015-02-11 09:35:21 (GMT)
commit779f0d57bc9d90300aad0b1386dc937612ac35f4 (patch)
tree2b7beb4db6af92eef45a6adaf0118d3ba149056b /Swiften/FileTransfer
parent66567c962202920b0d6bc06029ed37565cd4a81c (diff)
downloadswift-779f0d57bc9d90300aad0b1386dc937612ac35f4.zip
swift-779f0d57bc9d90300aad0b1386dc937612ac35f4.tar.bz2
Support domain names in S5B proxy <streamhost> tags.
S5BProxyManager now resolves DNS names of proxy entries discovered via service discovery. Test-Information: Tested against a XMPP installation that uses domain names in proxy entires. Change-Id: I728243333ec6e62e86f088f2a7b6e222c629757b
Diffstat (limited to 'Swiften/FileTransfer')
-rw-r--r--Swiften/FileTransfer/FileTransferManagerImpl.cpp3
-rw-r--r--Swiften/FileTransfer/FileTransferManagerImpl.h16
-rw-r--r--Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.cpp109
-rw-r--r--Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.h49
-rw-r--r--Swiften/FileTransfer/SOCKS5BytestreamProxyFinder.h11
-rw-r--r--Swiften/FileTransfer/UnitTest/IncomingJingleFileTransferTest.cpp8
6 files changed, 158 insertions, 38 deletions
diff --git a/Swiften/FileTransfer/FileTransferManagerImpl.cpp b/Swiften/FileTransfer/FileTransferManagerImpl.cpp
index f439197..ab4cb5c 100644
--- a/Swiften/FileTransfer/FileTransferManagerImpl.cpp
+++ b/Swiften/FileTransfer/FileTransferManagerImpl.cpp
@@ -48,6 +48,7 @@ FileTransferManagerImpl::FileTransferManagerImpl(
ConnectionFactory* connectionFactory,
ConnectionServerFactory* connectionServerFactory,
TimerFactory* timerFactory,
+ DomainNameResolver* domainNameResolver,
NetworkEnvironment* networkEnvironment,
NATTraverser* natTraverser,
CryptoProvider* crypto) :
@@ -60,7 +61,7 @@ FileTransferManagerImpl::FileTransferManagerImpl(
bytestreamRegistry = new SOCKS5BytestreamRegistry();
s5bServerManager = new SOCKS5BytestreamServerManager(
bytestreamRegistry, connectionServerFactory, networkEnvironment, natTraverser);
- bytestreamProxy = new SOCKS5BytestreamProxiesManager(connectionFactory, timerFactory);
+ bytestreamProxy = new SOCKS5BytestreamProxiesManager(connectionFactory, timerFactory, domainNameResolver, iqRouter, JID(ownFullJID.getDomain()));
transporterFactory = new DefaultFileTransferTransporterFactory(
bytestreamRegistry,
diff --git a/Swiften/FileTransfer/FileTransferManagerImpl.h b/Swiften/FileTransfer/FileTransferManagerImpl.h
index 678261a..de6e857 100644
--- a/Swiften/FileTransfer/FileTransferManagerImpl.h
+++ b/Swiften/FileTransfer/FileTransferManagerImpl.h
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (c) 2013 Isode Limited.
+ * Copyright (c) 2013-2015 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
@@ -33,21 +33,22 @@
namespace Swift {
class ConnectionFactory;
class ConnectionServerFactory;
- class SOCKS5BytestreamServerManager;
+ class CryptoProvider;
+ class DomainNameResolver;
class EntityCapsProvider;
+ class FileTransferTransporterFactory;
class IQRouter;
class IncomingFileTransferManager;
class JingleSessionManager;
- class OutgoingFileTransferManager;
class NATTraverser;
+ class NetworkEnvironment;
+ class OutgoingFileTransferManager;
class PresenceOracle;
class ReadBytestream;
- class FileTransferTransporterFactory;
- class SOCKS5BytestreamRegistry;
class SOCKS5BytestreamProxiesManager;
+ class SOCKS5BytestreamRegistry;
+ class SOCKS5BytestreamServerManager;
class TimerFactory;
- class CryptoProvider;
- class NetworkEnvironment;
class SWIFTEN_API FileTransferManagerImpl : public FileTransferManager {
public:
@@ -60,6 +61,7 @@ namespace Swift {
ConnectionFactory* connectionFactory,
ConnectionServerFactory* connectionServerFactory,
TimerFactory* timerFactory,
+ DomainNameResolver* domainNameResolver,
NetworkEnvironment* networkEnvironment,
NATTraverser* natTraverser,
CryptoProvider* crypto);
diff --git a/Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.cpp b/Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.cpp
index 0b94763..ef0a733 100644
--- a/Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.cpp
+++ b/Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.cpp
@@ -4,69 +4,144 @@
* See Documentation/Licenses/BSD-simplified.txt for more information.
*/
+/*
+ * Copyright (c) 2015 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
+
#include <Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.h>
#include <boost/smart_ptr/make_shared.hpp>
+#include <boost/bind.hpp>
#include <Swiften/Base/foreach.h>
#include <Swiften/FileTransfer/SOCKS5BytestreamClientSession.h>
#include <Swiften/Base/Log.h>
+#include <Swiften/Network/DomainNameResolver.h>
+#include <Swiften/Network/ConnectionFactory.h>
+#include <Swiften/Network/TimerFactory.h>
+#include <Swiften/Network/DomainNameAddressQuery.h>
+#include <Swiften/Network/DomainNameResolveError.h>
namespace Swift {
-SOCKS5BytestreamProxiesManager::SOCKS5BytestreamProxiesManager(ConnectionFactory *connFactory, TimerFactory *timeFactory) : connectionFactory(connFactory), timerFactory(timeFactory) {
+SOCKS5BytestreamProxiesManager::SOCKS5BytestreamProxiesManager(ConnectionFactory *connFactory, TimerFactory *timeFactory, DomainNameResolver* resolver, IQRouter* iqRouter, const JID& serviceRoot) : connectionFactory_(connFactory), timerFactory_(timeFactory), resolver_(resolver), iqRouter_(iqRouter), serviceRoot_(serviceRoot) {
+
+}
+SOCKS5BytestreamProxiesManager::~SOCKS5BytestreamProxiesManager() {
+ if (proxyFinder_) {
+ proxyFinder_->stop();
+ }
}
void SOCKS5BytestreamProxiesManager::addS5BProxy(S5BProxyRequest::ref proxy) {
- localS5BProxies.push_back(proxy);
+ if (proxy) {
+ SWIFT_LOG_ASSERT(HostAddress(proxy->getStreamHost().get().host).isValid(), warning) << std::endl;
+ if (!localS5BProxies_) {
+ localS5BProxies_ = std::vector<S5BProxyRequest::ref>();
+ }
+ localS5BProxies_->push_back(proxy);
+ onDiscoveredProxiesChanged();
+ }
}
-const std::vector<S5BProxyRequest::ref>& SOCKS5BytestreamProxiesManager::getS5BProxies() const {
- return localS5BProxies;
+const boost::optional<std::vector<S5BProxyRequest::ref> >& SOCKS5BytestreamProxiesManager::getOrDiscoverS5BProxies() {
+ if (!localS5BProxies_ && !proxyFinder_) {
+ queryForProxies();
+ }
+ return localS5BProxies_;
}
void SOCKS5BytestreamProxiesManager::connectToProxies(const std::string& sessionID) {
SWIFT_LOG(debug) << "session ID: " << sessionID << std::endl;
ProxyJIDClientSessionMap clientSessions;
- foreach(S5BProxyRequest::ref proxy, localS5BProxies) {
- boost::shared_ptr<Connection> conn = connectionFactory->createConnection();
+ if (localS5BProxies_) {
+ foreach(S5BProxyRequest::ref proxy, localS5BProxies_.get()) {
+ boost::shared_ptr<Connection> conn = connectionFactory_->createConnection();
- boost::shared_ptr<SOCKS5BytestreamClientSession> session = boost::make_shared<SOCKS5BytestreamClientSession>(conn, proxy->getStreamHost().get().addressPort, sessionID, timerFactory);
- clientSessions[proxy->getStreamHost().get().jid] = session;
- session->start();
+ HostAddressPort addressPort = HostAddressPort(proxy->getStreamHost().get().host, proxy->getStreamHost().get().port);
+ SWIFT_LOG_ASSERT(addressPort.isValid(), warning) << std::endl;
+ boost::shared_ptr<SOCKS5BytestreamClientSession> session = boost::make_shared<SOCKS5BytestreamClientSession>(conn, addressPort, sessionID, timerFactory_);
+ clientSessions[proxy->getStreamHost().get().jid] = session;
+ session->start();
+ }
}
- proxySessions[sessionID] = clientSessions;
+ proxySessions_[sessionID] = clientSessions;
}
boost::shared_ptr<SOCKS5BytestreamClientSession> SOCKS5BytestreamProxiesManager::getProxySessionAndCloseOthers(const JID& proxyJID, const std::string& sessionID) {
// checking parameters
- if (proxySessions.find(sessionID) == proxySessions.end()) {
+ if (proxySessions_.find(sessionID) == proxySessions_.end()) {
return boost::shared_ptr<SOCKS5BytestreamClientSession>();
}
- if (proxySessions[sessionID].find(proxyJID) == proxySessions[sessionID].end()) {
+ if (proxySessions_[sessionID].find(proxyJID) == proxySessions_[sessionID].end()) {
return boost::shared_ptr<SOCKS5BytestreamClientSession>();
}
// get active session
- boost::shared_ptr<SOCKS5BytestreamClientSession> activeSession = proxySessions[sessionID][proxyJID];
- proxySessions[sessionID].erase(proxyJID);
+ boost::shared_ptr<SOCKS5BytestreamClientSession> activeSession = proxySessions_[sessionID][proxyJID];
+ proxySessions_[sessionID].erase(proxyJID);
// close other sessions
- foreach(const ProxyJIDClientSessionMap::value_type& myPair, proxySessions[sessionID]) {
+ foreach(const ProxyJIDClientSessionMap::value_type& myPair, proxySessions_[sessionID]) {
myPair.second->stop();
}
- proxySessions.erase(sessionID);
+ proxySessions_.erase(sessionID);
return activeSession;
}
boost::shared_ptr<SOCKS5BytestreamClientSession> SOCKS5BytestreamProxiesManager::createSOCKS5BytestreamClientSession(HostAddressPort addressPort, const std::string& destAddr) {
- SOCKS5BytestreamClientSession::ref connection = boost::make_shared<SOCKS5BytestreamClientSession>(connectionFactory->createConnection(), addressPort, destAddr, timerFactory);
+ SOCKS5BytestreamClientSession::ref connection = boost::make_shared<SOCKS5BytestreamClientSession>(connectionFactory_->createConnection(), addressPort, destAddr, timerFactory_);
return connection;
}
+void SOCKS5BytestreamProxiesManager::handleProxyFound(S5BProxyRequest::ref proxy) {
+ if (proxy) {
+ if (HostAddress(proxy->getStreamHost().get().host).isValid()) {
+ addS5BProxy(proxy);
+ }
+ else {
+ DomainNameAddressQuery::ref resolveRequest = resolver_->createAddressQuery(proxy->getStreamHost().get().host);
+ resolveRequest->onResult.connect(boost::bind(&SOCKS5BytestreamProxiesManager::handleNameLookupResult, this, _1, _2, proxy));
+ resolveRequest->run();
+ }
+ }
+ else {
+ onDiscoveredProxiesChanged();
+ }
+ proxyFinder_->stop();
+}
+
+void SOCKS5BytestreamProxiesManager::handleNameLookupResult(const std::vector<HostAddress>& address, boost::optional<DomainNameResolveError> error, S5BProxyRequest::ref proxy) {
+ if (error) {
+ onDiscoveredProxiesChanged();
+ }
+ else {
+ if (address.empty()) {
+ SWIFT_LOG(warning) << "S5B proxy hostname does not resolve." << std::endl;
+ onDiscoveredProxiesChanged();
+ }
+ else {
+ S5BProxyRequest::StreamHost streamHost = proxy->getStreamHost().get();
+ streamHost.host = address[0].toString();
+ proxy->setStreamHost(streamHost);
+ addS5BProxy(proxy);
+ }
+ }
+}
+
+void SOCKS5BytestreamProxiesManager::queryForProxies() {
+ proxyFinder_ = boost::make_shared<SOCKS5BytestreamProxyFinder>(serviceRoot_, iqRouter_);
+
+ proxyFinder_->onProxyFound.connect(boost::bind(&SOCKS5BytestreamProxiesManager::handleProxyFound, this, _1));
+ proxyFinder_->start();
+}
+
}
diff --git a/Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.h b/Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.h
index f3fed80..06db76c 100644
--- a/Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.h
+++ b/Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.h
@@ -4,6 +4,13 @@
* See Documentation/Licenses/BSD-simplified.txt for more information.
*/
+/*
+ * Copyright (c) 2015 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
+
#pragma once
#include <string>
@@ -13,11 +20,13 @@
#include <Swiften/Elements/S5BProxyRequest.h>
#include <Swiften/FileTransfer/SOCKS5BytestreamClientSession.h>
#include <Swiften/JID/JID.h>
-#include <Swiften/Network/ConnectionFactory.h>
-#include <Swiften/Network/TimerFactory.h>
+#include <Swiften/FileTransfer/SOCKS5BytestreamProxyFinder.h>
namespace Swift {
- class SOCKS5BytestreamProxiesDiscoverRequest;
+ class TimerFactory;
+ class ConnectionFactory;
+ class DomainNameResolver;
+ class DomainNameResolveError;
/**
* - manages list of working S5B proxies
@@ -25,26 +34,44 @@ namespace Swift {
*/
class SWIFTEN_API SOCKS5BytestreamProxiesManager {
public:
- SOCKS5BytestreamProxiesManager(ConnectionFactory*, TimerFactory*);
-
- boost::shared_ptr<SOCKS5BytestreamProxiesDiscoverRequest> createDiscoverProxiesRequest();
+ SOCKS5BytestreamProxiesManager(ConnectionFactory*, TimerFactory*, DomainNameResolver*, IQRouter*, const JID&);
+ ~SOCKS5BytestreamProxiesManager();
void addS5BProxy(S5BProxyRequest::ref);
- const std::vector<S5BProxyRequest::ref>& getS5BProxies() const;
+
+ /*
+ * Returns a list of external S5B proxies. If the optinal return value is not initialized a discovery process has been started and
+ * onDiscoveredProxiesChanged signal will be emitted when it is finished.
+ */
+ const boost::optional<std::vector<S5BProxyRequest::ref> >& getOrDiscoverS5BProxies();
void connectToProxies(const std::string& sessionID);
boost::shared_ptr<SOCKS5BytestreamClientSession> getProxySessionAndCloseOthers(const JID& proxyJID, const std::string& sessionID);
boost::shared_ptr<SOCKS5BytestreamClientSession> createSOCKS5BytestreamClientSession(HostAddressPort addressPort, const std::string& destAddr);
+ public:
+ boost::signal<void ()> onDiscoveredProxiesChanged;
+
+ private:
+ void handleProxyFound(S5BProxyRequest::ref proxy);
+ void handleNameLookupResult(const std::vector<HostAddress>&, boost::optional<DomainNameResolveError>, S5BProxyRequest::ref proxy);
+
+ void queryForProxies();
+
private:
- ConnectionFactory* connectionFactory;
- TimerFactory* timerFactory;
+ ConnectionFactory* connectionFactory_;
+ TimerFactory* timerFactory_;
+ DomainNameResolver* resolver_;
+ IQRouter* iqRouter_;
+ JID serviceRoot_;
typedef std::map<JID, boost::shared_ptr<SOCKS5BytestreamClientSession> > ProxyJIDClientSessionMap;
- std::map<std::string, ProxyJIDClientSessionMap> proxySessions;
+ std::map<std::string, ProxyJIDClientSessionMap> proxySessions_;
+
+ boost::shared_ptr<SOCKS5BytestreamProxyFinder> proxyFinder_;
- std::vector<S5BProxyRequest::ref> localS5BProxies;
+ boost::optional<std::vector<S5BProxyRequest::ref> > localS5BProxies_;
};
}
diff --git a/Swiften/FileTransfer/SOCKS5BytestreamProxyFinder.h b/Swiften/FileTransfer/SOCKS5BytestreamProxyFinder.h
index 8265157..54c2075 100644
--- a/Swiften/FileTransfer/SOCKS5BytestreamProxyFinder.h
+++ b/Swiften/FileTransfer/SOCKS5BytestreamProxyFinder.h
@@ -4,6 +4,13 @@
* See Documentation/Licenses/BSD-simplified.txt for more information.
*/
+/*
+ * Copyright (c) 2015 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
+
#pragma once
#include <boost/shared_ptr.hpp>
@@ -17,6 +24,10 @@ namespace Swift {
class JID;
class IQRouter;
+/*
+ * This class is designed to find possible SOCKS5 bytestream proxies which are used for peer-to-peer data transfers in
+ * restrictive environments.
+ */
class SOCKS5BytestreamProxyFinder {
public:
SOCKS5BytestreamProxyFinder(const JID& service, IQRouter *iqRouter);
diff --git a/Swiften/FileTransfer/UnitTest/IncomingJingleFileTransferTest.cpp b/Swiften/FileTransfer/UnitTest/IncomingJingleFileTransferTest.cpp
index 207f590..aaf90ea 100644
--- a/Swiften/FileTransfer/UnitTest/IncomingJingleFileTransferTest.cpp
+++ b/Swiften/FileTransfer/UnitTest/IncomingJingleFileTransferTest.cpp
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (c) 2013-2014 Isode Limited.
+ * Copyright (c) 2013-2015 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
@@ -28,6 +28,7 @@
#include <Swiften/FileTransfer/IncomingJingleFileTransfer.h>
#include <Swiften/FileTransfer/SOCKS5BytestreamRegistry.h>
#include <Swiften/Network/PlatformNetworkEnvironment.h>
+#include <Swiften/Network/StaticDomainNameResolver.h>
#include <Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.h>
#include <Swiften/FileTransfer/SOCKS5BytestreamServerManager.h>
#include <Swiften/Jingle/FakeJingleSession.h>
@@ -67,6 +68,7 @@ public:
void setUp() {
crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create());
eventLoop = new DummyEventLoop();
+ resolver = new StaticDomainNameResolver(eventLoop);
session = boost::make_shared<FakeJingleSession>("foo@bar.com/baz", "mysession");
jingleContentPayload = make_shared<JingleContentPayload>();
// fakeRJTCSF = make_shared<FakeRemoteJingleTransportCandidateSelectorFactory>();
@@ -81,7 +83,7 @@ public:
bytestreamServerManager = new SOCKS5BytestreamServerManager(bytestreamRegistry, serverConnectionFactory, networkEnvironment, natTraverser);
idGenerator = new SimpleIDGenerator();
timerFactory = new DummyTimerFactory();
- bytestreamProxy = new SOCKS5BytestreamProxiesManager(connectionFactory, timerFactory);
+ bytestreamProxy = new SOCKS5BytestreamProxiesManager(connectionFactory, timerFactory, resolver, iqRouter, "bar.com");
ftTransporterFactory = new DefaultFileTransferTransporterFactory(bytestreamRegistry, bytestreamServerManager, bytestreamProxy, idGenerator, connectionFactory, timerFactory, crypto.get(), iqRouter);
}
@@ -94,6 +96,7 @@ public:
delete bytestreamRegistry;
delete iqRouter;
delete stanzaChannel;
+ delete resolver;
delete eventLoop;
Log::setLogLevel(Log::error);
}
@@ -232,6 +235,7 @@ private:
NetworkEnvironment* networkEnvironment;
NATTraverser* natTraverser;
IDGenerator* idGenerator;
+ DomainNameResolver* resolver;
};
CPPUNIT_TEST_SUITE_REGISTRATION(IncomingJingleFileTransferTest);