diff options
author | Tobias Markmann <tm@ayena.de> | 2015-01-11 17:13:41 (GMT) |
---|---|---|
committer | Swift Review <review@swift.im> | 2015-02-11 09:36:14 (GMT) |
commit | a049c80f0862a994a76e8e63d71c633bce63f66a (patch) | |
tree | c5fc7786d2d245c765067545bb9a0e433e58a3f9 | |
parent | f176050a50fb846bbad3fb49d6b2f7a2c81e3589 (diff) | |
download | swift-a049c80f0862a994a76e8e63d71c633bce63f66a.zip swift-a049c80f0862a994a76e8e63d71c633bce63f66a.tar.bz2 |
Renable SOCKS5 bytestream proxy support for Jingle file transfers.
Test-Information:
Tested interoperability with Swiften using FileTransferTest.
Change-Id: Ic13a68a91cad199be0bfc8852ff43c25c7085f12
-rw-r--r-- | Swiften/FileTransfer/DefaultFileTransferTransporter.cpp | 134 | ||||
-rw-r--r-- | Swiften/FileTransfer/DefaultFileTransferTransporter.h | 20 | ||||
-rw-r--r-- | Swiften/FileTransfer/FileTransferTransporter.h | 14 | ||||
-rw-r--r-- | Swiften/FileTransfer/IncomingJingleFileTransfer.cpp | 21 | ||||
-rw-r--r-- | Swiften/FileTransfer/IncomingJingleFileTransfer.h | 5 | ||||
-rw-r--r-- | Swiften/FileTransfer/JingleFileTransfer.cpp | 16 | ||||
-rw-r--r-- | Swiften/FileTransfer/JingleFileTransfer.h | 5 | ||||
-rw-r--r-- | Swiften/FileTransfer/OutgoingJingleFileTransfer.cpp | 22 | ||||
-rw-r--r-- | Swiften/FileTransfer/OutgoingJingleFileTransfer.h | 5 | ||||
-rw-r--r-- | Swiften/FileTransfer/SOCKS5BytestreamClientSession.cpp | 12 | ||||
-rw-r--r-- | Swiften/Network/BoostNetworkFactories.h | 4 |
11 files changed, 176 insertions, 82 deletions
diff --git a/Swiften/FileTransfer/DefaultFileTransferTransporter.cpp b/Swiften/FileTransfer/DefaultFileTransferTransporter.cpp index 2c54d88..22b4a84 100644 --- a/Swiften/FileTransfer/DefaultFileTransferTransporter.cpp +++ b/Swiften/FileTransfer/DefaultFileTransferTransporter.cpp @@ -8,25 +8,26 @@ #include <boost/bind.hpp> #include <boost/smart_ptr/make_shared.hpp> #include <Swiften/Base/Log.h> #include <Swiften/Base/foreach.h> -#include <Swiften/FileTransfer/SOCKS5BytestreamServerSession.h> -#include <Swiften/FileTransfer/RemoteJingleTransportCandidateSelector.h> +#include <Swiften/Crypto/CryptoProvider.h> +#include <Swiften/FileTransfer/FileTransferOptions.h> +#include <Swiften/FileTransfer/IBBReceiveSession.h> +#include <Swiften/FileTransfer/IBBSendSession.h> #include <Swiften/FileTransfer/LocalJingleTransportCandidateGenerator.h> -#include <Swiften/FileTransfer/SOCKS5BytestreamRegistry.h> +#include <Swiften/FileTransfer/RemoteJingleTransportCandidateSelector.h> #include <Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.h> -#include <Swiften/FileTransfer/SOCKS5BytestreamServerManager.h> +#include <Swiften/FileTransfer/SOCKS5BytestreamRegistry.h> #include <Swiften/FileTransfer/SOCKS5BytestreamServer.h> -#include <Swiften/FileTransfer/IBBSendSession.h> -#include <Swiften/FileTransfer/IBBReceiveSession.h> +#include <Swiften/FileTransfer/SOCKS5BytestreamServerManager.h> +#include <Swiften/FileTransfer/SOCKS5BytestreamServerSession.h> #include <Swiften/FileTransfer/TransportSession.h> -#include <Swiften/StringCodecs/Hexify.h> -#include <Swiften/Crypto/CryptoProvider.h> #include <Swiften/Queries/GenericRequest.h> +#include <Swiften/StringCodecs/Hexify.h> using namespace Swift; namespace { class IBBSendTransportSession : public TransportSession { public: @@ -69,12 +70,13 @@ namespace { boost::bsignals::scoped_connection bytesSentConnection; }; class FailingTransportSession : public TransportSession { public: virtual void start() SWIFTEN_OVERRIDE { + assert(false); onFinished(FileTransferError(FileTransferError::PeerError)); } virtual void stop() SWIFTEN_OVERRIDE { } }; @@ -142,12 +144,13 @@ DefaultFileTransferTransporter::DefaultFileTransferTransporter( const FileTransferOptions& options) : initiator(initiator), responder(responder), role(role), s5bRegistry(s5bRegistry), s5bServerManager(s5bServerManager), + s5bProxy(s5bProxy), crypto(crypto), router(router) { localCandidateGenerator = new LocalJingleTransportCandidateGenerator( s5bServerManager, s5bProxy, @@ -163,12 +166,13 @@ DefaultFileTransferTransporter::DefaultFileTransferTransporter( options); remoteCandidateSelector->onCandidateSelectFinished.connect( boost::bind(&DefaultFileTransferTransporter::handleRemoteCandidateSelectFinished, this, _1, _2)); } DefaultFileTransferTransporter::~DefaultFileTransferTransporter() { + stopGeneratingLocalCandidates(); delete remoteCandidateSelector; delete localCandidateGenerator; } void DefaultFileTransferTransporter::initialize() { s5bSessionID = s5bRegistry->generateSessionID(); @@ -186,49 +190,52 @@ void DefaultFileTransferTransporter::stopGeneratingLocalCandidates() { localCandidateGenerator->stop(); } void DefaultFileTransferTransporter::handleLocalCandidatesGenerated( const std::vector<JingleS5BTransportPayload::Candidate>& candidates) { s5bRegistry->setHasBytestream(getSOCKS5DstAddr(), true); - onLocalCandidatesGenerated(s5bSessionID, candidates); + s5bProxy->connectToProxies(getSOCKS5DstAddr()); + onLocalCandidatesGenerated(s5bSessionID, candidates, getSOCKS5DstAddr()); } void DefaultFileTransferTransporter::handleRemoteCandidateSelectFinished( const boost::optional<JingleS5BTransportPayload::Candidate>& candidate, boost::shared_ptr<SOCKS5BytestreamClientSession> session) { remoteS5BClientSession = session; onRemoteCandidateSelectFinished(s5bSessionID, candidate); } void DefaultFileTransferTransporter::addRemoteCandidates( - const std::vector<JingleS5BTransportPayload::Candidate>& candidates) { - remoteCandidateSelector->setSOCKS5DstAddr(getSOCKS5DstAddr()); + const std::vector<JingleS5BTransportPayload::Candidate>& candidates, const std::string& dstAddr) { + remoteCandidateSelector->setSOCKS5DstAddr(dstAddr.empty() ? getRemoteCandidateSOCKS5DstAddr() : dstAddr); remoteCandidateSelector->addCandidates(candidates); } void DefaultFileTransferTransporter::startTryingRemoteCandidates() { remoteCandidateSelector->startSelectingCandidate(); } void DefaultFileTransferTransporter::stopTryingRemoteCandidates() { remoteCandidateSelector->stopSelectingCandidate(); } -void DefaultFileTransferTransporter::startActivatingProxy(const JID&) { - // TODO - assert(false); - /* +void DefaultFileTransferTransporter::handleActivateProxySessionResult(const std::string& sessionID, ErrorPayload::ref error) { + onProxyActivated(sessionID, error); +} + +void DefaultFileTransferTransporter::startActivatingProxy(const JID& proxyServiceJID) { + // activate proxy + SWIFT_LOG(debug) << "Start activating proxy " << proxyServiceJID.toString() << " with sid = " << s5bSessionID << "." << std::endl; S5BProxyRequest::ref proxyRequest = boost::make_shared<S5BProxyRequest>(); proxyRequest->setSID(s5bSessionID); - proxyRequest->setActivate(getTarget()); + proxyRequest->setActivate(role == Initiator ? responder : initiator); - boost::shared_ptr<GenericRequest<S5BProxyRequest> > request = boost::make_shared<GenericRequest<S5BProxyRequest> >(IQ::Set, proxy, proxyRequest, router); - request->onResponse.connect(boost::bind(&OutgoingJingleFileTransfer::handleActivateProxySessionResult, this, _1, _2)); + boost::shared_ptr<GenericRequest<S5BProxyRequest> > request = boost::make_shared<GenericRequest<S5BProxyRequest> >(IQ::Set, proxyServiceJID, proxyRequest, router); + request->onResponse.connect(boost::bind(&DefaultFileTransferTransporter::handleActivateProxySessionResult, this, s5bSessionID, _2)); request->send(); - */ } void DefaultFileTransferTransporter::stopActivatingProxy() { // TODO assert(false); } @@ -252,20 +259,20 @@ boost::shared_ptr<TransportSession> DefaultFileTransferTransporter::createIBBRec boost::shared_ptr<IBBReceiveSession> ibbSession = boost::make_shared<IBBReceiveSession>( sessionID, initiator, responder, size, stream, router); return boost::make_shared<IBBReceiveTransportSession>(ibbSession); } boost::shared_ptr<TransportSession> DefaultFileTransferTransporter::createRemoteCandidateSession( - boost::shared_ptr<ReadBytestream> stream) { + boost::shared_ptr<ReadBytestream> stream, const JingleS5BTransportPayload::Candidate& candidate) { closeLocalSession(); return boost::make_shared<S5BTransportSession<SOCKS5BytestreamClientSession> >( remoteS5BClientSession, stream); } boost::shared_ptr<TransportSession> DefaultFileTransferTransporter::createRemoteCandidateSession( - boost::shared_ptr<WriteBytestream> stream) { + boost::shared_ptr<WriteBytestream> stream, const JingleS5BTransportPayload::Candidate& candidate) { closeLocalSession(); return boost::make_shared<S5BTransportSession<SOCKS5BytestreamClientSession> >( remoteS5BClientSession, stream); } boost::shared_ptr<SOCKS5BytestreamServerSession> DefaultFileTransferTransporter::getServerSession() { @@ -277,40 +284,95 @@ boost::shared_ptr<SOCKS5BytestreamServerSession> DefaultFileTransferTransporter: serverSessions.pop_back(); session->stop(); } return !serverSessions.empty() ? serverSessions.front() : boost::shared_ptr<SOCKS5BytestreamServerSession>(); } - boost::shared_ptr<TransportSession> DefaultFileTransferTransporter::createLocalCandidateSession( - boost::shared_ptr<ReadBytestream> stream) { + boost::shared_ptr<ReadBytestream> stream, const JingleS5BTransportPayload::Candidate& candidate) { closeRemoteSession(); - boost::shared_ptr<SOCKS5BytestreamServerSession> serverSession = getServerSession(); - if (serverSession) { - return boost::make_shared<S5BTransportSession<SOCKS5BytestreamServerSession> >(serverSession, stream); + boost::shared_ptr<TransportSession> transportSession; + if (candidate.type == JingleS5BTransportPayload::Candidate::ProxyType) { + SOCKS5BytestreamClientSession::ref proxySession = s5bProxy->getProxySessionAndCloseOthers(candidate.jid, getLocalCandidateSOCKS5DstAddr()); + assert(proxySession); + transportSession = boost::make_shared<S5BTransportSession<SOCKS5BytestreamClientSession> >(proxySession, stream); } - else { - return boost::make_shared<FailingTransportSession>(); + + if (!transportSession) { + boost::shared_ptr<SOCKS5BytestreamServerSession> serverSession = getServerSession(); + if (serverSession) { + transportSession = boost::make_shared<S5BTransportSession<SOCKS5BytestreamServerSession> >(serverSession, stream); + } } + + if (!transportSession) { + transportSession = boost::make_shared<FailingTransportSession>(); + } + return transportSession; } boost::shared_ptr<TransportSession> DefaultFileTransferTransporter::createLocalCandidateSession( - boost::shared_ptr<WriteBytestream> stream) { + boost::shared_ptr<WriteBytestream> stream, const JingleS5BTransportPayload::Candidate& candidate) { closeRemoteSession(); - boost::shared_ptr<SOCKS5BytestreamServerSession> serverSession = getServerSession(); - if (serverSession) { - return boost::make_shared<S5BTransportSession<SOCKS5BytestreamServerSession> >(serverSession, stream); + boost::shared_ptr<TransportSession> transportSession; + if (candidate.type == JingleS5BTransportPayload::Candidate::ProxyType) { + SOCKS5BytestreamClientSession::ref proxySession = s5bProxy->getProxySessionAndCloseOthers(candidate.jid, getLocalCandidateSOCKS5DstAddr()); + assert(proxySession); + transportSession = boost::make_shared<S5BTransportSession<SOCKS5BytestreamClientSession> >(proxySession, stream); } - else { - return boost::make_shared<FailingTransportSession>(); + + if (!transportSession) { + boost::shared_ptr<SOCKS5BytestreamServerSession> serverSession = getServerSession(); + if (serverSession) { + transportSession = boost::make_shared<S5BTransportSession<SOCKS5BytestreamServerSession> >(serverSession, stream); + } + } + + if (!transportSession) { + transportSession = boost::make_shared<FailingTransportSession>(); } + return transportSession; } std::string DefaultFileTransferTransporter::getSOCKS5DstAddr() const { - return Hexify::hexify(crypto->getSHA1Hash( - createSafeByteArray(s5bSessionID + initiator.toString() + initiator.toString()))); + std::string result; + if (role == Initiator) { + result = getInitiatorCandidateSOCKS5DstAddr(); + SWIFT_LOG(debug) << "Initiator S5B DST.ADDR = " << s5bSessionID << " + " << initiator.toString() << " + " << responder.toString() << " : " << result << std::endl; + } + else { + result = getResponderCandidateSOCKS5DstAddr(); + SWIFT_LOG(debug) << "Responder S5B DST.ADDR = " << s5bSessionID << " + " << responder.toString() << " + " << initiator.toString() << " : " << result << std::endl; + } + return result; +} + +std::string DefaultFileTransferTransporter::getInitiatorCandidateSOCKS5DstAddr() const { + return Hexify::hexify(crypto->getSHA1Hash(createSafeByteArray(s5bSessionID + initiator.toString() + responder.toString()))); +} + +std::string DefaultFileTransferTransporter::getResponderCandidateSOCKS5DstAddr() const { + return Hexify::hexify(crypto->getSHA1Hash(createSafeByteArray(s5bSessionID + responder.toString() + initiator.toString()))); +} + +std::string DefaultFileTransferTransporter::getRemoteCandidateSOCKS5DstAddr() const { + if (role == Initiator) { + return getResponderCandidateSOCKS5DstAddr(); + } + else { + return getInitiatorCandidateSOCKS5DstAddr(); + } +} + +std::string DefaultFileTransferTransporter::getLocalCandidateSOCKS5DstAddr() const { + if (role == Responder) { + return getResponderCandidateSOCKS5DstAddr(); + } + else { + return getInitiatorCandidateSOCKS5DstAddr(); + } } void DefaultFileTransferTransporter::closeLocalSession() { s5bRegistry->setHasBytestream(getSOCKS5DstAddr(), false); std::vector<boost::shared_ptr<SOCKS5BytestreamServerSession> > serverSessions = s5bServerManager->getServer()->getSessions(getSOCKS5DstAddr()); diff --git a/Swiften/FileTransfer/DefaultFileTransferTransporter.h b/Swiften/FileTransfer/DefaultFileTransferTransporter.h index f5a4b9d..347c313 100644 --- a/Swiften/FileTransfer/DefaultFileTransferTransporter.h +++ b/Swiften/FileTransfer/DefaultFileTransferTransporter.h @@ -6,12 +6,13 @@ #pragma once #include <Swiften/Base/Override.h> #include <Swiften/Base/API.h> #include <Swiften/FileTransfer/FileTransferTransporter.h> +#include <Swiften/Elements/ErrorPayload.h> namespace Swift { class LocalJingleTransportCandidateGenerator; class RemoteJingleTransportCandidateSelector; class SOCKS5BytestreamRegistry; class SOCKS5BytestreamServerManager; @@ -54,48 +55,55 @@ namespace Swift { virtual void initialize(const std::string& s5bSessionID); virtual void startGeneratingLocalCandidates() SWIFTEN_OVERRIDE; virtual void stopGeneratingLocalCandidates() SWIFTEN_OVERRIDE; virtual void addRemoteCandidates( - const std::vector<JingleS5BTransportPayload::Candidate>&) SWIFTEN_OVERRIDE; + const std::vector<JingleS5BTransportPayload::Candidate>&, const std::string&) SWIFTEN_OVERRIDE; virtual void startTryingRemoteCandidates() SWIFTEN_OVERRIDE; virtual void stopTryingRemoteCandidates() SWIFTEN_OVERRIDE; virtual void startActivatingProxy(const JID& jid) SWIFTEN_OVERRIDE; virtual void stopActivatingProxy() SWIFTEN_OVERRIDE; virtual boost::shared_ptr<TransportSession> createIBBSendSession( const std::string& sessionID, unsigned int blockSize, boost::shared_ptr<ReadBytestream>) SWIFTEN_OVERRIDE; virtual boost::shared_ptr<TransportSession> createIBBReceiveSession( const std::string& sessionID, unsigned long long size, boost::shared_ptr<WriteBytestream>) SWIFTEN_OVERRIDE; virtual boost::shared_ptr<TransportSession> createRemoteCandidateSession( - boost::shared_ptr<ReadBytestream>) SWIFTEN_OVERRIDE; + boost::shared_ptr<ReadBytestream>, const JingleS5BTransportPayload::Candidate& candidate) SWIFTEN_OVERRIDE; virtual boost::shared_ptr<TransportSession> createRemoteCandidateSession( - boost::shared_ptr<WriteBytestream>) SWIFTEN_OVERRIDE; + boost::shared_ptr<WriteBytestream>, const JingleS5BTransportPayload::Candidate& candidate) SWIFTEN_OVERRIDE; virtual boost::shared_ptr<TransportSession> createLocalCandidateSession( - boost::shared_ptr<ReadBytestream>) SWIFTEN_OVERRIDE; + boost::shared_ptr<ReadBytestream>, const JingleS5BTransportPayload::Candidate& candidate) SWIFTEN_OVERRIDE; virtual boost::shared_ptr<TransportSession> createLocalCandidateSession( - boost::shared_ptr<WriteBytestream>) SWIFTEN_OVERRIDE; + boost::shared_ptr<WriteBytestream>, const JingleS5BTransportPayload::Candidate& candidate) SWIFTEN_OVERRIDE; private: void handleLocalCandidatesGenerated(const std::vector<JingleS5BTransportPayload::Candidate>&); void handleRemoteCandidateSelectFinished( const boost::optional<JingleS5BTransportPayload::Candidate>&, boost::shared_ptr<SOCKS5BytestreamClientSession>); - std::string getSOCKS5DstAddr() const; + void handleActivateProxySessionResult(const std::string& sessionID, ErrorPayload::ref error); void closeLocalSession(); void closeRemoteSession(); boost::shared_ptr<SOCKS5BytestreamServerSession> getServerSession(); + std::string getSOCKS5DstAddr() const; + std::string getInitiatorCandidateSOCKS5DstAddr() const; + std::string getResponderCandidateSOCKS5DstAddr() const; + std::string getRemoteCandidateSOCKS5DstAddr() const; + std::string getLocalCandidateSOCKS5DstAddr() const; + private: JID initiator; JID responder; Role role; SOCKS5BytestreamRegistry* s5bRegistry; SOCKS5BytestreamServerManager* s5bServerManager; + SOCKS5BytestreamProxiesManager* s5bProxy; CryptoProvider* crypto; IQRouter* router; LocalJingleTransportCandidateGenerator* localCandidateGenerator; RemoteJingleTransportCandidateSelector* remoteCandidateSelector; std::string s5bSessionID; boost::shared_ptr<SOCKS5BytestreamClientSession> remoteS5BClientSession; diff --git a/Swiften/FileTransfer/FileTransferTransporter.h b/Swiften/FileTransfer/FileTransferTransporter.h index 2116f0d..45eb811 100644 --- a/Swiften/FileTransfer/FileTransferTransporter.h +++ b/Swiften/FileTransfer/FileTransferTransporter.h @@ -1,8 +1,8 @@ /* - * Copyright (c) 2013-2014 Isode Limited. + * Copyright (c) 2013-2015 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #pragma once @@ -30,31 +30,31 @@ namespace Swift { virtual ~FileTransferTransporter(); virtual void startGeneratingLocalCandidates() = 0; virtual void stopGeneratingLocalCandidates() = 0; virtual void addRemoteCandidates( - const std::vector<JingleS5BTransportPayload::Candidate>&) = 0; + const std::vector<JingleS5BTransportPayload::Candidate>&, const std::string&) = 0; virtual void startTryingRemoteCandidates() = 0; virtual void stopTryingRemoteCandidates() = 0; virtual void startActivatingProxy(const JID& proxy) = 0; virtual void stopActivatingProxy() = 0; virtual boost::shared_ptr<TransportSession> createIBBSendSession( const std::string& sessionID, unsigned int blockSize, boost::shared_ptr<ReadBytestream>) = 0; virtual boost::shared_ptr<TransportSession> createIBBReceiveSession( const std::string& sessionID, unsigned long long size, boost::shared_ptr<WriteBytestream>) = 0; virtual boost::shared_ptr<TransportSession> createRemoteCandidateSession( - boost::shared_ptr<ReadBytestream>) = 0; + boost::shared_ptr<ReadBytestream>, const JingleS5BTransportPayload::Candidate& candidate) = 0; virtual boost::shared_ptr<TransportSession> createRemoteCandidateSession( - boost::shared_ptr<WriteBytestream>) = 0; + boost::shared_ptr<WriteBytestream>, const JingleS5BTransportPayload::Candidate& candidate) = 0; virtual boost::shared_ptr<TransportSession> createLocalCandidateSession( - boost::shared_ptr<ReadBytestream>) = 0; + boost::shared_ptr<ReadBytestream>, const JingleS5BTransportPayload::Candidate& candidate) = 0; virtual boost::shared_ptr<TransportSession> createLocalCandidateSession( - boost::shared_ptr<WriteBytestream>) = 0; + boost::shared_ptr<WriteBytestream>, const JingleS5BTransportPayload::Candidate& candidate) = 0; - boost::signal<void (const std::string& /* sessionID */, const std::vector<JingleS5BTransportPayload::Candidate>&)> onLocalCandidatesGenerated; + boost::signal<void (const std::string& /* sessionID */, const std::vector<JingleS5BTransportPayload::Candidate>&, const std::string& /* dstAddr */)> onLocalCandidatesGenerated; boost::signal<void (const std::string& /* sessionID */, const boost::optional<JingleS5BTransportPayload::Candidate>&)> onRemoteCandidateSelectFinished; boost::signal<void (const std::string& /* sessionID */, boost::shared_ptr<ErrorPayload>)> onProxyActivated; }; } diff --git a/Swiften/FileTransfer/IncomingJingleFileTransfer.cpp b/Swiften/FileTransfer/IncomingJingleFileTransfer.cpp index daecf92..a0cd47c 100644 --- a/Swiften/FileTransfer/IncomingJingleFileTransfer.cpp +++ b/Swiften/FileTransfer/IncomingJingleFileTransfer.cpp @@ -77,13 +77,13 @@ void IncomingJingleFileTransfer::accept( boost::bind(&IncomingJingleFileTransfer::handleWriteStreamDataReceived, this, _1)); if (JingleS5BTransportPayload::ref s5bTransport = initialContent->getTransport<JingleS5BTransportPayload>()) { SWIFT_LOG(debug) << "Got S5B transport as initial payload." << std::endl; setTransporter(transporterFactory->createResponderTransporter( getInitiator(), getResponder(), s5bTransport->getSessionID(), options)); - transporter->addRemoteCandidates(s5bTransport->getCandidates()); + transporter->addRemoteCandidates(s5bTransport->getCandidates(), s5bTransport->getDstAddr()); setState(GeneratingInitialLocalCandidates); transporter->startGeneratingLocalCandidates(); } else if (JingleIBBTransportPayload::ref ibbTransport = initialContent->getTransport<JingleIBBTransportPayload>()) { SWIFT_LOG(debug) << "Got IBB transport as initial payload." << std::endl; setTransporter(transporterFactory->createResponderTransporter( @@ -106,21 +106,23 @@ void IncomingJingleFileTransfer::cancel() { SWIFT_LOG(debug) << std::endl; terminate(state == Initial ? JinglePayload::Reason::Decline : JinglePayload::Reason::Cancel); } void IncomingJingleFileTransfer::handleLocalTransportCandidatesGenerated( const std::string& s5bSessionID, - const std::vector<JingleS5BTransportPayload::Candidate>& candidates) { + const std::vector<JingleS5BTransportPayload::Candidate>& candidates, + const std::string& dstAddr) { SWIFT_LOG(debug) << std::endl; if (state != GeneratingInitialLocalCandidates) { SWIFT_LOG(warning) << "Incorrect state" << std::endl; return; } fillCandidateMap(localCandidates, candidates); JingleS5BTransportPayload::ref transport = boost::make_shared<JingleS5BTransportPayload>(); transport->setSessionID(s5bSessionID); transport->setMode(JingleS5BTransportPayload::TCPMode); + transport->setDstAddr(dstAddr); foreach(JingleS5BTransportPayload::Candidate candidate, candidates) { transport->addCandidate(candidate); } session->sendAccept(getContentID(), initialContent->getDescriptions()[0], transport); setState(TryingCandidates); @@ -216,13 +218,14 @@ void IncomingJingleFileTransfer::handleTransportReplaceReceived( SWIFT_LOG(debug) << std::endl; if (state != WaitingForFallbackOrTerminate) { SWIFT_LOG(warning) << "Incorrect state" << std::endl; return; } - if (JingleIBBTransportPayload::ref ibbTransport = boost::dynamic_pointer_cast<JingleIBBTransportPayload>(transport)) { + JingleIBBTransportPayload::ref ibbTransport; + if (options.isInBandAllowed() && (ibbTransport = boost::dynamic_pointer_cast<JingleIBBTransportPayload>(transport))) { SWIFT_LOG(debug) << "transport replaced with IBB" << std::endl; startTransferring(transporter->createIBBReceiveSession( ibbTransport->getSessionID(), description->getFileInfo().getSize(), stream)); @@ -335,18 +338,13 @@ void IncomingJingleFileTransfer::stopAll() { bool IncomingJingleFileTransfer::hasPriorityOnCandidateTie() const { return false; } void IncomingJingleFileTransfer::fallback() { - if (options.isInBandAllowed()) { - setState(WaitingForFallbackOrTerminate); - } - else { - terminate(JinglePayload::Reason::ConnectivityError); - } + setState(WaitingForFallbackOrTerminate); } void IncomingJingleFileTransfer::startTransferViaRemoteCandidate() { SWIFT_LOG(debug) << std::endl; if (ourCandidateChoice->type == JingleS5BTransportPayload::Candidate::ProxyType) { @@ -366,13 +364,12 @@ void IncomingJingleFileTransfer::startTransferViaLocalCandidate() { } else { startTransferring(createLocalCandidateSession()); } } - void IncomingJingleFileTransfer::startTransferring(boost::shared_ptr<TransportSession> transportSession) { SWIFT_LOG(debug) << std::endl; this->transportSession = transportSession; transferFinishedConnection = transportSession->onFinished.connect( boost::bind(&IncomingJingleFileTransfer::handleTransferFinished, this, _1)); @@ -390,17 +387,17 @@ bool IncomingJingleFileTransfer::isWaitingForLocalProxyActivate() const { bool IncomingJingleFileTransfer::isTryingCandidates() const { return state == TryingCandidates; } boost::shared_ptr<TransportSession> IncomingJingleFileTransfer::createLocalCandidateSession() { - return transporter->createLocalCandidateSession(stream); + return transporter->createLocalCandidateSession(stream, theirCandidateChoice.get()); } boost::shared_ptr<TransportSession> IncomingJingleFileTransfer::createRemoteCandidateSession() { - return transporter->createRemoteCandidateSession(stream); + return transporter->createRemoteCandidateSession(stream, ourCandidateChoice.get()); } void IncomingJingleFileTransfer::terminate(JinglePayload::Reason::Type reason) { SWIFT_LOG(debug) << reason << std::endl; if (state != Finished) { diff --git a/Swiften/FileTransfer/IncomingJingleFileTransfer.h b/Swiften/FileTransfer/IncomingJingleFileTransfer.h index 7fc22f4..9820e34 100644 --- a/Swiften/FileTransfer/IncomingJingleFileTransfer.h +++ b/Swiften/FileTransfer/IncomingJingleFileTransfer.h @@ -1,8 +1,8 @@ /* - * Copyright (c) 2010-2014 Isode Limited. + * Copyright (c) 2010-2015 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #pragma once @@ -73,13 +73,14 @@ namespace Swift { virtual void handleSessionInfoReceived(boost::shared_ptr<JinglePayload>) SWIFTEN_OVERRIDE; virtual void handleTransportReplaceReceived( const JingleContentID&, boost::shared_ptr<JingleTransportPayload>) SWIFTEN_OVERRIDE; virtual void handleLocalTransportCandidatesGenerated( const std::string& s5bSessionID, - const std::vector<JingleS5BTransportPayload::Candidate>&) SWIFTEN_OVERRIDE; + const std::vector<JingleS5BTransportPayload::Candidate>&, + const std::string& dstAddr) SWIFTEN_OVERRIDE; void handleWriteStreamDataReceived(const std::vector<unsigned char>& data); void stopActiveTransport(); void checkCandidateSelected(); virtual JingleContentID getContentID() const SWIFTEN_OVERRIDE; void checkIfAllDataReceived(); diff --git a/Swiften/FileTransfer/JingleFileTransfer.cpp b/Swiften/FileTransfer/JingleFileTransfer.cpp index e2c0f3a..dbc4391 100644 --- a/Swiften/FileTransfer/JingleFileTransfer.cpp +++ b/Swiften/FileTransfer/JingleFileTransfer.cpp @@ -1,8 +1,8 @@ /* - * Copyright (c) 2013 Isode Limited. + * Copyright (c) 2013-2015 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #include <Swiften/FileTransfer/JingleFileTransfer.h> @@ -109,32 +109,38 @@ void JingleFileTransfer::decideOnCandidates() { } if (!ourCandidateChoice && !theirCandidateChoice) { SWIFT_LOG(debug) << "No candidates succeeded." << std::endl; fallback(); } else if (ourCandidateChoice && !theirCandidateChoice) { + SWIFT_LOG(debug) << "Start transfer using remote candidate: " << ourCandidateChoice.get().cid << "." << std::endl; startTransferViaRemoteCandidate(); } else if (theirCandidateChoice && !ourCandidateChoice) { + SWIFT_LOG(debug) << "Start transfer using local candidate: " << theirCandidateChoice.get().cid << "." << std::endl; startTransferViaLocalCandidate(); } else { SWIFT_LOG(debug) << "Choosing between candidates " << ourCandidateChoice->cid << "(" << ourCandidateChoice->priority << ")" << " and " << theirCandidateChoice->cid << "(" << theirCandidateChoice->priority << ")" << std::endl; if (ourCandidateChoice->priority > theirCandidateChoice->priority) { + SWIFT_LOG(debug) << "Start transfer using remote candidate: " << ourCandidateChoice.get().cid << "." << std::endl; startTransferViaRemoteCandidate(); } else if (ourCandidateChoice->priority < theirCandidateChoice->priority) { + SWIFT_LOG(debug) << "Start transfer using local candidate:" << theirCandidateChoice.get().cid << "." << std::endl; startTransferViaLocalCandidate(); } else { if (hasPriorityOnCandidateTie()) { + SWIFT_LOG(debug) << "Start transfer using remote candidate: " << ourCandidateChoice.get().cid << std::endl; startTransferViaRemoteCandidate(); } else { + SWIFT_LOG(debug) << "Start transfer using local candidate: " << theirCandidateChoice.get().cid << std::endl; startTransferViaLocalCandidate(); } } } } @@ -153,13 +159,13 @@ void JingleFileTransfer::handleProxyActivateFinished( } else { JingleS5BTransportPayload::ref proxyActivate = boost::make_shared<JingleS5BTransportPayload>(); proxyActivate->setSessionID(s5bSessionID); proxyActivate->setActivated(theirCandidateChoice->cid); session->sendTransportInfo(getContentID(), proxyActivate); - startTransferring(createRemoteCandidateSession()); + startTransferring(createLocalCandidateSession()); } } void JingleFileTransfer::handleTransportInfoReceived( const JingleContentID& /* contentID */, JingleTransportPayload::ref transport) { SWIFT_LOG(debug) << std::endl; @@ -190,25 +196,29 @@ void JingleFileTransfer::handleTransportInfoReceived( } else { SWIFT_LOG(warning) << "ourCandidateChoice doesn't match activated proxy candidate!" << std::endl; terminate(JinglePayload::Reason::GeneralError); } } + else if (s5bPayload->hasProxyError()) { + SWIFT_LOG(debug) << "Received proxy error. Trying to fall back to IBB." << std::endl; + fallback(); + } else { SWIFT_LOG(debug) << "Ignoring unknown info" << std::endl; } } else { SWIFT_LOG(debug) << "Ignoring unknown info" << std::endl; } } void JingleFileTransfer::setTransporter(FileTransferTransporter* transporter) { this->transporter = transporter; localTransportCandidatesGeneratedConnection = transporter->onLocalCandidatesGenerated.connect( - boost::bind(&JingleFileTransfer::handleLocalTransportCandidatesGenerated, this, _1, _2)); + boost::bind(&JingleFileTransfer::handleLocalTransportCandidatesGenerated, this, _1, _2, _3)); remoteTransportCandidateSelectFinishedConnection = transporter->onRemoteCandidateSelectFinished.connect( boost::bind(&JingleFileTransfer::handleRemoteTransportCandidateSelectFinished, this, _1, _2)); proxyActivatedConnection = transporter->onProxyActivated.connect( boost::bind(&JingleFileTransfer::handleProxyActivateFinished, this, _1, _2)); } diff --git a/Swiften/FileTransfer/JingleFileTransfer.h b/Swiften/FileTransfer/JingleFileTransfer.h index 6ab0d86..aabeec2 100644 --- a/Swiften/FileTransfer/JingleFileTransfer.h +++ b/Swiften/FileTransfer/JingleFileTransfer.h @@ -1,8 +1,8 @@ /* - * Copyright (c) 2013 Isode Limited. + * Copyright (c) 2013-2015 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #pragma once @@ -36,13 +36,14 @@ namespace Swift { virtual ~JingleFileTransfer(); protected: virtual void handleTransportInfoReceived(const JingleContentID&, JingleTransportPayload::ref); virtual void handleLocalTransportCandidatesGenerated( const std::string& s5bSessionID, - const std::vector<JingleS5BTransportPayload::Candidate>&) = 0; + const std::vector<JingleS5BTransportPayload::Candidate>&, + const std::string& dstAddr) = 0; virtual void handleProxyActivateFinished( const std::string& s5bSessionID, ErrorPayload::ref error); virtual void decideOnCandidates(); void handleRemoteTransportCandidateSelectFinished( const std::string& s5bSessionID, const boost::optional<JingleS5BTransportPayload::Candidate>&); diff --git a/Swiften/FileTransfer/OutgoingJingleFileTransfer.cpp b/Swiften/FileTransfer/OutgoingJingleFileTransfer.cpp index 07e927e..7ff1a08 100644 --- a/Swiften/FileTransfer/OutgoingJingleFileTransfer.cpp +++ b/Swiften/FileTransfer/OutgoingJingleFileTransfer.cpp @@ -108,25 +108,25 @@ void OutgoingJingleFileTransfer::handleSessionAcceptReceived( JingleDescription::ref, JingleTransportPayload::ref transportPayload) { SWIFT_LOG(debug) << std::endl; if (state != WaitingForAccept) { SWIFT_LOG(warning) << "Incorrect state" << std::endl; return; } if (JingleS5BTransportPayload::ref s5bPayload = boost::dynamic_pointer_cast<JingleS5BTransportPayload>(transportPayload)) { - transporter->addRemoteCandidates(s5bPayload->getCandidates()); + transporter->addRemoteCandidates(s5bPayload->getCandidates(), s5bPayload->getDstAddr()); setState(TryingCandidates); transporter->startTryingRemoteCandidates(); } else { SWIFT_LOG(debug) << "Unknown transport payload. Falling back." << std::endl; fallback(); } } void OutgoingJingleFileTransfer::handleSessionTerminateReceived(boost::optional<JinglePayload::Reason> reason) { SWIFT_LOG(debug) << std::endl; - if (state == Finished) { SWIFT_LOG(warning) << "Incorrect state" << std::endl; return; } + if (state == Finished) { SWIFT_LOG(warning) << "Incorrect state: " << state << std::endl; return; } stopAll(); if (reason && reason->type == JinglePayload::Reason::Cancel) { setFinishedState(FileTransfer::State::Canceled, FileTransferError(FileTransferError::PeerError)); } else if (reason && reason->type == JinglePayload::Reason::Success) { @@ -147,23 +147,29 @@ void OutgoingJingleFileTransfer::handleTransportAcceptReceived(const JingleConte else { SWIFT_LOG(debug) << "Unknown transport replacement" << std::endl; terminate(JinglePayload::Reason::FailedTransport); } } +void OutgoingJingleFileTransfer::handleTransportRejectReceived(const JingleContentID &, boost::shared_ptr<JingleTransportPayload>) { + SWIFT_LOG(debug) << std::endl; + + terminate(JinglePayload::Reason::UnsupportedTransports); +} + void OutgoingJingleFileTransfer::sendSessionInfoHash() { SWIFT_LOG(debug) << std::endl; JingleFileTransferHash::ref hashElement = boost::make_shared<JingleFileTransferHash>(); hashElement->getFileInfo().addHash(HashElement("sha-1", hashCalculator->getSHA1Hash())); hashElement->getFileInfo().addHash(HashElement("md5", hashCalculator->getMD5Hash())); session->sendInfo(hashElement); } void OutgoingJingleFileTransfer::handleLocalTransportCandidatesGenerated( - const std::string& s5bSessionID, const std::vector<JingleS5BTransportPayload::Candidate>& candidates) { + const std::string& s5bSessionID, const std::vector<JingleS5BTransportPayload::Candidate>& candidates, const std::string& dstAddr) { SWIFT_LOG(debug) << std::endl; if (state != GeneratingInitialLocalCandidates) { SWIFT_LOG(warning) << "Incorrect state" << std::endl; return; } fillCandidateMap(localCandidates, candidates); JingleFileTransferDescription::ref description = boost::make_shared<JingleFileTransferDescription>(); @@ -171,36 +177,38 @@ void OutgoingJingleFileTransfer::handleLocalTransportCandidatesGenerated( fileInfo.addHash(HashElement("md5", ByteArray())); description->setFileInfo(fileInfo); JingleS5BTransportPayload::ref transport = boost::make_shared<JingleS5BTransportPayload>(); transport->setSessionID(s5bSessionID); transport->setMode(JingleS5BTransportPayload::TCPMode); + transport->setDstAddr(dstAddr); foreach(JingleS5BTransportPayload::Candidate candidate, candidates) { transport->addCandidate(candidate); } setState(WaitingForAccept); session->sendInitiate(contentID, description, transport); } void OutgoingJingleFileTransfer::fallback() { - SWIFT_LOG(debug) << std::endl; if (options.isInBandAllowed()) { + SWIFT_LOG(debug) << "Trying to fallback to IBB transport." << std::endl; JingleIBBTransportPayload::ref ibbTransport = boost::make_shared<JingleIBBTransportPayload>(); ibbTransport->setBlockSize(DEFAULT_BLOCK_SIZE); ibbTransport->setSessionID(idGenerator->generateID()); setState(FallbackRequested); session->sendTransportReplace(contentID, ibbTransport); } else { + SWIFT_LOG(debug) << "Fallback to IBB transport not allowed." << std::endl; terminate(JinglePayload::Reason::ConnectivityError); } } void OutgoingJingleFileTransfer::handleTransferFinished(boost::optional<FileTransferError> error) { SWIFT_LOG(debug) << std::endl; - if (state != Transferring) { SWIFT_LOG(warning) << "Incorrect state" << std::endl; return; } + if (state != Transferring) { SWIFT_LOG(warning) << "Incorrect state: " << state << std::endl; return; } if (error) { terminate(JinglePayload::Reason::ConnectivityError); } else { sendSessionInfoHash(); @@ -344,17 +352,17 @@ bool OutgoingJingleFileTransfer::isWaitingForLocalProxyActivate() const { bool OutgoingJingleFileTransfer::isTryingCandidates() const { return state == TryingCandidates; } boost::shared_ptr<TransportSession> OutgoingJingleFileTransfer::createLocalCandidateSession() { - return transporter->createLocalCandidateSession(stream); + return transporter->createLocalCandidateSession(stream, theirCandidateChoice.get()); } boost::shared_ptr<TransportSession> OutgoingJingleFileTransfer::createRemoteCandidateSession() { - return transporter->createRemoteCandidateSession(stream); + return transporter->createRemoteCandidateSession(stream, ourCandidateChoice.get()); } void OutgoingJingleFileTransfer::handleWaitForRemoteTerminationTimeout() { assert(state == WaitForTermination); SWIFT_LOG(warning) << "Other party did not terminate session. Terminate it now." << std::endl; waitForRemoteTermination->stop(); diff --git a/Swiften/FileTransfer/OutgoingJingleFileTransfer.h b/Swiften/FileTransfer/OutgoingJingleFileTransfer.h index 52960d5..4cb2685 100644 --- a/Swiften/FileTransfer/OutgoingJingleFileTransfer.h +++ b/Swiften/FileTransfer/OutgoingJingleFileTransfer.h @@ -51,13 +51,13 @@ namespace Swift { virtual void start() SWIFTEN_OVERRIDE; virtual void cancel() SWIFTEN_OVERRIDE; private: enum State { Initial, - GeneratingInitialLocalCandidates, + GeneratingInitialLocalCandidates, WaitingForAccept, TryingCandidates, WaitingForPeerProxyActivate, WaitingForLocalProxyActivate, WaitingForCandidateAcknowledge, FallbackRequested, @@ -66,17 +66,18 @@ namespace Swift { Finished }; virtual void handleSessionAcceptReceived(const JingleContentID&, boost::shared_ptr<JingleDescription>, boost::shared_ptr<JingleTransportPayload>) SWIFTEN_OVERRIDE; virtual void handleSessionTerminateReceived(boost::optional<JinglePayload::Reason> reason) SWIFTEN_OVERRIDE; virtual void handleTransportAcceptReceived(const JingleContentID&, boost::shared_ptr<JingleTransportPayload>) SWIFTEN_OVERRIDE; + virtual void handleTransportRejectReceived(const JingleContentID &, boost::shared_ptr<JingleTransportPayload>) SWIFTEN_OVERRIDE; virtual void startTransferViaRemoteCandidate() SWIFTEN_OVERRIDE; virtual void startTransferViaLocalCandidate() SWIFTEN_OVERRIDE; void startTransferringIfCandidateAcknowledged(); - virtual void handleLocalTransportCandidatesGenerated(const std::string& s5bSessionID, const std::vector<JingleS5BTransportPayload::Candidate>&) SWIFTEN_OVERRIDE; + virtual void handleLocalTransportCandidatesGenerated(const std::string& s5bSessionID, const std::vector<JingleS5BTransportPayload::Candidate>&, const std::string& dstAddr) SWIFTEN_OVERRIDE; virtual void handleTransportInfoAcknowledged(const std::string& id) SWIFTEN_OVERRIDE; virtual JingleContentID getContentID() const SWIFTEN_OVERRIDE; virtual void terminate(JinglePayload::Reason::Type reason) SWIFTEN_OVERRIDE; diff --git a/Swiften/FileTransfer/SOCKS5BytestreamClientSession.cpp b/Swiften/FileTransfer/SOCKS5BytestreamClientSession.cpp index 82fd17e..812adbe 100644 --- a/Swiften/FileTransfer/SOCKS5BytestreamClientSession.cpp +++ b/Swiften/FileTransfer/SOCKS5BytestreamClientSession.cpp @@ -2,13 +2,13 @@ * Copyright (c) 2011 Tobias Markmann * Licensed under the simplified BSD license. * See Documentation/Licenses/BSD-simplified.txt for more information. */ /* - * Copyright (c) 2013 Isode Limited. + * Copyright (c) 2013-2015 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #include "SOCKS5BytestreamClientSession.h" @@ -33,13 +33,13 @@ SOCKS5BytestreamClientSession::SOCKS5BytestreamClientSession( TimerFactory* timerFactory) : connection(connection), addressPort(addressPort), destination(destination), state(Initial), chunkSize(131072) { - weFailedTimeout = timerFactory->createTimer(2000); + weFailedTimeout = timerFactory->createTimer(3000); weFailedTimeout->onTick.connect( boost::bind(&SOCKS5BytestreamClientSession::handleWeFailedTimeout, this)); } SOCKS5BytestreamClientSession::~SOCKS5BytestreamClientSession() { } @@ -52,12 +52,15 @@ void SOCKS5BytestreamClientSession::start() { boost::bind(&SOCKS5BytestreamClientSession::handleConnectFinished, this, _1)); connection->connect(addressPort); } void SOCKS5BytestreamClientSession::stop() { SWIFT_LOG(debug) << std::endl; + if (state < Ready) { + weFailedTimeout->stop(); + } if (state == Finished) { return; } closeConnection(); readBytestream.reset(); state = Finished; @@ -198,13 +201,15 @@ void SOCKS5BytestreamClientSession::sendData() { finish(false); } } void SOCKS5BytestreamClientSession::finish(bool error) { SWIFT_LOG(debug) << std::endl; - weFailedTimeout->stop(); + if (state < Ready) { + weFailedTimeout->stop(); + } closeConnection(); readBytestream.reset(); if (state == Initial || state == Hello || state == Authenticating) { onSessionReady(true); } else { @@ -225,12 +230,13 @@ void SOCKS5BytestreamClientSession::handleConnectFinished(bool error) { } else { SWIFT_LOG(debug) << "Successfully connected via TCP" << addressPort.toString() << "." << std::endl; disconnectedConnection = connection->onDisconnected.connect( boost::bind(&SOCKS5BytestreamClientSession::handleDisconnected, this, _1)); dataReadConnection = connection->onDataRead.connect( boost::bind(&SOCKS5BytestreamClientSession::handleDataRead, this, _1)); + weFailedTimeout->stop(); weFailedTimeout->start(); process(); } } void SOCKS5BytestreamClientSession::handleDataRead(boost::shared_ptr<SafeByteArray> data) { diff --git a/Swiften/Network/BoostNetworkFactories.h b/Swiften/Network/BoostNetworkFactories.h index baadbf1..32fdd93 100644 --- a/Swiften/Network/BoostNetworkFactories.h +++ b/Swiften/Network/BoostNetworkFactories.h @@ -1,8 +1,8 @@ /* - * Copyright (c) 2010-2013 Isode Limited. + * Copyright (c) 2010-2015 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #pragma once @@ -16,13 +16,13 @@ namespace Swift { class NATTraverser; class PlatformTLSFactories; class SWIFTEN_API BoostNetworkFactories : public NetworkFactories { public: BoostNetworkFactories(EventLoop* eventLoop); - ~BoostNetworkFactories(); + virtual ~BoostNetworkFactories(); virtual TimerFactory* getTimerFactory() const SWIFTEN_OVERRIDE { return timerFactory; } virtual ConnectionFactory* getConnectionFactory() const SWIFTEN_OVERRIDE { |