diff options
4 files changed, 54 insertions, 27 deletions
diff --git a/Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.cpp b/Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.cpp index 1036e12..25a12ea 100644 --- a/Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.cpp +++ b/Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.cpp @@ -109,27 +109,26 @@ boost::shared_ptr<SOCKS5BytestreamClientSession> SOCKS5BytestreamProxiesManager: boost::shared_ptr<SOCKS5BytestreamClientSession> SOCKS5BytestreamProxiesManager::createSOCKS5BytestreamClientSession(HostAddressPort addressPort, const std::string& destAddr) { 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); - onDiscoveredProxiesChanged(); - } - else { - DomainNameAddressQuery::ref resolveRequest = resolver_->createAddressQuery(proxy->getStreamHost().get().host); - resolveRequest->onResult.connect(boost::bind(&SOCKS5BytestreamProxiesManager::handleNameLookupResult, this, _1, _2, proxy)); - resolveRequest->run(); +void SOCKS5BytestreamProxiesManager::handleProxiesFound(std::vector<S5BProxyRequest::ref> proxyHosts) { + foreach(S5BProxyRequest::ref proxy, proxyHosts) { + if (proxy) { + if (HostAddress(proxy->getStreamHost().get().host).isValid()) { + addS5BProxy(proxy); + onDiscoveredProxiesChanged(); + } + 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(); proxyFinder_.reset(); } void SOCKS5BytestreamProxiesManager::handleNameLookupResult(const std::vector<HostAddress>& addresses, boost::optional<DomainNameResolveError> error, S5BProxyRequest::ref proxy) { if (error) { @@ -154,18 +153,18 @@ void SOCKS5BytestreamProxiesManager::handleNameLookupResult(const std::vector<Ho } } void SOCKS5BytestreamProxiesManager::queryForProxies() { proxyFinder_ = boost::make_shared<SOCKS5BytestreamProxyFinder>(serviceRoot_, iqRouter_); - proxyFinder_->onProxyFound.connect(boost::bind(&SOCKS5BytestreamProxiesManager::handleProxyFound, this, _1)); + proxyFinder_->onProxiesFound.connect(boost::bind(&SOCKS5BytestreamProxiesManager::handleProxiesFound, this, _1)); proxyFinder_->start(); } void SOCKS5BytestreamProxiesManager::handleProxySessionReady(const std::string& sessionID, const JID& jid, boost::shared_ptr<SOCKS5BytestreamClientSession> session, bool error) { - session->onSessionReady.disconnect(boost::bind(&SOCKS5BytestreamProxiesManager::handleProxySessionFinished, this, boost::cref(sessionID), boost::cref(jid), session, _1)); + session->onSessionReady.disconnect(boost::bind(&SOCKS5BytestreamProxiesManager::handleProxySessionReady, this, boost::cref(sessionID), boost::cref(jid), session, _1)); if (!error) { // The SOCKS5 bytestream session to the proxy succeeded; stop and remove other sessions. if (proxySessions_.find(sessionID) != proxySessions_.end()) { for (ProxyJIDClientSessionVector::iterator i = proxySessions_[sessionID].begin(); i != proxySessions_[sessionID].end();) { if ((i->first == jid) && (i->second != session)) { i->second->stop(); diff --git a/Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.h b/Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.h index e4bf1d9..c7daee7 100644 --- a/Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.h +++ b/Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.h @@ -26,12 +26,13 @@ namespace Swift { class TimerFactory; class ConnectionFactory; class DomainNameResolver; class DomainNameResolveError; + class IQRouter; /** * - manages list of working S5B proxies * - creates initial connections (for the candidates you provide) */ class SWIFTEN_API SOCKS5BytestreamProxiesManager { @@ -53,13 +54,13 @@ namespace Swift { boost::shared_ptr<SOCKS5BytestreamClientSession> createSOCKS5BytestreamClientSession(HostAddressPort addressPort, const std::string& destAddr); public: boost::signal<void ()> onDiscoveredProxiesChanged; private: - void handleProxyFound(S5BProxyRequest::ref proxy); + void handleProxiesFound(std::vector<S5BProxyRequest::ref> proxyHosts); void handleNameLookupResult(const std::vector<HostAddress>&, boost::optional<DomainNameResolveError>, S5BProxyRequest::ref proxy); void queryForProxies(); void handleProxySessionReady(const std::string& sessionID, const JID& jid, boost::shared_ptr<SOCKS5BytestreamClientSession> session, bool error); void handleProxySessionFinished(const std::string& sessionID, const JID& jid, boost::shared_ptr<SOCKS5BytestreamClientSession> session, boost::optional<FileTransferError> error); diff --git a/Swiften/FileTransfer/SOCKS5BytestreamProxyFinder.cpp b/Swiften/FileTransfer/SOCKS5BytestreamProxyFinder.cpp index 9d7505b..78cf2e6 100644 --- a/Swiften/FileTransfer/SOCKS5BytestreamProxyFinder.cpp +++ b/Swiften/FileTransfer/SOCKS5BytestreamProxyFinder.cpp @@ -1,18 +1,25 @@ /* * Copyright (c) 2011 Tobias Markmann * Licensed under the simplified BSD license. * 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/SOCKS5BytestreamProxyFinder.h> -#include <boost/smart_ptr/make_shared.hpp> #include <boost/bind.hpp> +#include <boost/smart_ptr/make_shared.hpp> #include <Swiften/Base/Log.h> +#include <Swiften/Base/foreach.h> #include <Swiften/Elements/S5BProxyRequest.h> #include <Swiften/Queries/GenericRequest.h> #include <Swiften/Queries/IQRouter.h> namespace Swift { @@ -22,41 +29,59 @@ SOCKS5BytestreamProxyFinder::SOCKS5BytestreamProxyFinder(const JID& service, IQR SOCKS5BytestreamProxyFinder::~SOCKS5BytestreamProxyFinder() { } void SOCKS5BytestreamProxyFinder::start() { serviceWalker = boost::make_shared<DiscoServiceWalker>(service, iqRouter); serviceWalker->onServiceFound.connect(boost::bind(&SOCKS5BytestreamProxyFinder::handleServiceFound, this, _1, _2)); + serviceWalker->onWalkComplete.connect(boost::bind(&SOCKS5BytestreamProxyFinder::handleWalkEnded, this)); serviceWalker->beginWalk(); } void SOCKS5BytestreamProxyFinder::stop() { + typedef boost::shared_ptr<GenericRequest<S5BProxyRequest> > S5BProxyRequestGenericRequest; + foreach (S5BProxyRequestGenericRequest requester, pendingRequests) { + requester->onResponse.disconnect(boost::bind(&SOCKS5BytestreamProxyFinder::handleProxyResponse, this, requester, _1, _2)); + } + serviceWalker->endWalk(); serviceWalker->onServiceFound.disconnect(boost::bind(&SOCKS5BytestreamProxyFinder::handleServiceFound, this, _1, _2)); + serviceWalker->onWalkComplete.disconnect(boost::bind(&SOCKS5BytestreamProxyFinder::handleWalkEnded, this)); serviceWalker.reset(); } void SOCKS5BytestreamProxyFinder::sendBytestreamQuery(const JID& jid) { S5BProxyRequest::ref proxyRequest = boost::make_shared<S5BProxyRequest>(); boost::shared_ptr<GenericRequest<S5BProxyRequest> > request = boost::make_shared<GenericRequest<S5BProxyRequest> >(IQ::Get, jid, proxyRequest, iqRouter); - request->onResponse.connect(boost::bind(&SOCKS5BytestreamProxyFinder::handleProxyResponse, this, _1, _2)); + request->onResponse.connect(boost::bind(&SOCKS5BytestreamProxyFinder::handleProxyResponse, this, request, _1, _2)); + pendingRequests.insert(request); request->send(); } void SOCKS5BytestreamProxyFinder::handleServiceFound(const JID& jid, boost::shared_ptr<DiscoInfo> discoInfo) { if (discoInfo->hasFeature(DiscoInfo::Bytestream)) { sendBytestreamQuery(jid); } } -void SOCKS5BytestreamProxyFinder::handleProxyResponse(boost::shared_ptr<S5BProxyRequest> request, ErrorPayload::ref error) { +void SOCKS5BytestreamProxyFinder::handleWalkEnded() { + if (pendingRequests.empty()) { + onProxiesFound(proxyHosts); + } +} + +void SOCKS5BytestreamProxyFinder::handleProxyResponse(boost::shared_ptr<GenericRequest<S5BProxyRequest> > requester, boost::shared_ptr<S5BProxyRequest> request, ErrorPayload::ref error) { + requester->onResponse.disconnect(boost::bind(&SOCKS5BytestreamProxyFinder::handleProxyResponse, this, requester, _1, _2)); + pendingRequests.erase(requester); if (error) { SWIFT_LOG(debug) << "ERROR" << std::endl; } else { if (request) { - onProxyFound(request); - } else { - //assert(false); + SWIFT_LOG(debug) << "add request" << std::endl; + proxyHosts.push_back(request); } } + if (pendingRequests.empty() && !serviceWalker->isActive()) { + onProxiesFound(proxyHosts); + } } } diff --git a/Swiften/FileTransfer/SOCKS5BytestreamProxyFinder.h b/Swiften/FileTransfer/SOCKS5BytestreamProxyFinder.h index c5ad72a..1c24497 100644 --- a/Swiften/FileTransfer/SOCKS5BytestreamProxyFinder.h +++ b/Swiften/FileTransfer/SOCKS5BytestreamProxyFinder.h @@ -14,13 +14,12 @@ #pragma once #include <boost/shared_ptr.hpp> #include <Swiften/Base/API.h> #include <Swiften/Disco/DiscoServiceWalker.h> -#include <Swiften/Network/HostAddressPort.h> #include <Swiften/Elements/S5BProxyRequest.h> namespace Swift { class JID; class IQRouter; @@ -34,21 +33,24 @@ class SWIFTEN_API SOCKS5BytestreamProxyFinder { SOCKS5BytestreamProxyFinder(const JID& service, IQRouter *iqRouter); ~SOCKS5BytestreamProxyFinder(); void start(); void stop(); - boost::signal<void(boost::shared_ptr<S5BProxyRequest>)> onProxyFound; + boost::signal<void(std::vector<boost::shared_ptr<S5BProxyRequest> >)> onProxiesFound; private: void sendBytestreamQuery(const JID&); void handleServiceFound(const JID&, boost::shared_ptr<DiscoInfo>); - void handleProxyResponse(boost::shared_ptr<S5BProxyRequest>, ErrorPayload::ref); + void handleProxyResponse(boost::shared_ptr<GenericRequest<S5BProxyRequest> > requester, boost::shared_ptr<S5BProxyRequest>, ErrorPayload::ref); + void handleWalkEnded(); + private: JID service; IQRouter* iqRouter; boost::shared_ptr<DiscoServiceWalker> serviceWalker; - std::vector<boost::shared_ptr<GenericRequest<S5BProxyRequest> > > requests; - }; + std::vector<S5BProxyRequest::ref> proxyHosts; + std::set<boost::shared_ptr<GenericRequest<S5BProxyRequest> > > pendingRequests; +}; } |