summaryrefslogtreecommitdiffstats
blob: a0e7a6f24e0a1d1eb07fad3dca78c5ff5ea9c3dc (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
98
/*
 * 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 <memory>

#include <boost/bind.hpp>
#include <boost/signals2.hpp>

#include <Swiften/Base/Log.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>(), std::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())) {
            std::shared_ptr<Connection> connection = connectionFactory->createConnection();
            s5bSession = std::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;
}