summaryrefslogtreecommitdiffstats
blob: 97e2706daee422c42a29e5b146769e6229d578e9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
/*
 * Copyright (c) 2011 Tobias Markmann
 * Licensed under the simplified BSD license.
 * See Documentation/Licenses/BSD-simplified.txt for more information.
 */

/*
 * Copyright (c) 2013-2016 Isode Limited.
 * All rights reserved.
 * See the COPYING file for more information.
 */

#include <Swiften/FileTransfer/RemoteJingleTransportCandidateSelector.h>

#include <boost/bind.hpp>
#include <boost/smart_ptr/make_shared.hpp>

#include <Swiften/Base/Log.h>
#include <Swiften/Base/boost_bsignals.h>
#include <Swiften/Base/foreach.h>
#include <Swiften/Elements/JingleS5BTransportPayload.h>
#include <Swiften/FileTransfer/SOCKS5BytestreamRegistry.h>
#include <Swiften/Network/ConnectionFactory.h>

using namespace Swift;

RemoteJingleTransportCandidateSelector::RemoteJingleTransportCandidateSelector(
		ConnectionFactory* connectionFactory, 
		TimerFactory* timerFactory,
		const FileTransferOptions& options) :
			connectionFactory(connectionFactory), 
			timerFactory(timerFactory),
			options(options) {
}

RemoteJingleTransportCandidateSelector::~RemoteJingleTransportCandidateSelector() {
}

void RemoteJingleTransportCandidateSelector::addCandidates(
		const std::vector<JingleS5BTransportPayload::Candidate>& candidates) {
	foreach(JingleS5BTransportPayload::Candidate c,  candidates) {
		this->candidates.push(c);
	}
}

void RemoteJingleTransportCandidateSelector::startSelectingCandidate() {
	tryNextCandidate();
}

void RemoteJingleTransportCandidateSelector::stopSelectingCandidate() {
	if (s5bSession) {
		sessionReadyConnection.disconnect();
		s5bSession->stop();
	}
}

void RemoteJingleTransportCandidateSelector::tryNextCandidate() {
	if (candidates.empty()) {
		SWIFT_LOG(debug) << "No more candidates" << std::endl;
		onCandidateSelectFinished(
				boost::optional<JingleS5BTransportPayload::Candidate>(), boost::shared_ptr<SOCKS5BytestreamClientSession>());
	} 
	else {
		lastCandidate = candidates.top();
		candidates.pop();
		SWIFT_LOG(debug) << "Trying candidate " << lastCandidate.cid << std::endl;
		if ((lastCandidate.type == JingleS5BTransportPayload::Candidate::DirectType && options.isDirectAllowed()) ||
			(lastCandidate.type == JingleS5BTransportPayload::Candidate::AssistedType && options.isAssistedAllowed()) ||
			(lastCandidate.type == JingleS5BTransportPayload::Candidate::ProxyType && options.isProxiedAllowed())) {
			boost::shared_ptr<Connection> connection = connectionFactory->createConnection();
			s5bSession = boost::make_shared<SOCKS5BytestreamClientSession>(
					connection, lastCandidate.hostPort, socks5DstAddr, timerFactory);
			sessionReadyConnection = s5bSession->onSessionReady.connect(
					boost::bind(&RemoteJingleTransportCandidateSelector::handleSessionReady, this, _1));
			s5bSession->start();
		} 
		else {
			SWIFT_LOG(debug) << "Can't handle this type of candidate" << std::endl;
			tryNextCandidate();
		}
	}
}

void RemoteJingleTransportCandidateSelector::handleSessionReady(bool error) {
	sessionReadyConnection.disconnect();
	if (error) {
		s5bSession.reset();
		tryNextCandidate();
	}
	else {
		onCandidateSelectFinished(lastCandidate, s5bSession);
	}
}

void RemoteJingleTransportCandidateSelector::setSOCKS5DstAddr(const std::string& socks5DstAddr) {
	this->socks5DstAddr = socks5DstAddr;
}