summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTobias Markmann <tm@ayena.de>2015-10-07 21:57:17 (GMT)
committerTobias Markmann <tm@ayena.de>2015-10-07 21:57:17 (GMT)
commitdf5bfad6f032b17ee0dffe85cdaadc2c20edaae2 (patch)
tree5b5166d0aeae60ab78d75528adeea8ef620cd7bd
parent37aafcb4d693a0b4f5944a52e0c070e5aa384245 (diff)
downloadswift-df5bfad6f032b17ee0dffe85cdaadc2c20edaae2.zip
swift-df5bfad6f032b17ee0dffe85cdaadc2c20edaae2.tar.bz2
Fix hang during file-transfer preparation with missing proxy
The code used to call the onProxiesFound signal only if a proxy was found. In case of missing S5B proxy at the users server, the file-transfer preparation would hang. Now the code wants until the discovery phase is done and then calls the onProxiesFound signal with the list of discovered proxies. In case of missing S5B proxy server the signal is called with an empty list so the file-transfer flow can continue. Test-Information: Ran FileTransferTest integration test and manually tested a file-transfer on a server without S5B proxy. Change-Id: I31d3cc08fe6453b5cdfe6be286f884a920470d28
-rw-r--r--Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.cpp29
-rw-r--r--Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.h3
-rw-r--r--Swiften/FileTransfer/SOCKS5BytestreamProxyFinder.cpp37
-rw-r--r--Swiften/FileTransfer/SOCKS5BytestreamProxyFinder.h12
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
@@ -110,25 +110,24 @@ boost::shared_ptr<SOCKS5BytestreamClientSession> SOCKS5BytestreamProxiesManager:
110boost::shared_ptr<SOCKS5BytestreamClientSession> SOCKS5BytestreamProxiesManager::createSOCKS5BytestreamClientSession(HostAddressPort addressPort, const std::string& destAddr) { 110boost::shared_ptr<SOCKS5BytestreamClientSession> SOCKS5BytestreamProxiesManager::createSOCKS5BytestreamClientSession(HostAddressPort addressPort, const std::string& destAddr) {
111 SOCKS5BytestreamClientSession::ref connection = boost::make_shared<SOCKS5BytestreamClientSession>(connectionFactory_->createConnection(), addressPort, destAddr, timerFactory_); 111 SOCKS5BytestreamClientSession::ref connection = boost::make_shared<SOCKS5BytestreamClientSession>(connectionFactory_->createConnection(), addressPort, destAddr, timerFactory_);
112 return connection; 112 return connection;
113} 113}
114 114
115void SOCKS5BytestreamProxiesManager::handleProxyFound(S5BProxyRequest::ref proxy) { 115void SOCKS5BytestreamProxiesManager::handleProxiesFound(std::vector<S5BProxyRequest::ref> proxyHosts) {
116 if (proxy) { 116 foreach(S5BProxyRequest::ref proxy, proxyHosts) {
117 if (HostAddress(proxy->getStreamHost().get().host).isValid()) { 117 if (proxy) {
118 addS5BProxy(proxy); 118 if (HostAddress(proxy->getStreamHost().get().host).isValid()) {
119 onDiscoveredProxiesChanged(); 119 addS5BProxy(proxy);
120 } 120 onDiscoveredProxiesChanged();
121 else { 121 }
122 DomainNameAddressQuery::ref resolveRequest = resolver_->createAddressQuery(proxy->getStreamHost().get().host); 122 else {
123 resolveRequest->onResult.connect(boost::bind(&SOCKS5BytestreamProxiesManager::handleNameLookupResult, this, _1, _2, proxy)); 123 DomainNameAddressQuery::ref resolveRequest = resolver_->createAddressQuery(proxy->getStreamHost().get().host);
124 resolveRequest->run(); 124 resolveRequest->onResult.connect(boost::bind(&SOCKS5BytestreamProxiesManager::handleNameLookupResult, this, _1, _2, proxy));
125 resolveRequest->run();
126 }
125 } 127 }
126 } 128 }
127 else {
128 onDiscoveredProxiesChanged();
129 }
130 proxyFinder_->stop(); 129 proxyFinder_->stop();
131 proxyFinder_.reset(); 130 proxyFinder_.reset();
132} 131}
133 132
134void SOCKS5BytestreamProxiesManager::handleNameLookupResult(const std::vector<HostAddress>& addresses, boost::optional<DomainNameResolveError> error, S5BProxyRequest::ref proxy) { 133void SOCKS5BytestreamProxiesManager::handleNameLookupResult(const std::vector<HostAddress>& addresses, boost::optional<DomainNameResolveError> error, S5BProxyRequest::ref proxy) {
@@ -155,16 +154,16 @@ void SOCKS5BytestreamProxiesManager::handleNameLookupResult(const std::vector<Ho
155} 154}
156 155
157void SOCKS5BytestreamProxiesManager::queryForProxies() { 156void SOCKS5BytestreamProxiesManager::queryForProxies() {
158 proxyFinder_ = boost::make_shared<SOCKS5BytestreamProxyFinder>(serviceRoot_, iqRouter_); 157 proxyFinder_ = boost::make_shared<SOCKS5BytestreamProxyFinder>(serviceRoot_, iqRouter_);
159 158
160 proxyFinder_->onProxyFound.connect(boost::bind(&SOCKS5BytestreamProxiesManager::handleProxyFound, this, _1)); 159 proxyFinder_->onProxiesFound.connect(boost::bind(&SOCKS5BytestreamProxiesManager::handleProxiesFound, this, _1));
161 proxyFinder_->start(); 160 proxyFinder_->start();
162} 161}
163 162
164void SOCKS5BytestreamProxiesManager::handleProxySessionReady(const std::string& sessionID, const JID& jid, boost::shared_ptr<SOCKS5BytestreamClientSession> session, bool error) { 163void SOCKS5BytestreamProxiesManager::handleProxySessionReady(const std::string& sessionID, const JID& jid, boost::shared_ptr<SOCKS5BytestreamClientSession> session, bool error) {
165 session->onSessionReady.disconnect(boost::bind(&SOCKS5BytestreamProxiesManager::handleProxySessionFinished, this, boost::cref(sessionID), boost::cref(jid), session, _1)); 164 session->onSessionReady.disconnect(boost::bind(&SOCKS5BytestreamProxiesManager::handleProxySessionReady, this, boost::cref(sessionID), boost::cref(jid), session, _1));
166 if (!error) { 165 if (!error) {
167 // The SOCKS5 bytestream session to the proxy succeeded; stop and remove other sessions. 166 // The SOCKS5 bytestream session to the proxy succeeded; stop and remove other sessions.
168 if (proxySessions_.find(sessionID) != proxySessions_.end()) { 167 if (proxySessions_.find(sessionID) != proxySessions_.end()) {
169 for (ProxyJIDClientSessionVector::iterator i = proxySessions_[sessionID].begin(); i != proxySessions_[sessionID].end();) { 168 for (ProxyJIDClientSessionVector::iterator i = proxySessions_[sessionID].begin(); i != proxySessions_[sessionID].end();) {
170 if ((i->first == jid) && (i->second != session)) { 169 if ((i->first == jid) && (i->second != session)) {
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
@@ -27,10 +27,11 @@
27namespace Swift { 27namespace Swift {
28 class TimerFactory; 28 class TimerFactory;
29 class ConnectionFactory; 29 class ConnectionFactory;
30 class DomainNameResolver; 30 class DomainNameResolver;
31 class DomainNameResolveError; 31 class DomainNameResolveError;
32 class IQRouter;
32 33
33 /** 34 /**
34 * - manages list of working S5B proxies 35 * - manages list of working S5B proxies
35 * - creates initial connections (for the candidates you provide) 36 * - creates initial connections (for the candidates you provide)
36 */ 37 */
@@ -54,11 +55,11 @@ namespace Swift {
54 55
55 public: 56 public:
56 boost::signal<void ()> onDiscoveredProxiesChanged; 57 boost::signal<void ()> onDiscoveredProxiesChanged;
57 58
58 private: 59 private:
59 void handleProxyFound(S5BProxyRequest::ref proxy); 60 void handleProxiesFound(std::vector<S5BProxyRequest::ref> proxyHosts);
60 void handleNameLookupResult(const std::vector<HostAddress>&, boost::optional<DomainNameResolveError>, S5BProxyRequest::ref proxy); 61 void handleNameLookupResult(const std::vector<HostAddress>&, boost::optional<DomainNameResolveError>, S5BProxyRequest::ref proxy);
61 62
62 void queryForProxies(); 63 void queryForProxies();
63 64
64 void handleProxySessionReady(const std::string& sessionID, const JID& jid, boost::shared_ptr<SOCKS5BytestreamClientSession> session, bool error); 65 void handleProxySessionReady(const std::string& sessionID, const JID& jid, boost::shared_ptr<SOCKS5BytestreamClientSession> session, bool 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
@@ -2,16 +2,23 @@
2 * Copyright (c) 2011 Tobias Markmann 2 * Copyright (c) 2011 Tobias Markmann
3 * Licensed under the simplified BSD license. 3 * Licensed under the simplified BSD license.
4 * See Documentation/Licenses/BSD-simplified.txt for more information. 4 * See Documentation/Licenses/BSD-simplified.txt for more information.
5 */ 5 */
6 6
7/*
8 * Copyright (c) 2015 Isode Limited.
9 * All rights reserved.
10 * See the COPYING file for more information.
11 */
12
7#include <Swiften/FileTransfer/SOCKS5BytestreamProxyFinder.h> 13#include <Swiften/FileTransfer/SOCKS5BytestreamProxyFinder.h>
8 14
9#include <boost/smart_ptr/make_shared.hpp>
10#include <boost/bind.hpp> 15#include <boost/bind.hpp>
16#include <boost/smart_ptr/make_shared.hpp>
11 17
12#include <Swiften/Base/Log.h> 18#include <Swiften/Base/Log.h>
19#include <Swiften/Base/foreach.h>
13#include <Swiften/Elements/S5BProxyRequest.h> 20#include <Swiften/Elements/S5BProxyRequest.h>
14#include <Swiften/Queries/GenericRequest.h> 21#include <Swiften/Queries/GenericRequest.h>
15#include <Swiften/Queries/IQRouter.h> 22#include <Swiften/Queries/IQRouter.h>
16 23
17namespace Swift { 24namespace Swift {
@@ -23,40 +30,58 @@ SOCKS5BytestreamProxyFinder::~SOCKS5BytestreamProxyFinder() {
23} 30}
24 31
25void SOCKS5BytestreamProxyFinder::start() { 32void SOCKS5BytestreamProxyFinder::start() {
26 serviceWalker = boost::make_shared<DiscoServiceWalker>(service, iqRouter); 33 serviceWalker = boost::make_shared<DiscoServiceWalker>(service, iqRouter);
27 serviceWalker->onServiceFound.connect(boost::bind(&SOCKS5BytestreamProxyFinder::handleServiceFound, this, _1, _2)); 34 serviceWalker->onServiceFound.connect(boost::bind(&SOCKS5BytestreamProxyFinder::handleServiceFound, this, _1, _2));
35 serviceWalker->onWalkComplete.connect(boost::bind(&SOCKS5BytestreamProxyFinder::handleWalkEnded, this));
28 serviceWalker->beginWalk(); 36 serviceWalker->beginWalk();
29} 37}
30 38
31void SOCKS5BytestreamProxyFinder::stop() { 39void SOCKS5BytestreamProxyFinder::stop() {
40 typedef boost::shared_ptr<GenericRequest<S5BProxyRequest> > S5BProxyRequestGenericRequest;
41 foreach (S5BProxyRequestGenericRequest requester, pendingRequests) {
42 requester->onResponse.disconnect(boost::bind(&SOCKS5BytestreamProxyFinder::handleProxyResponse, this, requester, _1, _2));
43 }
44
32 serviceWalker->endWalk(); 45 serviceWalker->endWalk();
33 serviceWalker->onServiceFound.disconnect(boost::bind(&SOCKS5BytestreamProxyFinder::handleServiceFound, this, _1, _2)); 46 serviceWalker->onServiceFound.disconnect(boost::bind(&SOCKS5BytestreamProxyFinder::handleServiceFound, this, _1, _2));
47 serviceWalker->onWalkComplete.disconnect(boost::bind(&SOCKS5BytestreamProxyFinder::handleWalkEnded, this));
34 serviceWalker.reset(); 48 serviceWalker.reset();
35} 49}
36 50
37void SOCKS5BytestreamProxyFinder::sendBytestreamQuery(const JID& jid) { 51void SOCKS5BytestreamProxyFinder::sendBytestreamQuery(const JID& jid) {
38 S5BProxyRequest::ref proxyRequest = boost::make_shared<S5BProxyRequest>(); 52 S5BProxyRequest::ref proxyRequest = boost::make_shared<S5BProxyRequest>();
39 boost::shared_ptr<GenericRequest<S5BProxyRequest> > request = boost::make_shared<GenericRequest<S5BProxyRequest> >(IQ::Get, jid, proxyRequest, iqRouter); 53 boost::shared_ptr<GenericRequest<S5BProxyRequest> > request = boost::make_shared<GenericRequest<S5BProxyRequest> >(IQ::Get, jid, proxyRequest, iqRouter);
40 request->onResponse.connect(boost::bind(&SOCKS5BytestreamProxyFinder::handleProxyResponse, this, _1, _2)); 54 request->onResponse.connect(boost::bind(&SOCKS5BytestreamProxyFinder::handleProxyResponse, this, request, _1, _2));
55 pendingRequests.insert(request);
41 request->send(); 56 request->send();
42} 57}
43 58
44void SOCKS5BytestreamProxyFinder::handleServiceFound(const JID& jid, boost::shared_ptr<DiscoInfo> discoInfo) { 59void SOCKS5BytestreamProxyFinder::handleServiceFound(const JID& jid, boost::shared_ptr<DiscoInfo> discoInfo) {
45 if (discoInfo->hasFeature(DiscoInfo::Bytestream)) { 60 if (discoInfo->hasFeature(DiscoInfo::Bytestream)) {
46 sendBytestreamQuery(jid); 61 sendBytestreamQuery(jid);
47 } 62 }
48} 63}
49 64
50void SOCKS5BytestreamProxyFinder::handleProxyResponse(boost::shared_ptr<S5BProxyRequest> request, ErrorPayload::ref error) { 65void SOCKS5BytestreamProxyFinder::handleWalkEnded() {
66 if (pendingRequests.empty()) {
67 onProxiesFound(proxyHosts);
68 }
69}
70
71void SOCKS5BytestreamProxyFinder::handleProxyResponse(boost::shared_ptr<GenericRequest<S5BProxyRequest> > requester, boost::shared_ptr<S5BProxyRequest> request, ErrorPayload::ref error) {
72 requester->onResponse.disconnect(boost::bind(&SOCKS5BytestreamProxyFinder::handleProxyResponse, this, requester, _1, _2));
73 pendingRequests.erase(requester);
51 if (error) { 74 if (error) {
52 SWIFT_LOG(debug) << "ERROR" << std::endl; 75 SWIFT_LOG(debug) << "ERROR" << std::endl;
53 } else { 76 } else {
54 if (request) { 77 if (request) {
55 onProxyFound(request); 78 SWIFT_LOG(debug) << "add request" << std::endl;
56 } else { 79 proxyHosts.push_back(request);
57 //assert(false);
58 } 80 }
59 } 81 }
82 if (pendingRequests.empty() && !serviceWalker->isActive()) {
83 onProxiesFound(proxyHosts);
84 }
60} 85}
61 86
62} 87}
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
@@ -15,11 +15,10 @@
15 15
16#include <boost/shared_ptr.hpp> 16#include <boost/shared_ptr.hpp>
17 17
18#include <Swiften/Base/API.h> 18#include <Swiften/Base/API.h>
19#include <Swiften/Disco/DiscoServiceWalker.h> 19#include <Swiften/Disco/DiscoServiceWalker.h>
20#include <Swiften/Network/HostAddressPort.h>
21#include <Swiften/Elements/S5BProxyRequest.h> 20#include <Swiften/Elements/S5BProxyRequest.h>
22 21
23namespace Swift { 22namespace Swift {
24 23
25class JID; 24class JID;
@@ -35,20 +34,23 @@ class SWIFTEN_API SOCKS5BytestreamProxyFinder {
35 ~SOCKS5BytestreamProxyFinder(); 34 ~SOCKS5BytestreamProxyFinder();
36 35
37 void start(); 36 void start();
38 void stop(); 37 void stop();
39 38
40 boost::signal<void(boost::shared_ptr<S5BProxyRequest>)> onProxyFound; 39 boost::signal<void(std::vector<boost::shared_ptr<S5BProxyRequest> >)> onProxiesFound;
41 40
42 private: 41 private:
43 void sendBytestreamQuery(const JID&); 42 void sendBytestreamQuery(const JID&);
44 43
45 void handleServiceFound(const JID&, boost::shared_ptr<DiscoInfo>); 44 void handleServiceFound(const JID&, boost::shared_ptr<DiscoInfo>);
46 void handleProxyResponse(boost::shared_ptr<S5BProxyRequest>, ErrorPayload::ref); 45 void handleProxyResponse(boost::shared_ptr<GenericRequest<S5BProxyRequest> > requester, boost::shared_ptr<S5BProxyRequest>, ErrorPayload::ref);
46 void handleWalkEnded();
47
47 private: 48 private:
48 JID service; 49 JID service;
49 IQRouter* iqRouter; 50 IQRouter* iqRouter;
50 boost::shared_ptr<DiscoServiceWalker> serviceWalker; 51 boost::shared_ptr<DiscoServiceWalker> serviceWalker;
51 std::vector<boost::shared_ptr<GenericRequest<S5BProxyRequest> > > requests; 52 std::vector<S5BProxyRequest::ref> proxyHosts;
52 }; 53 std::set<boost::shared_ptr<GenericRequest<S5BProxyRequest> > > pendingRequests;
54};
53 55
54} 56}