diff options
Diffstat (limited to 'Swiften/FileTransfer')
84 files changed, 5404 insertions, 5383 deletions
diff --git a/Swiften/FileTransfer/ByteArrayReadBytestream.cpp b/Swiften/FileTransfer/ByteArrayReadBytestream.cpp index 66095bf..cd9fa4a 100644 --- a/Swiften/FileTransfer/ByteArrayReadBytestream.cpp +++ b/Swiften/FileTransfer/ByteArrayReadBytestream.cpp @@ -1,33 +1,34 @@ /* - * Copyright (c) 2010-2013 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #include <Swiften/FileTransfer/ByteArrayReadBytestream.h> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> + #include <boost/numeric/conversion/cast.hpp> #include <Swiften/Base/Algorithm.h> using namespace Swift; -boost::shared_ptr<ByteArray> ByteArrayReadBytestream::read(size_t size) { - size_t readSize = size; - if (position + readSize > data.size()) { - readSize = data.size() - position; - } - boost::shared_ptr<ByteArray> result = boost::make_shared<ByteArray>( - data.begin() + boost::numeric_cast<long long>(position), - data.begin() + boost::numeric_cast<long long>(position) + boost::numeric_cast<long long>(readSize)); - - onRead(*result); - position += readSize; - return result; +std::shared_ptr<ByteArray> ByteArrayReadBytestream::read(size_t size) { + size_t readSize = size; + if (position + readSize > data.size()) { + readSize = data.size() - position; + } + std::shared_ptr<ByteArray> result = std::make_shared<ByteArray>( + data.begin() + boost::numeric_cast<long long>(position), + data.begin() + boost::numeric_cast<long long>(position) + boost::numeric_cast<long long>(readSize)); + + onRead(*result); + position += readSize; + return result; } void ByteArrayReadBytestream::addData(const std::vector<unsigned char>& moreData) { - append(data, moreData); - onDataAvailable(); + append(data, moreData); + onDataAvailable(); } diff --git a/Swiften/FileTransfer/ByteArrayReadBytestream.h b/Swiften/FileTransfer/ByteArrayReadBytestream.h index 308d8c5..d90e5cc 100644 --- a/Swiften/FileTransfer/ByteArrayReadBytestream.h +++ b/Swiften/FileTransfer/ByteArrayReadBytestream.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2015 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ @@ -9,30 +9,30 @@ #include <vector> #include <Swiften/Base/API.h> -#include <Swiften/FileTransfer/ReadBytestream.h> #include <Swiften/Base/ByteArray.h> +#include <Swiften/FileTransfer/ReadBytestream.h> namespace Swift { - class SWIFTEN_API ByteArrayReadBytestream : public ReadBytestream { - public: - ByteArrayReadBytestream(const std::vector<unsigned char>& data) : data(data), position(0), dataComplete(true) { - } + class SWIFTEN_API ByteArrayReadBytestream : public ReadBytestream { + public: + ByteArrayReadBytestream(const std::vector<unsigned char>& data) : data(data), position(0), dataComplete(true) { + } - virtual boost::shared_ptr<ByteArray> read(size_t size); + virtual std::shared_ptr<ByteArray> read(size_t size); - virtual bool isFinished() const { - return position >= data.size() && dataComplete; - } + virtual bool isFinished() const { + return position >= data.size() && dataComplete; + } - virtual void setDataComplete(bool b) { - dataComplete = b; - } + virtual void setDataComplete(bool b) { + dataComplete = b; + } - void addData(const std::vector<unsigned char>& moreData); + void addData(const std::vector<unsigned char>& moreData); - private: - std::vector<unsigned char> data; - size_t position; - bool dataComplete; - }; + private: + std::vector<unsigned char> data; + size_t position; + bool dataComplete; + }; } diff --git a/Swiften/FileTransfer/ByteArrayWriteBytestream.h b/Swiften/FileTransfer/ByteArrayWriteBytestream.h index 08c4d4b..ec9d101 100644 --- a/Swiften/FileTransfer/ByteArrayWriteBytestream.h +++ b/Swiften/FileTransfer/ByteArrayWriteBytestream.h @@ -10,22 +10,22 @@ #include <Swiften/FileTransfer/WriteBytestream.h> namespace Swift { - class SWIFTEN_API ByteArrayWriteBytestream : public WriteBytestream { - public: - ByteArrayWriteBytestream() { - } + class SWIFTEN_API ByteArrayWriteBytestream : public WriteBytestream { + public: + ByteArrayWriteBytestream() { + } - virtual bool write(const std::vector<unsigned char>& bytes) { - data.insert(data.end(), bytes.begin(), bytes.end()); - onWrite(bytes); - return true; - } + virtual bool write(const std::vector<unsigned char>& bytes) { + data.insert(data.end(), bytes.begin(), bytes.end()); + onWrite(bytes); + return true; + } - const std::vector<unsigned char>& getData() const { - return data; - } + const std::vector<unsigned char>& getData() const { + return data; + } - private: - std::vector<unsigned char> data; - }; + private: + std::vector<unsigned char> data; + }; } diff --git a/Swiften/FileTransfer/BytestreamException.h b/Swiften/FileTransfer/BytestreamException.h index 202315e..02d1e98 100644 --- a/Swiften/FileTransfer/BytestreamException.h +++ b/Swiften/FileTransfer/BytestreamException.h @@ -11,9 +11,9 @@ #include <Swiften/Base/API.h> namespace Swift { - class SWIFTEN_API BytestreamException : public std::exception { - public: - BytestreamException() { - } - }; + class SWIFTEN_API BytestreamException : public std::exception { + public: + BytestreamException() { + } + }; } diff --git a/Swiften/FileTransfer/BytestreamsRequest.h b/Swiften/FileTransfer/BytestreamsRequest.h index 65fda9a..d278e79 100644 --- a/Swiften/FileTransfer/BytestreamsRequest.h +++ b/Swiften/FileTransfer/BytestreamsRequest.h @@ -1,35 +1,35 @@ /* - * Copyright (c) 2010-2015 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> #include <Swiften/Base/API.h> -#include <Swiften/Queries/GenericRequest.h> #include <Swiften/Elements/Bytestreams.h> +#include <Swiften/Queries/GenericRequest.h> namespace Swift { - class SWIFTEN_API BytestreamsRequest : public GenericRequest<Bytestreams> { - public: - typedef boost::shared_ptr<BytestreamsRequest> ref; + class SWIFTEN_API BytestreamsRequest : public GenericRequest<Bytestreams> { + public: + typedef std::shared_ptr<BytestreamsRequest> ref; - static ref create(const JID& jid, boost::shared_ptr<Bytestreams> payload, IQRouter* router) { - return ref(new BytestreamsRequest(jid, payload, router)); - } + static ref create(const JID& jid, std::shared_ptr<Bytestreams> payload, IQRouter* router) { + return ref(new BytestreamsRequest(jid, payload, router)); + } - static ref create(const JID& from, const JID& to, boost::shared_ptr<Bytestreams> payload, IQRouter* router) { - return ref(new BytestreamsRequest(from, to, payload, router)); - } + static ref create(const JID& from, const JID& to, std::shared_ptr<Bytestreams> payload, IQRouter* router) { + return ref(new BytestreamsRequest(from, to, payload, router)); + } - private: - BytestreamsRequest(const JID& jid, boost::shared_ptr<Bytestreams> payload, IQRouter* router) : GenericRequest<Bytestreams>(IQ::Set, jid, payload, router) { - } + private: + BytestreamsRequest(const JID& jid, std::shared_ptr<Bytestreams> payload, IQRouter* router) : GenericRequest<Bytestreams>(IQ::Set, jid, payload, router) { + } - BytestreamsRequest(const JID& from, const JID& to, boost::shared_ptr<Bytestreams> payload, IQRouter* router) : GenericRequest<Bytestreams>(IQ::Set, from, to, payload, router) { - } - }; + BytestreamsRequest(const JID& from, const JID& to, std::shared_ptr<Bytestreams> payload, IQRouter* router) : GenericRequest<Bytestreams>(IQ::Set, from, to, payload, router) { + } + }; } diff --git a/Swiften/FileTransfer/DefaultFileTransferTransporter.cpp b/Swiften/FileTransfer/DefaultFileTransferTransporter.cpp index 1e68bc6..c6987c0 100644 --- a/Swiften/FileTransfer/DefaultFileTransferTransporter.cpp +++ b/Swiften/FileTransfer/DefaultFileTransferTransporter.cpp @@ -1,16 +1,16 @@ /* - * Copyright (c) 2013-2015 Isode Limited. + * Copyright (c) 2013-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #include <Swiften/FileTransfer/DefaultFileTransferTransporter.h> +#include <memory> + #include <boost/bind.hpp> -#include <boost/smart_ptr/make_shared.hpp> #include <Swiften/Base/Log.h> -#include <Swiften/Base/foreach.h> #include <Swiften/Crypto/CryptoProvider.h> #include <Swiften/FileTransfer/FailingTransportSession.h> #include <Swiften/FileTransfer/FileTransferOptions.h> @@ -33,268 +33,276 @@ using namespace Swift; DefaultFileTransferTransporter::DefaultFileTransferTransporter( - const JID& initiator, - const JID& responder, - Role role, - SOCKS5BytestreamRegistry* s5bRegistry, - SOCKS5BytestreamServerManager* s5bServerManager, - SOCKS5BytestreamProxiesManager* s5bProxy, - IDGenerator* idGenerator, - ConnectionFactory* connectionFactory, - TimerFactory* timerFactory, - CryptoProvider* crypto, - IQRouter* router, - const FileTransferOptions& options) : - initiator(initiator), - responder(responder), - role(role), - s5bRegistry(s5bRegistry), - s5bServerManager(s5bServerManager), - s5bProxy(s5bProxy), - crypto(crypto), - router(router) { - - localCandidateGenerator = new LocalJingleTransportCandidateGenerator( - s5bServerManager, - s5bProxy, - role == Initiator ? initiator : responder, - idGenerator, - options); - localCandidateGenerator->onLocalTransportCandidatesGenerated.connect( - boost::bind(&DefaultFileTransferTransporter::handleLocalCandidatesGenerated, this, _1)); - - remoteCandidateSelector = new RemoteJingleTransportCandidateSelector( - connectionFactory, - timerFactory, - options); - remoteCandidateSelector->onCandidateSelectFinished.connect( - boost::bind(&DefaultFileTransferTransporter::handleRemoteCandidateSelectFinished, this, _1, _2)); + const JID& initiator, + const JID& responder, + Role role, + SOCKS5BytestreamRegistry* s5bRegistry, + SOCKS5BytestreamServerManager* s5bServerManager, + SOCKS5BytestreamProxiesManager* s5bProxy, + IDGenerator* idGenerator, + ConnectionFactory* connectionFactory, + TimerFactory* timerFactory, + CryptoProvider* crypto, + IQRouter* router, + const FileTransferOptions& options) : + initiator(initiator), + responder(responder), + role(role), + s5bRegistry(s5bRegistry), + s5bServerManager(s5bServerManager), + s5bProxy(s5bProxy), + crypto(crypto), + router(router) { + + localCandidateGenerator = new LocalJingleTransportCandidateGenerator( + s5bServerManager, + s5bProxy, + role == Initiator ? initiator : responder, + idGenerator, + options); + localCandidateGenerator->onLocalTransportCandidatesGenerated.connect( + boost::bind(&DefaultFileTransferTransporter::handleLocalCandidatesGenerated, this, _1)); + + remoteCandidateSelector = new RemoteJingleTransportCandidateSelector( + connectionFactory, + timerFactory, + options); + remoteCandidateSelector->onCandidateSelectFinished.connect( + boost::bind(&DefaultFileTransferTransporter::handleRemoteCandidateSelectFinished, this, _1, _2)); } DefaultFileTransferTransporter::~DefaultFileTransferTransporter() { - DefaultFileTransferTransporter::stopGeneratingLocalCandidates(); - remoteCandidateSelector->onCandidateSelectFinished.disconnect( - boost::bind(&DefaultFileTransferTransporter::handleRemoteCandidateSelectFinished, this, _1, _2)); - delete remoteCandidateSelector; - - localCandidateGenerator->onLocalTransportCandidatesGenerated.disconnect( - boost::bind(&DefaultFileTransferTransporter::handleLocalCandidatesGenerated, this, _1)); - delete localCandidateGenerator; + DefaultFileTransferTransporter::stopGeneratingLocalCandidates(); + remoteCandidateSelector->onCandidateSelectFinished.disconnect( + boost::bind(&DefaultFileTransferTransporter::handleRemoteCandidateSelectFinished, this, _1, _2)); + delete remoteCandidateSelector; + + localCandidateGenerator->onLocalTransportCandidatesGenerated.disconnect( + boost::bind(&DefaultFileTransferTransporter::handleLocalCandidatesGenerated, this, _1)); + delete localCandidateGenerator; } void DefaultFileTransferTransporter::initialize() { - s5bSessionID = s5bRegistry->generateSessionID(); + s5bSessionID = s5bRegistry->generateSessionID(); } void DefaultFileTransferTransporter::initialize(const std::string& s5bSessionID) { - this->s5bSessionID = s5bSessionID; + this->s5bSessionID = s5bSessionID; } void DefaultFileTransferTransporter::startGeneratingLocalCandidates() { - localCandidateGenerator->start(); + localCandidateGenerator->start(); } void DefaultFileTransferTransporter::stopGeneratingLocalCandidates() { - localCandidateGenerator->stop(); + localCandidateGenerator->stop(); } - + void DefaultFileTransferTransporter::handleLocalCandidatesGenerated( - const std::vector<JingleS5BTransportPayload::Candidate>& candidates) { - s5bRegistry->setHasBytestream(getSOCKS5DstAddr(), true); - s5bProxy->connectToProxies(getSOCKS5DstAddr()); - onLocalCandidatesGenerated(s5bSessionID, candidates, getSOCKS5DstAddr()); + const std::vector<JingleS5BTransportPayload::Candidate>& candidates) { + s5bRegistry->setHasBytestream(getSOCKS5DstAddr(), true); + 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); + const boost::optional<JingleS5BTransportPayload::Candidate>& candidate, + std::shared_ptr<SOCKS5BytestreamClientSession> session) { + remoteS5BClientSession = session; + onRemoteCandidateSelectFinished(s5bSessionID, candidate); } void DefaultFileTransferTransporter::addRemoteCandidates( - const std::vector<JingleS5BTransportPayload::Candidate>& candidates, const std::string& dstAddr) { - remoteCandidateSelector->setSOCKS5DstAddr(dstAddr.empty() ? getRemoteCandidateSOCKS5DstAddr() : dstAddr); - remoteCandidateSelector->addCandidates(candidates); + const std::vector<JingleS5BTransportPayload::Candidate>& candidates, const std::string& dstAddr) { + remoteCandidateSelector->setSOCKS5DstAddr(dstAddr.empty() ? getRemoteCandidateSOCKS5DstAddr() : dstAddr); + remoteCandidateSelector->addCandidates(candidates); } void DefaultFileTransferTransporter::startTryingRemoteCandidates() { - remoteCandidateSelector->startSelectingCandidate(); + remoteCandidateSelector->startSelectingCandidate(); } void DefaultFileTransferTransporter::stopTryingRemoteCandidates() { - remoteCandidateSelector->stopSelectingCandidate(); + remoteCandidateSelector->stopSelectingCandidate(); } void DefaultFileTransferTransporter::handleActivateProxySessionResult(const std::string& sessionID, ErrorPayload::ref error) { - onProxyActivated(sessionID, 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(role == Initiator ? responder : initiator); - - 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(); + // activate proxy + SWIFT_LOG(debug) << "Start activating proxy " << proxyServiceJID.toString() << " with sid = " << s5bSessionID << "." << std::endl; + S5BProxyRequest::ref proxyRequest = std::make_shared<S5BProxyRequest>(); + proxyRequest->setSID(s5bSessionID); + proxyRequest->setActivate(role == Initiator ? responder : initiator); + + std::shared_ptr<GenericRequest<S5BProxyRequest> > request = std::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); + // TODO + assert(false); } -boost::shared_ptr<TransportSession> DefaultFileTransferTransporter::createIBBSendSession( - const std::string& sessionID, unsigned int blockSize, boost::shared_ptr<ReadBytestream> stream) { - if (s5bServerManager->getServer()) { - closeLocalSession(); - } - closeRemoteSession(); - boost::shared_ptr<IBBSendSession> ibbSession = boost::make_shared<IBBSendSession>( - sessionID, initiator, responder, stream, router); - ibbSession->setBlockSize(blockSize); - return boost::make_shared<IBBSendTransportSession>(ibbSession); +std::shared_ptr<TransportSession> DefaultFileTransferTransporter::createIBBSendSession( + const std::string& sessionID, unsigned int blockSize, std::shared_ptr<ReadBytestream> stream) { + if (s5bServerManager->getServer()) { + closeLocalSession(); + } + closeRemoteSession(); + std::shared_ptr<IBBSendSession> ibbSession = std::make_shared<IBBSendSession>( + sessionID, initiator, responder, stream, router); + ibbSession->setBlockSize(blockSize); + return std::make_shared<IBBSendTransportSession>(ibbSession); } -boost::shared_ptr<TransportSession> DefaultFileTransferTransporter::createIBBReceiveSession( - const std::string& sessionID, unsigned long long size, boost::shared_ptr<WriteBytestream> stream) { - if (s5bServerManager->getServer()) { - closeLocalSession(); - } - closeRemoteSession(); - boost::shared_ptr<IBBReceiveSession> ibbSession = boost::make_shared<IBBReceiveSession>( - sessionID, initiator, responder, size, stream, router); - return boost::make_shared<IBBReceiveTransportSession>(ibbSession); +std::shared_ptr<TransportSession> DefaultFileTransferTransporter::createIBBReceiveSession( + const std::string& sessionID, unsigned long long size, std::shared_ptr<WriteBytestream> stream) { + if (s5bServerManager->getServer()) { + closeLocalSession(); + } + closeRemoteSession(); + std::shared_ptr<IBBReceiveSession> ibbSession = std::make_shared<IBBReceiveSession>( + sessionID, initiator, responder, size, stream, router); + return std::make_shared<IBBReceiveTransportSession>(ibbSession); } -boost::shared_ptr<TransportSession> DefaultFileTransferTransporter::createRemoteCandidateSession( - boost::shared_ptr<ReadBytestream> stream, const JingleS5BTransportPayload::Candidate& /* candidate */) { - closeLocalSession(); - return boost::make_shared<S5BTransportSession<SOCKS5BytestreamClientSession> >( - remoteS5BClientSession, stream); +std::shared_ptr<TransportSession> DefaultFileTransferTransporter::createRemoteCandidateSession( + std::shared_ptr<ReadBytestream> stream, const JingleS5BTransportPayload::Candidate& /* candidate */) { + closeLocalSession(); + return std::make_shared<S5BTransportSession<SOCKS5BytestreamClientSession> >( + remoteS5BClientSession, stream); } -boost::shared_ptr<TransportSession> DefaultFileTransferTransporter::createRemoteCandidateSession( - boost::shared_ptr<WriteBytestream> stream, const JingleS5BTransportPayload::Candidate& /* candidate */) { - closeLocalSession(); - return boost::make_shared<S5BTransportSession<SOCKS5BytestreamClientSession> >( - remoteS5BClientSession, stream); +std::shared_ptr<TransportSession> DefaultFileTransferTransporter::createRemoteCandidateSession( + std::shared_ptr<WriteBytestream> stream, const JingleS5BTransportPayload::Candidate& /* candidate */) { + closeLocalSession(); + return std::make_shared<S5BTransportSession<SOCKS5BytestreamClientSession> >( + remoteS5BClientSession, stream); } -boost::shared_ptr<SOCKS5BytestreamServerSession> DefaultFileTransferTransporter::getServerSession() { - s5bRegistry->setHasBytestream(getSOCKS5DstAddr(), false); - std::vector<boost::shared_ptr<SOCKS5BytestreamServerSession> > serverSessions = - s5bServerManager->getServer()->getSessions(getSOCKS5DstAddr()); - while (serverSessions.size() > 1) { - boost::shared_ptr<SOCKS5BytestreamServerSession> session = serverSessions.back(); - serverSessions.pop_back(); - session->stop(); - } - return !serverSessions.empty() ? serverSessions.front() : boost::shared_ptr<SOCKS5BytestreamServerSession>(); +std::shared_ptr<SOCKS5BytestreamServerSession> DefaultFileTransferTransporter::getServerSession() { + s5bRegistry->setHasBytestream(getSOCKS5DstAddr(), false); + std::vector<std::shared_ptr<SOCKS5BytestreamServerSession> > serverSessions = + s5bServerManager->getServer()->getSessions(getSOCKS5DstAddr()); + while (serverSessions.size() > 1) { + std::shared_ptr<SOCKS5BytestreamServerSession> session = serverSessions.back(); + serverSessions.pop_back(); + session->stop(); + } + return !serverSessions.empty() ? serverSessions.front() : std::shared_ptr<SOCKS5BytestreamServerSession>(); } -boost::shared_ptr<TransportSession> DefaultFileTransferTransporter::createLocalCandidateSession( - boost::shared_ptr<ReadBytestream> stream, const JingleS5BTransportPayload::Candidate& candidate) { - closeRemoteSession(); - 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); - } - - 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::shared_ptr<TransportSession> DefaultFileTransferTransporter::createLocalCandidateSession( + std::shared_ptr<ReadBytestream> stream, const JingleS5BTransportPayload::Candidate& candidate) { + closeRemoteSession(); + std::shared_ptr<TransportSession> transportSession; + if (candidate.type == JingleS5BTransportPayload::Candidate::ProxyType) { + SOCKS5BytestreamClientSession::ref proxySession = s5bProxy->getProxySessionAndCloseOthers(candidate.jid, getLocalCandidateSOCKS5DstAddr()); + if (proxySession) { + transportSession = std::make_shared<S5BTransportSession<SOCKS5BytestreamClientSession> >(proxySession, stream); + } + else { + SWIFT_LOG(error) << "Failed obtaining proxy session with candidate JID " << candidate.jid << " and dstAddr " << getLocalCandidateSOCKS5DstAddr() << "." << std::endl; + } + } + + if (!transportSession) { + std::shared_ptr<SOCKS5BytestreamServerSession> serverSession = getServerSession(); + if (serverSession) { + transportSession = std::make_shared<S5BTransportSession<SOCKS5BytestreamServerSession> >(serverSession, stream); + } + } + + if (!transportSession) { + transportSession = std::make_shared<FailingTransportSession>(); + } + return transportSession; } -boost::shared_ptr<TransportSession> DefaultFileTransferTransporter::createLocalCandidateSession( - boost::shared_ptr<WriteBytestream> stream, const JingleS5BTransportPayload::Candidate& candidate) { - closeRemoteSession(); - 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); - } - - 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::shared_ptr<TransportSession> DefaultFileTransferTransporter::createLocalCandidateSession( + std::shared_ptr<WriteBytestream> stream, const JingleS5BTransportPayload::Candidate& candidate) { + closeRemoteSession(); + std::shared_ptr<TransportSession> transportSession; + if (candidate.type == JingleS5BTransportPayload::Candidate::ProxyType) { + SOCKS5BytestreamClientSession::ref proxySession = s5bProxy->getProxySessionAndCloseOthers(candidate.jid, getLocalCandidateSOCKS5DstAddr()); + if (proxySession) { + transportSession = std::make_shared<S5BTransportSession<SOCKS5BytestreamClientSession> >(proxySession, stream); + } + else { + SWIFT_LOG(error) << "Failed obtaining proxy session with candidate JID " << candidate.jid << " and dstAddr " << getLocalCandidateSOCKS5DstAddr() << "." << std::endl; + } + } + + if (!transportSession) { + std::shared_ptr<SOCKS5BytestreamServerSession> serverSession = getServerSession(); + if (serverSession) { + transportSession = std::make_shared<S5BTransportSession<SOCKS5BytestreamServerSession> >(serverSession, stream); + } + } + + if (!transportSession) { + transportSession = std::make_shared<FailingTransportSession>(); + } + return transportSession; } std::string DefaultFileTransferTransporter::getSOCKS5DstAddr() const { - 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 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()))); + 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()))); + return Hexify::hexify(crypto->getSHA1Hash(createSafeByteArray(s5bSessionID + responder.toString() + initiator.toString()))); } std::string DefaultFileTransferTransporter::getRemoteCandidateSOCKS5DstAddr() const { - if (role == Initiator) { - return getResponderCandidateSOCKS5DstAddr(); - } - else { - return getInitiatorCandidateSOCKS5DstAddr(); - } + if (role == Initiator) { + return getResponderCandidateSOCKS5DstAddr(); + } + else { + return getInitiatorCandidateSOCKS5DstAddr(); + } } std::string DefaultFileTransferTransporter::getLocalCandidateSOCKS5DstAddr() const { - if (role == Responder) { - return getResponderCandidateSOCKS5DstAddr(); - } - else { - return getInitiatorCandidateSOCKS5DstAddr(); - } + if (role == Responder) { + return getResponderCandidateSOCKS5DstAddr(); + } + else { + return getInitiatorCandidateSOCKS5DstAddr(); + } } void DefaultFileTransferTransporter::closeLocalSession() { - s5bRegistry->setHasBytestream(getSOCKS5DstAddr(), false); - if (s5bServerManager->getServer()) { - std::vector<boost::shared_ptr<SOCKS5BytestreamServerSession> > serverSessions = s5bServerManager->getServer()->getSessions(getSOCKS5DstAddr()); - foreach(boost::shared_ptr<SOCKS5BytestreamServerSession> session, serverSessions) { - session->stop(); - } - } + s5bRegistry->setHasBytestream(getSOCKS5DstAddr(), false); + if (s5bServerManager->getServer()) { + std::vector<std::shared_ptr<SOCKS5BytestreamServerSession> > serverSessions = s5bServerManager->getServer()->getSessions(getSOCKS5DstAddr()); + for (auto&& session : serverSessions) { + session->stop(); + } + } } void DefaultFileTransferTransporter::closeRemoteSession() { - if (remoteS5BClientSession) { - remoteS5BClientSession->stop(); - remoteS5BClientSession.reset(); - } + if (remoteS5BClientSession) { + remoteS5BClientSession->stop(); + remoteS5BClientSession.reset(); + } } diff --git a/Swiften/FileTransfer/DefaultFileTransferTransporter.h b/Swiften/FileTransfer/DefaultFileTransferTransporter.h index 347c313..339232f 100644 --- a/Swiften/FileTransfer/DefaultFileTransferTransporter.h +++ b/Swiften/FileTransfer/DefaultFileTransferTransporter.h @@ -1,112 +1,112 @@ /* - * Copyright (c) 2013-2015 Isode Limited. + * Copyright (c) 2013-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> #include <Swiften/Base/API.h> -#include <Swiften/FileTransfer/FileTransferTransporter.h> +#include <Swiften/Base/Override.h> #include <Swiften/Elements/ErrorPayload.h> +#include <Swiften/FileTransfer/FileTransferTransporter.h> namespace Swift { - class LocalJingleTransportCandidateGenerator; - class RemoteJingleTransportCandidateSelector; - class SOCKS5BytestreamRegistry; - class SOCKS5BytestreamServerManager; - class SOCKS5BytestreamProxiesManager; - class SOCKS5BytestreamClientSession; - class SOCKS5BytestreamServerSession; - class IDGenerator; - class IQRouter; - class ReadBytestream; - class WriteBytestream; - class ConnectionFactory; - class TimerFactory; - class CryptoProvider; - class FileTransferOptions; + class LocalJingleTransportCandidateGenerator; + class RemoteJingleTransportCandidateSelector; + class SOCKS5BytestreamRegistry; + class SOCKS5BytestreamServerManager; + class SOCKS5BytestreamProxiesManager; + class SOCKS5BytestreamClientSession; + class SOCKS5BytestreamServerSession; + class IDGenerator; + class IQRouter; + class ReadBytestream; + class WriteBytestream; + class ConnectionFactory; + class TimerFactory; + class CryptoProvider; + class FileTransferOptions; + + class SWIFTEN_API DefaultFileTransferTransporter : public FileTransferTransporter { + public: + enum Role { + Initiator, + Responder + }; - class SWIFTEN_API DefaultFileTransferTransporter : public FileTransferTransporter { - public: - enum Role { - Initiator, - Responder - }; + DefaultFileTransferTransporter( + const JID& initiator, + const JID& responder, + Role role, + SOCKS5BytestreamRegistry*, + SOCKS5BytestreamServerManager* s5bServerManager, + SOCKS5BytestreamProxiesManager* s5bProxy, + IDGenerator* idGenerator, + ConnectionFactory*, + TimerFactory*, + CryptoProvider*, + IQRouter*, + const FileTransferOptions&); + virtual ~DefaultFileTransferTransporter(); - DefaultFileTransferTransporter( - const JID& initiator, - const JID& responder, - Role role, - SOCKS5BytestreamRegistry*, - SOCKS5BytestreamServerManager* s5bServerManager, - SOCKS5BytestreamProxiesManager* s5bProxy, - IDGenerator* idGenerator, - ConnectionFactory*, - TimerFactory*, - CryptoProvider*, - IQRouter*, - const FileTransferOptions&); - virtual ~DefaultFileTransferTransporter(); - - virtual void initialize(); - virtual void initialize(const std::string& s5bSessionID); + virtual void initialize(); + virtual void initialize(const std::string& s5bSessionID); - virtual void startGeneratingLocalCandidates() SWIFTEN_OVERRIDE; - virtual void stopGeneratingLocalCandidates() SWIFTEN_OVERRIDE; + virtual void startGeneratingLocalCandidates() SWIFTEN_OVERRIDE; + virtual void stopGeneratingLocalCandidates() SWIFTEN_OVERRIDE; - virtual void addRemoteCandidates( - const std::vector<JingleS5BTransportPayload::Candidate>&, const std::string&) SWIFTEN_OVERRIDE; - virtual void startTryingRemoteCandidates() SWIFTEN_OVERRIDE; - virtual void stopTryingRemoteCandidates() SWIFTEN_OVERRIDE; + virtual void addRemoteCandidates( + 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 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>, const JingleS5BTransportPayload::Candidate& candidate) SWIFTEN_OVERRIDE; - virtual boost::shared_ptr<TransportSession> createRemoteCandidateSession( - boost::shared_ptr<WriteBytestream>, const JingleS5BTransportPayload::Candidate& candidate) SWIFTEN_OVERRIDE; - virtual boost::shared_ptr<TransportSession> createLocalCandidateSession( - boost::shared_ptr<ReadBytestream>, const JingleS5BTransportPayload::Candidate& candidate) SWIFTEN_OVERRIDE; - virtual boost::shared_ptr<TransportSession> createLocalCandidateSession( - boost::shared_ptr<WriteBytestream>, const JingleS5BTransportPayload::Candidate& candidate) SWIFTEN_OVERRIDE; + virtual std::shared_ptr<TransportSession> createIBBSendSession( + const std::string& sessionID, unsigned int blockSize, std::shared_ptr<ReadBytestream>) SWIFTEN_OVERRIDE; + virtual std::shared_ptr<TransportSession> createIBBReceiveSession( + const std::string& sessionID, unsigned long long size, std::shared_ptr<WriteBytestream>) SWIFTEN_OVERRIDE; + virtual std::shared_ptr<TransportSession> createRemoteCandidateSession( + std::shared_ptr<ReadBytestream>, const JingleS5BTransportPayload::Candidate& candidate) SWIFTEN_OVERRIDE; + virtual std::shared_ptr<TransportSession> createRemoteCandidateSession( + std::shared_ptr<WriteBytestream>, const JingleS5BTransportPayload::Candidate& candidate) SWIFTEN_OVERRIDE; + virtual std::shared_ptr<TransportSession> createLocalCandidateSession( + std::shared_ptr<ReadBytestream>, const JingleS5BTransportPayload::Candidate& candidate) SWIFTEN_OVERRIDE; + virtual std::shared_ptr<TransportSession> createLocalCandidateSession( + std::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>); - void handleActivateProxySessionResult(const std::string& sessionID, ErrorPayload::ref error); - void closeLocalSession(); - void closeRemoteSession(); - boost::shared_ptr<SOCKS5BytestreamServerSession> getServerSession(); + private: + void handleLocalCandidatesGenerated(const std::vector<JingleS5BTransportPayload::Candidate>&); + void handleRemoteCandidateSelectFinished( + const boost::optional<JingleS5BTransportPayload::Candidate>&, + std::shared_ptr<SOCKS5BytestreamClientSession>); + void handleActivateProxySessionResult(const std::string& sessionID, ErrorPayload::ref error); + void closeLocalSession(); + void closeRemoteSession(); + std::shared_ptr<SOCKS5BytestreamServerSession> getServerSession(); - std::string getSOCKS5DstAddr() const; - std::string getInitiatorCandidateSOCKS5DstAddr() const; - std::string getResponderCandidateSOCKS5DstAddr() const; - std::string getRemoteCandidateSOCKS5DstAddr() const; - std::string getLocalCandidateSOCKS5DstAddr() const; + 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; - }; + private: + JID initiator; + JID responder; + Role role; + SOCKS5BytestreamRegistry* s5bRegistry; + SOCKS5BytestreamServerManager* s5bServerManager; + SOCKS5BytestreamProxiesManager* s5bProxy; + CryptoProvider* crypto; + IQRouter* router; + LocalJingleTransportCandidateGenerator* localCandidateGenerator; + RemoteJingleTransportCandidateSelector* remoteCandidateSelector; + std::string s5bSessionID; + std::shared_ptr<SOCKS5BytestreamClientSession> remoteS5BClientSession; + }; } diff --git a/Swiften/FileTransfer/DefaultFileTransferTransporterFactory.cpp b/Swiften/FileTransfer/DefaultFileTransferTransporterFactory.cpp index ffa0a12..3af2cad 100644 --- a/Swiften/FileTransfer/DefaultFileTransferTransporterFactory.cpp +++ b/Swiften/FileTransfer/DefaultFileTransferTransporterFactory.cpp @@ -11,22 +11,22 @@ using namespace Swift; DefaultFileTransferTransporterFactory::DefaultFileTransferTransporterFactory( - SOCKS5BytestreamRegistry* s5bRegistry, - SOCKS5BytestreamServerManager* s5bServerManager, - SOCKS5BytestreamProxiesManager* s5bProxiesManager, - IDGenerator* idGenerator, - ConnectionFactory* connectionFactory, - TimerFactory* timerFactory, - CryptoProvider* cryptoProvider, - IQRouter* iqRouter) : - s5bRegistry(s5bRegistry), - s5bServerManager(s5bServerManager), - s5bProxiesManager(s5bProxiesManager), - idGenerator(idGenerator), - connectionFactory(connectionFactory), - timerFactory(timerFactory), - cryptoProvider(cryptoProvider), - iqRouter(iqRouter) + SOCKS5BytestreamRegistry* s5bRegistry, + SOCKS5BytestreamServerManager* s5bServerManager, + SOCKS5BytestreamProxiesManager* s5bProxiesManager, + IDGenerator* idGenerator, + ConnectionFactory* connectionFactory, + TimerFactory* timerFactory, + CryptoProvider* cryptoProvider, + IQRouter* iqRouter) : + s5bRegistry(s5bRegistry), + s5bServerManager(s5bServerManager), + s5bProxiesManager(s5bProxiesManager), + idGenerator(idGenerator), + connectionFactory(connectionFactory), + timerFactory(timerFactory), + cryptoProvider(cryptoProvider), + iqRouter(iqRouter) { } @@ -34,39 +34,39 @@ DefaultFileTransferTransporterFactory::~DefaultFileTransferTransporterFactory() } FileTransferTransporter* DefaultFileTransferTransporterFactory::createInitiatorTransporter( - const JID& initiator, const JID& responder, const FileTransferOptions& options) { - DefaultFileTransferTransporter* transporter = new DefaultFileTransferTransporter( - initiator, - responder, - DefaultFileTransferTransporter::Initiator, - s5bRegistry, - s5bServerManager, - s5bProxiesManager, - idGenerator, - connectionFactory, - timerFactory, - cryptoProvider, - iqRouter, - options); - transporter->initialize(); - return transporter; + const JID& initiator, const JID& responder, const FileTransferOptions& options) { + DefaultFileTransferTransporter* transporter = new DefaultFileTransferTransporter( + initiator, + responder, + DefaultFileTransferTransporter::Initiator, + s5bRegistry, + s5bServerManager, + s5bProxiesManager, + idGenerator, + connectionFactory, + timerFactory, + cryptoProvider, + iqRouter, + options); + transporter->initialize(); + return transporter; } FileTransferTransporter* DefaultFileTransferTransporterFactory::createResponderTransporter( - const JID& initiator, const JID& responder, const std::string& s5bSessionID, const FileTransferOptions& options) { - DefaultFileTransferTransporter* transporter = new DefaultFileTransferTransporter( - initiator, - responder, - DefaultFileTransferTransporter::Responder, - s5bRegistry, - s5bServerManager, - s5bProxiesManager, - idGenerator, - connectionFactory, - timerFactory, - cryptoProvider, - iqRouter, - options); - transporter->initialize(s5bSessionID); - return transporter; + const JID& initiator, const JID& responder, const std::string& s5bSessionID, const FileTransferOptions& options) { + DefaultFileTransferTransporter* transporter = new DefaultFileTransferTransporter( + initiator, + responder, + DefaultFileTransferTransporter::Responder, + s5bRegistry, + s5bServerManager, + s5bProxiesManager, + idGenerator, + connectionFactory, + timerFactory, + cryptoProvider, + iqRouter, + options); + transporter->initialize(s5bSessionID); + return transporter; } diff --git a/Swiften/FileTransfer/DefaultFileTransferTransporterFactory.h b/Swiften/FileTransfer/DefaultFileTransferTransporterFactory.h index 93cf262..3cc3455 100644 --- a/Swiften/FileTransfer/DefaultFileTransferTransporterFactory.h +++ b/Swiften/FileTransfer/DefaultFileTransferTransporterFactory.h @@ -1,51 +1,51 @@ /* - * Copyright (c) 2013-2015 Isode Limited. + * Copyright (c) 2013-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> #include <Swiften/Base/API.h> +#include <Swiften/Base/Override.h> #include <Swiften/FileTransfer/FileTransferTransporterFactory.h> namespace Swift { - class SOCKS5BytestreamRegistry; - class SOCKS5BytestreamServerManager; - class SOCKS5BytestreamProxiesManager; - class IDGenerator; - class ConnectionFactory; - class TimerFactory; - class CryptoProvider; - class IQRouter; + class SOCKS5BytestreamRegistry; + class SOCKS5BytestreamServerManager; + class SOCKS5BytestreamProxiesManager; + class IDGenerator; + class ConnectionFactory; + class TimerFactory; + class CryptoProvider; + class IQRouter; - class SWIFTEN_API DefaultFileTransferTransporterFactory : public FileTransferTransporterFactory { - public: - DefaultFileTransferTransporterFactory( - SOCKS5BytestreamRegistry*, - SOCKS5BytestreamServerManager* s5bServerManager, - SOCKS5BytestreamProxiesManager* s5bProxy, - IDGenerator* idGenerator, - ConnectionFactory*, - TimerFactory*, - CryptoProvider*, - IQRouter*); - virtual ~DefaultFileTransferTransporterFactory(); + class SWIFTEN_API DefaultFileTransferTransporterFactory : public FileTransferTransporterFactory { + public: + DefaultFileTransferTransporterFactory( + SOCKS5BytestreamRegistry*, + SOCKS5BytestreamServerManager* s5bServerManager, + SOCKS5BytestreamProxiesManager* s5bProxy, + IDGenerator* idGenerator, + ConnectionFactory*, + TimerFactory*, + CryptoProvider*, + IQRouter*); + virtual ~DefaultFileTransferTransporterFactory(); - virtual FileTransferTransporter* createInitiatorTransporter( - const JID& initiator, const JID& responder, const FileTransferOptions&) SWIFTEN_OVERRIDE; - virtual FileTransferTransporter* createResponderTransporter( - const JID& initiator, const JID& responder, const std::string& s5bSessionID, const FileTransferOptions&) SWIFTEN_OVERRIDE; + virtual FileTransferTransporter* createInitiatorTransporter( + const JID& initiator, const JID& responder, const FileTransferOptions&) SWIFTEN_OVERRIDE; + virtual FileTransferTransporter* createResponderTransporter( + const JID& initiator, const JID& responder, const std::string& s5bSessionID, const FileTransferOptions&) SWIFTEN_OVERRIDE; - private: - SOCKS5BytestreamRegistry* s5bRegistry; - SOCKS5BytestreamServerManager* s5bServerManager; - SOCKS5BytestreamProxiesManager* s5bProxiesManager; - IDGenerator* idGenerator; - ConnectionFactory* connectionFactory; - TimerFactory* timerFactory; - CryptoProvider* cryptoProvider; - IQRouter* iqRouter; - }; + private: + SOCKS5BytestreamRegistry* s5bRegistry; + SOCKS5BytestreamServerManager* s5bServerManager; + SOCKS5BytestreamProxiesManager* s5bProxiesManager; + IDGenerator* idGenerator; + ConnectionFactory* connectionFactory; + TimerFactory* timerFactory; + CryptoProvider* cryptoProvider; + IQRouter* iqRouter; + }; } diff --git a/Swiften/FileTransfer/FailingTransportSession.cpp b/Swiften/FileTransfer/FailingTransportSession.cpp new file mode 100644 index 0000000..d1eb6a6 --- /dev/null +++ b/Swiften/FileTransfer/FailingTransportSession.cpp @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Swiften/FileTransfer/FailingTransportSession.h> + +#include <Swiften/Base/Log.h> + +namespace Swift { + +FailingTransportSession::~FailingTransportSession() { +} + +void FailingTransportSession::start() { + SWIFT_LOG(error) << "Trying to start failing transport." << std::endl; + onFinished(FileTransferError(FileTransferError::PeerError)); +} + +void FailingTransportSession::stop() { +} + +} diff --git a/Swiften/FileTransfer/FailingTransportSession.h b/Swiften/FileTransfer/FailingTransportSession.h index c197052..6e0e16e 100644 --- a/Swiften/FileTransfer/FailingTransportSession.h +++ b/Swiften/FileTransfer/FailingTransportSession.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Isode Limited. + * Copyright (c) 2015-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ @@ -12,17 +12,11 @@ namespace Swift { class SWIFTEN_API FailingTransportSession : public TransportSession { - public: - virtual ~FailingTransportSession() { - } + public: + virtual ~FailingTransportSession(); - virtual void start() SWIFTEN_OVERRIDE { - assert(false); - onFinished(FileTransferError(FileTransferError::PeerError)); - } - - virtual void stop() SWIFTEN_OVERRIDE { - } + virtual void start() SWIFTEN_OVERRIDE; + virtual void stop() SWIFTEN_OVERRIDE; }; } diff --git a/Swiften/FileTransfer/FileReadBytestream.cpp b/Swiften/FileTransfer/FileReadBytestream.cpp index 4700a9c..2ff00dc 100644 --- a/Swiften/FileTransfer/FileReadBytestream.cpp +++ b/Swiften/FileTransfer/FileReadBytestream.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2015 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ @@ -7,41 +7,41 @@ #include <Swiften/FileTransfer/FileReadBytestream.h> #include <cassert> +#include <memory> #include <boost/filesystem/fstream.hpp> #include <boost/numeric/conversion/cast.hpp> -#include <boost/smart_ptr/make_shared.hpp> #include <Swiften/Base/ByteArray.h> namespace Swift { -FileReadBytestream::FileReadBytestream(const boost::filesystem::path& file) : file(file), stream(NULL) { +FileReadBytestream::FileReadBytestream(const boost::filesystem::path& file) : file(file), stream(nullptr) { } FileReadBytestream::~FileReadBytestream() { - if (stream) { - stream->close(); - delete stream; - stream = NULL; - } + if (stream) { + stream->close(); + delete stream; + stream = nullptr; + } } -boost::shared_ptr<ByteArray> FileReadBytestream::read(size_t size) { - if (!stream) { - stream = new boost::filesystem::ifstream(file, std::ios_base::in|std::ios_base::binary); - } - boost::shared_ptr<ByteArray> result = boost::make_shared<ByteArray>(); - result->resize(size); - assert(stream->good()); - stream->read(reinterpret_cast<char*>(vecptr(*result)), boost::numeric_cast<std::streamsize>(size)); - result->resize(boost::numeric_cast<size_t>(stream->gcount())); - onRead(*result); - return result; +std::shared_ptr<ByteArray> FileReadBytestream::read(size_t size) { + if (!stream) { + stream = new boost::filesystem::ifstream(file, std::ios_base::in|std::ios_base::binary); + } + std::shared_ptr<ByteArray> result = std::make_shared<ByteArray>(); + result->resize(size); + assert(stream->good()); + stream->read(reinterpret_cast<char*>(vecptr(*result)), boost::numeric_cast<std::streamsize>(size)); + result->resize(boost::numeric_cast<size_t>(stream->gcount())); + onRead(*result); + return result; } bool FileReadBytestream::isFinished() const { - return stream && !stream->good(); + return stream && !stream->good(); } } diff --git a/Swiften/FileTransfer/FileReadBytestream.h b/Swiften/FileTransfer/FileReadBytestream.h index 5ea197e..aaf3de3 100644 --- a/Swiften/FileTransfer/FileReadBytestream.h +++ b/Swiften/FileTransfer/FileReadBytestream.h @@ -13,16 +13,16 @@ #include <Swiften/FileTransfer/ReadBytestream.h> namespace Swift { - class SWIFTEN_API FileReadBytestream : public ReadBytestream { - public: - FileReadBytestream(const boost::filesystem::path& file); - virtual ~FileReadBytestream(); + class SWIFTEN_API FileReadBytestream : public ReadBytestream { + public: + FileReadBytestream(const boost::filesystem::path& file); + virtual ~FileReadBytestream(); - virtual boost::shared_ptr< std::vector<unsigned char> > read(size_t size); - virtual bool isFinished() const; + virtual std::shared_ptr< std::vector<unsigned char> > read(size_t size); + virtual bool isFinished() const; - private: - boost::filesystem::path file; - boost::filesystem::ifstream* stream; - }; + private: + boost::filesystem::path file; + boost::filesystem::ifstream* stream; + }; } diff --git a/Swiften/FileTransfer/FileTransfer.cpp b/Swiften/FileTransfer/FileTransfer.cpp index 4782d39..32c9f53 100644 --- a/Swiften/FileTransfer/FileTransfer.cpp +++ b/Swiften/FileTransfer/FileTransfer.cpp @@ -15,12 +15,12 @@ FileTransfer::~FileTransfer() { } void FileTransfer::setState(const State& state) { - state_ = state; - onStateChanged(state); + state_ = state; + onStateChanged(state); } void FileTransfer::setFileInfo(const std::string& name, boost::uintmax_t size, const std::string& description) { - filename_ = name; - fileSizeInBytes_ = size; - description_ = description; + filename_ = name; + fileSizeInBytes_ = size; + description_ = description; } diff --git a/Swiften/FileTransfer/FileTransfer.h b/Swiften/FileTransfer/FileTransfer.h index ab8e806..1d74a84 100644 --- a/Swiften/FileTransfer/FileTransfer.h +++ b/Swiften/FileTransfer/FileTransfer.h @@ -5,84 +5,85 @@ */ /* - * Copyright (c) 2013-2015 Isode Limited. + * Copyright (c) 2013-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #pragma once +#include <memory> + #include <boost/cstdint.hpp> #include <boost/optional.hpp> -#include <boost/shared_ptr.hpp> +#include <boost/signals2.hpp> #include <Swiften/Base/API.h> -#include <Swiften/Base/boost_bsignals.h> #include <Swiften/FileTransfer/FileTransferError.h> namespace Swift { - /** - * The FileTransfer class provides a general interface for file-transfer - * implmenetations. Currently, only Jingle File Transfer based on XEP-0234 is - * implementated in the \ref OutgoingJingleFileTransfer and - * \ref IncomingJingleFileTransfer classes. - */ - class SWIFTEN_API FileTransfer { - public: - struct State { - enum Type { - Initial, - WaitingForStart, - Negotiating, - WaitingForAccept, - Transferring, - Canceled, - Failed, - Finished - }; - - State(Type type, const std::string& message = "") : type(type), message(message) {} - - Type type; - std::string message; - }; - typedef boost::shared_ptr<FileTransfer> ref; - - public: - FileTransfer(); - virtual ~FileTransfer(); - - virtual void cancel() = 0; - - const std::string& getFileName() const { - return filename_; - } - - boost::uintmax_t getFileSizeInBytes() const { - return fileSizeInBytes_; - } - - const State& getState() const { - return state_; - } - - const std::string& getDescription() const { - return description_; - } - - public: - boost::signal<void (size_t /* proccessedBytes */)> onProcessedBytes; - boost::signal<void (const State&)> onStateChanged; - boost::signal<void (boost::optional<FileTransferError>)> onFinished; - - protected: - void setState(const State& state); - void setFileInfo(const std::string& name, boost::uintmax_t size, const std::string& description); - - private: - boost::uintmax_t fileSizeInBytes_; - std::string filename_; - std::string description_; - State state_; - }; + /** + * The FileTransfer class provides a general interface for file-transfer + * implmenetations. Currently, only Jingle File Transfer based on XEP-0234 is + * implementated in the \ref OutgoingJingleFileTransfer and + * \ref IncomingJingleFileTransfer classes. + */ + class SWIFTEN_API FileTransfer { + public: + struct State { + enum Type { + Initial, + WaitingForStart, + Negotiating, + WaitingForAccept, + Transferring, + Canceled, + Failed, + Finished + }; + + State(Type type, const std::string& message = "") : type(type), message(message) {} + + Type type; + std::string message; + }; + typedef std::shared_ptr<FileTransfer> ref; + + public: + FileTransfer(); + virtual ~FileTransfer(); + + virtual void cancel() = 0; + + const std::string& getFileName() const { + return filename_; + } + + boost::uintmax_t getFileSizeInBytes() const { + return fileSizeInBytes_; + } + + const State& getState() const { + return state_; + } + + const std::string& getDescription() const { + return description_; + } + + public: + boost::signals2::signal<void (size_t /* proccessedBytes */)> onProcessedBytes; + boost::signals2::signal<void (const State&)> onStateChanged; + boost::signals2::signal<void (boost::optional<FileTransferError>)> onFinished; + + protected: + void setState(const State& state); + void setFileInfo(const std::string& name, boost::uintmax_t size, const std::string& description); + + private: + boost::uintmax_t fileSizeInBytes_; + std::string filename_; + std::string description_; + State state_; + }; } diff --git a/Swiften/FileTransfer/FileTransferError.h b/Swiften/FileTransfer/FileTransferError.h index eff8ca9..e94ee7a 100644 --- a/Swiften/FileTransfer/FileTransferError.h +++ b/Swiften/FileTransfer/FileTransferError.h @@ -9,23 +9,23 @@ #include <Swiften/Base/API.h> namespace Swift { - class SWIFTEN_API FileTransferError { - public: - enum Type { - UnknownError, - PeerError, - ReadError, - WriteError, - ClosedError - }; + class SWIFTEN_API FileTransferError { + public: + enum Type { + UnknownError, + PeerError, + ReadError, + WriteError, + ClosedError + }; - FileTransferError(Type type = UnknownError) : type(type) {} + FileTransferError(Type type = UnknownError) : type(type) {} - Type getType() const { - return type; - } + Type getType() const { + return type; + } - private: - Type type; - }; + private: + Type type; + }; } diff --git a/Swiften/FileTransfer/FileTransferManager.cpp b/Swiften/FileTransfer/FileTransferManager.cpp index 0c7d894..a5d7313 100644 --- a/Swiften/FileTransfer/FileTransferManager.cpp +++ b/Swiften/FileTransfer/FileTransferManager.cpp @@ -4,6 +4,12 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #include <Swiften/FileTransfer/FileTransferManager.h> namespace Swift { @@ -11,13 +17,4 @@ namespace Swift { FileTransferManager::~FileTransferManager() { } -bool FileTransferManager::isSupportedBy(const DiscoInfo::ref info) { - if (info) { - return info->hasFeature(DiscoInfo::JingleFeature) - && info->hasFeature(DiscoInfo::JingleFTFeature) - && (info->hasFeature(DiscoInfo::JingleTransportsIBBFeature) || info->hasFeature(DiscoInfo::JingleTransportsS5BFeature)); - } - return false; -} - } diff --git a/Swiften/FileTransfer/FileTransferManager.h b/Swiften/FileTransfer/FileTransferManager.h index 2d75367..07cfc90 100644 --- a/Swiften/FileTransfer/FileTransferManager.h +++ b/Swiften/FileTransfer/FileTransferManager.h @@ -5,7 +5,7 @@ */ /* - * Copyright (c) 2013 Isode Limited. + * Copyright (c) 2013-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ @@ -13,41 +13,40 @@ #pragma once #include <string> -#include <boost/filesystem/path.hpp> + #include <boost/date_time/posix_time/posix_time.hpp> +#include <boost/filesystem/path.hpp> +#include <boost/signals2.hpp> #include <Swiften/Base/API.h> -#include <Swiften/Base/boost_bsignals.h> #include <Swiften/Elements/DiscoInfo.h> -#include <Swiften/JID/JID.h> #include <Swiften/FileTransfer/FileTransferOptions.h> -#include <Swiften/FileTransfer/OutgoingFileTransfer.h> #include <Swiften/FileTransfer/IncomingFileTransfer.h> +#include <Swiften/FileTransfer/OutgoingFileTransfer.h> +#include <Swiften/JID/JID.h> namespace Swift { - class ReadBytestream; - - class SWIFTEN_API FileTransferManager { - public: - virtual ~FileTransferManager(); - - virtual OutgoingFileTransfer::ref createOutgoingFileTransfer( - const JID& to, - const boost::filesystem::path& filepath, - const std::string& description, - boost::shared_ptr<ReadBytestream> bytestream, - const FileTransferOptions& = FileTransferOptions()) = 0; - virtual OutgoingFileTransfer::ref createOutgoingFileTransfer( - const JID& to, - const std::string& filename, - const std::string& description, - const boost::uintmax_t sizeInBytes, - const boost::posix_time::ptime& lastModified, - boost::shared_ptr<ReadBytestream> bytestream, - const FileTransferOptions& = FileTransferOptions()) = 0; - - static bool isSupportedBy(const DiscoInfo::ref info); - - boost::signal<void (IncomingFileTransfer::ref)> onIncomingFileTransfer; - }; + class ReadBytestream; + + class SWIFTEN_API FileTransferManager { + public: + virtual ~FileTransferManager(); + + virtual OutgoingFileTransfer::ref createOutgoingFileTransfer( + const JID& to, + const boost::filesystem::path& filepath, + const std::string& description, + std::shared_ptr<ReadBytestream> bytestream, + const FileTransferOptions& = FileTransferOptions()) = 0; + virtual OutgoingFileTransfer::ref createOutgoingFileTransfer( + const JID& to, + const std::string& filename, + const std::string& description, + const boost::uintmax_t sizeInBytes, + const boost::posix_time::ptime& lastModified, + std::shared_ptr<ReadBytestream> bytestream, + const FileTransferOptions& = FileTransferOptions()) = 0; + + boost::signals2::signal<void (IncomingFileTransfer::ref)> onIncomingFileTransfer; + }; } diff --git a/Swiften/FileTransfer/FileTransferManagerImpl.cpp b/Swiften/FileTransfer/FileTransferManagerImpl.cpp index f4b4202..05dd3bb 100644 --- a/Swiften/FileTransfer/FileTransferManagerImpl.cpp +++ b/Swiften/FileTransfer/FileTransferManagerImpl.cpp @@ -5,7 +5,7 @@ */ /* - * Copyright (c) 2013-2015 Isode Limited. + * Copyright (c) 2013-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ @@ -16,11 +16,11 @@ #include <boost/cstdint.hpp> #include <boost/filesystem.hpp> -#include "Swiften/Disco/EntityCapsProvider.h" #include <Swiften/Base/BoostFilesystemVersion.h> #include <Swiften/Base/Log.h> #include <Swiften/Base/Path.h> -#include <Swiften/Base/foreach.h> +#include <Swiften/Disco/EntityCapsProvider.h> +#include <Swiften/Disco/FeatureOracle.h> #include <Swiften/Elements/JingleFileTransferFileInfo.h> #include <Swiften/Elements/Presence.h> #include <Swiften/FileTransfer/DefaultFileTransferTransporterFactory.h> @@ -40,147 +40,126 @@ namespace Swift { FileTransferManagerImpl::FileTransferManagerImpl( - const JID& ownJID, - JingleSessionManager* jingleSessionManager, - IQRouter* router, - EntityCapsProvider* capsProvider, - PresenceOracle* presOracle, - ConnectionFactory* connectionFactory, - ConnectionServerFactory* connectionServerFactory, - TimerFactory* timerFactory, - DomainNameResolver* domainNameResolver, - NetworkEnvironment* networkEnvironment, - NATTraverser* natTraverser, - CryptoProvider* crypto) : - iqRouter(router), - capsProvider(capsProvider), - presenceOracle(presOracle) { - bytestreamRegistry = new SOCKS5BytestreamRegistry(); - s5bServerManager = new SOCKS5BytestreamServerManager( - bytestreamRegistry, connectionServerFactory, networkEnvironment, natTraverser); - bytestreamProxy = new SOCKS5BytestreamProxiesManager(connectionFactory, timerFactory, domainNameResolver, iqRouter, JID(ownJID.getDomain())); - - transporterFactory = new DefaultFileTransferTransporterFactory( - bytestreamRegistry, - s5bServerManager, - bytestreamProxy, - &idGenerator, - connectionFactory, - timerFactory, - crypto, - iqRouter); - outgoingFTManager = new OutgoingFileTransferManager( - jingleSessionManager, - iqRouter, - transporterFactory, - timerFactory, - crypto); - incomingFTManager = new IncomingFileTransferManager( - jingleSessionManager, - transporterFactory, - timerFactory, - crypto); - incomingFTManager->onIncomingFileTransfer.connect(onIncomingFileTransfer); + const JID& ownJID, + JingleSessionManager* jingleSessionManager, + IQRouter* router, + EntityCapsProvider* capsProvider, + PresenceOracle* presOracle, + ConnectionFactory* connectionFactory, + ConnectionServerFactory* connectionServerFactory, + TimerFactory* timerFactory, + DomainNameResolver* domainNameResolver, + NetworkEnvironment* networkEnvironment, + NATTraverser* natTraverser, + CryptoProvider* crypto) : + iqRouter(router), + capsProvider(capsProvider), + presenceOracle(presOracle) { + bytestreamRegistry = new SOCKS5BytestreamRegistry(); + s5bServerManager = new SOCKS5BytestreamServerManager( + bytestreamRegistry, connectionServerFactory, networkEnvironment, natTraverser); + bytestreamProxy = new SOCKS5BytestreamProxiesManager(connectionFactory, timerFactory, domainNameResolver, iqRouter, JID(ownJID.getDomain())); + + transporterFactory = new DefaultFileTransferTransporterFactory( + bytestreamRegistry, + s5bServerManager, + bytestreamProxy, + &idGenerator, + connectionFactory, + timerFactory, + crypto, + iqRouter); + outgoingFTManager = new OutgoingFileTransferManager( + jingleSessionManager, + iqRouter, + transporterFactory, + timerFactory, + crypto); + incomingFTManager = new IncomingFileTransferManager( + jingleSessionManager, + transporterFactory, + timerFactory, + crypto); + incomingFTManager->onIncomingFileTransfer.connect(onIncomingFileTransfer); } FileTransferManagerImpl::~FileTransferManagerImpl() { - delete incomingFTManager; - delete outgoingFTManager; - delete transporterFactory; - delete bytestreamProxy; - delete s5bServerManager; - delete bytestreamRegistry; + delete incomingFTManager; + delete outgoingFTManager; + delete transporterFactory; + delete bytestreamProxy; + delete s5bServerManager; + delete bytestreamRegistry; } void FileTransferManagerImpl::start() { } void FileTransferManagerImpl::stop() { - s5bServerManager->stop(); -} - -boost::optional<JID> FileTransferManagerImpl::highestPriorityJIDSupportingFileTransfer(const JID& bareJID) { - JID fullReceipientJID; - int priority = INT_MIN; - - //getAllPresence(bareJID) gives you all presences for the bare JID (i.e. all resources) Isode Limited. @ 11:11 - std::vector<Presence::ref> presences = presenceOracle->getAllPresence(bareJID); - - //iterate over them - foreach(Presence::ref pres, presences) { - if (pres->getPriority() > priority) { - // look up caps from the jid - DiscoInfo::ref info = capsProvider->getCaps(pres->getFrom()); - if (isSupportedBy(info)) { - priority = pres->getPriority(); - fullReceipientJID = pres->getFrom(); - } - } - } - - return fullReceipientJID.isValid() ? boost::optional<JID>(fullReceipientJID) : boost::optional<JID>(); + s5bServerManager->stop(); } OutgoingFileTransfer::ref FileTransferManagerImpl::createOutgoingFileTransfer( - const JID& to, - const boost::filesystem::path& filepath, - const std::string& description, - boost::shared_ptr<ReadBytestream> bytestream, - const FileTransferOptions& config) { + const JID& to, + const boost::filesystem::path& filepath, + const std::string& description, + std::shared_ptr<ReadBytestream> bytestream, + const FileTransferOptions& config) { #if BOOST_FILESYSTEM_VERSION == 2 // TODO: Delete this when boost 1.44 becomes a minimum requirement, and we no longer need v2 - std::string filename = filepath.filename(); + std::string filename = filepath.filename(); #else - std::string filename = pathToString(filepath.filename()); + std::string filename = pathToString(filepath.filename()); #endif - boost::uintmax_t sizeInBytes = boost::filesystem::file_size(filepath); - boost::posix_time::ptime lastModified = boost::posix_time::from_time_t(boost::filesystem::last_write_time(filepath)); - return createOutgoingFileTransfer(to, filename, description, sizeInBytes, lastModified, bytestream, config); + boost::uintmax_t sizeInBytes = boost::filesystem::file_size(filepath); + boost::posix_time::ptime lastModified = boost::posix_time::from_time_t(boost::filesystem::last_write_time(filepath)); + return createOutgoingFileTransfer(to, filename, description, sizeInBytes, lastModified, bytestream, config); } OutgoingFileTransfer::ref FileTransferManagerImpl::createOutgoingFileTransfer( - const JID& to, - const std::string& filename, - const std::string& description, - const boost::uintmax_t sizeInBytes, - const boost::posix_time::ptime& lastModified, - boost::shared_ptr<ReadBytestream> bytestream, - const FileTransferOptions& config) { - JingleFileTransferFileInfo fileInfo; - fileInfo.setDate(lastModified); - fileInfo.setSize(sizeInBytes); - fileInfo.setName(filename); - fileInfo.setDescription(description); - - JID receipient = to; - - if(receipient.isBare()) { - boost::optional<JID> fullJID = highestPriorityJIDSupportingFileTransfer(receipient); - if (fullJID.is_initialized()) { - receipient = fullJID.get(); - } else { - return OutgoingFileTransfer::ref(); - } - } - - assert(!iqRouter->getJID().isBare()); - - DiscoInfo::ref capabilities = capsProvider->getCaps(receipient); - - FileTransferOptions options = config; - if (capabilities) { - if (!capabilities->hasFeature(DiscoInfo::JingleTransportsS5BFeature)) { - options = options.withAssistedAllowed(false).withDirectAllowed(false).withProxiedAllowed(false); - } - if (!capabilities->hasFeature(DiscoInfo::JingleTransportsIBBFeature)) { - options = options.withInBandAllowed(false); - } - } - else { - SWIFT_LOG(warning) << "No entity capabilities information for " << receipient.toString() << std::endl; - } - - return outgoingFTManager->createOutgoingFileTransfer(iqRouter->getJID(), receipient, bytestream, fileInfo, options); + const JID& to, + const std::string& filename, + const std::string& description, + const boost::uintmax_t sizeInBytes, + const boost::posix_time::ptime& lastModified, + std::shared_ptr<ReadBytestream> bytestream, + const FileTransferOptions& config) { + JingleFileTransferFileInfo fileInfo; + fileInfo.setDate(lastModified); + fileInfo.setSize(sizeInBytes); + fileInfo.setName(filename); + fileInfo.setDescription(description); + + JID receipient = to; + + if(receipient.isBare()) { + auto featureOracle = FeatureOracle(capsProvider, presenceOracle); + JID fullJID = featureOracle.getMostAvailableClientForFileTrasfer(receipient); + if (!fullJID.toString().empty()) { + receipient = fullJID; + } else { + return OutgoingFileTransfer::ref(); + } + } + + assert(!iqRouter->getJID().isBare()); + + DiscoInfo::ref capabilities = capsProvider->getCaps(receipient); + + FileTransferOptions options = config; + if (capabilities) { + if (!capabilities->hasFeature(DiscoInfo::JingleTransportsS5BFeature)) { + options = options.withAssistedAllowed(false).withDirectAllowed(false).withProxiedAllowed(false); + } + if (!capabilities->hasFeature(DiscoInfo::JingleTransportsIBBFeature)) { + options = options.withInBandAllowed(false); + } + } + else { + SWIFT_LOG(warning) << "No entity capabilities information for " << receipient.toString() << std::endl; + } + + return outgoingFTManager->createOutgoingFileTransfer(iqRouter->getJID(), receipient, bytestream, fileInfo, options); } } diff --git a/Swiften/FileTransfer/FileTransferManagerImpl.h b/Swiften/FileTransfer/FileTransferManagerImpl.h index 49490c8..026c8b7 100644 --- a/Swiften/FileTransfer/FileTransferManagerImpl.h +++ b/Swiften/FileTransfer/FileTransferManagerImpl.h @@ -5,7 +5,7 @@ */ /* - * Copyright (c) 2013-2015 Isode Limited. + * Copyright (c) 2013-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ @@ -18,11 +18,11 @@ #include <boost/date_time/posix_time/posix_time.hpp> #include <boost/filesystem/path.hpp> #include <boost/optional.hpp> +#include <boost/signals2.hpp> #include <Swiften/Base/API.h> #include <Swiften/Base/IDGenerator.h> #include <Swiften/Base/Override.h> -#include <Swiften/Base/boost_bsignals.h> #include <Swiften/Elements/S5BProxyRequest.h> #include <Swiften/FileTransfer/FileTransferManager.h> #include <Swiften/FileTransfer/FileTransferOptions.h> @@ -30,74 +30,74 @@ #include <Swiften/FileTransfer/OutgoingFileTransfer.h> namespace Swift { - class ConnectionFactory; - class ConnectionServerFactory; - class CryptoProvider; - class DomainNameResolver; - class EntityCapsProvider; - class FileTransferTransporterFactory; - class IQRouter; - class IncomingFileTransferManager; - class JID; - class JingleSessionManager; - class NATTraverser; - class NetworkEnvironment; - class OutgoingFileTransferManager; - class PresenceOracle; - class ReadBytestream; - class SOCKS5BytestreamProxiesManager; - class SOCKS5BytestreamRegistry; - class SOCKS5BytestreamServerManager; - class TimerFactory; + class ConnectionFactory; + class ConnectionServerFactory; + class CryptoProvider; + class DomainNameResolver; + class EntityCapsProvider; + class FileTransferTransporterFactory; + class IQRouter; + class IncomingFileTransferManager; + class JID; + class JingleSessionManager; + class NATTraverser; + class NetworkEnvironment; + class OutgoingFileTransferManager; + class PresenceOracle; + class ReadBytestream; + class SOCKS5BytestreamProxiesManager; + class SOCKS5BytestreamRegistry; + class SOCKS5BytestreamServerManager; + class TimerFactory; - class SWIFTEN_API FileTransferManagerImpl : public FileTransferManager { - public: - FileTransferManagerImpl( - const JID& ownFullJID, - JingleSessionManager* jingleSessionManager, - IQRouter* router, - EntityCapsProvider* capsProvider, - PresenceOracle* presOracle, - ConnectionFactory* connectionFactory, - ConnectionServerFactory* connectionServerFactory, - TimerFactory* timerFactory, - DomainNameResolver* domainNameResolver, - NetworkEnvironment* networkEnvironment, - NATTraverser* natTraverser, - CryptoProvider* crypto); - virtual ~FileTransferManagerImpl(); - - OutgoingFileTransfer::ref createOutgoingFileTransfer( - const JID& to, - const boost::filesystem::path& filepath, - const std::string& description, - boost::shared_ptr<ReadBytestream> bytestream, - const FileTransferOptions&) SWIFTEN_OVERRIDE; - OutgoingFileTransfer::ref createOutgoingFileTransfer( - const JID& to, - const std::string& filename, - const std::string& description, - const boost::uintmax_t sizeInBytes, - const boost::posix_time::ptime& lastModified, - boost::shared_ptr<ReadBytestream> bytestream, - const FileTransferOptions&) SWIFTEN_OVERRIDE; + class SWIFTEN_API FileTransferManagerImpl : public FileTransferManager { + public: + FileTransferManagerImpl( + const JID& ownFullJID, + JingleSessionManager* jingleSessionManager, + IQRouter* router, + EntityCapsProvider* capsProvider, + PresenceOracle* presOracle, + ConnectionFactory* connectionFactory, + ConnectionServerFactory* connectionServerFactory, + TimerFactory* timerFactory, + DomainNameResolver* domainNameResolver, + NetworkEnvironment* networkEnvironment, + NATTraverser* natTraverser, + CryptoProvider* crypto); + virtual ~FileTransferManagerImpl(); - void start(); - void stop(); - - private: - boost::optional<JID> highestPriorityJIDSupportingFileTransfer(const JID& bareJID); - - private: - OutgoingFileTransferManager* outgoingFTManager; - IncomingFileTransferManager* incomingFTManager; - FileTransferTransporterFactory* transporterFactory; - IQRouter* iqRouter; - EntityCapsProvider* capsProvider; - PresenceOracle* presenceOracle; - IDGenerator idGenerator; - SOCKS5BytestreamRegistry* bytestreamRegistry; - SOCKS5BytestreamProxiesManager* bytestreamProxy; - SOCKS5BytestreamServerManager* s5bServerManager; - }; + OutgoingFileTransfer::ref createOutgoingFileTransfer( + const JID& to, + const boost::filesystem::path& filepath, + const std::string& description, + std::shared_ptr<ReadBytestream> bytestream, + const FileTransferOptions&) SWIFTEN_OVERRIDE; + OutgoingFileTransfer::ref createOutgoingFileTransfer( + const JID& to, + const std::string& filename, + const std::string& description, + const boost::uintmax_t sizeInBytes, + const boost::posix_time::ptime& lastModified, + std::shared_ptr<ReadBytestream> bytestream, + const FileTransferOptions&) SWIFTEN_OVERRIDE; + + void start(); + void stop(); + + private: + boost::optional<JID> highestPriorityJIDSupportingFileTransfer(const JID& bareJID); + + private: + OutgoingFileTransferManager* outgoingFTManager; + IncomingFileTransferManager* incomingFTManager; + FileTransferTransporterFactory* transporterFactory; + IQRouter* iqRouter; + EntityCapsProvider* capsProvider; + PresenceOracle* presenceOracle; + IDGenerator idGenerator; + SOCKS5BytestreamRegistry* bytestreamRegistry; + SOCKS5BytestreamProxiesManager* bytestreamProxy; + SOCKS5BytestreamServerManager* s5bServerManager; + }; } diff --git a/Swiften/FileTransfer/FileTransferOptions.h b/Swiften/FileTransfer/FileTransferOptions.h index baaa36d..2bc4ee1 100644 --- a/Swiften/FileTransfer/FileTransferOptions.h +++ b/Swiften/FileTransfer/FileTransferOptions.h @@ -1,66 +1,66 @@ /* - * Copyright (c) 2013-2015 Isode Limited. + * Copyright (c) 2013-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> #include <Swiften/Base/API.h> +#include <Swiften/Base/Override.h> namespace Swift { - class SWIFTEN_API FileTransferOptions { - public: - FileTransferOptions() : allowInBand_(true), allowAssisted_(true), allowProxied_(true), allowDirect_(true) { - } - SWIFTEN_DEFAULT_COPY_CONSTRUCTOR(FileTransferOptions) - ~FileTransferOptions(); + class SWIFTEN_API FileTransferOptions { + public: + FileTransferOptions() : allowInBand_(true), allowAssisted_(true), allowProxied_(true), allowDirect_(true) { + } + SWIFTEN_DEFAULT_COPY_CONSTRUCTOR(FileTransferOptions) + ~FileTransferOptions(); - FileTransferOptions& withInBandAllowed(bool b) { - allowInBand_ = b; - return *this; - } + FileTransferOptions& withInBandAllowed(bool b) { + allowInBand_ = b; + return *this; + } - bool isInBandAllowed() const { - return allowInBand_; - } + bool isInBandAllowed() const { + return allowInBand_; + } - FileTransferOptions& withAssistedAllowed(bool b) { - allowAssisted_ = b; - return *this; - } + FileTransferOptions& withAssistedAllowed(bool b) { + allowAssisted_ = b; + return *this; + } - bool isAssistedAllowed() const { - return allowAssisted_; - } + bool isAssistedAllowed() const { + return allowAssisted_; + } - FileTransferOptions& withProxiedAllowed(bool b) { - allowProxied_ = b; - return *this; - } + FileTransferOptions& withProxiedAllowed(bool b) { + allowProxied_ = b; + return *this; + } - bool isProxiedAllowed() const { - return allowProxied_; - } + bool isProxiedAllowed() const { + return allowProxied_; + } - FileTransferOptions& withDirectAllowed(bool b) { - allowDirect_ = b; - return *this; - } + FileTransferOptions& withDirectAllowed(bool b) { + allowDirect_ = b; + return *this; + } - bool isDirectAllowed() const { - return allowDirect_; - } + bool isDirectAllowed() const { + return allowDirect_; + } - SWIFTEN_DEFAULT_COPY_ASSIGMNENT_OPERATOR(FileTransferOptions) + SWIFTEN_DEFAULT_COPY_ASSIGMNENT_OPERATOR(FileTransferOptions) - private: - bool allowInBand_; - bool allowAssisted_; - bool allowProxied_; - bool allowDirect_; - }; + private: + bool allowInBand_; + bool allowAssisted_; + bool allowProxied_; + bool allowDirect_; + }; } diff --git a/Swiften/FileTransfer/FileTransferTransporter.h b/Swiften/FileTransfer/FileTransferTransporter.h index cad3d28..e0ffc87 100644 --- a/Swiften/FileTransfer/FileTransferTransporter.h +++ b/Swiften/FileTransfer/FileTransferTransporter.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015 Isode Limited. + * Copyright (c) 2013-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ @@ -9,52 +9,52 @@ #include <vector> #include <boost/optional/optional.hpp> +#include <boost/signals2.hpp> -#include <Swiften/Elements/JingleS5BTransportPayload.h> #include <Swiften/Base/API.h> -#include <Swiften/Base/boost_bsignals.h> +#include <Swiften/Elements/JingleS5BTransportPayload.h> namespace Swift { - class TransportSession; - class ErrorPayload; - class ReadBytestream; - class WriteBytestream; - - /** - * @brief The FileTransferTransporter class is an abstract factory definition - * to generate SOCKS5 bytestream transports or IBB bytestreams for use in file - * transfers. - */ - class SWIFTEN_API FileTransferTransporter { - public: - virtual ~FileTransferTransporter(); - - virtual void startGeneratingLocalCandidates() = 0; - virtual void stopGeneratingLocalCandidates() = 0; - - virtual void addRemoteCandidates( - 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>, const JingleS5BTransportPayload::Candidate& candidate) = 0; - virtual boost::shared_ptr<TransportSession> createRemoteCandidateSession( - boost::shared_ptr<WriteBytestream>, const JingleS5BTransportPayload::Candidate& candidate) = 0; - virtual boost::shared_ptr<TransportSession> createLocalCandidateSession( - boost::shared_ptr<ReadBytestream>, const JingleS5BTransportPayload::Candidate& candidate) = 0; - virtual boost::shared_ptr<TransportSession> createLocalCandidateSession( - boost::shared_ptr<WriteBytestream>, const JingleS5BTransportPayload::Candidate& candidate) = 0; - - 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; - }; + class TransportSession; + class ErrorPayload; + class ReadBytestream; + class WriteBytestream; + + /** + * @brief The FileTransferTransporter class is an abstract factory definition + * to generate SOCKS5 bytestream transports or IBB bytestreams for use in file + * transfers. + */ + class SWIFTEN_API FileTransferTransporter { + public: + virtual ~FileTransferTransporter(); + + virtual void startGeneratingLocalCandidates() = 0; + virtual void stopGeneratingLocalCandidates() = 0; + + virtual void addRemoteCandidates( + 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 std::shared_ptr<TransportSession> createIBBSendSession( + const std::string& sessionID, unsigned int blockSize, std::shared_ptr<ReadBytestream>) = 0; + virtual std::shared_ptr<TransportSession> createIBBReceiveSession( + const std::string& sessionID, unsigned long long size, std::shared_ptr<WriteBytestream>) = 0; + virtual std::shared_ptr<TransportSession> createRemoteCandidateSession( + std::shared_ptr<ReadBytestream>, const JingleS5BTransportPayload::Candidate& candidate) = 0; + virtual std::shared_ptr<TransportSession> createRemoteCandidateSession( + std::shared_ptr<WriteBytestream>, const JingleS5BTransportPayload::Candidate& candidate) = 0; + virtual std::shared_ptr<TransportSession> createLocalCandidateSession( + std::shared_ptr<ReadBytestream>, const JingleS5BTransportPayload::Candidate& candidate) = 0; + virtual std::shared_ptr<TransportSession> createLocalCandidateSession( + std::shared_ptr<WriteBytestream>, const JingleS5BTransportPayload::Candidate& candidate) = 0; + + boost::signals2::signal<void (const std::string& /* sessionID */, const std::vector<JingleS5BTransportPayload::Candidate>&, const std::string& /* dstAddr */)> onLocalCandidatesGenerated; + boost::signals2::signal<void (const std::string& /* sessionID */, const boost::optional<JingleS5BTransportPayload::Candidate>&)> onRemoteCandidateSelectFinished; + boost::signals2::signal<void (const std::string& /* sessionID */, std::shared_ptr<ErrorPayload>)> onProxyActivated; + }; } diff --git a/Swiften/FileTransfer/FileTransferTransporterFactory.h b/Swiften/FileTransfer/FileTransferTransporterFactory.h index a1af4af..4adf32e 100644 --- a/Swiften/FileTransfer/FileTransferTransporterFactory.h +++ b/Swiften/FileTransfer/FileTransferTransporterFactory.h @@ -11,22 +11,22 @@ #include <Swiften/Base/API.h> namespace Swift { - class JID; - class FileTransferTransporter; - class FileTransferOptions; + class JID; + class FileTransferTransporter; + class FileTransferOptions; - class SWIFTEN_API FileTransferTransporterFactory { - public: - virtual ~FileTransferTransporterFactory(); + class SWIFTEN_API FileTransferTransporterFactory { + public: + virtual ~FileTransferTransporterFactory(); - virtual FileTransferTransporter* createInitiatorTransporter( - const JID& initiator, - const JID& responder, - const FileTransferOptions& options) = 0; - virtual FileTransferTransporter* createResponderTransporter( - const JID& initiator, - const JID& responder, - const std::string& s5bSessionID, - const FileTransferOptions& options) = 0; - }; + virtual FileTransferTransporter* createInitiatorTransporter( + const JID& initiator, + const JID& responder, + const FileTransferOptions& options) = 0; + virtual FileTransferTransporter* createResponderTransporter( + const JID& initiator, + const JID& responder, + const std::string& s5bSessionID, + const FileTransferOptions& options) = 0; + }; } diff --git a/Swiften/FileTransfer/FileWriteBytestream.cpp b/Swiften/FileTransfer/FileWriteBytestream.cpp index c39d63a..e7daa2c 100644 --- a/Swiften/FileTransfer/FileWriteBytestream.cpp +++ b/Swiften/FileTransfer/FileWriteBytestream.cpp @@ -13,40 +13,40 @@ namespace Swift { -FileWriteBytestream::FileWriteBytestream(const boost::filesystem::path& file) : file(file), stream(NULL) { +FileWriteBytestream::FileWriteBytestream(const boost::filesystem::path& file) : file(file), stream(nullptr) { } FileWriteBytestream::~FileWriteBytestream() { - if (stream) { - stream->close(); - delete stream; - stream = NULL; - } + if (stream) { + stream->close(); + delete stream; + stream = nullptr; + } } bool FileWriteBytestream::write(const std::vector<unsigned char>& data) { - if (data.empty()) { - return true; - } - if (!stream) { - stream = new boost::filesystem::ofstream(file, std::ios_base::out|std::ios_base::binary); - } - if (stream->good()) { - stream->write(reinterpret_cast<const char*>(&data[0]), boost::numeric_cast<std::streamsize>(data.size())); - if (stream->good()) { - onWrite(data); - return true; - } - } - return false; + if (data.empty()) { + return true; + } + if (!stream) { + stream = new boost::filesystem::ofstream(file, std::ios_base::out|std::ios_base::binary); + } + if (stream->good()) { + stream->write(reinterpret_cast<const char*>(&data[0]), boost::numeric_cast<std::streamsize>(data.size())); + if (stream->good()) { + onWrite(data); + return true; + } + } + return false; } void FileWriteBytestream::close() { - if (stream) { - stream->close(); - delete stream; - stream = NULL; - } + if (stream) { + stream->close(); + delete stream; + stream = nullptr; + } } } diff --git a/Swiften/FileTransfer/FileWriteBytestream.h b/Swiften/FileTransfer/FileWriteBytestream.h index 02e1b46..c563789 100644 --- a/Swiften/FileTransfer/FileWriteBytestream.h +++ b/Swiften/FileTransfer/FileWriteBytestream.h @@ -13,16 +13,16 @@ #include <Swiften/FileTransfer/WriteBytestream.h> namespace Swift { - class SWIFTEN_API FileWriteBytestream : public WriteBytestream { - public: - FileWriteBytestream(const boost::filesystem::path& file); - virtual ~FileWriteBytestream(); + class SWIFTEN_API FileWriteBytestream : public WriteBytestream { + public: + FileWriteBytestream(const boost::filesystem::path& file); + virtual ~FileWriteBytestream(); - virtual bool write(const std::vector<unsigned char>&); - void close(); + virtual bool write(const std::vector<unsigned char>&); + void close(); - private: - boost::filesystem::path file; - boost::filesystem::ofstream* stream; - }; + private: + boost::filesystem::path file; + boost::filesystem::ofstream* stream; + }; } diff --git a/Swiften/FileTransfer/IBBReceiveSession.cpp b/Swiften/FileTransfer/IBBReceiveSession.cpp index ac58b34..24996ed 100644 --- a/Swiften/FileTransfer/IBBReceiveSession.cpp +++ b/Swiften/FileTransfer/IBBReceiveSession.cpp @@ -1,118 +1,118 @@ /* - * Copyright (c) 2010-2015 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #include <Swiften/FileTransfer/IBBReceiveSession.h> +#include <cassert> + #include <boost/bind.hpp> #include <Swiften/Base/Log.h> -#include <Swiften/Queries/IQRouter.h> -#include <Swiften/FileTransfer/IBBRequest.h> #include <Swiften/FileTransfer/BytestreamException.h> +#include <Swiften/FileTransfer/IBBRequest.h> +#include <Swiften/Queries/IQRouter.h> #include <Swiften/Queries/SetResponder.h> -#include <cassert> - namespace Swift { class IBBReceiveSession::IBBResponder : public SetResponder<IBB> { - public: - IBBResponder(IBBReceiveSession* session, IQRouter* router) : SetResponder<IBB>(router), session(session), sequenceNumber(0), receivedSize(0) { - setFinal(false); - } + public: + IBBResponder(IBBReceiveSession* session, IQRouter* router) : SetResponder<IBB>(router), session(session), sequenceNumber(0), receivedSize(0) { + setFinal(false); + } - virtual bool handleSetRequest(const JID& from, const JID&, const std::string& id, IBB::ref ibb) { - if (from == session->from && ibb->getStreamID() == session->id) { - if (ibb->getAction() == IBB::Data) { - if (sequenceNumber == ibb->getSequenceNumber()) { - session->bytestream->write(ibb->getData()); - receivedSize += ibb->getData().size(); - sequenceNumber++; - sendResponse(from, id, IBB::ref()); - if (receivedSize >= session->size) { - if (receivedSize > session->size) { - SWIFT_LOG(warning) << "Received more data than expected"; - } - session->finish(boost::optional<FileTransferError>()); - } - } - else { - SWIFT_LOG(warning) << "Received data out of order"; - sendError(from, id, ErrorPayload::NotAcceptable, ErrorPayload::Cancel); - session->finish(FileTransferError(FileTransferError::ClosedError)); - } - } - else if (ibb->getAction() == IBB::Open) { - SWIFT_LOG(debug) << "IBB open received"; - sendResponse(from, id, IBB::ref()); - } - else if (ibb->getAction() == IBB::Close) { - SWIFT_LOG(debug) << "IBB close received"; - sendResponse(from, id, IBB::ref()); - session->finish(FileTransferError(FileTransferError::ClosedError)); - } - return true; - } - SWIFT_LOG(debug) << "wrong from/sessionID: " << from << " == " << session->from << " / " <<ibb->getStreamID() << " == " << session->id; - return false; - } + virtual bool handleSetRequest(const JID& from, const JID&, const std::string& id, IBB::ref ibb) { + if (from == session->from && ibb->getStreamID() == session->id) { + if (ibb->getAction() == IBB::Data) { + if (sequenceNumber == ibb->getSequenceNumber()) { + session->bytestream->write(ibb->getData()); + receivedSize += ibb->getData().size(); + sequenceNumber++; + sendResponse(from, id, IBB::ref()); + if (receivedSize >= session->size) { + if (receivedSize > session->size) { + SWIFT_LOG(warning) << "Received more data than expected"; + } + session->finish(boost::optional<FileTransferError>()); + } + } + else { + SWIFT_LOG(warning) << "Received data out of order"; + sendError(from, id, ErrorPayload::NotAcceptable, ErrorPayload::Cancel); + session->finish(FileTransferError(FileTransferError::ClosedError)); + } + } + else if (ibb->getAction() == IBB::Open) { + SWIFT_LOG(debug) << "IBB open received"; + sendResponse(from, id, IBB::ref()); + } + else if (ibb->getAction() == IBB::Close) { + SWIFT_LOG(debug) << "IBB close received"; + sendResponse(from, id, IBB::ref()); + session->finish(FileTransferError(FileTransferError::ClosedError)); + } + return true; + } + SWIFT_LOG(debug) << "wrong from/sessionID: " << from << " == " << session->from << " / " <<ibb->getStreamID() << " == " << session->id; + return false; + } - private: - IBBReceiveSession* session; - int sequenceNumber; - unsigned long long receivedSize; + private: + IBBReceiveSession* session; + int sequenceNumber; + unsigned long long receivedSize; }; IBBReceiveSession::IBBReceiveSession( - const std::string& id, - const JID& from, - const JID& to, - unsigned long long size, - boost::shared_ptr<WriteBytestream> bytestream, - IQRouter* router) : - id(id), - from(from), - to(to), - size(size), - bytestream(bytestream), - router(router), - active(false) { - assert(!id.empty()); - assert(from.isValid()); - responder = new IBBResponder(this, router); + const std::string& id, + const JID& from, + const JID& to, + unsigned long long size, + std::shared_ptr<WriteBytestream> bytestream, + IQRouter* router) : + id(id), + from(from), + to(to), + size(size), + bytestream(bytestream), + router(router), + active(false) { + assert(!id.empty()); + assert(from.isValid()); + responder = new IBBResponder(this, router); } IBBReceiveSession::~IBBReceiveSession() { - if (active) { - SWIFT_LOG(warning) << "Session still active"; - } - delete responder; + if (active) { + SWIFT_LOG(warning) << "Session still active"; + } + delete responder; } void IBBReceiveSession::start() { - SWIFT_LOG(debug) << "receive session started"; - active = true; - responder->start(); + SWIFT_LOG(debug) << "receive session started"; + active = true; + responder->start(); } void IBBReceiveSession::stop() { - SWIFT_LOG(debug) << "receive session stopped"; - responder->stop(); - if (active) { - if (router->isAvailable()) { - IBBRequest::create(to, from, IBB::createIBBClose(id), router)->send(); - } - finish(boost::optional<FileTransferError>()); - } + SWIFT_LOG(debug) << "receive session stopped"; + responder->stop(); + if (active) { + if (router->isAvailable()) { + IBBRequest::create(to, from, IBB::createIBBClose(id), router)->send(); + } + finish(boost::optional<FileTransferError>()); + } } void IBBReceiveSession::finish(boost::optional<FileTransferError> error) { - active = false; - onFinished(error); + active = false; + onFinished(error); } } diff --git a/Swiften/FileTransfer/IBBReceiveSession.h b/Swiften/FileTransfer/IBBReceiveSession.h index d400a1e..797394c 100644 --- a/Swiften/FileTransfer/IBBReceiveSession.h +++ b/Swiften/FileTransfer/IBBReceiveSession.h @@ -1,63 +1,64 @@ /* - * Copyright (c) 2010 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> + #include <boost/optional/optional.hpp> +#include <boost/signals2.hpp> #include <Swiften/Base/API.h> -#include <Swiften/Base/boost_bsignals.h> -#include <Swiften/FileTransfer/WriteBytestream.h> -#include <Swiften/JID/JID.h> #include <Swiften/Elements/IBB.h> #include <Swiften/FileTransfer/FileTransferError.h> +#include <Swiften/FileTransfer/WriteBytestream.h> +#include <Swiften/JID/JID.h> namespace Swift { - class IQRouter; - - class SWIFTEN_API IBBReceiveSession { - public: - IBBReceiveSession( - const std::string& id, - const JID& from, - const JID& to, - unsigned long long size, - boost::shared_ptr<WriteBytestream> bytestream, - IQRouter* router); - ~IBBReceiveSession(); - - void start(); - void stop(); - - const JID& getSender() const { - return from; - } - - const JID& getReceiver() const { - return to; - } - - boost::signal<void (boost::optional<FileTransferError>)> onFinished; - - private: - bool handleSetRequest(const JID& from, const JID& to, const std::string& id, IBB::ref payload); - void finish(boost::optional<FileTransferError>); - - private: - class IBBResponder; - friend class IBBResponder; - - std::string id; - JID from; - JID to; - unsigned long long size; - boost::shared_ptr<WriteBytestream> bytestream; - IQRouter* router; - IBBResponder* responder; - bool active; - }; + class IQRouter; + + class SWIFTEN_API IBBReceiveSession { + public: + IBBReceiveSession( + const std::string& id, + const JID& from, + const JID& to, + unsigned long long size, + std::shared_ptr<WriteBytestream> bytestream, + IQRouter* router); + ~IBBReceiveSession(); + + void start(); + void stop(); + + const JID& getSender() const { + return from; + } + + const JID& getReceiver() const { + return to; + } + + boost::signals2::signal<void (boost::optional<FileTransferError>)> onFinished; + + private: + bool handleSetRequest(const JID& from, const JID& to, const std::string& id, IBB::ref payload); + void finish(boost::optional<FileTransferError>); + + private: + class IBBResponder; + friend class IBBResponder; + + std::string id; + JID from; + JID to; + unsigned long long size; + std::shared_ptr<WriteBytestream> bytestream; + IQRouter* router; + IBBResponder* responder; + bool active; + }; } diff --git a/Swiften/FileTransfer/IBBReceiveTransportSession.cpp b/Swiften/FileTransfer/IBBReceiveTransportSession.cpp index 4464946..6e47ac6 100644 --- a/Swiften/FileTransfer/IBBReceiveTransportSession.cpp +++ b/Swiften/FileTransfer/IBBReceiveTransportSession.cpp @@ -1,28 +1,28 @@ /* - * Copyright (c) 2015 Isode Limited. + * Copyright (c) 2015-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ -#include <boost/bind.hpp> - #include <Swiften/FileTransfer/IBBReceiveTransportSession.h> +#include <boost/bind.hpp> + namespace Swift { -IBBReceiveTransportSession::IBBReceiveTransportSession(boost::shared_ptr<IBBReceiveSession> session) : session(session) { - finishedConnection = session->onFinished.connect(boost::bind(boost::ref(onFinished), _1)); +IBBReceiveTransportSession::IBBReceiveTransportSession(std::shared_ptr<IBBReceiveSession> session) : session(session) { + finishedConnection = session->onFinished.connect(boost::bind(boost::ref(onFinished), _1)); } IBBReceiveTransportSession::~IBBReceiveTransportSession() { } void IBBReceiveTransportSession::start() { - session->start(); + session->start(); } void IBBReceiveTransportSession::stop() { - session->stop(); + session->stop(); } } diff --git a/Swiften/FileTransfer/IBBReceiveTransportSession.h b/Swiften/FileTransfer/IBBReceiveTransportSession.h index 5fca26a..8b304c3 100644 --- a/Swiften/FileTransfer/IBBReceiveTransportSession.h +++ b/Swiften/FileTransfer/IBBReceiveTransportSession.h @@ -1,30 +1,31 @@ /* - * Copyright (c) 2015 Isode Limited. + * Copyright (c) 2015-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #pragma once +#include <boost/signals2.hpp> + #include <Swiften/Base/API.h> -#include <Swiften/Base/boost_bsignals.h> -#include <Swiften/FileTransfer/TransportSession.h> #include <Swiften/FileTransfer/IBBReceiveSession.h> +#include <Swiften/FileTransfer/TransportSession.h> namespace Swift { class SWIFTEN_API IBBReceiveTransportSession : public TransportSession { - public: - IBBReceiveTransportSession(boost::shared_ptr<IBBReceiveSession> session); - virtual ~IBBReceiveTransportSession(); + public: + IBBReceiveTransportSession(std::shared_ptr<IBBReceiveSession> session); + virtual ~IBBReceiveTransportSession(); - virtual void start() SWIFTEN_OVERRIDE; - virtual void stop() SWIFTEN_OVERRIDE; + virtual void start() SWIFTEN_OVERRIDE; + virtual void stop() SWIFTEN_OVERRIDE; - private: - boost::shared_ptr<IBBReceiveSession> session; - boost::bsignals::scoped_connection finishedConnection; - boost::bsignals::scoped_connection bytesSentConnection; + private: + std::shared_ptr<IBBReceiveSession> session; + boost::signals2::scoped_connection finishedConnection; + boost::signals2::scoped_connection bytesSentConnection; }; } diff --git a/Swiften/FileTransfer/IBBRequest.h b/Swiften/FileTransfer/IBBRequest.h index 1eef64b..67bd33a 100644 --- a/Swiften/FileTransfer/IBBRequest.h +++ b/Swiften/FileTransfer/IBBRequest.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2015 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ @@ -7,21 +7,20 @@ #pragma once #include <Swiften/Base/API.h> -#include <Swiften/Queries/GenericRequest.h> #include <Swiften/Elements/IBB.h> - +#include <Swiften/Queries/GenericRequest.h> namespace Swift { - class SWIFTEN_API IBBRequest : public GenericRequest<IBB> { - public: - typedef boost::shared_ptr<IBBRequest> ref; + class SWIFTEN_API IBBRequest : public GenericRequest<IBB> { + public: + typedef std::shared_ptr<IBBRequest> ref; - static ref create(const JID& from, const JID& to, boost::shared_ptr<IBB> payload, IQRouter* router) { - return ref(new IBBRequest(from, to, payload, router)); - } + static ref create(const JID& from, const JID& to, std::shared_ptr<IBB> payload, IQRouter* router) { + return ref(new IBBRequest(from, to, payload, router)); + } - private: - IBBRequest(const JID& from, const JID& to, boost::shared_ptr<IBB> payload, IQRouter* router) : GenericRequest<IBB>(IQ::Set, from, to, payload, router) { - } - }; + private: + IBBRequest(const JID& from, const JID& to, std::shared_ptr<IBB> payload, IQRouter* router) : GenericRequest<IBB>(IQ::Set, from, to, payload, router) { + } + }; } diff --git a/Swiften/FileTransfer/IBBSendSession.cpp b/Swiften/FileTransfer/IBBSendSession.cpp index 9f41532..e51c91c 100644 --- a/Swiften/FileTransfer/IBBSendSession.cpp +++ b/Swiften/FileTransfer/IBBSendSession.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2015 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ @@ -17,92 +17,92 @@ namespace Swift { IBBSendSession::IBBSendSession( - const std::string& id, - const JID& from, - const JID& to, - boost::shared_ptr<ReadBytestream> bytestream, - IQRouter* router) : - id(id), - from(from), - to(to), - bytestream(bytestream), - router(router), - blockSize(4096), - sequenceNumber(0), - active(false), - waitingForData(false) { - bytestream->onDataAvailable.connect(boost::bind(&IBBSendSession::handleDataAvailable, this)); + const std::string& id, + const JID& from, + const JID& to, + std::shared_ptr<ReadBytestream> bytestream, + IQRouter* router) : + id(id), + from(from), + to(to), + bytestream(bytestream), + router(router), + blockSize(4096), + sequenceNumber(0), + active(false), + waitingForData(false) { + bytestream->onDataAvailable.connect(boost::bind(&IBBSendSession::handleDataAvailable, this)); } IBBSendSession::~IBBSendSession() { - bytestream->onDataAvailable.disconnect(boost::bind(&IBBSendSession::handleDataAvailable, this)); + bytestream->onDataAvailable.disconnect(boost::bind(&IBBSendSession::handleDataAvailable, this)); } void IBBSendSession::start() { - IBBRequest::ref request = IBBRequest::create( - from, to, IBB::createIBBOpen(id, boost::numeric_cast<int>(blockSize)), router); - request->onResponse.connect(boost::bind(&IBBSendSession::handleIBBResponse, this, _1, _2)); - active = true; - request->send(); - currentRequest = request; + IBBRequest::ref request = IBBRequest::create( + from, to, IBB::createIBBOpen(id, boost::numeric_cast<int>(blockSize)), router); + request->onResponse.connect(boost::bind(&IBBSendSession::handleIBBResponse, this, _1, _2)); + active = true; + request->send(); + currentRequest = request; } void IBBSendSession::stop() { - if (active && router->isAvailable()) { - IBBRequest::create(from, to, IBB::createIBBClose(id), router)->send(); - } - if (currentRequest) { - currentRequest->onResponse.disconnect(boost::bind(&IBBSendSession::handleIBBResponse, this, _1, _2)); - } - finish(boost::optional<FileTransferError>()); + if (active && router->isAvailable()) { + IBBRequest::create(from, to, IBB::createIBBClose(id), router)->send(); + } + if (currentRequest) { + currentRequest->onResponse.disconnect(boost::bind(&IBBSendSession::handleIBBResponse, this, _1, _2)); + } + finish(boost::optional<FileTransferError>()); } void IBBSendSession::handleIBBResponse(IBB::ref, ErrorPayload::ref error) { - currentRequest.reset(); + currentRequest.reset(); - if (!error && active) { - if (!bytestream->isFinished()) { - sendMoreData(); - } - else { - finish(boost::optional<FileTransferError>()); - } - } - else { - finish(FileTransferError(FileTransferError::PeerError)); - } + if (!error && active) { + if (!bytestream->isFinished()) { + sendMoreData(); + } + else { + finish(boost::optional<FileTransferError>()); + } + } + else { + finish(FileTransferError(FileTransferError::PeerError)); + } } void IBBSendSession::sendMoreData() { - try { - boost::shared_ptr<ByteArray> data = bytestream->read(blockSize); - if (!data->empty()) { - waitingForData = false; - IBBRequest::ref request = IBBRequest::create(from, to, IBB::createIBBData(id, sequenceNumber, *data), router); - sequenceNumber++; - request->onResponse.connect(boost::bind(&IBBSendSession::handleIBBResponse, this, _1, _2)); - request->send(); - currentRequest = request; - onBytesSent(data->size()); - } - else { - waitingForData = true; - } - } - catch (const BytestreamException&) { - finish(FileTransferError(FileTransferError::ReadError)); - } + try { + std::shared_ptr<ByteArray> data = bytestream->read(blockSize); + if (!data->empty()) { + waitingForData = false; + IBBRequest::ref request = IBBRequest::create(from, to, IBB::createIBBData(id, sequenceNumber, *data), router); + sequenceNumber++; + request->onResponse.connect(boost::bind(&IBBSendSession::handleIBBResponse, this, _1, _2)); + request->send(); + currentRequest = request; + onBytesSent(data->size()); + } + else { + waitingForData = true; + } + } + catch (const BytestreamException&) { + finish(FileTransferError(FileTransferError::ReadError)); + } } void IBBSendSession::finish(boost::optional<FileTransferError> error) { - active = false; - onFinished(error); + active = false; + onFinished(error); } void IBBSendSession::handleDataAvailable() { - if (waitingForData) { - sendMoreData(); - } + if (waitingForData) { + sendMoreData(); + } } } diff --git a/Swiften/FileTransfer/IBBSendSession.h b/Swiften/FileTransfer/IBBSendSession.h index af8cc12..e45532d 100644 --- a/Swiften/FileTransfer/IBBSendSession.h +++ b/Swiften/FileTransfer/IBBSendSession.h @@ -1,16 +1,17 @@ /* - * Copyright (c) 2010-2015 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #pragma once +#include <memory> + #include <boost/optional.hpp> -#include <boost/shared_ptr.hpp> +#include <boost/signals2.hpp> #include <Swiften/Base/API.h> -#include <Swiften/Base/boost_bsignals.h> #include <Swiften/Elements/ErrorPayload.h> #include <Swiften/Elements/IBB.h> #include <Swiften/FileTransfer/FileTransferError.h> @@ -18,53 +19,53 @@ #include <Swiften/JID/JID.h> namespace Swift { - class IQRouter; - class IBBRequest; + class IQRouter; + class IBBRequest; - class SWIFTEN_API IBBSendSession { - public: - IBBSendSession( - const std::string& id, - const JID& from, - const JID& to, - boost::shared_ptr<ReadBytestream> bytestream, - IQRouter* router); - ~IBBSendSession(); + class SWIFTEN_API IBBSendSession { + public: + IBBSendSession( + const std::string& id, + const JID& from, + const JID& to, + std::shared_ptr<ReadBytestream> bytestream, + IQRouter* router); + ~IBBSendSession(); - void start(); - void stop(); + void start(); + void stop(); - const JID& getSender() const { - return from; - } + const JID& getSender() const { + return from; + } - const JID& getReceiver() const { - return to; - } + const JID& getReceiver() const { + return to; + } - void setBlockSize(unsigned int blockSize) { - this->blockSize = blockSize; - } + void setBlockSize(unsigned int blockSize) { + this->blockSize = blockSize; + } - boost::signal<void (boost::optional<FileTransferError>)> onFinished; - boost::signal<void (size_t)> onBytesSent; + boost::signals2::signal<void (boost::optional<FileTransferError>)> onFinished; + boost::signals2::signal<void (size_t)> onBytesSent; - private: - void handleIBBResponse(IBB::ref, ErrorPayload::ref); - void finish(boost::optional<FileTransferError>); - void sendMoreData(); - void handleDataAvailable(); + private: + void handleIBBResponse(IBB::ref, ErrorPayload::ref); + void finish(boost::optional<FileTransferError>); + void sendMoreData(); + void handleDataAvailable(); - private: - std::string id; - JID from; - JID to; - boost::shared_ptr<ReadBytestream> bytestream; - IQRouter* router; - unsigned int blockSize; - int sequenceNumber; - bool active; - bool waitingForData; - boost::shared_ptr<IBBRequest> currentRequest; - }; + private: + std::string id; + JID from; + JID to; + std::shared_ptr<ReadBytestream> bytestream; + IQRouter* router; + unsigned int blockSize; + int sequenceNumber; + bool active; + bool waitingForData; + std::shared_ptr<IBBRequest> currentRequest; + }; } diff --git a/Swiften/FileTransfer/IBBSendTransportSession.cpp b/Swiften/FileTransfer/IBBSendTransportSession.cpp index b4d2467..81972c9 100644 --- a/Swiften/FileTransfer/IBBSendTransportSession.cpp +++ b/Swiften/FileTransfer/IBBSendTransportSession.cpp @@ -1,29 +1,29 @@ /* - * Copyright (c) 2015 Isode Limited. + * Copyright (c) 2015-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ -#include <boost/bind.hpp> - #include <Swiften/FileTransfer/IBBSendTransportSession.h> +#include <boost/bind.hpp> + namespace Swift { -IBBSendTransportSession::IBBSendTransportSession(boost::shared_ptr<IBBSendSession> session) : session(session) { - finishedConnection = session->onFinished.connect(boost::bind(boost::ref(onFinished), _1)); - bytesSentConnection = session->onBytesSent.connect(boost::bind(boost::ref(onBytesSent), _1)); +IBBSendTransportSession::IBBSendTransportSession(std::shared_ptr<IBBSendSession> session) : session(session) { + finishedConnection = session->onFinished.connect(boost::bind(boost::ref(onFinished), _1)); + bytesSentConnection = session->onBytesSent.connect(boost::bind(boost::ref(onBytesSent), _1)); } IBBSendTransportSession::~IBBSendTransportSession() { } void IBBSendTransportSession::start() { - session->start(); + session->start(); } void IBBSendTransportSession::stop() { - session->stop(); + session->stop(); } } diff --git a/Swiften/FileTransfer/IBBSendTransportSession.h b/Swiften/FileTransfer/IBBSendTransportSession.h index 20abbd7..d1e786b 100644 --- a/Swiften/FileTransfer/IBBSendTransportSession.h +++ b/Swiften/FileTransfer/IBBSendTransportSession.h @@ -1,30 +1,31 @@ /* - * Copyright (c) 2015 Isode Limited. + * Copyright (c) 2015-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #pragma once +#include <boost/signals2.hpp> + #include <Swiften/Base/API.h> -#include <Swiften/Base/boost_bsignals.h> -#include <Swiften/FileTransfer/TransportSession.h> #include <Swiften/FileTransfer/IBBSendSession.h> +#include <Swiften/FileTransfer/TransportSession.h> namespace Swift { class SWIFTEN_API IBBSendTransportSession : public TransportSession { - public: - IBBSendTransportSession(boost::shared_ptr<IBBSendSession> session); - virtual ~IBBSendTransportSession(); + public: + IBBSendTransportSession(std::shared_ptr<IBBSendSession> session); + virtual ~IBBSendTransportSession(); - virtual void start() SWIFTEN_OVERRIDE; - virtual void stop() SWIFTEN_OVERRIDE; + virtual void start() SWIFTEN_OVERRIDE; + virtual void stop() SWIFTEN_OVERRIDE; - private: - boost::shared_ptr<IBBSendSession> session; - boost::bsignals::scoped_connection finishedConnection; - boost::bsignals::scoped_connection bytesSentConnection; + private: + std::shared_ptr<IBBSendSession> session; + boost::signals2::scoped_connection finishedConnection; + boost::signals2::scoped_connection bytesSentConnection; }; } diff --git a/Swiften/FileTransfer/IncomingFileTransfer.h b/Swiften/FileTransfer/IncomingFileTransfer.h index 16905b8..7236c35 100644 --- a/Swiften/FileTransfer/IncomingFileTransfer.h +++ b/Swiften/FileTransfer/IncomingFileTransfer.h @@ -1,37 +1,38 @@ /* - * Copyright (c) 2010-2015 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> + +#include <boost/signals2.hpp> #include <Swiften/Base/API.h> -#include <Swiften/Base/boost_bsignals.h> #include <Swiften/FileTransfer/FileTransfer.h> #include <Swiften/FileTransfer/FileTransferOptions.h> namespace Swift { - class WriteBytestream; - class JID; - - /** - * @brief The IncomingFileTransfer abstract class is the general interface in Swiften - * for incoming file transfers. - */ - class SWIFTEN_API IncomingFileTransfer : public FileTransfer { - public: - typedef boost::shared_ptr<IncomingFileTransfer> ref; - - virtual ~IncomingFileTransfer(); - - virtual void accept( - boost::shared_ptr<WriteBytestream>, - const FileTransferOptions& = FileTransferOptions()) = 0; - - virtual const JID& getSender() const = 0; - virtual const JID& getRecipient() const = 0; - }; + class WriteBytestream; + class JID; + + /** + * @brief The IncomingFileTransfer abstract class is the general interface in Swiften + * for incoming file transfers. + */ + class SWIFTEN_API IncomingFileTransfer : public FileTransfer { + public: + typedef std::shared_ptr<IncomingFileTransfer> ref; + + virtual ~IncomingFileTransfer(); + + virtual void accept( + std::shared_ptr<WriteBytestream>, + const FileTransferOptions& = FileTransferOptions()) = 0; + + virtual const JID& getSender() const = 0; + virtual const JID& getRecipient() const = 0; + }; } diff --git a/Swiften/FileTransfer/IncomingFileTransferManager.cpp b/Swiften/FileTransfer/IncomingFileTransferManager.cpp index f5b95ec..1c2b788 100644 --- a/Swiften/FileTransfer/IncomingFileTransferManager.cpp +++ b/Swiften/FileTransfer/IncomingFileTransferManager.cpp @@ -6,7 +6,7 @@ #include <Swiften/FileTransfer/IncomingFileTransferManager.h> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> #include <Swiften/Base/Log.h> #include <Swiften/Elements/JingleDescription.h> @@ -20,46 +20,46 @@ namespace Swift { IncomingFileTransferManager::IncomingFileTransferManager( - JingleSessionManager* jingleSessionManager, - FileTransferTransporterFactory* transporterFactory, - TimerFactory* timerFactory, - CryptoProvider* crypto) : - jingleSessionManager(jingleSessionManager), - transporterFactory(transporterFactory), - timerFactory(timerFactory), - crypto(crypto) { - jingleSessionManager->addIncomingSessionHandler(this); + JingleSessionManager* jingleSessionManager, + FileTransferTransporterFactory* transporterFactory, + TimerFactory* timerFactory, + CryptoProvider* crypto) : + jingleSessionManager(jingleSessionManager), + transporterFactory(transporterFactory), + timerFactory(timerFactory), + crypto(crypto) { + jingleSessionManager->addIncomingSessionHandler(this); } IncomingFileTransferManager::~IncomingFileTransferManager() { - jingleSessionManager->removeIncomingSessionHandler(this); + jingleSessionManager->removeIncomingSessionHandler(this); } bool IncomingFileTransferManager::handleIncomingJingleSession( - JingleSession::ref session, - const std::vector<JingleContentPayload::ref>& contents, - const JID& recipient) { - if (JingleContentPayload::ref content = Jingle::getContentWithDescription<JingleFileTransferDescription>(contents)) { - if (content->getTransport<JingleS5BTransportPayload>() || content->getTransport<JingleIBBTransportPayload>()) { - JingleFileTransferDescription::ref description = content->getDescription<JingleFileTransferDescription>(); - if (description) { - IncomingJingleFileTransfer::ref transfer = boost::make_shared<IncomingJingleFileTransfer>( - recipient, session, content, transporterFactory, timerFactory, crypto); - onIncomingFileTransfer(transfer); - } - else { - SWIFT_LOG(warning) << "Received a file-transfer request with no file description."; - session->sendTerminate(JinglePayload::Reason::FailedApplication); - } - } - else { - session->sendTerminate(JinglePayload::Reason::UnsupportedTransports); - } - return true; - } - else { - return false; - } + JingleSession::ref session, + const std::vector<JingleContentPayload::ref>& contents, + const JID& recipient) { + if (JingleContentPayload::ref content = Jingle::getContentWithDescription<JingleFileTransferDescription>(contents)) { + if (content->getTransport<JingleS5BTransportPayload>() || content->getTransport<JingleIBBTransportPayload>()) { + JingleFileTransferDescription::ref description = content->getDescription<JingleFileTransferDescription>(); + if (description) { + IncomingJingleFileTransfer::ref transfer = std::make_shared<IncomingJingleFileTransfer>( + recipient, session, content, transporterFactory, timerFactory, crypto); + onIncomingFileTransfer(transfer); + } + else { + SWIFT_LOG(warning) << "Received a file-transfer request with no file description."; + session->sendTerminate(JinglePayload::Reason::FailedApplication); + } + } + else { + session->sendTerminate(JinglePayload::Reason::UnsupportedTransports); + } + return true; + } + else { + return false; + } } diff --git a/Swiften/FileTransfer/IncomingFileTransferManager.h b/Swiften/FileTransfer/IncomingFileTransferManager.h index 285ff3f..a0cce10 100644 --- a/Swiften/FileTransfer/IncomingFileTransferManager.h +++ b/Swiften/FileTransfer/IncomingFileTransferManager.h @@ -1,45 +1,46 @@ /* - * Copyright (c) 2010-2015 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> + +#include <boost/signals2.hpp> #include <Swiften/Base/API.h> -#include <Swiften/Base/boost_bsignals.h> #include <Swiften/FileTransfer/IncomingFileTransfer.h> #include <Swiften/Jingle/IncomingJingleSessionHandler.h> namespace Swift { - class JingleSessionManager; - class FileTransferTransporterFactory; - class TimerFactory; - class CryptoProvider; - - class SWIFTEN_API IncomingFileTransferManager : public IncomingJingleSessionHandler { - public: - IncomingFileTransferManager( - JingleSessionManager* jingleSessionManager, - FileTransferTransporterFactory* transporterFactory, - TimerFactory* timerFactory, - CryptoProvider* crypto); - virtual ~IncomingFileTransferManager(); - - boost::signal<void (IncomingFileTransfer::ref)> onIncomingFileTransfer; - - private: - bool handleIncomingJingleSession( - JingleSession::ref session, - const std::vector<JingleContentPayload::ref>& contents, - const JID& recipient); - - private: - JingleSessionManager* jingleSessionManager; - FileTransferTransporterFactory* transporterFactory; - TimerFactory* timerFactory; - CryptoProvider* crypto; - }; + class JingleSessionManager; + class FileTransferTransporterFactory; + class TimerFactory; + class CryptoProvider; + + class SWIFTEN_API IncomingFileTransferManager : public IncomingJingleSessionHandler { + public: + IncomingFileTransferManager( + JingleSessionManager* jingleSessionManager, + FileTransferTransporterFactory* transporterFactory, + TimerFactory* timerFactory, + CryptoProvider* crypto); + virtual ~IncomingFileTransferManager(); + + boost::signals2::signal<void (IncomingFileTransfer::ref)> onIncomingFileTransfer; + + private: + bool handleIncomingJingleSession( + JingleSession::ref session, + const std::vector<JingleContentPayload::ref>& contents, + const JID& recipient); + + private: + JingleSessionManager* jingleSessionManager; + FileTransferTransporterFactory* transporterFactory; + TimerFactory* timerFactory; + CryptoProvider* crypto; + }; } diff --git a/Swiften/FileTransfer/IncomingJingleFileTransfer.cpp b/Swiften/FileTransfer/IncomingJingleFileTransfer.cpp index db17620..d5de5e4 100644 --- a/Swiften/FileTransfer/IncomingJingleFileTransfer.cpp +++ b/Swiften/FileTransfer/IncomingJingleFileTransfer.cpp @@ -6,13 +6,12 @@ #include <Swiften/FileTransfer/IncomingJingleFileTransfer.h> +#include <memory> #include <set> #include <boost/bind.hpp> -#include <boost/smart_ptr/make_shared.hpp> #include <Swiften/Base/Log.h> -#include <Swiften/Base/foreach.h> #include <Swiften/Elements/JingleFileTransferDescription.h> #include <Swiften/Elements/JingleFileTransferHash.h> #include <Swiften/Elements/JingleIBBTransportPayload.h> @@ -33,388 +32,388 @@ using namespace Swift; // TODO: ALlow terminate when already terminated. IncomingJingleFileTransfer::IncomingJingleFileTransfer( - const JID& toJID, - JingleSession::ref session, - JingleContentPayload::ref content, - FileTransferTransporterFactory* transporterFactory, - TimerFactory* timerFactory, - CryptoProvider* crypto) : - JingleFileTransfer(session, toJID, transporterFactory), - initialContent(content), - crypto(crypto), - state(Initial), - receivedBytes(0), - hashCalculator(NULL) { - description = initialContent->getDescription<JingleFileTransferDescription>(); - assert(description); - JingleFileTransferFileInfo fileInfo = description->getFileInfo(); - setFileInfo(fileInfo.getName(), fileInfo.getSize(), fileInfo.getDescription()); - hashes = fileInfo.getHashes(); - - waitOnHashTimer = timerFactory->createTimer(5000); - waitOnHashTimerTickedConnection = waitOnHashTimer->onTick.connect( - boost::bind(&IncomingJingleFileTransfer::handleWaitOnHashTimerTicked, this)); + const JID& toJID, + JingleSession::ref session, + JingleContentPayload::ref content, + FileTransferTransporterFactory* transporterFactory, + TimerFactory* timerFactory, + CryptoProvider* crypto) : + JingleFileTransfer(session, toJID, transporterFactory), + initialContent(content), + crypto(crypto), + state(Initial), + receivedBytes(0), + hashCalculator(nullptr) { + description = initialContent->getDescription<JingleFileTransferDescription>(); + assert(description); + JingleFileTransferFileInfo fileInfo = description->getFileInfo(); + setFileInfo(fileInfo.getName(), fileInfo.getSize(), fileInfo.getDescription()); + hashes = fileInfo.getHashes(); + + waitOnHashTimer = timerFactory->createTimer(5000); + waitOnHashTimerTickedConnection = waitOnHashTimer->onTick.connect( + boost::bind(&IncomingJingleFileTransfer::handleWaitOnHashTimerTicked, this)); } IncomingJingleFileTransfer::~IncomingJingleFileTransfer() { - if (waitOnHashTimer) { - waitOnHashTimer->stop(); - } + if (waitOnHashTimer) { + waitOnHashTimer->stop(); + } - delete hashCalculator; - hashCalculator = NULL; + delete hashCalculator; + hashCalculator = nullptr; } void IncomingJingleFileTransfer::accept( - boost::shared_ptr<WriteBytestream> stream, - const FileTransferOptions& options) { - SWIFT_LOG(debug) << std::endl; - if (state != Initial) { SWIFT_LOG(warning) << "Incorrect state" << std::endl; return; } - - assert(!this->stream); - this->stream = stream; - this->options = options; - - assert(!hashCalculator); - - hashCalculator = new IncrementalBytestreamHashCalculator( - hashes.find("md5") != hashes.end(), hashes.find("sha-1") != hashes.end(), crypto); - - writeStreamDataReceivedConnection = stream->onWrite.connect( - boost::bind(&IncomingJingleFileTransfer::handleWriteStreamDataReceived, this, _1)); - - JingleS5BTransportPayload::ref s5bTransport = initialContent->getTransport<JingleS5BTransportPayload>(); - JingleIBBTransportPayload::ref ibbTransport = initialContent->getTransport<JingleIBBTransportPayload>(); - if (s5bTransport) { - SWIFT_LOG(debug) << "Got S5B transport as initial payload." << std::endl; - setTransporter(transporterFactory->createResponderTransporter( - getInitiator(), getResponder(), s5bTransport->getSessionID(), options)); - transporter->addRemoteCandidates(s5bTransport->getCandidates(), s5bTransport->getDstAddr()); - setState(GeneratingInitialLocalCandidates); - transporter->startGeneratingLocalCandidates(); - } - else if (ibbTransport && options.isInBandAllowed()) { - SWIFT_LOG(debug) << "Got IBB transport as initial payload." << std::endl; - setTransporter(transporterFactory->createResponderTransporter( - getInitiator(), getResponder(), ibbTransport->getSessionID(), options)); - - startTransferring(transporter->createIBBReceiveSession( - ibbTransport->getSessionID(), - description->getFileInfo().getSize(), - stream)); - - session->sendAccept(getContentID(), initialContent->getDescriptions()[0], ibbTransport); - } - else { - // This might happen on incoming transfer which only list transport methods we are not allowed to use due to file-transfer options. - session->sendTerminate(JinglePayload::Reason::UnsupportedTransports); - setFinishedState(FileTransfer::State::Failed, FileTransferError(FileTransferError::PeerError)); - } + std::shared_ptr<WriteBytestream> stream, + const FileTransferOptions& options) { + SWIFT_LOG(debug) << std::endl; + if (state != Initial) { SWIFT_LOG(warning) << "Incorrect state" << std::endl; return; } + + assert(!this->stream); + this->stream = stream; + this->options = options; + + assert(!hashCalculator); + + hashCalculator = new IncrementalBytestreamHashCalculator( + hashes.find("md5") != hashes.end(), hashes.find("sha-1") != hashes.end(), crypto); + + writeStreamDataReceivedConnection = stream->onWrite.connect( + boost::bind(&IncomingJingleFileTransfer::handleWriteStreamDataReceived, this, _1)); + + JingleS5BTransportPayload::ref s5bTransport = initialContent->getTransport<JingleS5BTransportPayload>(); + JingleIBBTransportPayload::ref ibbTransport = initialContent->getTransport<JingleIBBTransportPayload>(); + if (s5bTransport) { + SWIFT_LOG(debug) << "Got S5B transport as initial payload." << std::endl; + setTransporter(transporterFactory->createResponderTransporter( + getInitiator(), getResponder(), s5bTransport->getSessionID(), options)); + transporter->addRemoteCandidates(s5bTransport->getCandidates(), s5bTransport->getDstAddr()); + setState(GeneratingInitialLocalCandidates); + transporter->startGeneratingLocalCandidates(); + } + else if (ibbTransport && options.isInBandAllowed()) { + SWIFT_LOG(debug) << "Got IBB transport as initial payload." << std::endl; + setTransporter(transporterFactory->createResponderTransporter( + getInitiator(), getResponder(), ibbTransport->getSessionID(), options)); + + startTransferring(transporter->createIBBReceiveSession( + ibbTransport->getSessionID(), + description->getFileInfo().getSize(), + stream)); + + session->sendAccept(getContentID(), initialContent->getDescriptions()[0], ibbTransport); + } + else { + // This might happen on incoming transfer which only list transport methods we are not allowed to use due to file-transfer options. + session->sendTerminate(JinglePayload::Reason::UnsupportedTransports); + setFinishedState(FileTransfer::State::Failed, FileTransferError(FileTransferError::PeerError)); + } } void IncomingJingleFileTransfer::cancel() { - SWIFT_LOG(debug) << std::endl; - terminate(state == Initial ? JinglePayload::Reason::Decline : JinglePayload::Reason::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::string& dstAddr) { - SWIFT_LOG(debug) << std::endl; - if (state != GeneratingInitialLocalCandidates) { SWIFT_LOG(warning) << "Incorrect state" << std::endl; return; } + 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); + 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); + JingleS5BTransportPayload::ref transport = std::make_shared<JingleS5BTransportPayload>(); + transport->setSessionID(s5bSessionID); + transport->setMode(JingleS5BTransportPayload::TCPMode); + transport->setDstAddr(dstAddr); + for (auto&& candidate : candidates) { + transport->addCandidate(candidate); + } + session->sendAccept(getContentID(), initialContent->getDescriptions()[0], transport); - setState(TryingCandidates); - transporter->startTryingRemoteCandidates(); + setState(TryingCandidates); + transporter->startTryingRemoteCandidates(); } void IncomingJingleFileTransfer::handleSessionInfoReceived(JinglePayload::ref jinglePayload) { - SWIFT_LOG(debug) << std::endl; - - JingleFileTransferHash::ref transferHash = jinglePayload->getPayload<JingleFileTransferHash>(); - if (transferHash) { - SWIFT_LOG(debug) << "Received hash information." << std::endl; - waitOnHashTimer->stop(); - if (transferHash->getFileInfo().getHashes().find("sha-1") != transferHash->getFileInfo().getHashes().end()) { - hashes["sha-1"] = transferHash->getFileInfo().getHash("sha-1").get(); - } - if (transferHash->getFileInfo().getHashes().find("md5") != transferHash->getFileInfo().getHashes().end()) { - hashes["md5"] = transferHash->getFileInfo().getHash("md5").get(); - } - if (state == WaitingForHash) { - checkHashAndTerminate(); - } - } - else { - SWIFT_LOG(debug) << "Ignoring unknown session info" << std::endl; - } + SWIFT_LOG(debug) << std::endl; + + JingleFileTransferHash::ref transferHash = jinglePayload->getPayload<JingleFileTransferHash>(); + if (transferHash) { + SWIFT_LOG(debug) << "Received hash information." << std::endl; + waitOnHashTimer->stop(); + if (transferHash->getFileInfo().getHashes().find("sha-1") != transferHash->getFileInfo().getHashes().end()) { + hashes["sha-1"] = transferHash->getFileInfo().getHash("sha-1").get(); + } + if (transferHash->getFileInfo().getHashes().find("md5") != transferHash->getFileInfo().getHashes().end()) { + hashes["md5"] = transferHash->getFileInfo().getHash("md5").get(); + } + if (state == WaitingForHash) { + checkHashAndTerminate(); + } + } + else { + SWIFT_LOG(debug) << "Ignoring unknown session info" << std::endl; + } } void IncomingJingleFileTransfer::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(debug) << "Already terminated" << 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) { - setFinishedState(FileTransfer::State::Finished, boost::optional<FileTransferError>()); - } - else { - setFinishedState(FileTransfer::State::Failed, FileTransferError(FileTransferError::PeerError)); - } + SWIFT_LOG(debug) << std::endl; + if (state == Finished) { SWIFT_LOG(warning) << "Incorrect state" << std::endl; return; } + + if (state == Finished) { + SWIFT_LOG(debug) << "Already terminated" << 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) { + setFinishedState(FileTransfer::State::Finished, boost::optional<FileTransferError>()); + } + else { + setFinishedState(FileTransfer::State::Failed, FileTransferError(FileTransferError::PeerError)); + } } void IncomingJingleFileTransfer::checkHashAndTerminate() { - if (verifyData()) { - terminate(JinglePayload::Reason::Success); - } - else { - SWIFT_LOG(warning) << "Hash verification failed" << std::endl; - terminate(JinglePayload::Reason::MediaError); - } + if (verifyData()) { + terminate(JinglePayload::Reason::Success); + } + else { + SWIFT_LOG(warning) << "Hash verification failed" << std::endl; + terminate(JinglePayload::Reason::MediaError); + } } void IncomingJingleFileTransfer::checkIfAllDataReceived() { - if (receivedBytes == getFileSizeInBytes()) { - SWIFT_LOG(debug) << "All data received." << std::endl; - bool hashInfoAvailable = false; - foreach(const JingleFileTransferFileInfo::HashElementMap::value_type& hashElement, hashes) { - hashInfoAvailable |= !hashElement.second.empty(); - } - - if (!hashInfoAvailable) { - SWIFT_LOG(debug) << "No hash information yet. Waiting a while on hash info." << std::endl; - setState(WaitingForHash); - waitOnHashTimer->start(); - } - else { - checkHashAndTerminate(); - } - } - else if (receivedBytes > getFileSizeInBytes()) { - SWIFT_LOG(debug) << "We got more than we could handle!" << std::endl; - terminate(JinglePayload::Reason::MediaError); - } + if (receivedBytes == getFileSizeInBytes()) { + SWIFT_LOG(debug) << "All data received." << std::endl; + bool hashInfoAvailable = false; + for (const auto& hashElement : hashes) { + hashInfoAvailable |= !hashElement.second.empty(); + } + + if (!hashInfoAvailable) { + SWIFT_LOG(debug) << "No hash information yet. Waiting a while on hash info." << std::endl; + setState(WaitingForHash); + waitOnHashTimer->start(); + } + else { + checkHashAndTerminate(); + } + } + else if (receivedBytes > getFileSizeInBytes()) { + SWIFT_LOG(debug) << "We got more than we could handle!" << std::endl; + terminate(JinglePayload::Reason::MediaError); + } } void IncomingJingleFileTransfer::handleWriteStreamDataReceived( - const std::vector<unsigned char>& data) { - hashCalculator->feedData(data); - receivedBytes += data.size(); - onProcessedBytes(data.size()); - checkIfAllDataReceived(); + const std::vector<unsigned char>& data) { + hashCalculator->feedData(data); + receivedBytes += data.size(); + onProcessedBytes(data.size()); + checkIfAllDataReceived(); } void IncomingJingleFileTransfer::handleTransportReplaceReceived( - const JingleContentID& content, JingleTransportPayload::ref transport) { - SWIFT_LOG(debug) << std::endl; - if (state != WaitingForFallbackOrTerminate) { - SWIFT_LOG(warning) << "Incorrect state" << std::endl; - return; - } - - 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)); - session->sendTransportAccept(content, ibbTransport); - } - else { - SWIFT_LOG(debug) << "Unknown replace transport" << std::endl; - session->sendTransportReject(content, transport); - } + const JingleContentID& content, JingleTransportPayload::ref transport) { + SWIFT_LOG(debug) << std::endl; + if (state != WaitingForFallbackOrTerminate) { + SWIFT_LOG(warning) << "Incorrect state" << std::endl; + return; + } + + JingleIBBTransportPayload::ref ibbTransport; + if (options.isInBandAllowed() && (ibbTransport = std::dynamic_pointer_cast<JingleIBBTransportPayload>(transport))) { + SWIFT_LOG(debug) << "transport replaced with IBB" << std::endl; + + startTransferring(transporter->createIBBReceiveSession( + ibbTransport->getSessionID(), + description->getFileInfo().getSize(), + stream)); + session->sendTransportAccept(content, ibbTransport); + } + else { + SWIFT_LOG(debug) << "Unknown replace transport" << std::endl; + session->sendTransportReject(content, transport); + } } JingleContentID IncomingJingleFileTransfer::getContentID() const { - return JingleContentID(initialContent->getName(), initialContent->getCreator()); + return JingleContentID(initialContent->getName(), initialContent->getCreator()); } bool IncomingJingleFileTransfer::verifyData() { - if (hashes.empty()) { - SWIFT_LOG(debug) << "no verification possible, skipping" << std::endl; - return true; - } - if (hashes.find("sha-1") != hashes.end()) { - SWIFT_LOG(debug) << "Verify SHA-1 hash: " << (hashes["sha-1"] == hashCalculator->getSHA1Hash()) << std::endl; - return hashes["sha-1"] == hashCalculator->getSHA1Hash(); - } - else if (hashes.find("md5") != hashes.end()) { - SWIFT_LOG(debug) << "Verify MD5 hash: " << (hashes["md5"] == hashCalculator->getMD5Hash()) << std::endl; - return hashes["md5"] == hashCalculator->getMD5Hash(); - } - else { - SWIFT_LOG(debug) << "Unknown hash, skipping" << std::endl; - return true; - } + if (hashes.empty()) { + SWIFT_LOG(debug) << "no verification possible, skipping" << std::endl; + return true; + } + if (hashes.find("sha-1") != hashes.end()) { + SWIFT_LOG(debug) << "Verify SHA-1 hash: " << (hashes["sha-1"] == hashCalculator->getSHA1Hash()) << std::endl; + return hashes["sha-1"] == hashCalculator->getSHA1Hash(); + } + else if (hashes.find("md5") != hashes.end()) { + SWIFT_LOG(debug) << "Verify MD5 hash: " << (hashes["md5"] == hashCalculator->getMD5Hash()) << std::endl; + return hashes["md5"] == hashCalculator->getMD5Hash(); + } + else { + SWIFT_LOG(debug) << "Unknown hash, skipping" << std::endl; + return true; + } } void IncomingJingleFileTransfer::handleWaitOnHashTimerTicked() { - SWIFT_LOG(debug) << std::endl; - waitOnHashTimer->stop(); - terminate(JinglePayload::Reason::Success); + SWIFT_LOG(debug) << std::endl; + waitOnHashTimer->stop(); + terminate(JinglePayload::Reason::Success); } const JID& IncomingJingleFileTransfer::getSender() const { - return getInitiator(); + return getInitiator(); } const JID& IncomingJingleFileTransfer::getRecipient() const { - return getResponder(); + return getResponder(); } void IncomingJingleFileTransfer::setState(State state) { - SWIFT_LOG(debug) << state << std::endl; - this->state = state; - onStateChanged(FileTransfer::State(getExternalState(state))); + SWIFT_LOG(debug) << state << std::endl; + this->state = state; + onStateChanged(FileTransfer::State(getExternalState(state))); } void IncomingJingleFileTransfer::setFinishedState( - FileTransfer::State::Type type, const boost::optional<FileTransferError>& error) { - SWIFT_LOG(debug) << std::endl; - this->state = Finished; - onStateChanged(type); - onFinished(error); + FileTransfer::State::Type type, const boost::optional<FileTransferError>& error) { + SWIFT_LOG(debug) << std::endl; + this->state = Finished; + onStateChanged(type); + onFinished(error); } void IncomingJingleFileTransfer::handleTransferFinished(boost::optional<FileTransferError> error) { - if (error && state != WaitingForHash) { - terminate(JinglePayload::Reason::MediaError); - } + if (error && state != WaitingForHash) { + terminate(JinglePayload::Reason::MediaError); + } } FileTransfer::State::Type IncomingJingleFileTransfer::getExternalState(State state) { - switch (state) { - case Initial: return FileTransfer::State::Initial; - case GeneratingInitialLocalCandidates: return FileTransfer::State::WaitingForStart; - case TryingCandidates: return FileTransfer::State::Negotiating; - case WaitingForPeerProxyActivate: return FileTransfer::State::Negotiating; - case WaitingForLocalProxyActivate: return FileTransfer::State::Negotiating; - case WaitingForFallbackOrTerminate: return FileTransfer::State::Negotiating; - case Transferring: return FileTransfer::State::Transferring; - case WaitingForHash: return FileTransfer::State::Transferring; - case Finished: return FileTransfer::State::Finished; - } - assert(false); - return FileTransfer::State::Initial; + switch (state) { + case Initial: return FileTransfer::State::Initial; + case GeneratingInitialLocalCandidates: return FileTransfer::State::WaitingForStart; + case TryingCandidates: return FileTransfer::State::Negotiating; + case WaitingForPeerProxyActivate: return FileTransfer::State::Negotiating; + case WaitingForLocalProxyActivate: return FileTransfer::State::Negotiating; + case WaitingForFallbackOrTerminate: return FileTransfer::State::Negotiating; + case Transferring: return FileTransfer::State::Transferring; + case WaitingForHash: return FileTransfer::State::Transferring; + case Finished: return FileTransfer::State::Finished; + } + assert(false); + return FileTransfer::State::Initial; } void IncomingJingleFileTransfer::stopAll() { - if (state != Initial) { - writeStreamDataReceivedConnection.disconnect(); - delete hashCalculator; - hashCalculator = NULL; - } - switch (state) { - case Initial: break; - case GeneratingInitialLocalCandidates: transporter->stopGeneratingLocalCandidates(); break; - case TryingCandidates: transporter->stopTryingRemoteCandidates(); break; - case WaitingForFallbackOrTerminate: break; - case WaitingForPeerProxyActivate: break; - case WaitingForLocalProxyActivate: transporter->stopActivatingProxy(); break; - case WaitingForHash: // Fallthrough - case Transferring: - assert(transportSession); - transferFinishedConnection.disconnect(); - transportSession->stop(); - transportSession.reset(); - break; - case Finished: SWIFT_LOG(warning) << "Already finished" << std::endl; break; - } - if (state != Initial) { - removeTransporter(); - } + if (state != Initial) { + writeStreamDataReceivedConnection.disconnect(); + delete hashCalculator; + hashCalculator = nullptr; + } + switch (state) { + case Initial: break; + case GeneratingInitialLocalCandidates: transporter->stopGeneratingLocalCandidates(); break; + case TryingCandidates: transporter->stopTryingRemoteCandidates(); break; + case WaitingForFallbackOrTerminate: break; + case WaitingForPeerProxyActivate: break; + case WaitingForLocalProxyActivate: transporter->stopActivatingProxy(); break; + case WaitingForHash: // Fallthrough + case Transferring: + assert(transportSession); + transferFinishedConnection.disconnect(); + transportSession->stop(); + transportSession.reset(); + break; + case Finished: SWIFT_LOG(warning) << "Already finished" << std::endl; break; + } + if (state != Initial) { + removeTransporter(); + } } bool IncomingJingleFileTransfer::hasPriorityOnCandidateTie() const { - return false; + return false; } void IncomingJingleFileTransfer::fallback() { - setState(WaitingForFallbackOrTerminate); + setState(WaitingForFallbackOrTerminate); } void IncomingJingleFileTransfer::startTransferViaRemoteCandidate() { - SWIFT_LOG(debug) << std::endl; + SWIFT_LOG(debug) << std::endl; - if (ourCandidateChoice->type == JingleS5BTransportPayload::Candidate::ProxyType) { - setState(WaitingForPeerProxyActivate); - } - else { - startTransferring(createRemoteCandidateSession()); - } + if (ourCandidateChoice->type == JingleS5BTransportPayload::Candidate::ProxyType) { + setState(WaitingForPeerProxyActivate); + } + else { + startTransferring(createRemoteCandidateSession()); + } } void IncomingJingleFileTransfer::startTransferViaLocalCandidate() { - SWIFT_LOG(debug) << std::endl; + SWIFT_LOG(debug) << std::endl; - if (theirCandidateChoice->type == JingleS5BTransportPayload::Candidate::ProxyType) { - setState(WaitingForLocalProxyActivate); - transporter->startActivatingProxy(theirCandidateChoice->jid); - } - else { - startTransferring(createLocalCandidateSession()); - } + if (theirCandidateChoice->type == JingleS5BTransportPayload::Candidate::ProxyType) { + setState(WaitingForLocalProxyActivate); + transporter->startActivatingProxy(theirCandidateChoice->jid); + } + else { + startTransferring(createLocalCandidateSession()); + } } -void IncomingJingleFileTransfer::startTransferring(boost::shared_ptr<TransportSession> transportSession) { - SWIFT_LOG(debug) << std::endl; +void IncomingJingleFileTransfer::startTransferring(std::shared_ptr<TransportSession> transportSession) { + SWIFT_LOG(debug) << std::endl; - this->transportSession = transportSession; - transferFinishedConnection = transportSession->onFinished.connect( - boost::bind(&IncomingJingleFileTransfer::handleTransferFinished, this, _1)); - setState(Transferring); - transportSession->start(); + this->transportSession = transportSession; + transferFinishedConnection = transportSession->onFinished.connect( + boost::bind(&IncomingJingleFileTransfer::handleTransferFinished, this, _1)); + setState(Transferring); + transportSession->start(); } bool IncomingJingleFileTransfer::isWaitingForPeerProxyActivate() const { - return state == WaitingForPeerProxyActivate; + return state == WaitingForPeerProxyActivate; } bool IncomingJingleFileTransfer::isWaitingForLocalProxyActivate() const { - return state == WaitingForLocalProxyActivate; + return state == WaitingForLocalProxyActivate; } bool IncomingJingleFileTransfer::isTryingCandidates() const { - return state == TryingCandidates; + return state == TryingCandidates; } -boost::shared_ptr<TransportSession> IncomingJingleFileTransfer::createLocalCandidateSession() { - return transporter->createLocalCandidateSession(stream, theirCandidateChoice.get()); +std::shared_ptr<TransportSession> IncomingJingleFileTransfer::createLocalCandidateSession() { + return transporter->createLocalCandidateSession(stream, theirCandidateChoice.get()); } -boost::shared_ptr<TransportSession> IncomingJingleFileTransfer::createRemoteCandidateSession() { - return transporter->createRemoteCandidateSession(stream, ourCandidateChoice.get()); +std::shared_ptr<TransportSession> IncomingJingleFileTransfer::createRemoteCandidateSession() { + return transporter->createRemoteCandidateSession(stream, ourCandidateChoice.get()); } void IncomingJingleFileTransfer::terminate(JinglePayload::Reason::Type reason) { - SWIFT_LOG(debug) << reason << std::endl; + SWIFT_LOG(debug) << reason << std::endl; - if (state != Finished) { - session->sendTerminate(reason); - } - stopAll(); - setFinishedState(getExternalFinishedState(reason), getFileTransferError(reason)); + if (state != Finished) { + session->sendTerminate(reason); + } + stopAll(); + setFinishedState(getExternalFinishedState(reason), getFileTransferError(reason)); } diff --git a/Swiften/FileTransfer/IncomingJingleFileTransfer.h b/Swiften/FileTransfer/IncomingJingleFileTransfer.h index e30db5e..3dd206d 100644 --- a/Swiften/FileTransfer/IncomingJingleFileTransfer.h +++ b/Swiften/FileTransfer/IncomingJingleFileTransfer.h @@ -1,128 +1,129 @@ /* - * Copyright (c) 2010-2015 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> -#include <boost/cstdint.hpp> +#include <memory> #include <string> +#include <boost/cstdint.hpp> + #include <Swiften/Base/API.h> +#include <Swiften/Base/ByteArray.h> #include <Swiften/Base/Override.h> -#include <Swiften/Jingle/JingleContentID.h> -#include <Swiften/FileTransfer/IncomingFileTransfer.h> -#include <Swiften/FileTransfer/JingleFileTransfer.h> #include <Swiften/Elements/JingleS5BTransportPayload.h> #include <Swiften/FileTransfer/FileTransferOptions.h> -#include <Swiften/Base/ByteArray.h> +#include <Swiften/FileTransfer/IncomingFileTransfer.h> +#include <Swiften/FileTransfer/JingleFileTransfer.h> +#include <Swiften/Jingle/JingleContentID.h> namespace Swift { - class JID; - class JingleSession; - class JingleContentPayload; - class FileTransferTransporter; - class FileTransferTransporterFactory; - class TimerFactory; - class Timer; - class CryptoProvider; - class IncrementalBytestreamHashCalculator; - class JingleFileTransferDescription; - class HashElement; - - /** - * @brief The IncomingJingleFileTransfer class contains the business logic for managing incoming - * Jingle file transfers. - * - * Calling IncomingJingleFileTransfer::accept will start to negotiate possible transfer - * methods and after a working method has been decided among peers the trasnfer is started. - */ - class SWIFTEN_API IncomingJingleFileTransfer : public IncomingFileTransfer, public JingleFileTransfer { - public: - typedef boost::shared_ptr<IncomingJingleFileTransfer> ref; - - IncomingJingleFileTransfer( - const JID& recipient, - boost::shared_ptr<JingleSession>, - boost::shared_ptr<JingleContentPayload> content, - FileTransferTransporterFactory*, - TimerFactory*, - CryptoProvider*); - virtual ~IncomingJingleFileTransfer(); - - virtual void accept(boost::shared_ptr<WriteBytestream>, const FileTransferOptions& = FileTransferOptions()) SWIFTEN_OVERRIDE; - virtual void cancel() SWIFTEN_OVERRIDE; - - private: - enum State { - Initial, - GeneratingInitialLocalCandidates, - TryingCandidates, - WaitingForPeerProxyActivate, - WaitingForLocalProxyActivate, - WaitingForFallbackOrTerminate, - Transferring, - WaitingForHash, - Finished - }; - - virtual void handleSessionTerminateReceived( - boost::optional<JinglePayload::Reason> reason) SWIFTEN_OVERRIDE; - 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>&, - 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(); - bool verifyData(); - void handleWaitOnHashTimerTicked(); - void handleTransferFinished(boost::optional<FileTransferError>); - - private: - virtual void startTransferViaRemoteCandidate() SWIFTEN_OVERRIDE; - virtual void startTransferViaLocalCandidate() SWIFTEN_OVERRIDE; - void checkHashAndTerminate(); - void stopAll(); - void setState(State state); - void setFinishedState(FileTransfer::State::Type, const boost::optional<FileTransferError>& error); - const JID& getSender() const SWIFTEN_OVERRIDE; - const JID& getRecipient() const SWIFTEN_OVERRIDE; - static FileTransfer::State::Type getExternalState(State state); - virtual bool hasPriorityOnCandidateTie() const SWIFTEN_OVERRIDE; - virtual void fallback() SWIFTEN_OVERRIDE; - virtual void startTransferring(boost::shared_ptr<TransportSession>) SWIFTEN_OVERRIDE; - virtual bool isWaitingForPeerProxyActivate() const SWIFTEN_OVERRIDE; - virtual bool isWaitingForLocalProxyActivate() const SWIFTEN_OVERRIDE; - virtual bool isTryingCandidates() const SWIFTEN_OVERRIDE; - virtual boost::shared_ptr<TransportSession> createLocalCandidateSession() SWIFTEN_OVERRIDE; - virtual boost::shared_ptr<TransportSession> createRemoteCandidateSession() SWIFTEN_OVERRIDE; - virtual void terminate(JinglePayload::Reason::Type reason) SWIFTEN_OVERRIDE; - - - private: - boost::shared_ptr<JingleContentPayload> initialContent; - CryptoProvider* crypto; - State state; - boost::shared_ptr<JingleFileTransferDescription> description; - boost::shared_ptr<WriteBytestream> stream; - boost::uintmax_t receivedBytes; - IncrementalBytestreamHashCalculator* hashCalculator; - boost::shared_ptr<Timer> waitOnHashTimer; - std::map<std::string, ByteArray> hashes; - FileTransferOptions options; - - boost::bsignals::scoped_connection writeStreamDataReceivedConnection; - boost::bsignals::scoped_connection waitOnHashTimerTickedConnection; - boost::bsignals::connection transferFinishedConnection; - }; + class JID; + class JingleSession; + class JingleContentPayload; + class FileTransferTransporter; + class FileTransferTransporterFactory; + class TimerFactory; + class Timer; + class CryptoProvider; + class IncrementalBytestreamHashCalculator; + class JingleFileTransferDescription; + class HashElement; + + /** + * @brief The IncomingJingleFileTransfer class contains the business logic for managing incoming + * Jingle file transfers. + * + * Calling IncomingJingleFileTransfer::accept will start to negotiate possible transfer + * methods and after a working method has been decided among peers the trasnfer is started. + */ + class SWIFTEN_API IncomingJingleFileTransfer : public IncomingFileTransfer, public JingleFileTransfer { + public: + typedef std::shared_ptr<IncomingJingleFileTransfer> ref; + + IncomingJingleFileTransfer( + const JID& recipient, + std::shared_ptr<JingleSession>, + std::shared_ptr<JingleContentPayload> content, + FileTransferTransporterFactory*, + TimerFactory*, + CryptoProvider*); + virtual ~IncomingJingleFileTransfer(); + + virtual void accept(std::shared_ptr<WriteBytestream>, const FileTransferOptions& = FileTransferOptions()) SWIFTEN_OVERRIDE; + virtual void cancel() SWIFTEN_OVERRIDE; + + private: + enum State { + Initial, + GeneratingInitialLocalCandidates, + TryingCandidates, + WaitingForPeerProxyActivate, + WaitingForLocalProxyActivate, + WaitingForFallbackOrTerminate, + Transferring, + WaitingForHash, + Finished + }; + + virtual void handleSessionTerminateReceived( + boost::optional<JinglePayload::Reason> reason) SWIFTEN_OVERRIDE; + virtual void handleSessionInfoReceived(std::shared_ptr<JinglePayload>) SWIFTEN_OVERRIDE; + virtual void handleTransportReplaceReceived( + const JingleContentID&, std::shared_ptr<JingleTransportPayload>) SWIFTEN_OVERRIDE; + + virtual void handleLocalTransportCandidatesGenerated( + const std::string& s5bSessionID, + 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(); + bool verifyData(); + void handleWaitOnHashTimerTicked(); + void handleTransferFinished(boost::optional<FileTransferError>); + + private: + virtual void startTransferViaRemoteCandidate() SWIFTEN_OVERRIDE; + virtual void startTransferViaLocalCandidate() SWIFTEN_OVERRIDE; + void checkHashAndTerminate(); + void stopAll(); + void setState(State state); + void setFinishedState(FileTransfer::State::Type, const boost::optional<FileTransferError>& error); + const JID& getSender() const SWIFTEN_OVERRIDE; + const JID& getRecipient() const SWIFTEN_OVERRIDE; + static FileTransfer::State::Type getExternalState(State state); + virtual bool hasPriorityOnCandidateTie() const SWIFTEN_OVERRIDE; + virtual void fallback() SWIFTEN_OVERRIDE; + virtual void startTransferring(std::shared_ptr<TransportSession>) SWIFTEN_OVERRIDE; + virtual bool isWaitingForPeerProxyActivate() const SWIFTEN_OVERRIDE; + virtual bool isWaitingForLocalProxyActivate() const SWIFTEN_OVERRIDE; + virtual bool isTryingCandidates() const SWIFTEN_OVERRIDE; + virtual std::shared_ptr<TransportSession> createLocalCandidateSession() SWIFTEN_OVERRIDE; + virtual std::shared_ptr<TransportSession> createRemoteCandidateSession() SWIFTEN_OVERRIDE; + virtual void terminate(JinglePayload::Reason::Type reason) SWIFTEN_OVERRIDE; + + + private: + std::shared_ptr<JingleContentPayload> initialContent; + CryptoProvider* crypto; + State state; + std::shared_ptr<JingleFileTransferDescription> description; + std::shared_ptr<WriteBytestream> stream; + boost::uintmax_t receivedBytes; + IncrementalBytestreamHashCalculator* hashCalculator; + std::shared_ptr<Timer> waitOnHashTimer; + std::map<std::string, ByteArray> hashes; + FileTransferOptions options; + + boost::signals2::scoped_connection writeStreamDataReceivedConnection; + boost::signals2::scoped_connection waitOnHashTimerTickedConnection; + boost::signals2::connection transferFinishedConnection; + }; } diff --git a/Swiften/FileTransfer/IncrementalBytestreamHashCalculator.cpp b/Swiften/FileTransfer/IncrementalBytestreamHashCalculator.cpp index 7eb9560..f177304 100644 --- a/Swiften/FileTransfer/IncrementalBytestreamHashCalculator.cpp +++ b/Swiften/FileTransfer/IncrementalBytestreamHashCalculator.cpp @@ -5,7 +5,7 @@ */ /* - * Copyright (c) 2013-2014 Isode Limited. + * Copyright (c) 2013-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ @@ -13,63 +13,63 @@ #include <Swiften/FileTransfer/IncrementalBytestreamHashCalculator.h> -#include <Swiften/StringCodecs/Hexify.h> #include <Swiften/Crypto/CryptoProvider.h> +#include <Swiften/StringCodecs/Hexify.h> namespace Swift { IncrementalBytestreamHashCalculator::IncrementalBytestreamHashCalculator(bool doMD5, bool doSHA1, CryptoProvider* crypto) { - md5Hasher = doMD5 ? crypto->createMD5() : NULL; - sha1Hasher = doSHA1 ? crypto->createSHA1() : NULL; + md5Hasher = doMD5 ? crypto->createMD5() : nullptr; + sha1Hasher = doSHA1 ? crypto->createSHA1() : nullptr; } IncrementalBytestreamHashCalculator::~IncrementalBytestreamHashCalculator() { - delete md5Hasher; - delete sha1Hasher; + delete md5Hasher; + delete sha1Hasher; } void IncrementalBytestreamHashCalculator::feedData(const ByteArray& data) { - if (md5Hasher) { - md5Hasher->update(data); - } - if (sha1Hasher) { - sha1Hasher->update(data); - } + if (md5Hasher) { + md5Hasher->update(data); + } + if (sha1Hasher) { + sha1Hasher->update(data); + } } /* void IncrementalBytestreamHashCalculator::feedData(const SafeByteArray& data) { - if (md5Hasher) { - md5Hasher->update(createByteArray(data.data(), data.size())); - } - if (sha1Hasher) { - sha1Hasher->update(createByteArray(data.data(), data.size())); - } + if (md5Hasher) { + md5Hasher->update(createByteArray(data.data(), data.size())); + } + if (sha1Hasher) { + sha1Hasher->update(createByteArray(data.data(), data.size())); + } }*/ ByteArray IncrementalBytestreamHashCalculator::getSHA1Hash() { - assert(sha1Hasher); - if (!sha1Hash) { - sha1Hash = sha1Hasher->getHash(); - } - return *sha1Hash; + assert(sha1Hasher); + if (!sha1Hash) { + sha1Hash = sha1Hasher->getHash(); + } + return *sha1Hash; } ByteArray IncrementalBytestreamHashCalculator::getMD5Hash() { - assert(md5Hasher); - if (!md5Hash) { - md5Hash = md5Hasher->getHash(); - } - return *md5Hash; + assert(md5Hasher); + if (!md5Hash) { + md5Hash = md5Hasher->getHash(); + } + return *md5Hash; } std::string IncrementalBytestreamHashCalculator::getSHA1String() { - assert(sha1Hasher); - return Hexify::hexify(getSHA1Hash());; + assert(sha1Hasher); + return Hexify::hexify(getSHA1Hash());; } std::string IncrementalBytestreamHashCalculator::getMD5String() { - assert(md5Hasher); - return Hexify::hexify(getMD5Hash());; + assert(md5Hasher); + return Hexify::hexify(getMD5Hash());; } } diff --git a/Swiften/FileTransfer/IncrementalBytestreamHashCalculator.h b/Swiften/FileTransfer/IncrementalBytestreamHashCalculator.h index bc4ebf9..4477ec1 100644 --- a/Swiften/FileTransfer/IncrementalBytestreamHashCalculator.h +++ b/Swiften/FileTransfer/IncrementalBytestreamHashCalculator.h @@ -5,7 +5,7 @@ */ /* - * Copyright (c) 2013-2014 Isode Limited. + * Copyright (c) 2013-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ @@ -14,33 +14,34 @@ #include <string> +#include <boost/optional.hpp> + #include <Swiften/Base/ByteArray.h> #include <Swiften/Base/SafeByteArray.h> -#include <boost/optional.hpp> namespace Swift { - class Hash; - class CryptoProvider; + class Hash; + class CryptoProvider; - class IncrementalBytestreamHashCalculator { - public: - IncrementalBytestreamHashCalculator(bool doMD5, bool doSHA1, CryptoProvider* crypto); - ~IncrementalBytestreamHashCalculator(); + class IncrementalBytestreamHashCalculator { + public: + IncrementalBytestreamHashCalculator(bool doMD5, bool doSHA1, CryptoProvider* crypto); + ~IncrementalBytestreamHashCalculator(); - void feedData(const ByteArray& data); - //void feedData(const SafeByteArray& data); + void feedData(const ByteArray& data); + //void feedData(const SafeByteArray& data); - ByteArray getSHA1Hash(); - ByteArray getMD5Hash(); + ByteArray getSHA1Hash(); + ByteArray getMD5Hash(); - std::string getSHA1String(); - std::string getMD5String(); + std::string getSHA1String(); + std::string getMD5String(); - private: - Hash* md5Hasher; - Hash* sha1Hasher; - boost::optional<ByteArray> md5Hash; - boost::optional<ByteArray> sha1Hash; - }; + private: + Hash* md5Hasher; + Hash* sha1Hasher; + boost::optional<ByteArray> md5Hash; + boost::optional<ByteArray> sha1Hash; + }; } diff --git a/Swiften/FileTransfer/JingleFileTransfer.cpp b/Swiften/FileTransfer/JingleFileTransfer.cpp index cf67a67..62c3a53 100644 --- a/Swiften/FileTransfer/JingleFileTransfer.cpp +++ b/Swiften/FileTransfer/JingleFileTransfer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015 Isode Limited. + * Copyright (c) 2013-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ @@ -9,7 +9,6 @@ #include <boost/typeof/typeof.hpp> #include <Swiften/Base/Log.h> -#include <Swiften/Base/foreach.h> #include <Swiften/Crypto/CryptoProvider.h> #include <Swiften/FileTransfer/FileTransferTransporter.h> #include <Swiften/JID/JID.h> @@ -19,217 +18,217 @@ using namespace Swift; JingleFileTransfer::JingleFileTransfer( - boost::shared_ptr<JingleSession> session, - const JID& target, - FileTransferTransporterFactory* transporterFactory) : - session(session), - target(target), - transporterFactory(transporterFactory), - transporter(NULL), - ourCandidateSelectFinished(false), - theirCandidateSelectFinished(false) { - - session->addListener(this); + std::shared_ptr<JingleSession> session, + const JID& target, + FileTransferTransporterFactory* transporterFactory) : + session(session), + target(target), + transporterFactory(transporterFactory), + transporter(nullptr), + ourCandidateSelectFinished(false), + theirCandidateSelectFinished(false) { + + session->addListener(this); } JingleFileTransfer::~JingleFileTransfer() { - session->removeListener(this); + session->removeListener(this); } void JingleFileTransfer::fillCandidateMap(CandidateMap& map, const std::vector<JingleS5BTransportPayload::Candidate>& candidates) { - map.clear(); - foreach (JingleS5BTransportPayload::Candidate candidate, candidates) { - map[candidate.cid] = candidate; - } + map.clear(); + for (auto&& candidate : candidates) { + map[candidate.cid] = candidate; + } } /* std::string JingleFileTransfer::getS5BDstAddr(const JID& requester, const JID& target) const { - return Hexify::hexify(crypto->getSHA1Hash( - createSafeByteArray(s5bSessionID + requester.toString() + target.toString()))); + return Hexify::hexify(crypto->getSHA1Hash( + createSafeByteArray(s5bSessionID + requester.toString() + target.toString()))); } */ const JID& JingleFileTransfer::getInitiator() const { - return session->getInitiator(); + return session->getInitiator(); } const JID& JingleFileTransfer::getResponder() const { - return target; + return target; } FileTransfer::State::Type JingleFileTransfer::getExternalFinishedState(JinglePayload::Reason::Type reason) { - if (reason == JinglePayload::Reason::Cancel || reason == JinglePayload::Reason::Decline) { - return FileTransfer::State::Canceled; - } - else if (reason == JinglePayload::Reason::Success) { - return FileTransfer::State::Finished; - } - else { - return FileTransfer::State::Failed; - } + if (reason == JinglePayload::Reason::Cancel || reason == JinglePayload::Reason::Decline) { + return FileTransfer::State::Canceled; + } + else if (reason == JinglePayload::Reason::Success) { + return FileTransfer::State::Finished; + } + else { + return FileTransfer::State::Failed; + } } boost::optional<FileTransferError> JingleFileTransfer::getFileTransferError(JinglePayload::Reason::Type reason) { - if (reason == JinglePayload::Reason::Success) { - return boost::optional<FileTransferError>(); - } - else { - return boost::optional<FileTransferError>(FileTransferError::UnknownError); - } + if (reason == JinglePayload::Reason::Success) { + return boost::optional<FileTransferError>(); + } + else { + return boost::optional<FileTransferError>(FileTransferError::UnknownError); + } } void JingleFileTransfer::handleRemoteTransportCandidateSelectFinished( - const std::string& s5bSessionID, const boost::optional<JingleS5BTransportPayload::Candidate>& candidate) { - SWIFT_LOG(debug) << std::endl; - - ourCandidateChoice = candidate; - ourCandidateSelectFinished = true; - - JingleS5BTransportPayload::ref s5bPayload = boost::make_shared<JingleS5BTransportPayload>(); - s5bPayload->setSessionID(s5bSessionID); - if (candidate) { - s5bPayload->setCandidateUsed(candidate->cid); - } - else { - s5bPayload->setCandidateError(true); - } - candidateSelectRequestID = session->sendTransportInfo(getContentID(), s5bPayload); - - decideOnCandidates(); + const std::string& s5bSessionID, const boost::optional<JingleS5BTransportPayload::Candidate>& candidate) { + SWIFT_LOG(debug) << std::endl; + + ourCandidateChoice = candidate; + ourCandidateSelectFinished = true; + + JingleS5BTransportPayload::ref s5bPayload = std::make_shared<JingleS5BTransportPayload>(); + s5bPayload->setSessionID(s5bSessionID); + if (candidate) { + s5bPayload->setCandidateUsed(candidate->cid); + } + else { + s5bPayload->setCandidateError(true); + } + candidateSelectRequestID = session->sendTransportInfo(getContentID(), s5bPayload); + + decideOnCandidates(); } // decide on candidates according to http://xmpp.org/extensions/xep-0260.html#complete void JingleFileTransfer::decideOnCandidates() { - SWIFT_LOG(debug) << std::endl; - if (!ourCandidateSelectFinished || !theirCandidateSelectFinished) { - SWIFT_LOG(debug) << "Can't make a decision yet!" << std::endl; - return; - } - 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(); - } - } - } + SWIFT_LOG(debug) << std::endl; + if (!ourCandidateSelectFinished || !theirCandidateSelectFinished) { + SWIFT_LOG(debug) << "Can't make a decision yet!" << std::endl; + return; + } + 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(); + } + } + } } void JingleFileTransfer::handleProxyActivateFinished( - const std::string& s5bSessionID, ErrorPayload::ref error) { - SWIFT_LOG(debug) << std::endl; - if (!isWaitingForLocalProxyActivate()) { SWIFT_LOG(warning) << "Incorrect state" << std::endl; return; } - - if (error) { - SWIFT_LOG(debug) << "Error activating proxy" << std::endl; - JingleS5BTransportPayload::ref proxyError = boost::make_shared<JingleS5BTransportPayload>(); - proxyError->setSessionID(s5bSessionID); - proxyError->setProxyError(true); - session->sendTransportInfo(getContentID(), proxyError); - fallback(); - } - else { - JingleS5BTransportPayload::ref proxyActivate = boost::make_shared<JingleS5BTransportPayload>(); - proxyActivate->setSessionID(s5bSessionID); - proxyActivate->setActivated(theirCandidateChoice->cid); - session->sendTransportInfo(getContentID(), proxyActivate); - startTransferring(createLocalCandidateSession()); - } + const std::string& s5bSessionID, ErrorPayload::ref error) { + SWIFT_LOG(debug) << std::endl; + if (!isWaitingForLocalProxyActivate()) { SWIFT_LOG(warning) << "Incorrect state" << std::endl; return; } + + if (error) { + SWIFT_LOG(debug) << "Error activating proxy" << std::endl; + JingleS5BTransportPayload::ref proxyError = std::make_shared<JingleS5BTransportPayload>(); + proxyError->setSessionID(s5bSessionID); + proxyError->setProxyError(true); + session->sendTransportInfo(getContentID(), proxyError); + fallback(); + } + else { + JingleS5BTransportPayload::ref proxyActivate = std::make_shared<JingleS5BTransportPayload>(); + proxyActivate->setSessionID(s5bSessionID); + proxyActivate->setActivated(theirCandidateChoice->cid); + session->sendTransportInfo(getContentID(), proxyActivate); + startTransferring(createLocalCandidateSession()); + } } void JingleFileTransfer::handleTransportInfoReceived( - const JingleContentID& /* contentID */, JingleTransportPayload::ref transport) { - SWIFT_LOG(debug) << std::endl; - - if (JingleS5BTransportPayload::ref s5bPayload = boost::dynamic_pointer_cast<JingleS5BTransportPayload>(transport)) { - if (s5bPayload->hasCandidateError() || !s5bPayload->getCandidateUsed().empty()) { - SWIFT_LOG(debug) << "Received candidate decision from peer" << std::endl; - if (!isTryingCandidates()) { SWIFT_LOG(warning) << "Incorrect state" << std::endl; return; } - - theirCandidateSelectFinished = true; - if (!s5bPayload->hasCandidateError()) { - BOOST_AUTO(theirCandidate, localCandidates.find(s5bPayload->getCandidateUsed())); - if (theirCandidate == localCandidates.end()) { - SWIFT_LOG(warning) << "Got invalid candidate" << std::endl; - terminate(JinglePayload::Reason::GeneralError); - return; - } - theirCandidateChoice = theirCandidate->second; - } - decideOnCandidates(); - } - else if (!s5bPayload->getActivated().empty()) { - SWIFT_LOG(debug) << "Received peer activate from peer" << std::endl; - if (!isWaitingForPeerProxyActivate()) { SWIFT_LOG(warning) << "Incorrect state" << std::endl; return; } - - if (ourCandidateChoice->cid == s5bPayload->getActivated()) { - startTransferring(createRemoteCandidateSession()); - } - 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; - } + const JingleContentID& /* contentID */, JingleTransportPayload::ref transport) { + SWIFT_LOG(debug) << std::endl; + + if (JingleS5BTransportPayload::ref s5bPayload = std::dynamic_pointer_cast<JingleS5BTransportPayload>(transport)) { + if (s5bPayload->hasCandidateError() || !s5bPayload->getCandidateUsed().empty()) { + SWIFT_LOG(debug) << "Received candidate decision from peer" << std::endl; + if (!isTryingCandidates()) { SWIFT_LOG(warning) << "Incorrect state" << std::endl; return; } + + theirCandidateSelectFinished = true; + if (!s5bPayload->hasCandidateError()) { + BOOST_AUTO(theirCandidate, localCandidates.find(s5bPayload->getCandidateUsed())); + if (theirCandidate == localCandidates.end()) { + SWIFT_LOG(warning) << "Got invalid candidate" << std::endl; + terminate(JinglePayload::Reason::GeneralError); + return; + } + theirCandidateChoice = theirCandidate->second; + } + decideOnCandidates(); + } + else if (!s5bPayload->getActivated().empty()) { + SWIFT_LOG(debug) << "Received peer activate from peer" << std::endl; + if (!isWaitingForPeerProxyActivate()) { SWIFT_LOG(warning) << "Incorrect state" << std::endl; return; } + + if (ourCandidateChoice->cid == s5bPayload->getActivated()) { + startTransferring(createRemoteCandidateSession()); + } + 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) { - SWIFT_LOG_ASSERT(!this->transporter, error); - this->transporter = transporter; - localTransportCandidatesGeneratedConnection = transporter->onLocalCandidatesGenerated.connect( - 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)); + SWIFT_LOG_ASSERT(!this->transporter, error); + this->transporter = transporter; + localTransportCandidatesGeneratedConnection = transporter->onLocalCandidatesGenerated.connect( + 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)); } void JingleFileTransfer::removeTransporter() { - if (transporter) { - localTransportCandidatesGeneratedConnection.release(); - remoteTransportCandidateSelectFinishedConnection.release(); - proxyActivatedConnection.release(); - delete transporter; - transporter = NULL; - } + if (transporter) { + localTransportCandidatesGeneratedConnection.release(); + remoteTransportCandidateSelectFinishedConnection.release(); + proxyActivatedConnection.release(); + delete transporter; + transporter = nullptr; + } } diff --git a/Swiften/FileTransfer/JingleFileTransfer.h b/Swiften/FileTransfer/JingleFileTransfer.h index 16a55c6..5b9dd62 100644 --- a/Swiften/FileTransfer/JingleFileTransfer.h +++ b/Swiften/FileTransfer/JingleFileTransfer.h @@ -1,17 +1,17 @@ /* - * Copyright (c) 2013-2015 Isode Limited. + * Copyright (c) 2013-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #pragma once +#include <memory> #include <vector> -#include <boost/shared_ptr.hpp> +#include <boost/signals2.hpp> #include <Swiften/Base/API.h> -#include <Swiften/Base/boost_bsignals.h> #include <Swiften/Elements/ErrorPayload.h> #include <Swiften/Elements/JingleS5BTransportPayload.h> #include <Swiften/FileTransfer/FileTransfer.h> @@ -19,78 +19,78 @@ #include <Swiften/Jingle/JingleContentID.h> namespace Swift { - class CryptoProvider; - class IQRouter; - class RemoteJingleTransportCandidateSelector; - class LocalJingleTransportCandidateGenerator; - class JingleSession; - class FileTransferTransporter; - class FileTransferTransporterFactory; - class TransportSession; + class CryptoProvider; + class IQRouter; + class RemoteJingleTransportCandidateSelector; + class LocalJingleTransportCandidateGenerator; + class JingleSession; + class FileTransferTransporter; + class FileTransferTransporterFactory; + class TransportSession; - class SWIFTEN_API JingleFileTransfer : public AbstractJingleSessionListener { - public: - JingleFileTransfer( - boost::shared_ptr<JingleSession>, - const JID& target, - FileTransferTransporterFactory*); - virtual ~JingleFileTransfer(); + class SWIFTEN_API JingleFileTransfer : public AbstractJingleSessionListener { + public: + JingleFileTransfer( + std::shared_ptr<JingleSession>, + const JID& target, + FileTransferTransporterFactory*); + virtual ~JingleFileTransfer(); - protected: - virtual void handleTransportInfoReceived(const JingleContentID&, JingleTransportPayload::ref); - virtual void handleLocalTransportCandidatesGenerated( - const std::string& s5bSessionID, - 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>&); - virtual JingleContentID getContentID() const = 0; - virtual void startTransferring(boost::shared_ptr<TransportSession>) = 0; - virtual void terminate(JinglePayload::Reason::Type reason) = 0; - virtual void fallback() = 0; - virtual bool hasPriorityOnCandidateTie() const = 0; - virtual bool isWaitingForPeerProxyActivate() const = 0; - virtual bool isWaitingForLocalProxyActivate() const = 0; - virtual bool isTryingCandidates() const = 0; - virtual boost::shared_ptr<TransportSession> createLocalCandidateSession() = 0; - virtual boost::shared_ptr<TransportSession> createRemoteCandidateSession() = 0; - virtual void startTransferViaLocalCandidate() = 0; - virtual void startTransferViaRemoteCandidate() = 0; + protected: + virtual void handleTransportInfoReceived(const JingleContentID&, JingleTransportPayload::ref); + virtual void handleLocalTransportCandidatesGenerated( + const std::string& s5bSessionID, + 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>&); + virtual JingleContentID getContentID() const = 0; + virtual void startTransferring(std::shared_ptr<TransportSession>) = 0; + virtual void terminate(JinglePayload::Reason::Type reason) = 0; + virtual void fallback() = 0; + virtual bool hasPriorityOnCandidateTie() const = 0; + virtual bool isWaitingForPeerProxyActivate() const = 0; + virtual bool isWaitingForLocalProxyActivate() const = 0; + virtual bool isTryingCandidates() const = 0; + virtual std::shared_ptr<TransportSession> createLocalCandidateSession() = 0; + virtual std::shared_ptr<TransportSession> createRemoteCandidateSession() = 0; + virtual void startTransferViaLocalCandidate() = 0; + virtual void startTransferViaRemoteCandidate() = 0; - protected: - typedef std::map<std::string, JingleS5BTransportPayload::Candidate> CandidateMap; + protected: + typedef std::map<std::string, JingleS5BTransportPayload::Candidate> CandidateMap; - void setTransporter(FileTransferTransporter* transporter); - void removeTransporter(); - void fillCandidateMap( - CandidateMap& map, - const std::vector<JingleS5BTransportPayload::Candidate>&); - const JID& getInitiator() const; - const JID& getResponder() const; + void setTransporter(FileTransferTransporter* transporter); + void removeTransporter(); + void fillCandidateMap( + CandidateMap& map, + const std::vector<JingleS5BTransportPayload::Candidate>&); + const JID& getInitiator() const; + const JID& getResponder() const; - static FileTransfer::State::Type getExternalFinishedState(JinglePayload::Reason::Type); - static boost::optional<FileTransferError> getFileTransferError(JinglePayload::Reason::Type); + static FileTransfer::State::Type getExternalFinishedState(JinglePayload::Reason::Type); + static boost::optional<FileTransferError> getFileTransferError(JinglePayload::Reason::Type); - boost::shared_ptr<JingleSession> session; - JID target; - FileTransferTransporterFactory* transporterFactory; - FileTransferTransporter* transporter; + std::shared_ptr<JingleSession> session; + JID target; + FileTransferTransporterFactory* transporterFactory; + FileTransferTransporter* transporter; - std::string candidateSelectRequestID; - bool ourCandidateSelectFinished; - boost::optional<JingleS5BTransportPayload::Candidate> ourCandidateChoice; - bool theirCandidateSelectFinished; - boost::optional<JingleS5BTransportPayload::Candidate> theirCandidateChoice; - CandidateMap localCandidates; + std::string candidateSelectRequestID; + bool ourCandidateSelectFinished; + boost::optional<JingleS5BTransportPayload::Candidate> ourCandidateChoice; + bool theirCandidateSelectFinished; + boost::optional<JingleS5BTransportPayload::Candidate> theirCandidateChoice; + CandidateMap localCandidates; - boost::shared_ptr<TransportSession> transportSession; + std::shared_ptr<TransportSession> transportSession; - boost::bsignals::scoped_connection localTransportCandidatesGeneratedConnection; - boost::bsignals::scoped_connection remoteTransportCandidateSelectFinishedConnection; - boost::bsignals::scoped_connection proxyActivatedConnection; - }; + boost::signals2::scoped_connection localTransportCandidatesGeneratedConnection; + boost::signals2::scoped_connection remoteTransportCandidateSelectFinishedConnection; + boost::signals2::scoped_connection proxyActivatedConnection; + }; } diff --git a/Swiften/FileTransfer/LocalJingleTransportCandidateGenerator.cpp b/Swiften/FileTransfer/LocalJingleTransportCandidateGenerator.cpp index f6e6963..09b664f 100644 --- a/Swiften/FileTransfer/LocalJingleTransportCandidateGenerator.cpp +++ b/Swiften/FileTransfer/LocalJingleTransportCandidateGenerator.cpp @@ -5,21 +5,19 @@ */ /* - * Copyright (c) 2013-2015 Isode Limited. + * Copyright (c) 2013-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #include <Swiften/FileTransfer/LocalJingleTransportCandidateGenerator.h> +#include <memory> #include <vector> #include <boost/bind.hpp> -#include <boost/shared_ptr.hpp> -#include <boost/smart_ptr/make_shared.hpp> #include <Swiften/Base/Log.h> -#include <Swiften/Base/foreach.h> #include <Swiften/Elements/JingleS5BTransportPayload.h> #include <Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.h> #include <Swiften/FileTransfer/SOCKS5BytestreamServerManager.h> @@ -31,162 +29,163 @@ static const unsigned int LOCAL_PREFERENCE = 0; namespace Swift { LocalJingleTransportCandidateGenerator::LocalJingleTransportCandidateGenerator( - SOCKS5BytestreamServerManager* s5bServerManager, - SOCKS5BytestreamProxiesManager* s5bProxy, - const JID& ownJID, - IDGenerator* idGenerator, - const FileTransferOptions& options) : - s5bServerManager(s5bServerManager), - s5bProxy(s5bProxy), - ownJID(ownJID), - idGenerator(idGenerator), - triedServerInit_(false), - triedForwarding_(false), - triedProxyDiscovery_(false), - options_(options) { + SOCKS5BytestreamServerManager* s5bServerManager, + SOCKS5BytestreamProxiesManager* s5bProxy, + const JID& ownJID, + IDGenerator* idGenerator, + const FileTransferOptions& options) : + s5bServerManager(s5bServerManager), + s5bProxy(s5bProxy), + ownJID(ownJID), + idGenerator(idGenerator), + triedServerInit_(false), + triedForwarding_(false), + triedProxyDiscovery_(false), + options_(options) { } LocalJingleTransportCandidateGenerator::~LocalJingleTransportCandidateGenerator() { - SWIFT_LOG_ASSERT(!s5bServerInitializeRequest, warning) << std::endl; + SWIFT_LOG_ASSERT(!s5bServerInitializeRequest, warning) << std::endl; } void LocalJingleTransportCandidateGenerator::start() { - assert(!s5bServerInitializeRequest); - if (options_.isDirectAllowed() || options_.isAssistedAllowed()) { - s5bServerResourceUser_ = s5bServerManager->aquireResourceUser(); - if (s5bServerResourceUser_->isInitialized()) { - handleS5BServerInitialized(true); - } - else { - s5bServerResourceUser_->onSuccessfulInitialized.connect(boost::bind(&LocalJingleTransportCandidateGenerator::handleS5BServerInitialized, this, _1)); - } - } else { - handleS5BServerInitialized(false); - } - - if (options_.isProxiedAllowed()) { - s5bProxy->onDiscoveredProxiesChanged.connect(boost::bind(&LocalJingleTransportCandidateGenerator::handleDiscoveredProxiesChanged, this)); - if (s5bProxy->getOrDiscoverS5BProxies().is_initialized()) { - handleDiscoveredProxiesChanged(); - } - } + assert(!s5bServerInitializeRequest); + if (options_.isDirectAllowed() || options_.isAssistedAllowed()) { + s5bServerResourceUser_ = s5bServerManager->aquireResourceUser(); + if (s5bServerResourceUser_->isInitialized()) { + handleS5BServerInitialized(true); + } + else { + s5bServerResourceUser_->onSuccessfulInitialized.connect(boost::bind(&LocalJingleTransportCandidateGenerator::handleS5BServerInitialized, this, _1)); + } + } else { + handleS5BServerInitialized(false); + } + + if (options_.isProxiedAllowed()) { + s5bProxy->onDiscoveredProxiesChanged.connect(boost::bind(&LocalJingleTransportCandidateGenerator::handleDiscoveredProxiesChanged, this)); + if (s5bProxy->getOrDiscoverS5BProxies().is_initialized()) { + handleDiscoveredProxiesChanged(); + } + } } void LocalJingleTransportCandidateGenerator::stop() { - s5bProxy->onDiscoveredProxiesChanged.disconnect(boost::bind(&LocalJingleTransportCandidateGenerator::handleDiscoveredProxiesChanged, this)); - if (s5bServerPortForwardingUser_) { - s5bServerPortForwardingUser_->onSetup.disconnect(boost::bind(&LocalJingleTransportCandidateGenerator::handlePortForwardingSetup, this, _1)); - s5bServerPortForwardingUser_.reset(); - } - if (s5bServerResourceUser_) { - s5bServerResourceUser_->onSuccessfulInitialized.disconnect(boost::bind(&LocalJingleTransportCandidateGenerator::handleS5BServerInitialized, this, _1)); - s5bServerResourceUser_.reset(); - } + s5bProxy->onDiscoveredProxiesChanged.disconnect(boost::bind(&LocalJingleTransportCandidateGenerator::handleDiscoveredProxiesChanged, this)); + if (s5bServerPortForwardingUser_) { + s5bServerPortForwardingUser_->onSetup.disconnect(boost::bind(&LocalJingleTransportCandidateGenerator::handlePortForwardingSetup, this, _1)); + s5bServerPortForwardingUser_.reset(); + } + if (s5bServerResourceUser_) { + s5bServerResourceUser_->onSuccessfulInitialized.disconnect(boost::bind(&LocalJingleTransportCandidateGenerator::handleS5BServerInitialized, this, _1)); + s5bServerResourceUser_.reset(); + } } void LocalJingleTransportCandidateGenerator::handleS5BServerInitialized(bool success) { - if (s5bServerResourceUser_) { - s5bServerResourceUser_->onSuccessfulInitialized.disconnect(boost::bind(&LocalJingleTransportCandidateGenerator::handleS5BServerInitialized, this, _1)); - } - triedServerInit_ = true; - if (success) { - if (options_.isAssistedAllowed()) { - // try to setup port forwarding - s5bServerPortForwardingUser_ = s5bServerManager->aquirePortForwardingUser(); - s5bServerPortForwardingUser_->onSetup.connect(boost::bind(&LocalJingleTransportCandidateGenerator::handlePortForwardingSetup, this, _1)); - if (s5bServerPortForwardingUser_->isForwardingSetup()) { - handlePortForwardingSetup(true); - } - } - } - else { - SWIFT_LOG(warning) << "Unable to start SOCKS5 server" << std::endl; - if (s5bServerResourceUser_) { - s5bServerResourceUser_->onSuccessfulInitialized.disconnect(boost::bind(&LocalJingleTransportCandidateGenerator::handleS5BServerInitialized, this, _1)); - } - s5bServerResourceUser_.reset(); - handlePortForwardingSetup(false); - } - checkS5BCandidatesReady(); + if (s5bServerResourceUser_) { + s5bServerResourceUser_->onSuccessfulInitialized.disconnect(boost::bind(&LocalJingleTransportCandidateGenerator::handleS5BServerInitialized, this, _1)); + } + triedServerInit_ = true; + if (success) { + if (options_.isAssistedAllowed()) { + // try to setup port forwarding + s5bServerPortForwardingUser_ = s5bServerManager->aquirePortForwardingUser(); + s5bServerPortForwardingUser_->onSetup.connect(boost::bind(&LocalJingleTransportCandidateGenerator::handlePortForwardingSetup, this, _1)); + if (s5bServerPortForwardingUser_->isForwardingSetup()) { + handlePortForwardingSetup(true); + } + } + } + else { + SWIFT_LOG(warning) << "Unable to start SOCKS5 server" << std::endl; + if (s5bServerResourceUser_) { + s5bServerResourceUser_->onSuccessfulInitialized.disconnect(boost::bind(&LocalJingleTransportCandidateGenerator::handleS5BServerInitialized, this, _1)); + } + s5bServerResourceUser_.reset(); + handlePortForwardingSetup(false); + } + checkS5BCandidatesReady(); } void LocalJingleTransportCandidateGenerator::handlePortForwardingSetup(bool /* success */) { - if (s5bServerPortForwardingUser_) { - s5bServerPortForwardingUser_->onSetup.disconnect(boost::bind(&LocalJingleTransportCandidateGenerator::handlePortForwardingSetup, this, _1)); - } - triedForwarding_ = true; - checkS5BCandidatesReady(); + if (s5bServerPortForwardingUser_) { + s5bServerPortForwardingUser_->onSetup.disconnect(boost::bind(&LocalJingleTransportCandidateGenerator::handlePortForwardingSetup, this, _1)); + } + triedForwarding_ = true; + checkS5BCandidatesReady(); } void LocalJingleTransportCandidateGenerator::handleDiscoveredProxiesChanged() { - if (s5bProxy) { - s5bProxy->onDiscoveredProxiesChanged.disconnect(boost::bind(&LocalJingleTransportCandidateGenerator::handleDiscoveredProxiesChanged, this)); - } - triedProxyDiscovery_ = true; - checkS5BCandidatesReady(); + if (s5bProxy) { + s5bProxy->onDiscoveredProxiesChanged.disconnect(boost::bind(&LocalJingleTransportCandidateGenerator::handleDiscoveredProxiesChanged, this)); + } + triedProxyDiscovery_ = true; + checkS5BCandidatesReady(); } void LocalJingleTransportCandidateGenerator::checkS5BCandidatesReady() { - if ((!options_.isDirectAllowed() || (options_.isDirectAllowed() && triedServerInit_)) && - (!options_.isProxiedAllowed() || (options_.isProxiedAllowed() && triedProxyDiscovery_)) && - (!options_.isAssistedAllowed() || (options_.isAssistedAllowed() && triedForwarding_))) { - emitOnLocalTransportCandidatesGenerated(); - } + if ((!options_.isDirectAllowed() || (options_.isDirectAllowed() && triedServerInit_)) && + (!options_.isProxiedAllowed() || (options_.isProxiedAllowed() && triedProxyDiscovery_)) && + (!options_.isAssistedAllowed() || (options_.isAssistedAllowed() && triedForwarding_))) { + emitOnLocalTransportCandidatesGenerated(); + } } void LocalJingleTransportCandidateGenerator::emitOnLocalTransportCandidatesGenerated() { - std::vector<JingleS5BTransportPayload::Candidate> candidates; - - if (options_.isDirectAllowed()) { - // get direct candidates - std::vector<HostAddressPort> directCandidates = s5bServerManager->getHostAddressPorts(); - foreach(HostAddressPort addressPort, directCandidates) { - if (addressPort.getAddress().getRawAddress().is_v6() && - addressPort.getAddress().getRawAddress().to_v6().is_link_local()) { - continue; - } - JingleS5BTransportPayload::Candidate candidate; - candidate.type = JingleS5BTransportPayload::Candidate::DirectType; - candidate.jid = ownJID; - candidate.hostPort = addressPort; - candidate.priority = 65536 * 126 + LOCAL_PREFERENCE; - candidate.cid = idGenerator->generateID(); - candidates.push_back(candidate); - } - } - - if (options_.isAssistedAllowed()) { - // get assissted candidates - std::vector<HostAddressPort> assisstedCandidates = s5bServerManager->getAssistedHostAddressPorts(); - foreach(HostAddressPort addressPort, assisstedCandidates) { - JingleS5BTransportPayload::Candidate candidate; - candidate.type = JingleS5BTransportPayload::Candidate::AssistedType; - candidate.jid = ownJID; - candidate.hostPort = addressPort; - candidate.priority = 65536 * 120 + LOCAL_PREFERENCE; - candidate.cid = idGenerator->generateID(); - candidates.push_back(candidate); - } - } - - if (options_.isProxiedAllowed() && s5bProxy->getOrDiscoverS5BProxies().is_initialized()) { - foreach(S5BProxyRequest::ref proxy, s5bProxy->getOrDiscoverS5BProxies().get()) { - if (proxy->getStreamHost()) { // FIXME: Added this test, because there were cases where this wasn't initialized. Investigate this. (Remko) - JingleS5BTransportPayload::Candidate candidate; - candidate.type = JingleS5BTransportPayload::Candidate::ProxyType; - candidate.jid = (*proxy->getStreamHost()).jid; - HostAddress address = (*proxy->getStreamHost()).host; - assert(address.isValid()); - candidate.hostPort = HostAddressPort(address, (*proxy->getStreamHost()).port); - candidate.priority = 65536 * 10 + LOCAL_PREFERENCE; - candidate.cid = idGenerator->generateID(); - candidates.push_back(candidate); - } - } - } - - onLocalTransportCandidatesGenerated(candidates); + std::vector<JingleS5BTransportPayload::Candidate> candidates; + + if (options_.isDirectAllowed()) { + // get direct candidates + std::vector<HostAddressPort> directCandidates = s5bServerManager->getHostAddressPorts(); + for(auto&& addressPort : directCandidates) { + if (addressPort.getAddress().getRawAddress().is_v6() && + addressPort.getAddress().getRawAddress().to_v6().is_link_local()) { + continue; + } + JingleS5BTransportPayload::Candidate candidate; + candidate.type = JingleS5BTransportPayload::Candidate::DirectType; + candidate.jid = ownJID; + candidate.hostPort = addressPort; + candidate.priority = 65536 * 126 + LOCAL_PREFERENCE; + candidate.cid = idGenerator->generateID(); + candidates.push_back(candidate); + } + } + + if (options_.isAssistedAllowed()) { + // get assissted candidates + std::vector<HostAddressPort> assisstedCandidates = s5bServerManager->getAssistedHostAddressPorts(); + for (auto&& addressPort : assisstedCandidates) { + JingleS5BTransportPayload::Candidate candidate; + candidate.type = JingleS5BTransportPayload::Candidate::AssistedType; + candidate.jid = ownJID; + candidate.hostPort = addressPort; + candidate.priority = 65536 * 120 + LOCAL_PREFERENCE; + candidate.cid = idGenerator->generateID(); + candidates.push_back(candidate); + } + } + + if (options_.isProxiedAllowed() && s5bProxy->getOrDiscoverS5BProxies().is_initialized()) { + for (auto&& proxy : s5bProxy->getOrDiscoverS5BProxies().get()) { + if (proxy->getStreamHost()) { // FIXME: Added this test, because there were cases where this wasn't initialized. Investigate this. (Remko) + JingleS5BTransportPayload::Candidate candidate; + candidate.type = JingleS5BTransportPayload::Candidate::ProxyType; + candidate.jid = (*proxy->getStreamHost()).jid; + auto address = HostAddress::fromString((*proxy->getStreamHost()).host); + if (address) { + candidate.hostPort = HostAddressPort(address.get(), (*proxy->getStreamHost()).port); + candidate.priority = 65536 * 10 + LOCAL_PREFERENCE; + candidate.cid = idGenerator->generateID(); + candidates.push_back(candidate); + } + } + } + } + + onLocalTransportCandidatesGenerated(candidates); } } diff --git a/Swiften/FileTransfer/LocalJingleTransportCandidateGenerator.h b/Swiften/FileTransfer/LocalJingleTransportCandidateGenerator.h index bbf17a1..2159063 100644 --- a/Swiften/FileTransfer/LocalJingleTransportCandidateGenerator.h +++ b/Swiften/FileTransfer/LocalJingleTransportCandidateGenerator.h @@ -5,65 +5,66 @@ */ /* - * Copyright (c) 2013-2015 Isode Limited. + * Copyright (c) 2013-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/boost_bsignals.h> #include <Swiften/FileTransfer/LocalJingleTransportCandidateGenerator.h> +#include <boost/signals2.hpp> + #include <Swiften/Base/IDGenerator.h> #include <Swiften/Base/Override.h> -#include <Swiften/JID/JID.h> #include <Swiften/Elements/JingleS5BTransportPayload.h> #include <Swiften/FileTransfer/FileTransferOptions.h> #include <Swiften/FileTransfer/SOCKS5BytestreamProxyFinder.h> +#include <Swiften/JID/JID.h> namespace Swift { - class SOCKS5BytestreamServerManager; - class SOCKS5BytestreamProxiesManager; - class SOCKS5BytestreamServerInitializeRequest; - class SOCKS5BytestreamServerResourceUser; - class SOCKS5BytestreamServerPortForwardingUser; - class JingleS5BTransportPayload; + class SOCKS5BytestreamServerManager; + class SOCKS5BytestreamProxiesManager; + class SOCKS5BytestreamServerInitializeRequest; + class SOCKS5BytestreamServerResourceUser; + class SOCKS5BytestreamServerPortForwardingUser; + class JingleS5BTransportPayload; - class LocalJingleTransportCandidateGenerator { - public: - LocalJingleTransportCandidateGenerator( - SOCKS5BytestreamServerManager* s5bServerManager, - SOCKS5BytestreamProxiesManager* s5bProxy, - const JID& ownJID, - IDGenerator* idGenerator, - const FileTransferOptions& options); - virtual ~LocalJingleTransportCandidateGenerator(); + class LocalJingleTransportCandidateGenerator { + public: + LocalJingleTransportCandidateGenerator( + SOCKS5BytestreamServerManager* s5bServerManager, + SOCKS5BytestreamProxiesManager* s5bProxy, + const JID& ownJID, + IDGenerator* idGenerator, + const FileTransferOptions& options); + virtual ~LocalJingleTransportCandidateGenerator(); - virtual void start(); - virtual void stop(); + virtual void start(); + virtual void stop(); - boost::signal<void (const std::vector<JingleS5BTransportPayload::Candidate>&)> onLocalTransportCandidatesGenerated; + boost::signals2::signal<void (const std::vector<JingleS5BTransportPayload::Candidate>&)> onLocalTransportCandidatesGenerated; - private: - void handleS5BServerInitialized(bool success); - void handlePortForwardingSetup(bool success); - void handleDiscoveredProxiesChanged(); + private: + void handleS5BServerInitialized(bool success); + void handlePortForwardingSetup(bool success); + void handleDiscoveredProxiesChanged(); - void checkS5BCandidatesReady(); - void emitOnLocalTransportCandidatesGenerated(); + void checkS5BCandidatesReady(); + void emitOnLocalTransportCandidatesGenerated(); - private: - SOCKS5BytestreamServerManager* s5bServerManager; - SOCKS5BytestreamProxiesManager* s5bProxy; - JID ownJID; - IDGenerator* idGenerator; - boost::shared_ptr<SOCKS5BytestreamServerInitializeRequest> s5bServerInitializeRequest; - boost::shared_ptr<SOCKS5BytestreamServerResourceUser> s5bServerResourceUser_; - boost::shared_ptr<SOCKS5BytestreamServerPortForwardingUser> s5bServerPortForwardingUser_; - bool triedServerInit_; - bool triedForwarding_; - bool triedProxyDiscovery_; - FileTransferOptions options_; - }; + private: + SOCKS5BytestreamServerManager* s5bServerManager; + SOCKS5BytestreamProxiesManager* s5bProxy; + JID ownJID; + IDGenerator* idGenerator; + std::shared_ptr<SOCKS5BytestreamServerInitializeRequest> s5bServerInitializeRequest; + std::shared_ptr<SOCKS5BytestreamServerResourceUser> s5bServerResourceUser_; + std::shared_ptr<SOCKS5BytestreamServerPortForwardingUser> s5bServerPortForwardingUser_; + bool triedServerInit_; + bool triedForwarding_; + bool triedProxyDiscovery_; + FileTransferOptions options_; + }; } diff --git a/Swiften/FileTransfer/OutgoingFileTransfer.h b/Swiften/FileTransfer/OutgoingFileTransfer.h index 358cc2f..07fc6d2 100644 --- a/Swiften/FileTransfer/OutgoingFileTransfer.h +++ b/Swiften/FileTransfer/OutgoingFileTransfer.h @@ -1,23 +1,23 @@ /* - * Copyright (c) 2010-2015 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> #include <Swiften/Base/API.h> #include <Swiften/FileTransfer/FileTransfer.h> namespace Swift { - class SWIFTEN_API OutgoingFileTransfer : public FileTransfer { - public: - typedef boost::shared_ptr<OutgoingFileTransfer> ref; - public: - virtual ~OutgoingFileTransfer(); + class SWIFTEN_API OutgoingFileTransfer : public FileTransfer { + public: + typedef std::shared_ptr<OutgoingFileTransfer> ref; + public: + virtual ~OutgoingFileTransfer(); - virtual void start() = 0; - }; + virtual void start() = 0; + }; } diff --git a/Swiften/FileTransfer/OutgoingFileTransferManager.cpp b/Swiften/FileTransfer/OutgoingFileTransferManager.cpp index 0ed2395..c74aefb 100644 --- a/Swiften/FileTransfer/OutgoingFileTransferManager.cpp +++ b/Swiften/FileTransfer/OutgoingFileTransferManager.cpp @@ -5,61 +5,61 @@ */ /* - * Copyright (c) 2013-2015 Isode Limited. + * Copyright (c) 2013-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #include <Swiften/FileTransfer/OutgoingFileTransferManager.h> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> +#include <Swiften/Base/IDGenerator.h> +#include <Swiften/FileTransfer/OutgoingJingleFileTransfer.h> #include <Swiften/JID/JID.h> -#include <Swiften/Jingle/JingleSessionManager.h> -#include <Swiften/Jingle/JingleSessionImpl.h> #include <Swiften/Jingle/JingleContentID.h> -#include <Swiften/FileTransfer/OutgoingJingleFileTransfer.h> -#include <Swiften/Base/IDGenerator.h> +#include <Swiften/Jingle/JingleSessionImpl.h> +#include <Swiften/Jingle/JingleSessionManager.h> namespace Swift { OutgoingFileTransferManager::OutgoingFileTransferManager( - JingleSessionManager* jingleSessionManager, - IQRouter* router, - FileTransferTransporterFactory* transporterFactory, - TimerFactory* timerFactory, - CryptoProvider* crypto) : - jingleSessionManager(jingleSessionManager), - iqRouter(router), - transporterFactory(transporterFactory), - timerFactory(timerFactory), - crypto(crypto) { - idGenerator = new IDGenerator(); + JingleSessionManager* jingleSessionManager, + IQRouter* router, + FileTransferTransporterFactory* transporterFactory, + TimerFactory* timerFactory, + CryptoProvider* crypto) : + jingleSessionManager(jingleSessionManager), + iqRouter(router), + transporterFactory(transporterFactory), + timerFactory(timerFactory), + crypto(crypto) { + idGenerator = new IDGenerator(); } OutgoingFileTransferManager::~OutgoingFileTransferManager() { - delete idGenerator; + delete idGenerator; } -boost::shared_ptr<OutgoingFileTransfer> OutgoingFileTransferManager::createOutgoingFileTransfer( - const JID& from, - const JID& recipient, - boost::shared_ptr<ReadBytestream> readBytestream, - const JingleFileTransferFileInfo& fileInfo, - const FileTransferOptions& config) { - JingleSessionImpl::ref jingleSession = boost::make_shared<JingleSessionImpl>( - from, recipient, idGenerator->generateID(), iqRouter); - jingleSessionManager->registerOutgoingSession(from, jingleSession); - return boost::shared_ptr<OutgoingJingleFileTransfer>(new OutgoingJingleFileTransfer( - recipient, - jingleSession, - readBytestream, - transporterFactory, - timerFactory, - idGenerator, - fileInfo, - config, - crypto)); +std::shared_ptr<OutgoingFileTransfer> OutgoingFileTransferManager::createOutgoingFileTransfer( + const JID& from, + const JID& recipient, + std::shared_ptr<ReadBytestream> readBytestream, + const JingleFileTransferFileInfo& fileInfo, + const FileTransferOptions& config) { + JingleSessionImpl::ref jingleSession = std::make_shared<JingleSessionImpl>( + from, recipient, idGenerator->generateID(), iqRouter); + jingleSessionManager->registerOutgoingSession(from, jingleSession); + return std::shared_ptr<OutgoingJingleFileTransfer>(new OutgoingJingleFileTransfer( + recipient, + jingleSession, + readBytestream, + transporterFactory, + timerFactory, + idGenerator, + fileInfo, + config, + crypto)); } } diff --git a/Swiften/FileTransfer/OutgoingFileTransferManager.h b/Swiften/FileTransfer/OutgoingFileTransferManager.h index 1ad992e..48a6e5a 100644 --- a/Swiften/FileTransfer/OutgoingFileTransferManager.h +++ b/Swiften/FileTransfer/OutgoingFileTransferManager.h @@ -5,53 +5,53 @@ */ /* - * Copyright (c) 2013-2015 Isode Limited. + * Copyright (c) 2013-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> #include <Swiften/Base/API.h> namespace Swift { - class JingleSessionManager; - class IQRouter; - class FileTransferTransporterFactory; - class OutgoingFileTransfer; - class JID; - class IDGenerator; - class ReadBytestream; - class JingleFileTransferFileInfo; - class CryptoProvider; - class FileTransferOptions; - class TimerFactory; - - class SWIFTEN_API OutgoingFileTransferManager { - public: - OutgoingFileTransferManager( - JingleSessionManager* jingleSessionManager, - IQRouter* router, - FileTransferTransporterFactory* transporterFactory, - TimerFactory* timerFactory, - CryptoProvider* crypto); - ~OutgoingFileTransferManager(); - - boost::shared_ptr<OutgoingFileTransfer> createOutgoingFileTransfer( - const JID& from, - const JID& to, - boost::shared_ptr<ReadBytestream>, - const JingleFileTransferFileInfo&, - const FileTransferOptions&); - - private: - JingleSessionManager* jingleSessionManager; - IQRouter* iqRouter; - FileTransferTransporterFactory* transporterFactory; - TimerFactory* timerFactory; - IDGenerator* idGenerator; - CryptoProvider* crypto; - }; + class JingleSessionManager; + class IQRouter; + class FileTransferTransporterFactory; + class OutgoingFileTransfer; + class JID; + class IDGenerator; + class ReadBytestream; + class JingleFileTransferFileInfo; + class CryptoProvider; + class FileTransferOptions; + class TimerFactory; + + class SWIFTEN_API OutgoingFileTransferManager { + public: + OutgoingFileTransferManager( + JingleSessionManager* jingleSessionManager, + IQRouter* router, + FileTransferTransporterFactory* transporterFactory, + TimerFactory* timerFactory, + CryptoProvider* crypto); + ~OutgoingFileTransferManager(); + + std::shared_ptr<OutgoingFileTransfer> createOutgoingFileTransfer( + const JID& from, + const JID& to, + std::shared_ptr<ReadBytestream>, + const JingleFileTransferFileInfo&, + const FileTransferOptions&); + + private: + JingleSessionManager* jingleSessionManager; + IQRouter* iqRouter; + FileTransferTransporterFactory* transporterFactory; + TimerFactory* timerFactory; + IDGenerator* idGenerator; + CryptoProvider* crypto; + }; } diff --git a/Swiften/FileTransfer/OutgoingJingleFileTransfer.cpp b/Swiften/FileTransfer/OutgoingJingleFileTransfer.cpp index 2c43766..367fc97 100644 --- a/Swiften/FileTransfer/OutgoingJingleFileTransfer.cpp +++ b/Swiften/FileTransfer/OutgoingJingleFileTransfer.cpp @@ -10,20 +10,20 @@ * See the COPYING file for more information. */ -// TODO: +// TODO: // - We should handle incoming terminates after we have terminated, so the other // side can warn that he didn't receive all bytes correctly. // - Should the proby stuff also wait for candidate used acknowledgement? #include <Swiften/FileTransfer/OutgoingJingleFileTransfer.h> +#include <memory> + #include <boost/bind.hpp> -#include <boost/smart_ptr/make_shared.hpp> #include <boost/typeof/typeof.hpp> #include <Swiften/Base/IDGenerator.h> #include <Swiften/Base/Log.h> -#include <Swiften/Base/foreach.h> #include <Swiften/Crypto/CryptoProvider.h> #include <Swiften/Elements/JingleFileTransferDescription.h> #include <Swiften/Elements/JingleFileTransferHash.h> @@ -44,364 +44,364 @@ using namespace Swift; static const int DEFAULT_BLOCK_SIZE = 4096; OutgoingJingleFileTransfer::OutgoingJingleFileTransfer( - const JID& toJID, - JingleSession::ref session, - boost::shared_ptr<ReadBytestream> stream, - FileTransferTransporterFactory* transporterFactory, - TimerFactory* timerFactory, - IDGenerator* idGenerator, - const JingleFileTransferFileInfo& fileInfo, - const FileTransferOptions& options, - CryptoProvider* crypto) : - JingleFileTransfer(session, toJID, transporterFactory), - idGenerator(idGenerator), - stream(stream), - fileInfo(fileInfo), - options(options), - contentID(idGenerator->generateID(), JingleContentPayload::InitiatorCreator), - state(Initial), - candidateAcknowledged(false) { - - setFileInfo(fileInfo.getName(), fileInfo.getSize(), fileInfo.getDescription()); - - // calculate both, MD5 and SHA-1 since we don't know which one the other side supports - hashCalculator = new IncrementalBytestreamHashCalculator(true, true, crypto); - stream->onRead.connect( - boost::bind(&IncrementalBytestreamHashCalculator::feedData, hashCalculator, _1)); - - waitForRemoteTermination = timerFactory->createTimer(5000); - waitForRemoteTermination->onTick.connect(boost::bind(&OutgoingJingleFileTransfer::handleWaitForRemoteTerminationTimeout, this)); + const JID& toJID, + JingleSession::ref session, + std::shared_ptr<ReadBytestream> stream, + FileTransferTransporterFactory* transporterFactory, + TimerFactory* timerFactory, + IDGenerator* idGenerator, + const JingleFileTransferFileInfo& fileInfo, + const FileTransferOptions& options, + CryptoProvider* crypto) : + JingleFileTransfer(session, toJID, transporterFactory), + idGenerator(idGenerator), + stream(stream), + fileInfo(fileInfo), + options(options), + contentID(idGenerator->generateID(), JingleContentPayload::InitiatorCreator), + state(Initial), + candidateAcknowledged(false) { + + setFileInfo(fileInfo.getName(), fileInfo.getSize(), fileInfo.getDescription()); + + // calculate both, MD5 and SHA-1 since we don't know which one the other side supports + hashCalculator = new IncrementalBytestreamHashCalculator(true, true, crypto); + stream->onRead.connect( + boost::bind(&IncrementalBytestreamHashCalculator::feedData, hashCalculator, _1)); + + waitForRemoteTermination = timerFactory->createTimer(5000); + waitForRemoteTermination->onTick.connect(boost::bind(&OutgoingJingleFileTransfer::handleWaitForRemoteTerminationTimeout, this)); } OutgoingJingleFileTransfer::~OutgoingJingleFileTransfer() { - if (waitForRemoteTermination) { - waitForRemoteTermination->onTick.disconnect(boost::bind(&OutgoingJingleFileTransfer::handleWaitForRemoteTerminationTimeout, this)); - waitForRemoteTermination->stop(); - } - - stream->onRead.disconnect( - boost::bind(&IncrementalBytestreamHashCalculator::feedData, hashCalculator, _1)); - delete hashCalculator; - hashCalculator = NULL; - removeTransporter(); + if (waitForRemoteTermination) { + waitForRemoteTermination->onTick.disconnect(boost::bind(&OutgoingJingleFileTransfer::handleWaitForRemoteTerminationTimeout, this)); + waitForRemoteTermination->stop(); + } + + stream->onRead.disconnect( + boost::bind(&IncrementalBytestreamHashCalculator::feedData, hashCalculator, _1)); + delete hashCalculator; + hashCalculator = nullptr; + removeTransporter(); } - + void OutgoingJingleFileTransfer::start() { - SWIFT_LOG(debug) << std::endl; - if (state != Initial) { - SWIFT_LOG(warning) << "Incorrect state" << std::endl; - return; - } - - if (!options.isInBandAllowed() && !options.isDirectAllowed() && !options.isAssistedAllowed() && !options.isProxiedAllowed()) { - // Started outgoing file transfer while not supporting transport methods. - setFinishedState(FileTransfer::State::Failed, FileTransferError(FileTransferError::UnknownError)); - } - else { - setTransporter(transporterFactory->createInitiatorTransporter(getInitiator(), getResponder(), options)); - setInternalState(GeneratingInitialLocalCandidates); - transporter->startGeneratingLocalCandidates(); - } + SWIFT_LOG(debug) << std::endl; + if (state != Initial) { + SWIFT_LOG(warning) << "Incorrect state" << std::endl; + return; + } + + if (!options.isInBandAllowed() && !options.isDirectAllowed() && !options.isAssistedAllowed() && !options.isProxiedAllowed()) { + // Started outgoing file transfer while not supporting transport methods. + setFinishedState(FileTransfer::State::Failed, FileTransferError(FileTransferError::UnknownError)); + } + else { + setTransporter(transporterFactory->createInitiatorTransporter(getInitiator(), getResponder(), options)); + setInternalState(GeneratingInitialLocalCandidates); + transporter->startGeneratingLocalCandidates(); + } } void OutgoingJingleFileTransfer::cancel() { - terminate(JinglePayload::Reason::Cancel); + terminate(JinglePayload::Reason::Cancel); } void OutgoingJingleFileTransfer::terminate(JinglePayload::Reason::Type reason) { - SWIFT_LOG(debug) << reason << std::endl; + SWIFT_LOG(debug) << reason << std::endl; - if (state != Initial && state != GeneratingInitialLocalCandidates && state != Finished) { - session->sendTerminate(reason); - } - stopAll(); - setFinishedState(getExternalFinishedState(reason), getFileTransferError(reason)); + if (state != Initial && state != GeneratingInitialLocalCandidates && state != Finished) { + session->sendTerminate(reason); + } + stopAll(); + setFinishedState(getExternalFinishedState(reason), getFileTransferError(reason)); } void OutgoingJingleFileTransfer::handleSessionAcceptReceived( - const JingleContentID&, - 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(), s5bPayload->getDstAddr()); - setInternalState(TryingCandidates); - transporter->startTryingRemoteCandidates(); - } - else if (JingleIBBTransportPayload::ref ibbPayload = boost::dynamic_pointer_cast<JingleIBBTransportPayload>(transportPayload)) { - startTransferring(transporter->createIBBSendSession(ibbPayload->getSessionID(), ibbPayload->getBlockSize().get_value_or(DEFAULT_BLOCK_SIZE), stream)); - } - else { - SWIFT_LOG(debug) << "Unknown transport payload. Falling back." << std::endl; - fallback(); - } + const JingleContentID&, + 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 = std::dynamic_pointer_cast<JingleS5BTransportPayload>(transportPayload)) { + transporter->addRemoteCandidates(s5bPayload->getCandidates(), s5bPayload->getDstAddr()); + setInternalState(TryingCandidates); + transporter->startTryingRemoteCandidates(); + } + else if (JingleIBBTransportPayload::ref ibbPayload = std::dynamic_pointer_cast<JingleIBBTransportPayload>(transportPayload)) { + startTransferring(transporter->createIBBSendSession(ibbPayload->getSessionID(), ibbPayload->getBlockSize().get_value_or(DEFAULT_BLOCK_SIZE), stream)); + } + 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: " << state << std::endl; return; } - - stopAll(); - if (state == WaitForTermination) { - waitForRemoteTermination->stop(); - } - if (reason && reason->type == JinglePayload::Reason::Cancel) { - setFinishedState(FileTransfer::State::Canceled, FileTransferError(FileTransferError::PeerError)); - } - else if (reason && reason->type == JinglePayload::Reason::Decline) { - setFinishedState(FileTransfer::State::Canceled, boost::optional<FileTransferError>()); - } - else if (reason && reason->type == JinglePayload::Reason::Success) { - setFinishedState(FileTransfer::State::Finished, boost::optional<FileTransferError>()); - } - else { - setFinishedState(FileTransfer::State::Failed, FileTransferError(FileTransferError::PeerError)); - } + SWIFT_LOG(debug) << std::endl; + if (state == Finished) { SWIFT_LOG(warning) << "Incorrect state: " << state << std::endl; return; } + + stopAll(); + if (state == WaitForTermination) { + waitForRemoteTermination->stop(); + } + if (reason && reason->type == JinglePayload::Reason::Cancel) { + setFinishedState(FileTransfer::State::Canceled, FileTransferError(FileTransferError::PeerError)); + } + else if (reason && reason->type == JinglePayload::Reason::Decline) { + setFinishedState(FileTransfer::State::Canceled, boost::optional<FileTransferError>()); + } + else if (reason && reason->type == JinglePayload::Reason::Success) { + setFinishedState(FileTransfer::State::Finished, boost::optional<FileTransferError>()); + } + else { + setFinishedState(FileTransfer::State::Failed, FileTransferError(FileTransferError::PeerError)); + } } void OutgoingJingleFileTransfer::handleTransportAcceptReceived(const JingleContentID&, JingleTransportPayload::ref transport) { - SWIFT_LOG(debug) << std::endl; - if (state != FallbackRequested) { SWIFT_LOG(warning) << "Incorrect state" << std::endl; return; } - - if (JingleIBBTransportPayload::ref ibbPayload = boost::dynamic_pointer_cast<JingleIBBTransportPayload>(transport)) { - startTransferring(transporter->createIBBSendSession(ibbPayload->getSessionID(), ibbPayload->getBlockSize().get_value_or(DEFAULT_BLOCK_SIZE), stream)); - } - else { - SWIFT_LOG(debug) << "Unknown transport replacement" << std::endl; - terminate(JinglePayload::Reason::FailedTransport); - } + SWIFT_LOG(debug) << std::endl; + if (state != FallbackRequested) { SWIFT_LOG(warning) << "Incorrect state" << std::endl; return; } + + if (JingleIBBTransportPayload::ref ibbPayload = std::dynamic_pointer_cast<JingleIBBTransportPayload>(transport)) { + startTransferring(transporter->createIBBSendSession(ibbPayload->getSessionID(), ibbPayload->getBlockSize().get_value_or(DEFAULT_BLOCK_SIZE), stream)); + } + 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; +void OutgoingJingleFileTransfer::handleTransportRejectReceived(const JingleContentID &, std::shared_ptr<JingleTransportPayload>) { + SWIFT_LOG(debug) << std::endl; - terminate(JinglePayload::Reason::UnsupportedTransports); + terminate(JinglePayload::Reason::UnsupportedTransports); } void OutgoingJingleFileTransfer::sendSessionInfoHash() { - SWIFT_LOG(debug) << std::endl; + 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); + JingleFileTransferHash::ref hashElement = std::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& dstAddr) { - SWIFT_LOG(debug) << std::endl; - if (state != GeneratingInitialLocalCandidates) { SWIFT_LOG(warning) << "Incorrect state: " << state << std::endl; return; } - - fillCandidateMap(localCandidates, candidates); - - JingleFileTransferDescription::ref description = boost::make_shared<JingleFileTransferDescription>(); - fileInfo.addHash(HashElement("sha-1", ByteArray())); - fileInfo.addHash(HashElement("md5", ByteArray())); - description->setFileInfo(fileInfo); - - JingleTransportPayload::ref transport; - if (candidates.empty()) { - SWIFT_LOG(debug) << "no S5B candidates generated. Send IBB transport candidate." << std::endl; - JingleIBBTransportPayload::ref ibbTransport = boost::make_shared<JingleIBBTransportPayload>(); - ibbTransport->setBlockSize(DEFAULT_BLOCK_SIZE); - ibbTransport->setSessionID(idGenerator->generateID()); - transport = ibbTransport; - } - else { - JingleS5BTransportPayload::ref s5bTransport = boost::make_shared<JingleS5BTransportPayload>(); - s5bTransport->setSessionID(s5bSessionID); - s5bTransport->setMode(JingleS5BTransportPayload::TCPMode); - s5bTransport->setDstAddr(dstAddr); - foreach(JingleS5BTransportPayload::Candidate candidate, candidates) { - s5bTransport->addCandidate(candidate); - SWIFT_LOG(debug) << "\t" << "S5B candidate: " << candidate.hostPort.toString() << std::endl; - } - transport = s5bTransport; - } - setInternalState(WaitingForAccept); - session->sendInitiate(contentID, description, transport); + 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: " << state << std::endl; return; } + + fillCandidateMap(localCandidates, candidates); + + JingleFileTransferDescription::ref description = std::make_shared<JingleFileTransferDescription>(); + fileInfo.addHash(HashElement("sha-1", ByteArray())); + fileInfo.addHash(HashElement("md5", ByteArray())); + description->setFileInfo(fileInfo); + + JingleTransportPayload::ref transport; + if (candidates.empty()) { + SWIFT_LOG(debug) << "no S5B candidates generated. Send IBB transport candidate." << std::endl; + JingleIBBTransportPayload::ref ibbTransport = std::make_shared<JingleIBBTransportPayload>(); + ibbTransport->setBlockSize(DEFAULT_BLOCK_SIZE); + ibbTransport->setSessionID(idGenerator->generateID()); + transport = ibbTransport; + } + else { + JingleS5BTransportPayload::ref s5bTransport = std::make_shared<JingleS5BTransportPayload>(); + s5bTransport->setSessionID(s5bSessionID); + s5bTransport->setMode(JingleS5BTransportPayload::TCPMode); + s5bTransport->setDstAddr(dstAddr); + for (auto&& candidate : candidates) { + s5bTransport->addCandidate(candidate); + SWIFT_LOG(debug) << "\t" << "S5B candidate: " << candidate.hostPort.toString() << std::endl; + } + transport = s5bTransport; + } + setInternalState(WaitingForAccept); + session->sendInitiate(contentID, description, transport); } void OutgoingJingleFileTransfer::fallback() { - 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()); - setInternalState(FallbackRequested); - session->sendTransportReplace(contentID, ibbTransport); - } - else { - SWIFT_LOG(debug) << "Fallback to IBB transport not allowed." << std::endl; - terminate(JinglePayload::Reason::ConnectivityError); - } + if (options.isInBandAllowed()) { + SWIFT_LOG(debug) << "Trying to fallback to IBB transport." << std::endl; + JingleIBBTransportPayload::ref ibbTransport = std::make_shared<JingleIBBTransportPayload>(); + ibbTransport->setBlockSize(DEFAULT_BLOCK_SIZE); + ibbTransport->setSessionID(idGenerator->generateID()); + setInternalState(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: " << state << std::endl; return; } - - if (error) { - terminate(JinglePayload::Reason::ConnectivityError); - } - else { - sendSessionInfoHash(); - - // wait for other party to terminate session after they have verified the hash - setInternalState(WaitForTermination); - waitForRemoteTermination->start(); - } + SWIFT_LOG(debug) << std::endl; + if (state != Transferring) { SWIFT_LOG(warning) << "Incorrect state: " << state << std::endl; return; } + + if (error) { + terminate(JinglePayload::Reason::ConnectivityError); + } + else { + sendSessionInfoHash(); + + // wait for other party to terminate session after they have verified the hash + setInternalState(WaitForTermination); + waitForRemoteTermination->start(); + } } -void OutgoingJingleFileTransfer::startTransferring(boost::shared_ptr<TransportSession> transportSession) { - SWIFT_LOG(debug) << std::endl; +void OutgoingJingleFileTransfer::startTransferring(std::shared_ptr<TransportSession> transportSession) { + SWIFT_LOG(debug) << std::endl; - this->transportSession = transportSession; - processedBytesConnection = transportSession->onBytesSent.connect( - boost::bind(boost::ref(onProcessedBytes), _1)); - transferFinishedConnection = transportSession->onFinished.connect( - boost::bind(&OutgoingJingleFileTransfer::handleTransferFinished, this, _1)); - setInternalState(Transferring); - transportSession->start(); + this->transportSession = transportSession; + processedBytesConnection = transportSession->onBytesSent.connect( + boost::bind(boost::ref(onProcessedBytes), _1)); + transferFinishedConnection = transportSession->onFinished.connect( + boost::bind(&OutgoingJingleFileTransfer::handleTransferFinished, this, _1)); + setInternalState(Transferring); + transportSession->start(); } void OutgoingJingleFileTransfer::setInternalState(State state) { - SWIFT_LOG(debug) << state << std::endl; - this->state = state; - setState(FileTransfer::State(getExternalState(state))); + SWIFT_LOG(debug) << state << std::endl; + this->state = state; + setState(FileTransfer::State(getExternalState(state))); } void OutgoingJingleFileTransfer::setFinishedState( - FileTransfer::State::Type type, const boost::optional<FileTransferError>& error) { - SWIFT_LOG(debug) << std::endl; - this->state = Finished; - onStateChanged(type); - onFinished(error); + FileTransfer::State::Type type, const boost::optional<FileTransferError>& error) { + SWIFT_LOG(debug) << std::endl; + this->state = Finished; + onStateChanged(type); + onFinished(error); } FileTransfer::State::Type OutgoingJingleFileTransfer::getExternalState(State state) { - switch (state) { - case Initial: return FileTransfer::State::Initial; - case GeneratingInitialLocalCandidates: return FileTransfer::State::WaitingForStart; - case WaitingForAccept: return FileTransfer::State::WaitingForAccept; - case TryingCandidates: return FileTransfer::State::Negotiating; - case WaitingForPeerProxyActivate: return FileTransfer::State::Negotiating; - case WaitingForLocalProxyActivate: return FileTransfer::State::Negotiating; - case WaitingForCandidateAcknowledge: return FileTransfer::State::Negotiating; - case FallbackRequested: return FileTransfer::State::Negotiating; - case Transferring: return FileTransfer::State::Transferring; - case WaitForTermination: return FileTransfer::State::Transferring; - case Finished: return FileTransfer::State::Finished; - } - assert(false); - return FileTransfer::State::Initial; + switch (state) { + case Initial: return FileTransfer::State::Initial; + case GeneratingInitialLocalCandidates: return FileTransfer::State::WaitingForStart; + case WaitingForAccept: return FileTransfer::State::WaitingForAccept; + case TryingCandidates: return FileTransfer::State::Negotiating; + case WaitingForPeerProxyActivate: return FileTransfer::State::Negotiating; + case WaitingForLocalProxyActivate: return FileTransfer::State::Negotiating; + case WaitingForCandidateAcknowledge: return FileTransfer::State::Negotiating; + case FallbackRequested: return FileTransfer::State::Negotiating; + case Transferring: return FileTransfer::State::Transferring; + case WaitForTermination: return FileTransfer::State::Transferring; + case Finished: return FileTransfer::State::Finished; + } + assert(false); + return FileTransfer::State::Initial; } void OutgoingJingleFileTransfer::stopAll() { - SWIFT_LOG(debug) << state << std::endl; - switch (state) { - case Initial: SWIFT_LOG(warning) << "Not yet started" << std::endl; break; - case GeneratingInitialLocalCandidates: transporter->stopGeneratingLocalCandidates(); break; - case WaitingForAccept: break; - case TryingCandidates: transporter->stopTryingRemoteCandidates(); break; - case FallbackRequested: break; - case WaitingForPeerProxyActivate: break; - case WaitingForLocalProxyActivate: transporter->stopActivatingProxy(); break; - case WaitingForCandidateAcknowledge: // Fallthrough - case Transferring: - assert(transportSession); - processedBytesConnection.disconnect(); - transferFinishedConnection.disconnect(); - transportSession->stop(); - transportSession.reset(); - break; - case WaitForTermination: - break; - case Finished: SWIFT_LOG(warning) << "Already finished" << std::endl; break; - } - if (state != Initial) { - removeTransporter(); - } + SWIFT_LOG(debug) << state << std::endl; + switch (state) { + case Initial: SWIFT_LOG(warning) << "Not yet started" << std::endl; break; + case GeneratingInitialLocalCandidates: transporter->stopGeneratingLocalCandidates(); break; + case WaitingForAccept: break; + case TryingCandidates: transporter->stopTryingRemoteCandidates(); break; + case FallbackRequested: break; + case WaitingForPeerProxyActivate: break; + case WaitingForLocalProxyActivate: transporter->stopActivatingProxy(); break; + case WaitingForCandidateAcknowledge: // Fallthrough + case Transferring: + assert(transportSession); + processedBytesConnection.disconnect(); + transferFinishedConnection.disconnect(); + transportSession->stop(); + transportSession.reset(); + break; + case WaitForTermination: + break; + case Finished: SWIFT_LOG(warning) << "Already finished" << std::endl; break; + } + if (state != Initial) { + removeTransporter(); + } } void OutgoingJingleFileTransfer::startTransferViaRemoteCandidate() { - SWIFT_LOG(debug) << std::endl; - - if (ourCandidateChoice->type == JingleS5BTransportPayload::Candidate::ProxyType) { - setInternalState(WaitingForPeerProxyActivate); - } - else { - transportSession = createRemoteCandidateSession(); - startTransferringIfCandidateAcknowledged(); - } + SWIFT_LOG(debug) << std::endl; + + if (ourCandidateChoice->type == JingleS5BTransportPayload::Candidate::ProxyType) { + setInternalState(WaitingForPeerProxyActivate); + } + else { + transportSession = createRemoteCandidateSession(); + startTransferringIfCandidateAcknowledged(); + } } void OutgoingJingleFileTransfer::startTransferViaLocalCandidate() { - SWIFT_LOG(debug) << std::endl; - - if (theirCandidateChoice->type == JingleS5BTransportPayload::Candidate::ProxyType) { - setInternalState(WaitingForLocalProxyActivate); - transporter->startActivatingProxy(theirCandidateChoice->jid); - } - else { - transportSession = createLocalCandidateSession(); - startTransferringIfCandidateAcknowledged(); - } + SWIFT_LOG(debug) << std::endl; + + if (theirCandidateChoice->type == JingleS5BTransportPayload::Candidate::ProxyType) { + setInternalState(WaitingForLocalProxyActivate); + transporter->startActivatingProxy(theirCandidateChoice->jid); + } + else { + transportSession = createLocalCandidateSession(); + startTransferringIfCandidateAcknowledged(); + } } void OutgoingJingleFileTransfer::startTransferringIfCandidateAcknowledged() { - if (candidateAcknowledged) { - startTransferring(transportSession); - } - else { - setInternalState(WaitingForCandidateAcknowledge); - } + if (candidateAcknowledged) { + startTransferring(transportSession); + } + else { + setInternalState(WaitingForCandidateAcknowledge); + } } void OutgoingJingleFileTransfer::handleTransportInfoAcknowledged(const std::string& id) { - if (id == candidateSelectRequestID) { - candidateAcknowledged = true; - } - if (state == WaitingForCandidateAcknowledge) { - startTransferring(transportSession); - } + if (id == candidateSelectRequestID) { + candidateAcknowledged = true; + } + if (state == WaitingForCandidateAcknowledge) { + startTransferring(transportSession); + } } JingleContentID OutgoingJingleFileTransfer::getContentID() const { - return contentID; + return contentID; } bool OutgoingJingleFileTransfer::hasPriorityOnCandidateTie() const { - return true; + return true; } bool OutgoingJingleFileTransfer::isWaitingForPeerProxyActivate() const { - return state == WaitingForPeerProxyActivate; + return state == WaitingForPeerProxyActivate; } bool OutgoingJingleFileTransfer::isWaitingForLocalProxyActivate() const { - return state == WaitingForLocalProxyActivate; + return state == WaitingForLocalProxyActivate; } bool OutgoingJingleFileTransfer::isTryingCandidates() const { - return state == TryingCandidates; + return state == TryingCandidates; } -boost::shared_ptr<TransportSession> OutgoingJingleFileTransfer::createLocalCandidateSession() { - return transporter->createLocalCandidateSession(stream, theirCandidateChoice.get()); +std::shared_ptr<TransportSession> OutgoingJingleFileTransfer::createLocalCandidateSession() { + return transporter->createLocalCandidateSession(stream, theirCandidateChoice.get()); } -boost::shared_ptr<TransportSession> OutgoingJingleFileTransfer::createRemoteCandidateSession() { - return transporter->createRemoteCandidateSession(stream, ourCandidateChoice.get()); +std::shared_ptr<TransportSession> OutgoingJingleFileTransfer::createRemoteCandidateSession() { + 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(); - terminate(JinglePayload::Reason::MediaError); + assert(state == WaitForTermination); + SWIFT_LOG(warning) << "Other party did not terminate session. Terminate it now." << std::endl; + waitForRemoteTermination->stop(); + terminate(JinglePayload::Reason::MediaError); } diff --git a/Swiften/FileTransfer/OutgoingJingleFileTransfer.h b/Swiften/FileTransfer/OutgoingJingleFileTransfer.h index 96b465b..cd45948 100644 --- a/Swiften/FileTransfer/OutgoingJingleFileTransfer.h +++ b/Swiften/FileTransfer/OutgoingJingleFileTransfer.h @@ -5,15 +5,16 @@ */ /* - * Copyright (c) 2013-2015 Isode Limited. + * Copyright (c) 2013-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #pragma once +#include <memory> + #include <boost/optional/optional.hpp> -#include <boost/shared_ptr.hpp> #include <Swiften/Base/API.h> #include <Swiften/Base/Override.h> @@ -25,98 +26,98 @@ #include <Swiften/Network/Timer.h> namespace Swift { - class CryptoProvider; - class FileTransferTransporter; - class FileTransferTransporterFactory; - class IDGenerator; - class IncrementalBytestreamHashCalculator; - class ReadBytestream; - class TimerFactory; - class TransportSession; - - class SWIFTEN_API OutgoingJingleFileTransfer : public OutgoingFileTransfer, public JingleFileTransfer { - public: - OutgoingJingleFileTransfer( - const JID& to, - boost::shared_ptr<JingleSession>, - boost::shared_ptr<ReadBytestream>, - FileTransferTransporterFactory*, - TimerFactory*, - IDGenerator*, - const JingleFileTransferFileInfo&, - const FileTransferOptions&, - CryptoProvider*); - virtual ~OutgoingJingleFileTransfer(); - - virtual void start() SWIFTEN_OVERRIDE; - virtual void cancel() SWIFTEN_OVERRIDE; - - private: - enum State { - Initial, - GeneratingInitialLocalCandidates, - WaitingForAccept, - TryingCandidates, - WaitingForPeerProxyActivate, - WaitingForLocalProxyActivate, - WaitingForCandidateAcknowledge, - FallbackRequested, - Transferring, - WaitForTermination, - 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>&, 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; - - virtual void fallback() SWIFTEN_OVERRIDE; - void handleTransferFinished(boost::optional<FileTransferError>); - - void sendSessionInfoHash(); - - virtual void startTransferring(boost::shared_ptr<TransportSession>) SWIFTEN_OVERRIDE; - - virtual bool hasPriorityOnCandidateTie() const SWIFTEN_OVERRIDE; - virtual bool isWaitingForPeerProxyActivate() const SWIFTEN_OVERRIDE; - virtual bool isWaitingForLocalProxyActivate() const SWIFTEN_OVERRIDE; - virtual bool isTryingCandidates() const SWIFTEN_OVERRIDE; - virtual boost::shared_ptr<TransportSession> createLocalCandidateSession() SWIFTEN_OVERRIDE; - virtual boost::shared_ptr<TransportSession> createRemoteCandidateSession() SWIFTEN_OVERRIDE; - - void handleWaitForRemoteTerminationTimeout(); - - void stopAll(); - void setInternalState(State state); - void setFinishedState(FileTransfer::State::Type, const boost::optional<FileTransferError>& error); - - static FileTransfer::State::Type getExternalState(State state); - - private: - IDGenerator* idGenerator; - boost::shared_ptr<ReadBytestream> stream; - JingleFileTransferFileInfo fileInfo; - FileTransferOptions options; - JingleContentID contentID; - IncrementalBytestreamHashCalculator* hashCalculator; - State state; - bool candidateAcknowledged; - - Timer::ref waitForRemoteTermination; - - boost::bsignals::connection processedBytesConnection; - boost::bsignals::connection transferFinishedConnection; - }; + class CryptoProvider; + class FileTransferTransporter; + class FileTransferTransporterFactory; + class IDGenerator; + class IncrementalBytestreamHashCalculator; + class ReadBytestream; + class TimerFactory; + class TransportSession; + + class SWIFTEN_API OutgoingJingleFileTransfer : public OutgoingFileTransfer, public JingleFileTransfer { + public: + OutgoingJingleFileTransfer( + const JID& to, + std::shared_ptr<JingleSession>, + std::shared_ptr<ReadBytestream>, + FileTransferTransporterFactory*, + TimerFactory*, + IDGenerator*, + const JingleFileTransferFileInfo&, + const FileTransferOptions&, + CryptoProvider*); + virtual ~OutgoingJingleFileTransfer(); + + virtual void start() SWIFTEN_OVERRIDE; + virtual void cancel() SWIFTEN_OVERRIDE; + + private: + enum State { + Initial, + GeneratingInitialLocalCandidates, + WaitingForAccept, + TryingCandidates, + WaitingForPeerProxyActivate, + WaitingForLocalProxyActivate, + WaitingForCandidateAcknowledge, + FallbackRequested, + Transferring, + WaitForTermination, + Finished + }; + + virtual void handleSessionAcceptReceived(const JingleContentID&, std::shared_ptr<JingleDescription>, std::shared_ptr<JingleTransportPayload>) SWIFTEN_OVERRIDE; + virtual void handleSessionTerminateReceived(boost::optional<JinglePayload::Reason> reason) SWIFTEN_OVERRIDE; + virtual void handleTransportAcceptReceived(const JingleContentID&, std::shared_ptr<JingleTransportPayload>) SWIFTEN_OVERRIDE; + virtual void handleTransportRejectReceived(const JingleContentID &, std::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>&, 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; + + virtual void fallback() SWIFTEN_OVERRIDE; + void handleTransferFinished(boost::optional<FileTransferError>); + + void sendSessionInfoHash(); + + virtual void startTransferring(std::shared_ptr<TransportSession>) SWIFTEN_OVERRIDE; + + virtual bool hasPriorityOnCandidateTie() const SWIFTEN_OVERRIDE; + virtual bool isWaitingForPeerProxyActivate() const SWIFTEN_OVERRIDE; + virtual bool isWaitingForLocalProxyActivate() const SWIFTEN_OVERRIDE; + virtual bool isTryingCandidates() const SWIFTEN_OVERRIDE; + virtual std::shared_ptr<TransportSession> createLocalCandidateSession() SWIFTEN_OVERRIDE; + virtual std::shared_ptr<TransportSession> createRemoteCandidateSession() SWIFTEN_OVERRIDE; + + void handleWaitForRemoteTerminationTimeout(); + + void stopAll(); + void setInternalState(State state); + void setFinishedState(FileTransfer::State::Type, const boost::optional<FileTransferError>& error); + + static FileTransfer::State::Type getExternalState(State state); + + private: + IDGenerator* idGenerator; + std::shared_ptr<ReadBytestream> stream; + JingleFileTransferFileInfo fileInfo; + FileTransferOptions options; + JingleContentID contentID; + IncrementalBytestreamHashCalculator* hashCalculator; + State state; + bool candidateAcknowledged; + + Timer::ref waitForRemoteTermination; + + boost::signals2::connection processedBytesConnection; + boost::signals2::connection transferFinishedConnection; + }; } diff --git a/Swiften/FileTransfer/ReadBytestream.h b/Swiften/FileTransfer/ReadBytestream.h index 5841db7..f146c04 100644 --- a/Swiften/FileTransfer/ReadBytestream.h +++ b/Swiften/FileTransfer/ReadBytestream.h @@ -1,32 +1,33 @@ /* - * Copyright (c) 2010 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> #include <vector> +#include <boost/signals2.hpp> + #include <Swiften/Base/API.h> -#include <Swiften/Base/boost_bsignals.h> namespace Swift { - class SWIFTEN_API ReadBytestream { - public: - virtual ~ReadBytestream(); - - /** - * Return an empty vector if no more data is available. - * Use onDataAvailable signal for signaling there is data available again. - */ - virtual boost::shared_ptr< std::vector<unsigned char> > read(size_t size) = 0; - - virtual bool isFinished() const = 0; - - public: - boost::signal<void ()> onDataAvailable; - boost::signal<void (const std::vector<unsigned char>&)> onRead; - }; + class SWIFTEN_API ReadBytestream { + public: + virtual ~ReadBytestream(); + + /** + * Return an empty vector if no more data is available. + * Use onDataAvailable signal for signaling there is data available again. + */ + virtual std::shared_ptr< std::vector<unsigned char> > read(size_t size) = 0; + + virtual bool isFinished() const = 0; + + public: + boost::signals2::signal<void ()> onDataAvailable; + boost::signals2::signal<void (const std::vector<unsigned char>&)> onRead; + }; } diff --git a/Swiften/FileTransfer/RemoteJingleTransportCandidateSelector.cpp b/Swiften/FileTransfer/RemoteJingleTransportCandidateSelector.cpp index 05a0f0e..56013ca 100644 --- a/Swiften/FileTransfer/RemoteJingleTransportCandidateSelector.cpp +++ b/Swiften/FileTransfer/RemoteJingleTransportCandidateSelector.cpp @@ -5,93 +5,93 @@ */ /* - * Copyright (c) 2013-2015 Isode Limited. + * Copyright (c) 2013-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #include <Swiften/FileTransfer/RemoteJingleTransportCandidateSelector.h> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> + #include <boost/bind.hpp> +#include <boost/signals2.hpp> #include <Swiften/Base/Log.h> -#include <Swiften/Base/boost_bsignals.h> -#include <Swiften/Base/foreach.h> #include <Swiften/Elements/JingleS5BTransportPayload.h> -#include <Swiften/Network/ConnectionFactory.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) { + 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); - } + const std::vector<JingleS5BTransportPayload::Candidate>& candidates) { + for (auto&& c : candidates) { + this->candidates.push(c); + } } void RemoteJingleTransportCandidateSelector::startSelectingCandidate() { - tryNextCandidate(); + tryNextCandidate(); } void RemoteJingleTransportCandidateSelector::stopSelectingCandidate() { - if (s5bSession) { - sessionReadyConnection.disconnect(); - s5bSession->stop(); - } + 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(); - } - } + 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); - } + sessionReadyConnection.disconnect(); + if (error) { + s5bSession.reset(); + tryNextCandidate(); + } + else { + onCandidateSelectFinished(lastCandidate, s5bSession); + } } void RemoteJingleTransportCandidateSelector::setSOCKS5DstAddr(const std::string& socks5DstAddr) { - this->socks5DstAddr = socks5DstAddr; + this->socks5DstAddr = socks5DstAddr; } diff --git a/Swiften/FileTransfer/RemoteJingleTransportCandidateSelector.h b/Swiften/FileTransfer/RemoteJingleTransportCandidateSelector.h index 342655c..c4257f6 100644 --- a/Swiften/FileTransfer/RemoteJingleTransportCandidateSelector.h +++ b/Swiften/FileTransfer/RemoteJingleTransportCandidateSelector.h @@ -5,59 +5,58 @@ */ /* - * Copyright (c) 2013-2015 Isode Limited. + * Copyright (c) 2013-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #pragma once +#include <Swiften/FileTransfer/RemoteJingleTransportCandidateSelector.h> + +#include <memory> #include <queue> #include <vector> -#include <boost/shared_ptr.hpp> - #include <Swiften/Base/Override.h> -#include <Swiften/JID/JID.h> -#include <Swiften/Network/Connection.h> -#include <Swiften/FileTransfer/SOCKS5BytestreamClientSession.h> -#include <Swiften/FileTransfer/RemoteJingleTransportCandidateSelector.h> #include <Swiften/Elements/JingleS5BTransportPayload.h> #include <Swiften/FileTransfer/FileTransferOptions.h> - +#include <Swiften/FileTransfer/SOCKS5BytestreamClientSession.h> +#include <Swiften/JID/JID.h> +#include <Swiften/Network/Connection.h> namespace Swift { - class ConnectionFactory; - class TimerFactory; - - class RemoteJingleTransportCandidateSelector { - public: - RemoteJingleTransportCandidateSelector(ConnectionFactory*, TimerFactory*, const FileTransferOptions&); - virtual ~RemoteJingleTransportCandidateSelector(); - - virtual void addCandidates(const std::vector<JingleS5BTransportPayload::Candidate>&); - virtual void setSOCKS5DstAddr(const std::string&); - virtual void startSelectingCandidate(); - virtual void stopSelectingCandidate(); - - boost::signal<void (const boost::optional<JingleS5BTransportPayload::Candidate>&, boost::shared_ptr<SOCKS5BytestreamClientSession>)> onCandidateSelectFinished; - - private: - void tryNextCandidate(); - void handleSessionReady(bool error); - - private: - ConnectionFactory* connectionFactory; - TimerFactory* timerFactory; - - std::priority_queue< - JingleS5BTransportPayload::Candidate, - std::vector<JingleS5BTransportPayload::Candidate>, - JingleS5BTransportPayload::CompareCandidate> candidates; - boost::shared_ptr<SOCKS5BytestreamClientSession> s5bSession; - boost::bsignals::connection sessionReadyConnection; - JingleS5BTransportPayload::Candidate lastCandidate; - std::string socks5DstAddr; - FileTransferOptions options; - }; + class ConnectionFactory; + class TimerFactory; + + class RemoteJingleTransportCandidateSelector { + public: + RemoteJingleTransportCandidateSelector(ConnectionFactory*, TimerFactory*, const FileTransferOptions&); + virtual ~RemoteJingleTransportCandidateSelector(); + + virtual void addCandidates(const std::vector<JingleS5BTransportPayload::Candidate>&); + virtual void setSOCKS5DstAddr(const std::string&); + virtual void startSelectingCandidate(); + virtual void stopSelectingCandidate(); + + boost::signals2::signal<void (const boost::optional<JingleS5BTransportPayload::Candidate>&, std::shared_ptr<SOCKS5BytestreamClientSession>)> onCandidateSelectFinished; + + private: + void tryNextCandidate(); + void handleSessionReady(bool error); + + private: + ConnectionFactory* connectionFactory; + TimerFactory* timerFactory; + + std::priority_queue< + JingleS5BTransportPayload::Candidate, + std::vector<JingleS5BTransportPayload::Candidate>, + JingleS5BTransportPayload::CompareCandidate> candidates; + std::shared_ptr<SOCKS5BytestreamClientSession> s5bSession; + boost::signals2::connection sessionReadyConnection; + JingleS5BTransportPayload::Candidate lastCandidate; + std::string socks5DstAddr; + FileTransferOptions options; + }; } diff --git a/Swiften/FileTransfer/S5BTransportSession.h b/Swiften/FileTransfer/S5BTransportSession.h index b3eee3c..3e064fa 100644 --- a/Swiften/FileTransfer/S5BTransportSession.h +++ b/Swiften/FileTransfer/S5BTransportSession.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Isode Limited. + * Copyright (c) 2015-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ @@ -7,9 +7,9 @@ #pragma once #include <boost/bind.hpp> +#include <boost/signals2.hpp> #include <Swiften/Base/API.h> -#include <Swiften/Base/boost_bsignals.h> #include <Swiften/FileTransfer/ReadBytestream.h> #include <Swiften/FileTransfer/TransportSession.h> #include <Swiften/FileTransfer/WriteBytestream.h> @@ -18,52 +18,52 @@ namespace Swift { template <typename T> class SWIFTEN_API S5BTransportSession : public TransportSession { - public: - S5BTransportSession( - boost::shared_ptr<T> session, - boost::shared_ptr<ReadBytestream> readStream) : - session(session), - readStream(readStream) { - initialize(); - } + public: + S5BTransportSession( + std::shared_ptr<T> session, + std::shared_ptr<ReadBytestream> readStream) : + session(session), + readStream(readStream) { + initialize(); + } - S5BTransportSession( - boost::shared_ptr<T> session, - boost::shared_ptr<WriteBytestream> writeStream) : - session(session), - writeStream(writeStream) { - initialize(); - } + S5BTransportSession( + std::shared_ptr<T> session, + std::shared_ptr<WriteBytestream> writeStream) : + session(session), + writeStream(writeStream) { + initialize(); + } - virtual ~S5BTransportSession() { - } + virtual ~S5BTransportSession() { + } - virtual void start() SWIFTEN_OVERRIDE { - if (readStream) { - session->startSending(readStream); - } - else { - session->startReceiving(writeStream); - } - } + virtual void start() SWIFTEN_OVERRIDE { + if (readStream) { + session->startSending(readStream); + } + else { + session->startReceiving(writeStream); + } + } - virtual void stop() SWIFTEN_OVERRIDE { - session->stop(); - } + virtual void stop() SWIFTEN_OVERRIDE { + session->stop(); + } - private: - void initialize() { - finishedConnection = session->onFinished.connect(boost::bind(boost::ref(onFinished), _1)); - bytesSentConnection = session->onBytesSent.connect(boost::bind(boost::ref(onBytesSent), _1)); - } + private: + void initialize() { + finishedConnection = session->onFinished.connect(boost::bind(boost::ref(onFinished), _1)); + bytesSentConnection = session->onBytesSent.connect(boost::bind(boost::ref(onBytesSent), _1)); + } - private: - boost::shared_ptr<T> session; - boost::shared_ptr<ReadBytestream> readStream; - boost::shared_ptr<WriteBytestream> writeStream; + private: + std::shared_ptr<T> session; + std::shared_ptr<ReadBytestream> readStream; + std::shared_ptr<WriteBytestream> writeStream; - boost::bsignals::scoped_connection finishedConnection; - boost::bsignals::scoped_connection bytesSentConnection; + boost::signals2::scoped_connection finishedConnection; + boost::signals2::scoped_connection bytesSentConnection; }; } diff --git a/Swiften/FileTransfer/SConscript b/Swiften/FileTransfer/SConscript index 41af8d4..d49b596 100644 --- a/Swiften/FileTransfer/SConscript +++ b/Swiften/FileTransfer/SConscript @@ -1,52 +1,53 @@ Import("swiften_env", "env") sources = [ - "ByteArrayReadBytestream.cpp", - "OutgoingFileTransfer.cpp", - "OutgoingJingleFileTransfer.cpp", - "OutgoingFileTransferManager.cpp", - "IncomingFileTransfer.cpp", - "IncomingJingleFileTransfer.cpp", - "IncomingFileTransferManager.cpp", - "JingleFileTransfer.cpp", - "FileTransferOptions.cpp", - "FileTransferTransporter.cpp", - "FileTransferTransporterFactory.cpp", - "DefaultFileTransferTransporter.cpp", - "DefaultFileTransferTransporterFactory.cpp", - "RemoteJingleTransportCandidateSelector.cpp", - "LocalJingleTransportCandidateGenerator.cpp", - "ReadBytestream.cpp", - "WriteBytestream.cpp", - "FileReadBytestream.cpp", - "FileWriteBytestream.cpp", - "FileTransfer.cpp", - "TransportSession.cpp", - "IBBSendTransportSession.cpp", - "IBBReceiveTransportSession.cpp", - "SOCKS5BytestreamClientSession.cpp", - "SOCKS5BytestreamServerManager.cpp", - "SOCKS5BytestreamServer.cpp", - "SOCKS5BytestreamServerSession.cpp", - "SOCKS5BytestreamRegistry.cpp", - "SOCKS5BytestreamProxiesManager.cpp", - "SOCKS5BytestreamProxyFinder.cpp", - "IBBSendSession.cpp", - "IBBReceiveSession.cpp", - "FileTransferManager.cpp", - "FileTransferManagerImpl.cpp", - "IncrementalBytestreamHashCalculator.cpp", - "SOCKS5BytestreamServerResourceUser.cpp", - "SOCKS5BytestreamServerPortForwardingUser.cpp", - ] + "ByteArrayReadBytestream.cpp", + "DefaultFileTransferTransporter.cpp", + "DefaultFileTransferTransporterFactory.cpp", + "FailingTransportSession.cpp", + "FileReadBytestream.cpp", + "FileTransfer.cpp", + "FileTransferManager.cpp", + "FileTransferManagerImpl.cpp", + "FileTransferOptions.cpp", + "FileTransferTransporter.cpp", + "FileTransferTransporterFactory.cpp", + "FileWriteBytestream.cpp", + "IBBReceiveSession.cpp", + "IBBReceiveTransportSession.cpp", + "IBBSendSession.cpp", + "IBBSendTransportSession.cpp", + "IncomingFileTransfer.cpp", + "IncomingFileTransferManager.cpp", + "IncomingJingleFileTransfer.cpp", + "IncrementalBytestreamHashCalculator.cpp", + "JingleFileTransfer.cpp", + "LocalJingleTransportCandidateGenerator.cpp", + "OutgoingFileTransfer.cpp", + "OutgoingFileTransferManager.cpp", + "OutgoingJingleFileTransfer.cpp", + "ReadBytestream.cpp", + "RemoteJingleTransportCandidateSelector.cpp", + "SOCKS5BytestreamClientSession.cpp", + "SOCKS5BytestreamProxiesManager.cpp", + "SOCKS5BytestreamProxyFinder.cpp", + "SOCKS5BytestreamRegistry.cpp", + "SOCKS5BytestreamServer.cpp", + "SOCKS5BytestreamServerManager.cpp", + "SOCKS5BytestreamServerPortForwardingUser.cpp", + "SOCKS5BytestreamServerResourceUser.cpp", + "SOCKS5BytestreamServerSession.cpp", + "TransportSession.cpp", + "WriteBytestream.cpp", + ] swiften_env.Append(SWIFTEN_OBJECTS = swiften_env.SwiftenObject(sources)) env.Append(UNITTEST_SOURCES = [ - File("UnitTest/SOCKS5BytestreamServerSessionTest.cpp"), - File("UnitTest/SOCKS5BytestreamClientSessionTest.cpp"), - File("UnitTest/IBBSendSessionTest.cpp"), - File("UnitTest/IBBReceiveSessionTest.cpp"), - File("UnitTest/IncomingJingleFileTransferTest.cpp"), - File("UnitTest/OutgoingJingleFileTransferTest.cpp"), - ]) + File("UnitTest/IBBReceiveSessionTest.cpp"), + File("UnitTest/IBBSendSessionTest.cpp"), + File("UnitTest/IncomingJingleFileTransferTest.cpp"), + File("UnitTest/OutgoingJingleFileTransferTest.cpp"), + File("UnitTest/SOCKS5BytestreamClientSessionTest.cpp"), + File("UnitTest/SOCKS5BytestreamServerSessionTest.cpp"), + ]) diff --git a/Swiften/FileTransfer/SOCKS5BytestreamClientSession.cpp b/Swiften/FileTransfer/SOCKS5BytestreamClientSession.cpp index 4fc0246..5ddd32b 100644 --- a/Swiften/FileTransfer/SOCKS5BytestreamClientSession.cpp +++ b/Swiften/FileTransfer/SOCKS5BytestreamClientSession.cpp @@ -10,7 +10,7 @@ * See the COPYING file for more information. */ -#include "SOCKS5BytestreamClientSession.h" +#include <Swiften/FileTransfer/SOCKS5BytestreamClientSession.h> #include <boost/bind.hpp> #include <boost/numeric/conversion/cast.hpp> @@ -27,250 +27,250 @@ namespace Swift { SOCKS5BytestreamClientSession::SOCKS5BytestreamClientSession( - boost::shared_ptr<Connection> connection, - const HostAddressPort& addressPort, - const std::string& destination, - TimerFactory* timerFactory) : - connection(connection), - addressPort(addressPort), - destination(destination), - state(Initial), - chunkSize(131072) { - weFailedTimeout = timerFactory->createTimer(3000); - weFailedTimeout->onTick.connect( - boost::bind(&SOCKS5BytestreamClientSession::handleWeFailedTimeout, this)); + std::shared_ptr<Connection> connection, + const HostAddressPort& addressPort, + const std::string& destination, + TimerFactory* timerFactory) : + connection(connection), + addressPort(addressPort), + destination(destination), + state(Initial), + chunkSize(131072) { + weFailedTimeout = timerFactory->createTimer(3000); + weFailedTimeout->onTick.connect( + boost::bind(&SOCKS5BytestreamClientSession::handleWeFailedTimeout, this)); } SOCKS5BytestreamClientSession::~SOCKS5BytestreamClientSession() { - weFailedTimeout->onTick.disconnect( - boost::bind(&SOCKS5BytestreamClientSession::handleWeFailedTimeout, this)); - weFailedTimeout->stop(); + weFailedTimeout->onTick.disconnect( + boost::bind(&SOCKS5BytestreamClientSession::handleWeFailedTimeout, this)); + weFailedTimeout->stop(); } void SOCKS5BytestreamClientSession::start() { - assert(state == Initial); - SWIFT_LOG(debug) << "Trying to connect via TCP to " << addressPort.toString() << "." << std::endl; - weFailedTimeout->start(); - connectFinishedConnection = connection->onConnectFinished.connect( - boost::bind(&SOCKS5BytestreamClientSession::handleConnectFinished, this, _1)); - connection->connect(addressPort); + assert(state == Initial); + SWIFT_LOG(debug) << "Trying to connect via TCP to " << addressPort.toString() << "." << std::endl; + weFailedTimeout->start(); + connectFinishedConnection = connection->onConnectFinished.connect( + 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; + SWIFT_LOG(debug) << std::endl; + if (state < Ready) { + weFailedTimeout->stop(); + } + if (state == Finished) { + return; + } + closeConnection(); + readBytestream.reset(); + state = Finished; } void SOCKS5BytestreamClientSession::process() { - SWIFT_LOG(debug) << "unprocessedData.size(): " << unprocessedData.size() << std::endl; - ByteArray bndAddress; - switch(state) { - case Initial: - hello(); - break; - case Hello: - if (unprocessedData.size() > 1) { - unsigned char version = unprocessedData[0]; - unsigned char authMethod = unprocessedData[1]; - if (version != 5 || authMethod != 0) { - // signal failure to upper level - finish(true); - return; - } - unprocessedData.clear(); - authenticate(); - } - break; - case Authenticating: - if (unprocessedData.size() < 5) { - // need more data to start progressing - break; - } - if (unprocessedData[0] != '\x05') { - // wrong version - // disconnect & signal failure - finish(true); - break; - } - if (unprocessedData[1] != '\x00') { - // no success - // disconnect & signal failure - finish(true); - break; - } - if (unprocessedData[3] != '\x03') { - // we expect x'03' = DOMAINNAME here - // disconnect & signal failure - finish(true); - break; - } - if (static_cast<size_t>(unprocessedData[4]) + 1 > unprocessedData.size() + 5) { - // complete domainname and port not available yet - break; - } - bndAddress = createByteArray(&vecptr(unprocessedData)[5], unprocessedData[4]); - if (unprocessedData[unprocessedData[4] + 5] != 0 && bndAddress == createByteArray(destination)) { - // we expect a 0 as port - // disconnect and fail - finish(true); - } - unprocessedData.clear(); - state = Ready; - SWIFT_LOG(debug) << "session ready" << std::endl; - // issue ready signal so the bytestream can be used for reading or writing - weFailedTimeout->stop(); - onSessionReady(false); - break; - case Ready: - SWIFT_LOG(debug) << "Received further data in Ready state." << std::endl; - break; - case Reading: - case Writing: - case Finished: - SWIFT_LOG(debug) << "Unexpected receive of data. Current state: " << state << std::endl; - SWIFT_LOG(debug) << "Data: " << Hexify::hexify(unprocessedData) << std::endl; - unprocessedData.clear(); - //assert(false); - } + SWIFT_LOG(debug) << "unprocessedData.size(): " << unprocessedData.size() << std::endl; + ByteArray bndAddress; + switch(state) { + case Initial: + hello(); + break; + case Hello: + if (unprocessedData.size() > 1) { + unsigned char version = unprocessedData[0]; + unsigned char authMethod = unprocessedData[1]; + if (version != 5 || authMethod != 0) { + // signal failure to upper level + finish(true); + return; + } + unprocessedData.clear(); + authenticate(); + } + break; + case Authenticating: + if (unprocessedData.size() < 5) { + // need more data to start progressing + break; + } + if (unprocessedData[0] != '\x05') { + // wrong version + // disconnect & signal failure + finish(true); + break; + } + if (unprocessedData[1] != '\x00') { + // no success + // disconnect & signal failure + finish(true); + break; + } + if (unprocessedData[3] != '\x03') { + // we expect x'03' = DOMAINNAME here + // disconnect & signal failure + finish(true); + break; + } + if (static_cast<size_t>(unprocessedData[4]) + 1 > unprocessedData.size() + 5) { + // complete domainname and port not available yet + break; + } + bndAddress = createByteArray(&vecptr(unprocessedData)[5], unprocessedData[4]); + if (unprocessedData[unprocessedData[4] + 5] != 0 && bndAddress == createByteArray(destination)) { + // we expect a 0 as port + // disconnect and fail + finish(true); + } + unprocessedData.clear(); + state = Ready; + SWIFT_LOG(debug) << "session ready" << std::endl; + // issue ready signal so the bytestream can be used for reading or writing + weFailedTimeout->stop(); + onSessionReady(false); + break; + case Ready: + SWIFT_LOG(debug) << "Received further data in Ready state." << std::endl; + break; + case Reading: + case Writing: + case Finished: + SWIFT_LOG(debug) << "Unexpected receive of data. Current state: " << state << std::endl; + SWIFT_LOG(debug) << "Data: " << Hexify::hexify(unprocessedData) << std::endl; + unprocessedData.clear(); + //assert(false); + } } void SOCKS5BytestreamClientSession::hello() { - // Version 5, 1 auth method, No authentication - const SafeByteArray hello = createSafeByteArray("\x05\x01\x00", 3); - connection->write(hello); - state = Hello; + // Version 5, 1 auth method, No authentication + const SafeByteArray hello = createSafeByteArray("\x05\x01\x00", 3); + connection->write(hello); + state = Hello; } void SOCKS5BytestreamClientSession::authenticate() { - SWIFT_LOG(debug) << std::endl; - SafeByteArray header = createSafeByteArray("\x05\x01\x00\x03", 4); - SafeByteArray message = header; - append(message, createSafeByteArray(boost::numeric_cast<char>(destination.size()))); - authenticateAddress = createByteArray(destination); - append(message, authenticateAddress); - append(message, createSafeByteArray("\x00\x00", 2)); // 2 byte for port - connection->write(message); - state = Authenticating; + SWIFT_LOG(debug) << std::endl; + SafeByteArray header = createSafeByteArray("\x05\x01\x00\x03", 4); + SafeByteArray message = header; + append(message, createSafeByteArray(boost::numeric_cast<char>(destination.size()))); + authenticateAddress = createByteArray(destination); + append(message, authenticateAddress); + append(message, createSafeByteArray("\x00\x00", 2)); // 2 byte for port + connection->write(message); + state = Authenticating; } -void SOCKS5BytestreamClientSession::startReceiving(boost::shared_ptr<WriteBytestream> writeStream) { - if (state == Ready) { - state = Reading; - writeBytestream = writeStream; - writeBytestream->write(unprocessedData); - unprocessedData.clear(); - } else { - SWIFT_LOG(debug) << "Session isn't ready for transfer yet!" << std::endl; - } +void SOCKS5BytestreamClientSession::startReceiving(std::shared_ptr<WriteBytestream> writeStream) { + if (state == Ready) { + state = Reading; + writeBytestream = writeStream; + writeBytestream->write(unprocessedData); + unprocessedData.clear(); + } else { + SWIFT_LOG(debug) << "Session isn't ready for transfer yet!" << std::endl; + } } -void SOCKS5BytestreamClientSession::startSending(boost::shared_ptr<ReadBytestream> readStream) { - if (state == Ready) { - state = Writing; - readBytestream = readStream; - dataWrittenConnection = connection->onDataWritten.connect( - boost::bind(&SOCKS5BytestreamClientSession::sendData, this)); - sendData(); - } else { - SWIFT_LOG(debug) << "Session isn't ready for transfer yet!" << std::endl; - } +void SOCKS5BytestreamClientSession::startSending(std::shared_ptr<ReadBytestream> readStream) { + if (state == Ready) { + state = Writing; + readBytestream = readStream; + dataWrittenConnection = connection->onDataWritten.connect( + boost::bind(&SOCKS5BytestreamClientSession::sendData, this)); + sendData(); + } else { + SWIFT_LOG(debug) << "Session isn't ready for transfer yet!" << std::endl; + } } HostAddressPort SOCKS5BytestreamClientSession::getAddressPort() const { - return addressPort; + return addressPort; } void SOCKS5BytestreamClientSession::sendData() { - if (!readBytestream->isFinished()) { - try { - boost::shared_ptr<ByteArray> dataToSend = readBytestream->read(boost::numeric_cast<size_t>(chunkSize)); - connection->write(createSafeByteArray(*dataToSend)); - onBytesSent(dataToSend->size()); - } - catch (const BytestreamException&) { - finish(true); - } - } - else { - finish(false); - } + if (!readBytestream->isFinished()) { + try { + std::shared_ptr<ByteArray> dataToSend = readBytestream->read(boost::numeric_cast<size_t>(chunkSize)); + connection->write(createSafeByteArray(*dataToSend)); + onBytesSent(dataToSend->size()); + } + catch (const BytestreamException&) { + finish(true); + } + } + else { + finish(false); + } } void SOCKS5BytestreamClientSession::finish(bool error) { - SWIFT_LOG(debug) << std::endl; - if (state < Ready) { - weFailedTimeout->stop(); - } - closeConnection(); - readBytestream.reset(); - if (state == Initial || state == Hello || state == Authenticating) { - onSessionReady(true); - } - else { - state = Finished; - if (error) { - onFinished(boost::optional<FileTransferError>(FileTransferError::ReadError)); - } else { - onFinished(boost::optional<FileTransferError>()); - } - } + SWIFT_LOG(debug) << std::endl; + if (state < Ready) { + weFailedTimeout->stop(); + } + closeConnection(); + readBytestream.reset(); + if (state == Initial || state == Hello || state == Authenticating) { + onSessionReady(true); + } + else { + state = Finished; + if (error) { + onFinished(boost::optional<FileTransferError>(FileTransferError::ReadError)); + } else { + onFinished(boost::optional<FileTransferError>()); + } + } } void SOCKS5BytestreamClientSession::handleConnectFinished(bool error) { - connectFinishedConnection.disconnect(); - if (error) { - SWIFT_LOG(debug) << "Failed to connect via TCP to " << addressPort.toString() << "." << std::endl; - finish(true); - } 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(); - } + connectFinishedConnection.disconnect(); + if (error) { + SWIFT_LOG(debug) << "Failed to connect via TCP to " << addressPort.toString() << "." << std::endl; + finish(true); + } 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) { - SWIFT_LOG(debug) << "state: " << state << " data.size() = " << data->size() << std::endl; - if (state != Reading) { - append(unprocessedData, *data); - process(); - } - else { - writeBytestream->write(createByteArray(vecptr(*data), data->size())); - //onBytesReceived(data->size()); - } +void SOCKS5BytestreamClientSession::handleDataRead(std::shared_ptr<SafeByteArray> data) { + SWIFT_LOG(debug) << "state: " << state << " data.size() = " << data->size() << std::endl; + if (state != Reading) { + append(unprocessedData, *data); + process(); + } + else { + writeBytestream->write(createByteArray(vecptr(*data), data->size())); + //onBytesReceived(data->size()); + } } void SOCKS5BytestreamClientSession::handleDisconnected(const boost::optional<Connection::Error>& error) { - SWIFT_LOG(debug) << (error ? (error == Connection::ReadError ? "Read Error" : "Write Error") : "No Error") << std::endl; - if (error) { - finish(true); - } + SWIFT_LOG(debug) << (error ? (error == Connection::ReadError ? "Read Error" : "Write Error") : "No Error") << std::endl; + if (error) { + finish(true); + } } void SOCKS5BytestreamClientSession::handleWeFailedTimeout() { - SWIFT_LOG(debug) << "Failed due to timeout!" << std::endl; - finish(true); + SWIFT_LOG(debug) << "Failed due to timeout!" << std::endl; + finish(true); } void SOCKS5BytestreamClientSession::closeConnection() { - connectFinishedConnection.disconnect(); - dataWrittenConnection.disconnect(); - dataReadConnection.disconnect(); - disconnectedConnection.disconnect(); - connection->disconnect(); + connectFinishedConnection.disconnect(); + dataWrittenConnection.disconnect(); + dataReadConnection.disconnect(); + disconnectedConnection.disconnect(); + connection->disconnect(); } } diff --git a/Swiften/FileTransfer/SOCKS5BytestreamClientSession.h b/Swiften/FileTransfer/SOCKS5BytestreamClientSession.h index 1c0563a..b819910 100644 --- a/Swiften/FileTransfer/SOCKS5BytestreamClientSession.h +++ b/Swiften/FileTransfer/SOCKS5BytestreamClientSession.h @@ -5,15 +5,16 @@ */ /* - * Copyright (c) 2015 Isode Limited. + * Copyright (c) 2015-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #pragma once +#include <memory> + #include <boost/optional.hpp> -#include <boost/shared_ptr.hpp> #include <Swiften/Base/API.h> #include <Swiften/Base/ByteArray.h> @@ -37,75 +38,75 @@ class TimerFactory; */ class SWIFTEN_API SOCKS5BytestreamClientSession { public: - enum State { - Initial, - Hello, - Authenticating, - Ready, - Writing, - Reading, - Finished - }; + enum State { + Initial, + Hello, + Authenticating, + Ready, + Writing, + Reading, + Finished + }; public: - typedef boost::shared_ptr<SOCKS5BytestreamClientSession> ref; + typedef std::shared_ptr<SOCKS5BytestreamClientSession> ref; public: - SOCKS5BytestreamClientSession( - boost::shared_ptr<Connection> connection, - const HostAddressPort&, - const std::string&, - TimerFactory*); - ~SOCKS5BytestreamClientSession(); + SOCKS5BytestreamClientSession( + std::shared_ptr<Connection> connection, + const HostAddressPort&, + const std::string&, + TimerFactory*); + ~SOCKS5BytestreamClientSession(); - void start(); - void stop(); + void start(); + void stop(); - void startReceiving(boost::shared_ptr<WriteBytestream>); - void startSending(boost::shared_ptr<ReadBytestream>); + void startReceiving(std::shared_ptr<WriteBytestream>); + void startSending(std::shared_ptr<ReadBytestream>); - HostAddressPort getAddressPort() const; + HostAddressPort getAddressPort() const; - boost::signal<void (bool /*error*/)> onSessionReady; + boost::signals2::signal<void (bool /*error*/)> onSessionReady; - boost::signal<void (boost::optional<FileTransferError>)> onFinished; - boost::signal<void (size_t)> onBytesSent; - // boost::signal<void (size_t)> onBytesReceived; + boost::signals2::signal<void (boost::optional<FileTransferError>)> onFinished; + boost::signals2::signal<void (size_t)> onBytesSent; + // boost::signals2::signal<void (size_t)> onBytesReceived; private: - void process(); - void hello(); - void authenticate(); + void process(); + void hello(); + void authenticate(); - void handleConnectFinished(bool error); - void handleDataRead(boost::shared_ptr<SafeByteArray>); - void handleDisconnected(const boost::optional<Connection::Error>&); - void handleWeFailedTimeout(); + void handleConnectFinished(bool error); + void handleDataRead(std::shared_ptr<SafeByteArray>); + void handleDisconnected(const boost::optional<Connection::Error>&); + void handleWeFailedTimeout(); - void finish(bool error); - void sendData(); - void closeConnection(); + void finish(bool error); + void sendData(); + void closeConnection(); private: - boost::shared_ptr<Connection> connection; - HostAddressPort addressPort; - std::string destination; // hexify(SHA1(sessionID + requester + target)) + std::shared_ptr<Connection> connection; + HostAddressPort addressPort; + std::string destination; // hexify(SHA1(sessionID + requester + target)) - State state; + State state; - ByteArray unprocessedData; - ByteArray authenticateAddress; + ByteArray unprocessedData; + ByteArray authenticateAddress; - int chunkSize; - boost::shared_ptr<WriteBytestream> writeBytestream; - boost::shared_ptr<ReadBytestream> readBytestream; + int chunkSize; + std::shared_ptr<WriteBytestream> writeBytestream; + std::shared_ptr<ReadBytestream> readBytestream; - Timer::ref weFailedTimeout; + Timer::ref weFailedTimeout; - boost::bsignals::scoped_connection connectFinishedConnection; - boost::bsignals::scoped_connection dataWrittenConnection; - boost::bsignals::scoped_connection dataReadConnection; - boost::bsignals::scoped_connection disconnectedConnection; + boost::signals2::scoped_connection connectFinishedConnection; + boost::signals2::scoped_connection dataWrittenConnection; + boost::signals2::scoped_connection dataReadConnection; + boost::signals2::scoped_connection disconnectedConnection; }; } diff --git a/Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.cpp b/Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.cpp index a1ef8f6..cd4cfaa 100644 --- a/Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.cpp +++ b/Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.cpp @@ -5,7 +5,7 @@ */ /* - * Copyright (c) 2015 Isode Limited. + * Copyright (c) 2015-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ @@ -13,11 +13,11 @@ #include <Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.h> +#include <memory> + #include <boost/bind.hpp> -#include <boost/smart_ptr/make_shared.hpp> #include <Swiften/Base/Log.h> -#include <Swiften/Base/foreach.h> #include <Swiften/FileTransfer/SOCKS5BytestreamClientSession.h> #include <Swiften/Network/ConnectionFactory.h> #include <Swiften/Network/DomainNameAddressQuery.h> @@ -32,172 +32,176 @@ SOCKS5BytestreamProxiesManager::SOCKS5BytestreamProxiesManager(ConnectionFactory } SOCKS5BytestreamProxiesManager::~SOCKS5BytestreamProxiesManager() { - if (proxyFinder_) { - proxyFinder_->stop(); - } - - foreach (const ProxySessionsMap::value_type& sessionsForID, proxySessions_) { - foreach (const ProxyJIDClientSessionVector::value_type& session, sessionsForID.second) { - session.second->onSessionReady.disconnect(boost::bind(&SOCKS5BytestreamProxiesManager::handleProxySessionReady, this,sessionsForID.first, session.first, session.second, _1)); - session.second->onFinished.disconnect(boost::bind(&SOCKS5BytestreamProxiesManager::handleProxySessionFinished, this, sessionsForID.first, session.first, session.second, _1)); - } - } + if (proxyFinder_) { + proxyFinder_->stop(); + } + + for (const auto& sessionsForID : proxySessions_) { + for (const auto& session : sessionsForID.second) { + session.second->onSessionReady.disconnect(boost::bind(&SOCKS5BytestreamProxiesManager::handleProxySessionReady, this,sessionsForID.first, session.first, session.second, _1)); + session.second->onFinished.disconnect(boost::bind(&SOCKS5BytestreamProxiesManager::handleProxySessionFinished, this, sessionsForID.first, session.first, session.second, _1)); + } + } } void SOCKS5BytestreamProxiesManager::addS5BProxy(S5BProxyRequest::ref proxy) { - if (proxy) { - SWIFT_LOG_ASSERT(HostAddress(proxy->getStreamHost().get().host).isValid(), warning) << std::endl; - if (!localS5BProxies_) { - localS5BProxies_ = std::vector<S5BProxyRequest::ref>(); - } - localS5BProxies_->push_back(proxy); - } + if (proxy) { + SWIFT_LOG_ASSERT(HostAddress::fromString(proxy->getStreamHost().get().host), warning) << std::endl; + if (!localS5BProxies_) { + localS5BProxies_ = std::vector<S5BProxyRequest::ref>(); + } + localS5BProxies_->push_back(proxy); + } } const boost::optional<std::vector<S5BProxyRequest::ref> >& SOCKS5BytestreamProxiesManager::getOrDiscoverS5BProxies() { - if (!localS5BProxies_ && !proxyFinder_) { - queryForProxies(); - } - return localS5BProxies_; + if (!localS5BProxies_ && !proxyFinder_) { + queryForProxies(); + } + return localS5BProxies_; } void SOCKS5BytestreamProxiesManager::connectToProxies(const std::string& sessionID) { - SWIFT_LOG(debug) << "session ID: " << sessionID << std::endl; - ProxyJIDClientSessionVector clientSessions; - - if (localS5BProxies_) { - foreach(S5BProxyRequest::ref proxy, localS5BProxies_.get()) { - boost::shared_ptr<Connection> conn = connectionFactory_->createConnection(); - - HostAddressPort addressPort = HostAddressPort(proxy->getStreamHost().get().host, proxy->getStreamHost().get().port); - SWIFT_LOG_ASSERT(addressPort.isValid(), warning) << std::endl; - boost::shared_ptr<SOCKS5BytestreamClientSession> session = boost::make_shared<SOCKS5BytestreamClientSession>(conn, addressPort, sessionID, timerFactory_); - JID proxyJid = proxy->getStreamHost().get().jid; - clientSessions.push_back(std::pair<JID, boost::shared_ptr<SOCKS5BytestreamClientSession> >(proxyJid, session)); - session->onSessionReady.connect(boost::bind(&SOCKS5BytestreamProxiesManager::handleProxySessionReady, this,sessionID, proxyJid, session, _1)); - session->onFinished.connect(boost::bind(&SOCKS5BytestreamProxiesManager::handleProxySessionFinished, this, sessionID, proxyJid, session, _1)); - session->start(); - } - } - - proxySessions_[sessionID] = clientSessions; + SWIFT_LOG(debug) << "session ID: " << sessionID << std::endl; + ProxyJIDClientSessionVector clientSessions; + + if (localS5BProxies_) { + for (auto&& proxy : localS5BProxies_.get()) { + auto proxyHostAddress = HostAddress::fromString(proxy->getStreamHost().get().host); + if (proxyHostAddress) { + std::shared_ptr<Connection> conn = connectionFactory_->createConnection(); + HostAddressPort addressPort = HostAddressPort(proxyHostAddress.get(), proxy->getStreamHost().get().port); + SWIFT_LOG_ASSERT(addressPort.isValid(), warning) << std::endl; + std::shared_ptr<SOCKS5BytestreamClientSession> session = std::make_shared<SOCKS5BytestreamClientSession>(conn, addressPort, sessionID, timerFactory_); + JID proxyJid = proxy->getStreamHost().get().jid; + clientSessions.push_back(std::pair<JID, std::shared_ptr<SOCKS5BytestreamClientSession> >(proxyJid, session)); + session->onSessionReady.connect(boost::bind(&SOCKS5BytestreamProxiesManager::handleProxySessionReady, this,sessionID, proxyJid, session, _1)); + session->onFinished.connect(boost::bind(&SOCKS5BytestreamProxiesManager::handleProxySessionFinished, this, sessionID, proxyJid, session, _1)); + session->start(); + } + } + } + + proxySessions_[sessionID] = clientSessions; } -boost::shared_ptr<SOCKS5BytestreamClientSession> SOCKS5BytestreamProxiesManager::getProxySessionAndCloseOthers(const JID& proxyJID, const std::string& sessionID) { - // checking parameters - if (proxySessions_.find(sessionID) == proxySessions_.end()) { - return boost::shared_ptr<SOCKS5BytestreamClientSession>(); - } - - // get active session - boost::shared_ptr<SOCKS5BytestreamClientSession> activeSession; - for (ProxyJIDClientSessionVector::iterator i = proxySessions_[sessionID].begin(); i != proxySessions_[sessionID].end(); i++) { - i->second->onSessionReady.disconnect(boost::bind(&SOCKS5BytestreamProxiesManager::handleProxySessionReady, this,sessionID, proxyJID, i->second, _1)); - i->second->onFinished.disconnect(boost::bind(&SOCKS5BytestreamProxiesManager::handleProxySessionFinished, this, sessionID, proxyJID, i->second, _1)); - if (i->first == proxyJID && !activeSession) { - activeSession = i->second; - } - else { - i->second->stop(); - } - } - - proxySessions_.erase(sessionID); - - return activeSession; +std::shared_ptr<SOCKS5BytestreamClientSession> SOCKS5BytestreamProxiesManager::getProxySessionAndCloseOthers(const JID& proxyJID, const std::string& sessionID) { + // checking parameters + if (proxySessions_.find(sessionID) == proxySessions_.end()) { + return std::shared_ptr<SOCKS5BytestreamClientSession>(); + } + + // get active session + std::shared_ptr<SOCKS5BytestreamClientSession> activeSession; + for (ProxyJIDClientSessionVector::iterator i = proxySessions_[sessionID].begin(); i != proxySessions_[sessionID].end(); i++) { + i->second->onSessionReady.disconnect(boost::bind(&SOCKS5BytestreamProxiesManager::handleProxySessionReady, this,sessionID, proxyJID, i->second, _1)); + i->second->onFinished.disconnect(boost::bind(&SOCKS5BytestreamProxiesManager::handleProxySessionFinished, this, sessionID, proxyJID, i->second, _1)); + if (i->first == proxyJID && !activeSession) { + activeSession = i->second; + } + else { + i->second->stop(); + } + } + SWIFT_LOG_ASSERT(activeSession, warning) << "No active session with matching ID found." << std::endl; + + proxySessions_.erase(sessionID); + + return activeSession; } -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; +std::shared_ptr<SOCKS5BytestreamClientSession> SOCKS5BytestreamProxiesManager::createSOCKS5BytestreamClientSession(HostAddressPort addressPort, const std::string& destAddr) { + SOCKS5BytestreamClientSession::ref connection = std::make_shared<SOCKS5BytestreamClientSession>(connectionFactory_->createConnection(), addressPort, destAddr, timerFactory_); + return connection; } void SOCKS5BytestreamProxiesManager::handleProxiesFound(std::vector<S5BProxyRequest::ref> proxyHosts) { - proxyFinder_->onProxiesFound.disconnect(boost::bind(&SOCKS5BytestreamProxiesManager::handleProxiesFound, this, _1)); - 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(); - } - } - } - proxyFinder_->stop(); - proxyFinder_.reset(); - if (proxyHosts.empty()) { - onDiscoveredProxiesChanged(); - } + proxyFinder_->onProxiesFound.disconnect(boost::bind(&SOCKS5BytestreamProxiesManager::handleProxiesFound, this, _1)); + for (auto&& proxy : proxyHosts) { + if (proxy) { + auto proxyHostAddress = HostAddress::fromString(proxy->getStreamHost().get().host); + if (proxyHostAddress) { + 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(); + } + } + } + proxyFinder_->stop(); + proxyFinder_.reset(); + if (proxyHosts.empty()) { + onDiscoveredProxiesChanged(); + } } void SOCKS5BytestreamProxiesManager::handleNameLookupResult(const std::vector<HostAddress>& addresses, boost::optional<DomainNameResolveError> error, S5BProxyRequest::ref proxy) { - if (error) { - onDiscoveredProxiesChanged(); - } - else { - if (addresses.empty()) { - SWIFT_LOG(warning) << "S5B proxy hostname does not resolve." << std::endl; - } - else { - // generate proxy per returned address - foreach (const HostAddress& address, addresses) { - S5BProxyRequest::StreamHost streamHost = proxy->getStreamHost().get(); - S5BProxyRequest::ref proxyForAddress = boost::make_shared<S5BProxyRequest>(*proxy); - streamHost.host = address.toString(); - proxyForAddress->setStreamHost(streamHost); - addS5BProxy(proxyForAddress); - } - } - onDiscoveredProxiesChanged(); - } + if (error) { + onDiscoveredProxiesChanged(); + } + else { + if (addresses.empty()) { + SWIFT_LOG(warning) << "S5B proxy hostname does not resolve." << std::endl; + } + else { + // generate proxy per returned address + for (const auto& address : addresses) { + S5BProxyRequest::StreamHost streamHost = proxy->getStreamHost().get(); + S5BProxyRequest::ref proxyForAddress = std::make_shared<S5BProxyRequest>(*proxy); + streamHost.host = address.toString(); + proxyForAddress->setStreamHost(streamHost); + addS5BProxy(proxyForAddress); + } + } + onDiscoveredProxiesChanged(); + } } void SOCKS5BytestreamProxiesManager::queryForProxies() { - proxyFinder_ = boost::make_shared<SOCKS5BytestreamProxyFinder>(serviceRoot_, iqRouter_); + proxyFinder_ = std::make_shared<SOCKS5BytestreamProxyFinder>(serviceRoot_, iqRouter_); - proxyFinder_->onProxiesFound.connect(boost::bind(&SOCKS5BytestreamProxiesManager::handleProxiesFound, this, _1)); - proxyFinder_->start(); + 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::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(); - i = proxySessions_[sessionID].erase(i); - } - else { - i++; - } - } - } - } +void SOCKS5BytestreamProxiesManager::handleProxySessionReady(const std::string& sessionID, const JID& jid, std::shared_ptr<SOCKS5BytestreamClientSession> session, bool error) { + 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(); + i = proxySessions_[sessionID].erase(i); + } + else { + i++; + } + } + } + } } -void SOCKS5BytestreamProxiesManager::handleProxySessionFinished(const std::string& sessionID, const JID& jid, boost::shared_ptr<SOCKS5BytestreamClientSession> session, boost::optional<FileTransferError> error) { - session->onFinished.disconnect(boost::bind(&SOCKS5BytestreamProxiesManager::handleProxySessionFinished, this, sessionID, jid, session, _1)); - if (error.is_initialized()) { - // The SOCKS5 bytestream session to the proxy failed; remove it. - 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(); - i = proxySessions_[sessionID].erase(i); - break; - } - else { - i++; - } - } - } - } +void SOCKS5BytestreamProxiesManager::handleProxySessionFinished(const std::string& sessionID, const JID& jid, std::shared_ptr<SOCKS5BytestreamClientSession> session, boost::optional<FileTransferError> error) { + session->onFinished.disconnect(boost::bind(&SOCKS5BytestreamProxiesManager::handleProxySessionFinished, this, sessionID, jid, session, _1)); + if (error.is_initialized()) { + // The SOCKS5 bytestream session to the proxy failed; remove it. + 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(); + i = proxySessions_[sessionID].erase(i); + break; + } + else { + i++; + } + } + } + } } } diff --git a/Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.h b/Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.h index c7daee7..b5c5173 100644 --- a/Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.h +++ b/Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.h @@ -5,7 +5,7 @@ */ /* - * Copyright (c) 2015 Isode Limited. + * Copyright (c) 2015-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ @@ -25,60 +25,60 @@ #include <Swiften/JID/JID.h> namespace Swift { - class TimerFactory; - class ConnectionFactory; - class DomainNameResolver; - class DomainNameResolveError; - class IQRouter; + 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 { - public: - SOCKS5BytestreamProxiesManager(ConnectionFactory*, TimerFactory*, DomainNameResolver*, IQRouter*, const JID&); - ~SOCKS5BytestreamProxiesManager(); + /** + * - manages list of working S5B proxies + * - creates initial connections (for the candidates you provide) + */ + class SWIFTEN_API SOCKS5BytestreamProxiesManager { + public: + SOCKS5BytestreamProxiesManager(ConnectionFactory*, TimerFactory*, DomainNameResolver*, IQRouter*, const JID&); + ~SOCKS5BytestreamProxiesManager(); - void addS5BProxy(S5BProxyRequest::ref); + void addS5BProxy(S5BProxyRequest::ref); - /* - * Returns a list of external S5B proxies. If the optinal return value is not initialized a discovery process has been started and - * onDiscoveredProxiesChanged signal will be emitted when it is finished. - */ - const boost::optional<std::vector<S5BProxyRequest::ref> >& getOrDiscoverS5BProxies(); + /* + * Returns a list of external S5B proxies. If the optinal return value is not initialized a discovery process has been started and + * onDiscoveredProxiesChanged signal will be emitted when it is finished. + */ + const boost::optional<std::vector<S5BProxyRequest::ref> >& getOrDiscoverS5BProxies(); - void connectToProxies(const std::string& sessionID); - boost::shared_ptr<SOCKS5BytestreamClientSession> getProxySessionAndCloseOthers(const JID& proxyJID, const std::string& sessionID); + void connectToProxies(const std::string& sessionID); + std::shared_ptr<SOCKS5BytestreamClientSession> getProxySessionAndCloseOthers(const JID& proxyJID, const std::string& sessionID); - boost::shared_ptr<SOCKS5BytestreamClientSession> createSOCKS5BytestreamClientSession(HostAddressPort addressPort, const std::string& destAddr); + std::shared_ptr<SOCKS5BytestreamClientSession> createSOCKS5BytestreamClientSession(HostAddressPort addressPort, const std::string& destAddr); - public: - boost::signal<void ()> onDiscoveredProxiesChanged; + public: + boost::signals2::signal<void ()> onDiscoveredProxiesChanged; - private: - void handleProxiesFound(std::vector<S5BProxyRequest::ref> proxyHosts); - void handleNameLookupResult(const std::vector<HostAddress>&, boost::optional<DomainNameResolveError>, S5BProxyRequest::ref proxy); + private: + void handleProxiesFound(std::vector<S5BProxyRequest::ref> proxyHosts); + void handleNameLookupResult(const std::vector<HostAddress>&, boost::optional<DomainNameResolveError>, S5BProxyRequest::ref proxy); - void queryForProxies(); + 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); + void handleProxySessionReady(const std::string& sessionID, const JID& jid, std::shared_ptr<SOCKS5BytestreamClientSession> session, bool error); + void handleProxySessionFinished(const std::string& sessionID, const JID& jid, std::shared_ptr<SOCKS5BytestreamClientSession> session, boost::optional<FileTransferError> error); - private: - ConnectionFactory* connectionFactory_; - TimerFactory* timerFactory_; - DomainNameResolver* resolver_; - IQRouter* iqRouter_; - JID serviceRoot_; + private: + ConnectionFactory* connectionFactory_; + TimerFactory* timerFactory_; + DomainNameResolver* resolver_; + IQRouter* iqRouter_; + JID serviceRoot_; - typedef std::vector<std::pair<JID, boost::shared_ptr<SOCKS5BytestreamClientSession> > > ProxyJIDClientSessionVector; - typedef std::map<std::string, ProxyJIDClientSessionVector> ProxySessionsMap; - ProxySessionsMap proxySessions_; + typedef std::vector<std::pair<JID, std::shared_ptr<SOCKS5BytestreamClientSession> > > ProxyJIDClientSessionVector; + typedef std::map<std::string, ProxyJIDClientSessionVector> ProxySessionsMap; + ProxySessionsMap proxySessions_; - boost::shared_ptr<SOCKS5BytestreamProxyFinder> proxyFinder_; + std::shared_ptr<SOCKS5BytestreamProxyFinder> proxyFinder_; - boost::optional<std::vector<S5BProxyRequest::ref> > localS5BProxies_; - }; + boost::optional<std::vector<S5BProxyRequest::ref> > localS5BProxies_; + }; } diff --git a/Swiften/FileTransfer/SOCKS5BytestreamProxyFinder.cpp b/Swiften/FileTransfer/SOCKS5BytestreamProxyFinder.cpp index 78cf2e6..90c42dd 100644 --- a/Swiften/FileTransfer/SOCKS5BytestreamProxyFinder.cpp +++ b/Swiften/FileTransfer/SOCKS5BytestreamProxyFinder.cpp @@ -5,18 +5,18 @@ */ /* - * Copyright (c) 2015 Isode Limited. + * Copyright (c) 2015-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #include <Swiften/FileTransfer/SOCKS5BytestreamProxyFinder.h> +#include <memory> + #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> @@ -30,58 +30,57 @@ 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(); + serviceWalker = std::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(); + for (auto&& 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, request, _1, _2)); - pendingRequests.insert(request); - request->send(); + S5BProxyRequest::ref proxyRequest = std::make_shared<S5BProxyRequest>(); + std::shared_ptr<GenericRequest<S5BProxyRequest> > request = std::make_shared<GenericRequest<S5BProxyRequest> >(IQ::Get, jid, proxyRequest, iqRouter); + 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::handleServiceFound(const JID& jid, std::shared_ptr<DiscoInfo> discoInfo) { + if (discoInfo->hasFeature(DiscoInfo::Bytestream)) { + sendBytestreamQuery(jid); + } } void SOCKS5BytestreamProxyFinder::handleWalkEnded() { - if (pendingRequests.empty()) { - onProxiesFound(proxyHosts); - } + 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) { - SWIFT_LOG(debug) << "add request" << std::endl; - proxyHosts.push_back(request); - } - } - if (pendingRequests.empty() && !serviceWalker->isActive()) { - onProxiesFound(proxyHosts); - } +void SOCKS5BytestreamProxyFinder::handleProxyResponse(std::shared_ptr<GenericRequest<S5BProxyRequest> > requester, std::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) { + 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 1c24497..893f475 100644 --- a/Swiften/FileTransfer/SOCKS5BytestreamProxyFinder.h +++ b/Swiften/FileTransfer/SOCKS5BytestreamProxyFinder.h @@ -5,7 +5,7 @@ */ /* - * Copyright (c) 2015 Isode Limited. + * Copyright (c) 2015-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ @@ -13,7 +13,7 @@ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> #include <Swiften/Base/API.h> #include <Swiften/Disco/DiscoServiceWalker.h> @@ -29,28 +29,28 @@ class IQRouter; * restrictive environments. */ class SWIFTEN_API SOCKS5BytestreamProxyFinder { - public: - SOCKS5BytestreamProxyFinder(const JID& service, IQRouter *iqRouter); - ~SOCKS5BytestreamProxyFinder(); + public: + SOCKS5BytestreamProxyFinder(const JID& service, IQRouter *iqRouter); + ~SOCKS5BytestreamProxyFinder(); - void start(); - void stop(); + void start(); + void stop(); - boost::signal<void(std::vector<boost::shared_ptr<S5BProxyRequest> >)> onProxiesFound; + boost::signals2::signal<void(std::vector<std::shared_ptr<S5BProxyRequest> >)> onProxiesFound; - private: - void sendBytestreamQuery(const JID&); + private: + void sendBytestreamQuery(const JID&); - void handleServiceFound(const JID&, boost::shared_ptr<DiscoInfo>); - void handleProxyResponse(boost::shared_ptr<GenericRequest<S5BProxyRequest> > requester, boost::shared_ptr<S5BProxyRequest>, ErrorPayload::ref); - void handleWalkEnded(); + void handleServiceFound(const JID&, std::shared_ptr<DiscoInfo>); + void handleProxyResponse(std::shared_ptr<GenericRequest<S5BProxyRequest> > requester, std::shared_ptr<S5BProxyRequest>, ErrorPayload::ref); + void handleWalkEnded(); - private: - JID service; - IQRouter* iqRouter; - boost::shared_ptr<DiscoServiceWalker> serviceWalker; - std::vector<S5BProxyRequest::ref> proxyHosts; - std::set<boost::shared_ptr<GenericRequest<S5BProxyRequest> > > pendingRequests; + private: + JID service; + IQRouter* iqRouter; + std::shared_ptr<DiscoServiceWalker> serviceWalker; + std::vector<S5BProxyRequest::ref> proxyHosts; + std::set<std::shared_ptr<GenericRequest<S5BProxyRequest> > > pendingRequests; }; } diff --git a/Swiften/FileTransfer/SOCKS5BytestreamRegistry.cpp b/Swiften/FileTransfer/SOCKS5BytestreamRegistry.cpp index 5f3756d..9e214fc 100644 --- a/Swiften/FileTransfer/SOCKS5BytestreamRegistry.cpp +++ b/Swiften/FileTransfer/SOCKS5BytestreamRegistry.cpp @@ -1,16 +1,15 @@ /* - * Copyright (c) 2010-2013 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #include <Swiften/FileTransfer/SOCKS5BytestreamRegistry.h> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> #include <Swiften/Base/Algorithm.h> #include <Swiften/Base/Log.h> -#include <Swiften/Base/foreach.h> namespace Swift { @@ -18,20 +17,20 @@ SOCKS5BytestreamRegistry::SOCKS5BytestreamRegistry() { } void SOCKS5BytestreamRegistry::setHasBytestream(const std::string& destination, bool b) { - if (b) { - availableBytestreams.insert(destination); - } - else { - availableBytestreams.erase(destination); - } + if (b) { + availableBytestreams.insert(destination); + } + else { + availableBytestreams.erase(destination); + } } bool SOCKS5BytestreamRegistry::hasBytestream(const std::string& destination) const { - return availableBytestreams.find(destination) != availableBytestreams.end(); + return availableBytestreams.find(destination) != availableBytestreams.end(); } std::string SOCKS5BytestreamRegistry::generateSessionID() { - return idGenerator.generateID(); + return idGenerator.generateID(); } } diff --git a/Swiften/FileTransfer/SOCKS5BytestreamRegistry.h b/Swiften/FileTransfer/SOCKS5BytestreamRegistry.h index 240d98d..2fa67fa 100644 --- a/Swiften/FileTransfer/SOCKS5BytestreamRegistry.h +++ b/Swiften/FileTransfer/SOCKS5BytestreamRegistry.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2013 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ @@ -7,29 +7,29 @@ #pragma once #include <map> -#include <string> #include <set> +#include <string> #include <Swiften/Base/API.h> #include <Swiften/Base/IDGenerator.h> namespace Swift { - class SOCKS5BytestreamServerSession; + class SOCKS5BytestreamServerSession; - class SWIFTEN_API SOCKS5BytestreamRegistry { - public: - SOCKS5BytestreamRegistry(); + class SWIFTEN_API SOCKS5BytestreamRegistry { + public: + SOCKS5BytestreamRegistry(); - void setHasBytestream(const std::string& destination, bool); - bool hasBytestream(const std::string& destination) const; + void setHasBytestream(const std::string& destination, bool); + bool hasBytestream(const std::string& destination) const; - /** - * Generate a new session ID to use for new S5B streams. - */ - std::string generateSessionID(); + /** + * Generate a new session ID to use for new S5B streams. + */ + std::string generateSessionID(); - private: - std::set<std::string> availableBytestreams; - IDGenerator idGenerator; - }; + private: + std::set<std::string> availableBytestreams; + IDGenerator idGenerator; + }; } diff --git a/Swiften/FileTransfer/SOCKS5BytestreamServer.cpp b/Swiften/FileTransfer/SOCKS5BytestreamServer.cpp index da56438..483ea18 100644 --- a/Swiften/FileTransfer/SOCKS5BytestreamServer.cpp +++ b/Swiften/FileTransfer/SOCKS5BytestreamServer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2013 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ @@ -9,60 +9,59 @@ #include <boost/bind.hpp> #include <Swiften/Base/Log.h> -#include <Swiften/Base/foreach.h> -#include <Swiften/StringCodecs/Hexify.h> #include <Swiften/Crypto/CryptoProvider.h> -#include <Swiften/FileTransfer/SOCKS5BytestreamServerSession.h> #include <Swiften/FileTransfer/SOCKS5BytestreamRegistry.h> +#include <Swiften/FileTransfer/SOCKS5BytestreamServerSession.h> +#include <Swiften/StringCodecs/Hexify.h> namespace Swift { SOCKS5BytestreamServer::SOCKS5BytestreamServer( - boost::shared_ptr<ConnectionServer> connectionServer, - SOCKS5BytestreamRegistry* registry) : - connectionServer(connectionServer), - registry(registry) { + std::shared_ptr<ConnectionServer> connectionServer, + SOCKS5BytestreamRegistry* registry) : + connectionServer(connectionServer), + registry(registry) { } void SOCKS5BytestreamServer::start() { - connectionServer->onNewConnection.connect(boost::bind(&SOCKS5BytestreamServer::handleNewConnection, this, _1)); + connectionServer->onNewConnection.connect(boost::bind(&SOCKS5BytestreamServer::handleNewConnection, this, _1)); } void SOCKS5BytestreamServer::stop() { - connectionServer->onNewConnection.disconnect(boost::bind(&SOCKS5BytestreamServer::handleNewConnection, this, _1)); - foreach (boost::shared_ptr<SOCKS5BytestreamServerSession> session, sessions) { - session->onFinished.disconnect(boost::bind(&SOCKS5BytestreamServer::handleSessionFinished, this, session)); - session->stop(); - } - sessions.clear(); + connectionServer->onNewConnection.disconnect(boost::bind(&SOCKS5BytestreamServer::handleNewConnection, this, _1)); + for (auto&& session : sessions) { + session->onFinished.disconnect(boost::bind(&SOCKS5BytestreamServer::handleSessionFinished, this, session)); + session->stop(); + } + sessions.clear(); } -void SOCKS5BytestreamServer::handleNewConnection(boost::shared_ptr<Connection> connection) { - boost::shared_ptr<SOCKS5BytestreamServerSession> session = - boost::make_shared<SOCKS5BytestreamServerSession>(connection, registry); - session->onFinished.connect(boost::bind(&SOCKS5BytestreamServer::handleSessionFinished, this, session)); - sessions.push_back(session); - session->start(); +void SOCKS5BytestreamServer::handleNewConnection(std::shared_ptr<Connection> connection) { + std::shared_ptr<SOCKS5BytestreamServerSession> session = + std::make_shared<SOCKS5BytestreamServerSession>(connection, registry); + session->onFinished.connect(boost::bind(&SOCKS5BytestreamServer::handleSessionFinished, this, session)); + sessions.push_back(session); + session->start(); } HostAddressPort SOCKS5BytestreamServer::getAddressPort() const { - return connectionServer->getAddressPort(); + return connectionServer->getAddressPort(); } -std::vector< boost::shared_ptr<SOCKS5BytestreamServerSession> > SOCKS5BytestreamServer::getSessions( - const std::string& streamID) const { - std::vector< boost::shared_ptr<SOCKS5BytestreamServerSession> > result; - foreach (boost::shared_ptr<SOCKS5BytestreamServerSession> session, sessions) { - if (session->getStreamID() == streamID) { - result.push_back(session); - } - } - return result; +std::vector< std::shared_ptr<SOCKS5BytestreamServerSession> > SOCKS5BytestreamServer::getSessions( + const std::string& streamID) const { + std::vector< std::shared_ptr<SOCKS5BytestreamServerSession> > result; + for (auto&& session : sessions) { + if (session->getStreamID() == streamID) { + result.push_back(session); + } + } + return result; } -void SOCKS5BytestreamServer::handleSessionFinished(boost::shared_ptr<SOCKS5BytestreamServerSession> session) { - sessions.erase(std::remove(sessions.begin(), sessions.end(), session), sessions.end()); - session->onFinished.disconnect(boost::bind(&SOCKS5BytestreamServer::handleSessionFinished, this, session)); +void SOCKS5BytestreamServer::handleSessionFinished(std::shared_ptr<SOCKS5BytestreamServerSession> session) { + sessions.erase(std::remove(sessions.begin(), sessions.end(), session), sessions.end()); + session->onFinished.disconnect(boost::bind(&SOCKS5BytestreamServer::handleSessionFinished, this, session)); } } diff --git a/Swiften/FileTransfer/SOCKS5BytestreamServer.h b/Swiften/FileTransfer/SOCKS5BytestreamServer.h index c11de84..c8866c4 100644 --- a/Swiften/FileTransfer/SOCKS5BytestreamServer.h +++ b/Swiften/FileTransfer/SOCKS5BytestreamServer.h @@ -1,48 +1,48 @@ /* - * Copyright (c) 2010-2015 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <boost/shared_ptr.hpp> #include <map> - -#include <Swiften/Network/ConnectionServer.h> +#include <memory> #include <string> + #include <Swiften/Base/API.h> -#include <Swiften/JID/JID.h> #include <Swiften/FileTransfer/ReadBytestream.h> #include <Swiften/FileTransfer/SOCKS5BytestreamRegistry.h> +#include <Swiften/JID/JID.h> +#include <Swiften/Network/ConnectionServer.h> namespace Swift { - class SOCKS5BytestreamServerSession; - class CryptoProvider; + class SOCKS5BytestreamServerSession; + class CryptoProvider; - class SWIFTEN_API SOCKS5BytestreamServer { - public: - SOCKS5BytestreamServer( - boost::shared_ptr<ConnectionServer> connectionServer, - SOCKS5BytestreamRegistry* registry); + class SWIFTEN_API SOCKS5BytestreamServer { + public: + SOCKS5BytestreamServer( + std::shared_ptr<ConnectionServer> connectionServer, + SOCKS5BytestreamRegistry* registry); - HostAddressPort getAddressPort() const; + HostAddressPort getAddressPort() const; - void start(); - void stop(); + void start(); + void stop(); - std::vector< boost::shared_ptr<SOCKS5BytestreamServerSession> > getSessions(const std::string& id) const; + std::vector< std::shared_ptr<SOCKS5BytestreamServerSession> > getSessions(const std::string& id) const; - private: - void handleNewConnection(boost::shared_ptr<Connection> connection); - void handleSessionFinished(boost::shared_ptr<SOCKS5BytestreamServerSession>); + private: + void handleNewConnection(std::shared_ptr<Connection> connection); + void handleSessionFinished(std::shared_ptr<SOCKS5BytestreamServerSession>); - private: - friend class SOCKS5BytestreamServerSession; + private: + friend class SOCKS5BytestreamServerSession; - boost::shared_ptr<ConnectionServer> connectionServer; - SOCKS5BytestreamRegistry* registry; - std::vector<boost::shared_ptr<SOCKS5BytestreamServerSession> > sessions; - }; + std::shared_ptr<ConnectionServer> connectionServer; + SOCKS5BytestreamRegistry* registry; + std::vector<std::shared_ptr<SOCKS5BytestreamServerSession> > sessions; + }; } diff --git a/Swiften/FileTransfer/SOCKS5BytestreamServerManager.cpp b/Swiften/FileTransfer/SOCKS5BytestreamServerManager.cpp index 3b1be89..f749735 100644 --- a/Swiften/FileTransfer/SOCKS5BytestreamServerManager.cpp +++ b/Swiften/FileTransfer/SOCKS5BytestreamServerManager.cpp @@ -12,11 +12,11 @@ #include <Swiften/FileTransfer/SOCKS5BytestreamServerManager.h> +#include <memory> + #include <boost/bind.hpp> -#include <boost/smart_ptr/make_shared.hpp> #include <Swiften/Base/Log.h> -#include <Swiften/Base/foreach.h> #include <Swiften/FileTransfer/SOCKS5BytestreamServer.h> #include <Swiften/FileTransfer/SOCKS5BytestreamServerPortForwardingUser.h> #include <Swiften/FileTransfer/SOCKS5BytestreamServerResourceUser.h> @@ -34,223 +34,223 @@ static const int LISTEN_PORTS_BEGIN = 10000; static const int LISTEN_PORTS_END = 11000; SOCKS5BytestreamServerManager::SOCKS5BytestreamServerManager( - SOCKS5BytestreamRegistry* bytestreamRegistry, - ConnectionServerFactory* connectionServerFactory, - NetworkEnvironment* networkEnvironment, - NATTraverser* natTraverser) : - bytestreamRegistry(bytestreamRegistry), - connectionServerFactory(connectionServerFactory), - networkEnvironment(networkEnvironment), - natTraverser(natTraverser), - state(Start), - server(NULL), - attemptedPortMapping_(false) { + SOCKS5BytestreamRegistry* bytestreamRegistry, + ConnectionServerFactory* connectionServerFactory, + NetworkEnvironment* networkEnvironment, + NATTraverser* natTraverser) : + bytestreamRegistry(bytestreamRegistry), + connectionServerFactory(connectionServerFactory), + networkEnvironment(networkEnvironment), + natTraverser(natTraverser), + state(Start), + server(nullptr), + attemptedPortMapping_(false) { } SOCKS5BytestreamServerManager::~SOCKS5BytestreamServerManager() { - SWIFT_LOG_ASSERT(!connectionServer, warning) << std::endl; - SWIFT_LOG_ASSERT(!getPublicIPRequest, warning) << std::endl; - SWIFT_LOG_ASSERT(!forwardPortRequest, warning) << std::endl; - SWIFT_LOG_ASSERT(state == Start, warning) << std::endl; - if (portMapping && !unforwardPortRequest) { - SWIFT_LOG(warning) << "Port forwarding still alive. Trying to remove it now." << std::endl; - unforwardPortRequest = natTraverser->createRemovePortForwardingRequest(portMapping.get().getLocalPort(), portMapping.get().getPublicPort()); - unforwardPortRequest->start(); - } + SWIFT_LOG_ASSERT(!connectionServer, warning) << std::endl; + SWIFT_LOG_ASSERT(!getPublicIPRequest, warning) << std::endl; + SWIFT_LOG_ASSERT(!forwardPortRequest, warning) << std::endl; + SWIFT_LOG_ASSERT(state == Start, warning) << std::endl; + if (portMapping && !unforwardPortRequest) { + SWIFT_LOG(warning) << "Port forwarding still alive. Trying to remove it now." << std::endl; + unforwardPortRequest = natTraverser->createRemovePortForwardingRequest(portMapping.get().getLocalPort(), portMapping.get().getPublicPort()); + unforwardPortRequest->start(); + } } -boost::shared_ptr<SOCKS5BytestreamServerResourceUser> SOCKS5BytestreamServerManager::aquireResourceUser() { - boost::shared_ptr<SOCKS5BytestreamServerResourceUser> resourceUser; - if (s5bServerResourceUser_.expired()) { - resourceUser = boost::make_shared<SOCKS5BytestreamServerResourceUser>(this); - s5bServerResourceUser_ = resourceUser; - } - else { - resourceUser = s5bServerResourceUser_.lock(); - } - return resourceUser; +std::shared_ptr<SOCKS5BytestreamServerResourceUser> SOCKS5BytestreamServerManager::aquireResourceUser() { + std::shared_ptr<SOCKS5BytestreamServerResourceUser> resourceUser; + if (s5bServerResourceUser_.expired()) { + resourceUser = std::make_shared<SOCKS5BytestreamServerResourceUser>(this); + s5bServerResourceUser_ = resourceUser; + } + else { + resourceUser = s5bServerResourceUser_.lock(); + } + return resourceUser; } -boost::shared_ptr<SOCKS5BytestreamServerPortForwardingUser> SOCKS5BytestreamServerManager::aquirePortForwardingUser() { - boost::shared_ptr<SOCKS5BytestreamServerPortForwardingUser> portForwardingUser; - if (s5bServerPortForwardingUser_.expired()) { - portForwardingUser = boost::make_shared<SOCKS5BytestreamServerPortForwardingUser>(this); - s5bServerPortForwardingUser_ = portForwardingUser; - } - else { - portForwardingUser = s5bServerPortForwardingUser_.lock(); - } - return portForwardingUser; +std::shared_ptr<SOCKS5BytestreamServerPortForwardingUser> SOCKS5BytestreamServerManager::aquirePortForwardingUser() { + std::shared_ptr<SOCKS5BytestreamServerPortForwardingUser> portForwardingUser; + if (s5bServerPortForwardingUser_.expired()) { + portForwardingUser = std::make_shared<SOCKS5BytestreamServerPortForwardingUser>(this); + s5bServerPortForwardingUser_ = portForwardingUser; + } + else { + portForwardingUser = s5bServerPortForwardingUser_.lock(); + } + return portForwardingUser; } std::vector<HostAddressPort> SOCKS5BytestreamServerManager::getHostAddressPorts() const { - std::vector<HostAddressPort> result; - if (connectionServer) { - std::vector<NetworkInterface> networkInterfaces = networkEnvironment->getNetworkInterfaces(); - foreach (const NetworkInterface& networkInterface, networkInterfaces) { - foreach (const HostAddress& address, networkInterface.getAddresses()) { - result.push_back(HostAddressPort(address, connectionServerPort)); - } - } - } - return result; + std::vector<HostAddressPort> result; + if (connectionServer) { + std::vector<NetworkInterface> networkInterfaces = networkEnvironment->getNetworkInterfaces(); + for (const auto& networkInterface : networkInterfaces) { + for (const auto& address : networkInterface.getAddresses()) { + result.push_back(HostAddressPort(address, connectionServerPort)); + } + } + } + return result; } std::vector<HostAddressPort> SOCKS5BytestreamServerManager::getAssistedHostAddressPorts() const { - std::vector<HostAddressPort> result; - if (publicAddress && portMapping) { - result.push_back(HostAddressPort(*publicAddress, portMapping->getPublicPort())); - } - return result; + std::vector<HostAddressPort> result; + if (publicAddress && portMapping) { + result.push_back(HostAddressPort(*publicAddress, portMapping->getPublicPort())); + } + return result; } bool SOCKS5BytestreamServerManager::isInitialized() const { - return state == Initialized; + return state == Initialized; } void SOCKS5BytestreamServerManager::initialize() { - if (state == Start) { - state = Initializing; - - // Find a port to listen on - assert(!connectionServer); - int port; - for (port = LISTEN_PORTS_BEGIN; port < LISTEN_PORTS_END; ++port) { - SWIFT_LOG(debug) << "Trying to start server on port " << port << std::endl; - connectionServer = connectionServerFactory->createConnectionServer(HostAddress("::"), port); - boost::optional<ConnectionServer::Error> error = connectionServer->tryStart(); - if (!error) { - break; - } - else if (*error != ConnectionServer::Conflict) { - SWIFT_LOG(debug) << "Error starting server" << std::endl; - onInitialized(false); - return; - } - connectionServer.reset(); - } - if (!connectionServer) { - SWIFT_LOG(debug) << "Unable to find an open port" << std::endl; - onInitialized(false); - return; - } - SWIFT_LOG(debug) << "Server started succesfully" << std::endl; - connectionServerPort = port; - - // Start bytestream server. Should actually happen before the connectionserver is started - // but that doesn't really matter here. - assert(!server); - server = new SOCKS5BytestreamServer(connectionServer, bytestreamRegistry); - server->start(); - checkInitializeFinished(); - } + if (state == Start) { + state = Initializing; + + // Find a port to listen on + assert(!connectionServer); + int port; + for (port = LISTEN_PORTS_BEGIN; port < LISTEN_PORTS_END; ++port) { + SWIFT_LOG(debug) << "Trying to start server on port " << port << std::endl; + connectionServer = connectionServerFactory->createConnectionServer(HostAddress::fromString("::").get(), port); + boost::optional<ConnectionServer::Error> error = connectionServer->tryStart(); + if (!error) { + break; + } + else if (*error != ConnectionServer::Conflict) { + SWIFT_LOG(debug) << "Error starting server" << std::endl; + onInitialized(false); + return; + } + connectionServer.reset(); + } + if (!connectionServer) { + SWIFT_LOG(debug) << "Unable to find an open port" << std::endl; + onInitialized(false); + return; + } + SWIFT_LOG(debug) << "Server started succesfully" << std::endl; + connectionServerPort = port; + + // Start bytestream server. Should actually happen before the connectionserver is started + // but that doesn't really matter here. + assert(!server); + server = new SOCKS5BytestreamServer(connectionServer, bytestreamRegistry); + server->start(); + checkInitializeFinished(); + } } bool SOCKS5BytestreamServerManager::isPortForwardingReady() const { - return attemptedPortMapping_ && !getPublicIPRequest && !forwardPortRequest; + return attemptedPortMapping_ && !getPublicIPRequest && !forwardPortRequest; } void SOCKS5BytestreamServerManager::setupPortForwarding() { - assert(server); - attemptedPortMapping_ = true; - - // Retrieve public addresses - assert(!getPublicIPRequest); - publicAddress = boost::optional<HostAddress>(); - if ((getPublicIPRequest = natTraverser->createGetPublicIPRequest())) { - getPublicIPRequest->onResult.connect( - boost::bind(&SOCKS5BytestreamServerManager::handleGetPublicIPResult, this, _1)); - getPublicIPRequest->start(); - } - - // Forward ports - int port = server->getAddressPort().getPort(); - assert(!forwardPortRequest); - portMapping = boost::optional<NATPortMapping>(); - if ((forwardPortRequest = natTraverser->createForwardPortRequest(port, port))) { - forwardPortRequest->onResult.connect( - boost::bind(&SOCKS5BytestreamServerManager::handleForwardPortResult, this, _1)); - forwardPortRequest->start(); - } + assert(server); + attemptedPortMapping_ = true; + + // Retrieve public addresses + assert(!getPublicIPRequest); + publicAddress = boost::optional<HostAddress>(); + if ((getPublicIPRequest = natTraverser->createGetPublicIPRequest())) { + getPublicIPRequest->onResult.connect( + boost::bind(&SOCKS5BytestreamServerManager::handleGetPublicIPResult, this, _1)); + getPublicIPRequest->start(); + } + + // Forward ports + int port = server->getAddressPort().getPort(); + assert(!forwardPortRequest); + portMapping = boost::optional<NATPortMapping>(); + if ((forwardPortRequest = natTraverser->createForwardPortRequest(port, port))) { + forwardPortRequest->onResult.connect( + boost::bind(&SOCKS5BytestreamServerManager::handleForwardPortResult, this, _1)); + forwardPortRequest->start(); + } } void SOCKS5BytestreamServerManager::removePortForwarding() { - // remove port forwards - if (portMapping) { - unforwardPortRequest = natTraverser->createRemovePortForwardingRequest(portMapping.get().getLocalPort(), portMapping.get().getPublicPort()); - unforwardPortRequest->onResult.connect(boost::bind(&SOCKS5BytestreamServerManager::handleUnforwardPortResult, this, _1)); - unforwardPortRequest->start(); - } + // remove port forwards + if (portMapping) { + unforwardPortRequest = natTraverser->createRemovePortForwardingRequest(portMapping.get().getLocalPort(), portMapping.get().getPublicPort()); + unforwardPortRequest->onResult.connect(boost::bind(&SOCKS5BytestreamServerManager::handleUnforwardPortResult, this, _1)); + unforwardPortRequest->start(); + } } void SOCKS5BytestreamServerManager::stop() { - if (getPublicIPRequest) { - getPublicIPRequest->stop(); - getPublicIPRequest.reset(); - } - if (forwardPortRequest) { - forwardPortRequest->stop(); - forwardPortRequest.reset(); - } - if (unforwardPortRequest) { - unforwardPortRequest->stop(); - unforwardPortRequest.reset(); - } - if (server) { - server->stop(); - delete server; - server = NULL; - } - if (connectionServer) { - connectionServer->stop(); - connectionServer.reset(); - } - - state = Start; + if (getPublicIPRequest) { + getPublicIPRequest->stop(); + getPublicIPRequest.reset(); + } + if (forwardPortRequest) { + forwardPortRequest->stop(); + forwardPortRequest.reset(); + } + if (unforwardPortRequest) { + unforwardPortRequest->stop(); + unforwardPortRequest.reset(); + } + if (server) { + server->stop(); + delete server; + server = nullptr; + } + if (connectionServer) { + connectionServer->stop(); + connectionServer.reset(); + } + + state = Start; } void SOCKS5BytestreamServerManager::handleGetPublicIPResult(boost::optional<HostAddress> address) { - if (address) { - SWIFT_LOG(debug) << "Public IP discovered as " << address.get().toString() << "." << std::endl; - } - else { - SWIFT_LOG(debug) << "No public IP discoverable." << std::endl; - } + if (address) { + SWIFT_LOG(debug) << "Public IP discovered as " << address.get().toString() << "." << std::endl; + } + else { + SWIFT_LOG(debug) << "No public IP discoverable." << std::endl; + } - publicAddress = address; + publicAddress = address; - getPublicIPRequest->stop(); - getPublicIPRequest.reset(); + getPublicIPRequest->stop(); + getPublicIPRequest.reset(); } void SOCKS5BytestreamServerManager::handleForwardPortResult(boost::optional<NATPortMapping> mapping) { - if (mapping) { - SWIFT_LOG(debug) << "Mapping port was successful." << std::endl; - } - else { - SWIFT_LOG(debug) << "Mapping port has failed." << std::endl; - } - - portMapping = mapping; - onPortForwardingSetup(mapping.is_initialized()); - - forwardPortRequest->stop(); - forwardPortRequest.reset(); + if (mapping) { + SWIFT_LOG(debug) << "Mapping port was successful." << std::endl; + } + else { + SWIFT_LOG(debug) << "Mapping port has failed." << std::endl; + } + + portMapping = mapping; + onPortForwardingSetup(mapping.is_initialized()); + + forwardPortRequest->stop(); + forwardPortRequest.reset(); } void SOCKS5BytestreamServerManager::handleUnforwardPortResult(boost::optional<bool> result) { - if (result.is_initialized() && result.get()) { - portMapping.reset(); - } - else { - SWIFT_LOG(warning) << "Failed to remove port forwarding." << std::endl; - } - attemptedPortMapping_ = false; - unforwardPortRequest.reset(); + if (result.is_initialized() && result.get()) { + portMapping.reset(); + } + else { + SWIFT_LOG(warning) << "Failed to remove port forwarding." << std::endl; + } + attemptedPortMapping_ = false; + unforwardPortRequest.reset(); } void SOCKS5BytestreamServerManager::checkInitializeFinished() { - assert(state == Initializing); - state = Initialized; - onInitialized(true); + assert(state == Initializing); + state = Initialized; + onInitialized(true); } diff --git a/Swiften/FileTransfer/SOCKS5BytestreamServerManager.h b/Swiften/FileTransfer/SOCKS5BytestreamServerManager.h index 180745d..3c06513 100644 --- a/Swiften/FileTransfer/SOCKS5BytestreamServerManager.h +++ b/Swiften/FileTransfer/SOCKS5BytestreamServerManager.h @@ -1,94 +1,94 @@ /* - * Copyright (c) 2012-2015 Isode Limited. + * Copyright (c) 2012-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #pragma once +#include <memory> #include <vector> -#include <boost/shared_ptr.hpp> -#include <boost/weak_ptr.hpp> + +#include <boost/signals2.hpp> #include <Swiften/Base/API.h> -#include <Swiften/Base/boost_bsignals.h> #include <Swiften/Network/HostAddressPort.h> #include <Swiften/Network/NATPortMapping.h> namespace Swift { - class NetworkEnvironment; - class NATTraverser; - class NATTraversalGetPublicIPRequest; - class NATTraversalForwardPortRequest; - class NATTraversalRemovePortForwardingRequest; - class SOCKS5BytestreamRegistry; - class ConnectionServerFactory; - class ConnectionServer; - class SOCKS5BytestreamServer; - class SOCKS5BytestreamServerResourceUser; - class SOCKS5BytestreamServerPortForwardingUser; - - class SWIFTEN_API SOCKS5BytestreamServerManager { - friend class SOCKS5BytestreamServerResourceUser; - friend class SOCKS5BytestreamServerPortForwardingUser; - - public: - SOCKS5BytestreamServerManager( - SOCKS5BytestreamRegistry* bytestreamRegistry, - ConnectionServerFactory* connectionServerFactory, - NetworkEnvironment* networkEnvironment, - NATTraverser* natTraverser); - ~SOCKS5BytestreamServerManager(); - - boost::shared_ptr<SOCKS5BytestreamServerResourceUser> aquireResourceUser(); - boost::shared_ptr<SOCKS5BytestreamServerPortForwardingUser> aquirePortForwardingUser(); - - void stop(); - - std::vector<HostAddressPort> getHostAddressPorts() const; - std::vector<HostAddressPort> getAssistedHostAddressPorts() const; - - SOCKS5BytestreamServer* getServer() const { - return server; - } - - private: - bool isInitialized() const; - void initialize(); - - bool isPortForwardingReady() const; - void setupPortForwarding(); - void removePortForwarding(); - - void checkInitializeFinished(); - - void handleGetPublicIPResult(boost::optional<HostAddress> address); - void handleForwardPortResult(boost::optional<NATPortMapping> mapping); - void handleUnforwardPortResult(boost::optional<bool> result); - - boost::signal<void (bool /* success */)> onInitialized; - boost::signal<void (bool /* success */)> onPortForwardingSetup; - - private: - friend class SOCKS5BytestreamServerInitializeRequest; - SOCKS5BytestreamRegistry* bytestreamRegistry; - ConnectionServerFactory* connectionServerFactory; - NetworkEnvironment* networkEnvironment; - NATTraverser* natTraverser; - enum { Start, Initializing, Initialized } state; - SOCKS5BytestreamServer* server; - boost::shared_ptr<ConnectionServer> connectionServer; - int connectionServerPort; - - boost::shared_ptr<NATTraversalGetPublicIPRequest> getPublicIPRequest; - boost::shared_ptr<NATTraversalForwardPortRequest> forwardPortRequest; - boost::shared_ptr<NATTraversalRemovePortForwardingRequest> unforwardPortRequest; - boost::optional<HostAddress> publicAddress; - boost::optional<NATPortMapping> portMapping; - bool attemptedPortMapping_; - - boost::weak_ptr<SOCKS5BytestreamServerResourceUser> s5bServerResourceUser_; - boost::weak_ptr<SOCKS5BytestreamServerPortForwardingUser> s5bServerPortForwardingUser_; - }; + class NetworkEnvironment; + class NATTraverser; + class NATTraversalGetPublicIPRequest; + class NATTraversalForwardPortRequest; + class NATTraversalRemovePortForwardingRequest; + class SOCKS5BytestreamRegistry; + class ConnectionServerFactory; + class ConnectionServer; + class SOCKS5BytestreamServer; + class SOCKS5BytestreamServerResourceUser; + class SOCKS5BytestreamServerPortForwardingUser; + + class SWIFTEN_API SOCKS5BytestreamServerManager { + friend class SOCKS5BytestreamServerResourceUser; + friend class SOCKS5BytestreamServerPortForwardingUser; + + public: + SOCKS5BytestreamServerManager( + SOCKS5BytestreamRegistry* bytestreamRegistry, + ConnectionServerFactory* connectionServerFactory, + NetworkEnvironment* networkEnvironment, + NATTraverser* natTraverser); + ~SOCKS5BytestreamServerManager(); + + std::shared_ptr<SOCKS5BytestreamServerResourceUser> aquireResourceUser(); + std::shared_ptr<SOCKS5BytestreamServerPortForwardingUser> aquirePortForwardingUser(); + + void stop(); + + std::vector<HostAddressPort> getHostAddressPorts() const; + std::vector<HostAddressPort> getAssistedHostAddressPorts() const; + + SOCKS5BytestreamServer* getServer() const { + return server; + } + + private: + bool isInitialized() const; + void initialize(); + + bool isPortForwardingReady() const; + void setupPortForwarding(); + void removePortForwarding(); + + void checkInitializeFinished(); + + void handleGetPublicIPResult(boost::optional<HostAddress> address); + void handleForwardPortResult(boost::optional<NATPortMapping> mapping); + void handleUnforwardPortResult(boost::optional<bool> result); + + boost::signals2::signal<void (bool /* success */)> onInitialized; + boost::signals2::signal<void (bool /* success */)> onPortForwardingSetup; + + private: + friend class SOCKS5BytestreamServerInitializeRequest; + SOCKS5BytestreamRegistry* bytestreamRegistry; + ConnectionServerFactory* connectionServerFactory; + NetworkEnvironment* networkEnvironment; + NATTraverser* natTraverser; + enum { Start, Initializing, Initialized } state; + SOCKS5BytestreamServer* server; + std::shared_ptr<ConnectionServer> connectionServer; + int connectionServerPort = -1; + + std::shared_ptr<NATTraversalGetPublicIPRequest> getPublicIPRequest; + std::shared_ptr<NATTraversalForwardPortRequest> forwardPortRequest; + std::shared_ptr<NATTraversalRemovePortForwardingRequest> unforwardPortRequest; + boost::optional<HostAddress> publicAddress; + boost::optional<NATPortMapping> portMapping; + bool attemptedPortMapping_; + + std::weak_ptr<SOCKS5BytestreamServerResourceUser> s5bServerResourceUser_; + std::weak_ptr<SOCKS5BytestreamServerPortForwardingUser> s5bServerPortForwardingUser_; + }; } diff --git a/Swiften/FileTransfer/SOCKS5BytestreamServerPortForwardingUser.cpp b/Swiften/FileTransfer/SOCKS5BytestreamServerPortForwardingUser.cpp index e3b6d34..fc7fe58 100644 --- a/Swiften/FileTransfer/SOCKS5BytestreamServerPortForwardingUser.cpp +++ b/Swiften/FileTransfer/SOCKS5BytestreamServerPortForwardingUser.cpp @@ -1,41 +1,41 @@ /* - * Copyright (c) 2015 Isode Limited. + * Copyright (c) 2015-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #include <Swiften/FileTransfer/SOCKS5BytestreamServerPortForwardingUser.h> -#include <Swiften/FileTransfer/SOCKS5BytestreamServerManager.h> - #include <boost/bind.hpp> +#include <Swiften/FileTransfer/SOCKS5BytestreamServerManager.h> + namespace Swift { SOCKS5BytestreamServerPortForwardingUser::SOCKS5BytestreamServerPortForwardingUser(SOCKS5BytestreamServerManager* s5bServerManager) : s5bServerManager_(s5bServerManager) { - // the server should be initialized, so we know what port to setup a forward for - assert(s5bServerManager->isInitialized()); - if (s5bServerManager_->isPortForwardingReady()) { - onSetup(!s5bServerManager_->getAssistedHostAddressPorts().empty()); - } - else { - onPortForwardingSetupConnection_ = s5bServerManager_->onPortForwardingSetup.connect(boost::bind(&SOCKS5BytestreamServerPortForwardingUser::handleServerManagerPortForwardingSetup, this, _1)); - s5bServerManager_->setupPortForwarding(); - } + // the server should be initialized, so we know what port to setup a forward for + assert(s5bServerManager->isInitialized()); + if (s5bServerManager_->isPortForwardingReady()) { + onSetup(!s5bServerManager_->getAssistedHostAddressPorts().empty()); + } + else { + onPortForwardingSetupConnection_ = s5bServerManager_->onPortForwardingSetup.connect(boost::bind(&SOCKS5BytestreamServerPortForwardingUser::handleServerManagerPortForwardingSetup, this, _1)); + s5bServerManager_->setupPortForwarding(); + } } SOCKS5BytestreamServerPortForwardingUser::~SOCKS5BytestreamServerPortForwardingUser() { - if (s5bServerManager_->isPortForwardingReady()) { - s5bServerManager_->removePortForwarding(); - } + if (s5bServerManager_->isPortForwardingReady()) { + s5bServerManager_->removePortForwarding(); + } } bool SOCKS5BytestreamServerPortForwardingUser::isForwardingSetup() const { - return s5bServerManager_->isPortForwardingReady(); + return s5bServerManager_->isPortForwardingReady(); } void SOCKS5BytestreamServerPortForwardingUser::handleServerManagerPortForwardingSetup(bool successful) { - onSetup(successful); + onSetup(successful); } } diff --git a/Swiften/FileTransfer/SOCKS5BytestreamServerPortForwardingUser.h b/Swiften/FileTransfer/SOCKS5BytestreamServerPortForwardingUser.h index cd79ecc..19f3897 100644 --- a/Swiften/FileTransfer/SOCKS5BytestreamServerPortForwardingUser.h +++ b/Swiften/FileTransfer/SOCKS5BytestreamServerPortForwardingUser.h @@ -1,33 +1,34 @@ /* - * Copyright (c) 2015 Isode Limited. + * Copyright (c) 2015-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #pragma once +#include <boost/signals2.hpp> + #include <Swiften/Base/API.h> -#include <Swiften/Base/boost_bsignals.h> namespace Swift { class SOCKS5BytestreamServerManager; class SWIFTEN_API SOCKS5BytestreamServerPortForwardingUser { - public: - SOCKS5BytestreamServerPortForwardingUser(SOCKS5BytestreamServerManager* s5bServerManager); - ~SOCKS5BytestreamServerPortForwardingUser(); + public: + SOCKS5BytestreamServerPortForwardingUser(SOCKS5BytestreamServerManager* s5bServerManager); + ~SOCKS5BytestreamServerPortForwardingUser(); - bool isForwardingSetup() const; + bool isForwardingSetup() const; - boost::signal<void (bool /* success */)> onSetup; + boost::signals2::signal<void (bool /* success */)> onSetup; - private: - void handleServerManagerPortForwardingSetup(bool successful); + private: + void handleServerManagerPortForwardingSetup(bool successful); - private: - SOCKS5BytestreamServerManager* s5bServerManager_; - boost::bsignals::scoped_connection onPortForwardingSetupConnection_; + private: + SOCKS5BytestreamServerManager* s5bServerManager_; + boost::signals2::scoped_connection onPortForwardingSetupConnection_; }; } diff --git a/Swiften/FileTransfer/SOCKS5BytestreamServerResourceUser.cpp b/Swiften/FileTransfer/SOCKS5BytestreamServerResourceUser.cpp index b369347..2fc2e76 100644 --- a/Swiften/FileTransfer/SOCKS5BytestreamServerResourceUser.cpp +++ b/Swiften/FileTransfer/SOCKS5BytestreamServerResourceUser.cpp @@ -1,35 +1,35 @@ /* - * Copyright (c) 2015 Isode Limited. + * Copyright (c) 2015-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #include <Swiften/FileTransfer/SOCKS5BytestreamServerResourceUser.h> -#include <Swiften/FileTransfer/SOCKS5BytestreamServerManager.h> - #include <boost/bind.hpp> +#include <Swiften/FileTransfer/SOCKS5BytestreamServerManager.h> + namespace Swift { SOCKS5BytestreamServerResourceUser::SOCKS5BytestreamServerResourceUser(SOCKS5BytestreamServerManager* s5bServerManager) : s5bServerManager_(s5bServerManager) { - assert(!s5bServerManager_->isInitialized()); - onInitializedConnection_ = s5bServerManager_->onInitialized.connect(boost::bind(&SOCKS5BytestreamServerResourceUser::handleServerManagerInitialized, this, _1)); - s5bServerManager_->initialize(); + assert(!s5bServerManager_->isInitialized()); + onInitializedConnection_ = s5bServerManager_->onInitialized.connect(boost::bind(&SOCKS5BytestreamServerResourceUser::handleServerManagerInitialized, this, _1)); + s5bServerManager_->initialize(); } SOCKS5BytestreamServerResourceUser::~SOCKS5BytestreamServerResourceUser() { - if (s5bServerManager_->isInitialized()) { - s5bServerManager_->stop(); - } + if (s5bServerManager_->isInitialized()) { + s5bServerManager_->stop(); + } } bool SOCKS5BytestreamServerResourceUser::isInitialized() const { - return s5bServerManager_->isInitialized(); + return s5bServerManager_->isInitialized(); } void SOCKS5BytestreamServerResourceUser::handleServerManagerInitialized(bool successfulInitialize) { - onSuccessfulInitialized(successfulInitialize); + onSuccessfulInitialized(successfulInitialize); } } diff --git a/Swiften/FileTransfer/SOCKS5BytestreamServerResourceUser.h b/Swiften/FileTransfer/SOCKS5BytestreamServerResourceUser.h index 15c4fc7..8e42637 100644 --- a/Swiften/FileTransfer/SOCKS5BytestreamServerResourceUser.h +++ b/Swiften/FileTransfer/SOCKS5BytestreamServerResourceUser.h @@ -1,12 +1,13 @@ /* - * Copyright (c) 2015 Isode Limited. + * Copyright (c) 2015-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/boost_bsignals.h> +#include <boost/signals2.hpp> + #include <Swiften/Base/API.h> namespace Swift { @@ -14,20 +15,20 @@ namespace Swift { class SOCKS5BytestreamServerManager; class SWIFTEN_API SOCKS5BytestreamServerResourceUser { - public: - SOCKS5BytestreamServerResourceUser(SOCKS5BytestreamServerManager* s5bServerManager); - ~SOCKS5BytestreamServerResourceUser(); + public: + SOCKS5BytestreamServerResourceUser(SOCKS5BytestreamServerManager* s5bServerManager); + ~SOCKS5BytestreamServerResourceUser(); - bool isInitialized() const; + bool isInitialized() const; - boost::signal<void (bool /* success */)> onSuccessfulInitialized; + boost::signals2::signal<void (bool /* success */)> onSuccessfulInitialized; - private: - void handleServerManagerInitialized(bool successfulInitialize); + private: + void handleServerManagerInitialized(bool successfulInitialize); - private: - SOCKS5BytestreamServerManager* s5bServerManager_; - boost::bsignals::scoped_connection onInitializedConnection_; + private: + SOCKS5BytestreamServerManager* s5bServerManager_; + boost::signals2::scoped_connection onInitializedConnection_; }; } diff --git a/Swiften/FileTransfer/SOCKS5BytestreamServerSession.cpp b/Swiften/FileTransfer/SOCKS5BytestreamServerSession.cpp index 0e1eb6b..bc4e8e4 100644 --- a/Swiften/FileTransfer/SOCKS5BytestreamServerSession.cpp +++ b/Swiften/FileTransfer/SOCKS5BytestreamServerSession.cpp @@ -21,175 +21,175 @@ namespace Swift { SOCKS5BytestreamServerSession::SOCKS5BytestreamServerSession( - boost::shared_ptr<Connection> connection, - SOCKS5BytestreamRegistry* bytestreams) : - connection(connection), - bytestreams(bytestreams), - state(Initial), - chunkSize(131072), - waitingForData(false) { - disconnectedConnection = connection->onDisconnected.connect(boost::bind(&SOCKS5BytestreamServerSession::handleDisconnected, this, _1)); + std::shared_ptr<Connection> connection, + SOCKS5BytestreamRegistry* bytestreams) : + connection(connection), + bytestreams(bytestreams), + state(Initial), + chunkSize(131072), + waitingForData(false) { + disconnectedConnection = connection->onDisconnected.connect(boost::bind(&SOCKS5BytestreamServerSession::handleDisconnected, this, _1)); } SOCKS5BytestreamServerSession::~SOCKS5BytestreamServerSession() { - if (state != Finished && state != Initial) { - SWIFT_LOG(warning) << "SOCKS5BytestreamServerSession unfinished" << std::endl; - finish(); - } + if (state != Finished && state != Initial) { + SWIFT_LOG(warning) << "SOCKS5BytestreamServerSession unfinished" << std::endl; + finish(); + } } void SOCKS5BytestreamServerSession::start() { - SWIFT_LOG(debug) << std::endl; - dataReadConnection = connection->onDataRead.connect( - boost::bind(&SOCKS5BytestreamServerSession::handleDataRead, this, _1)); - state = WaitingForAuthentication; + SWIFT_LOG(debug) << std::endl; + dataReadConnection = connection->onDataRead.connect( + boost::bind(&SOCKS5BytestreamServerSession::handleDataRead, this, _1)); + state = WaitingForAuthentication; } void SOCKS5BytestreamServerSession::stop() { - finish(); + finish(); } -void SOCKS5BytestreamServerSession::startSending(boost::shared_ptr<ReadBytestream> stream) { - if (state != ReadyForTransfer) { SWIFT_LOG(debug) << "Not ready for transfer!" << std::endl; return; } +void SOCKS5BytestreamServerSession::startSending(std::shared_ptr<ReadBytestream> stream) { + if (state != ReadyForTransfer) { SWIFT_LOG(debug) << "Not ready for transfer!" << std::endl; return; } - readBytestream = stream; - state = WritingData; - dataAvailableConnection = readBytestream->onDataAvailable.connect( - boost::bind(&SOCKS5BytestreamServerSession::handleDataAvailable, this)); - dataWrittenConnection = connection->onDataWritten.connect( - boost::bind(&SOCKS5BytestreamServerSession::sendData, this)); - sendData(); + readBytestream = stream; + state = WritingData; + dataAvailableConnection = readBytestream->onDataAvailable.connect( + boost::bind(&SOCKS5BytestreamServerSession::handleDataAvailable, this)); + dataWrittenConnection = connection->onDataWritten.connect( + boost::bind(&SOCKS5BytestreamServerSession::sendData, this)); + sendData(); } -void SOCKS5BytestreamServerSession::startReceiving(boost::shared_ptr<WriteBytestream> stream) { - if (state != ReadyForTransfer) { SWIFT_LOG(debug) << "Not ready for transfer!" << std::endl; return; } +void SOCKS5BytestreamServerSession::startReceiving(std::shared_ptr<WriteBytestream> stream) { + if (state != ReadyForTransfer) { SWIFT_LOG(debug) << "Not ready for transfer!" << std::endl; return; } - writeBytestream = stream; - state = ReadingData; - writeBytestream->write(unprocessedData); - // onBytesReceived(unprocessedData.size()); - unprocessedData.clear(); + writeBytestream = stream; + state = ReadingData; + writeBytestream->write(unprocessedData); + // onBytesReceived(unprocessedData.size()); + unprocessedData.clear(); } HostAddressPort SOCKS5BytestreamServerSession::getAddressPort() const { - return connection->getLocalAddress(); + return connection->getLocalAddress(); } -void SOCKS5BytestreamServerSession::handleDataRead(boost::shared_ptr<SafeByteArray> data) { - if (state != ReadingData) { - append(unprocessedData, *data); - process(); - } else { - if (!writeBytestream->write(createByteArray(vecptr(*data), data->size()))) { - finish(boost::optional<FileTransferError>(FileTransferError::WriteError)); - } - } +void SOCKS5BytestreamServerSession::handleDataRead(std::shared_ptr<SafeByteArray> data) { + if (state != ReadingData) { + append(unprocessedData, *data); + process(); + } else { + if (!writeBytestream->write(createByteArray(vecptr(*data), data->size()))) { + finish(boost::optional<FileTransferError>(FileTransferError::WriteError)); + } + } } void SOCKS5BytestreamServerSession::handleDataAvailable() { - if (waitingForData) { - sendData(); - } + if (waitingForData) { + sendData(); + } } void SOCKS5BytestreamServerSession::handleDisconnected(const boost::optional<Connection::Error>& error) { - SWIFT_LOG(debug) << (error ? (error == Connection::ReadError ? "Read Error" : "Write Error") : "No Error") << std::endl; - finish(error ? boost::optional<FileTransferError>(FileTransferError::PeerError) : boost::optional<FileTransferError>()); + SWIFT_LOG(debug) << (error ? (error == Connection::ReadError ? "Read Error" : "Write Error") : "No Error") << std::endl; + finish(error ? boost::optional<FileTransferError>(FileTransferError::PeerError) : boost::optional<FileTransferError>()); } void SOCKS5BytestreamServerSession::process() { - if (state == WaitingForAuthentication) { - if (unprocessedData.size() >= 2) { - size_t authCount = unprocessedData[1]; - size_t i = 2; - while (i < 2 + authCount && i < unprocessedData.size()) { - // Skip authentication mechanism - ++i; - } - if (i == 2 + authCount) { - // Authentication message is complete - if (i != unprocessedData.size()) { - SWIFT_LOG(debug) << "Junk after authentication mechanism" << std::endl; - } - unprocessedData.clear(); - connection->write(createSafeByteArray("\x05\x00", 2)); - state = WaitingForRequest; - } - } - } - else if (state == WaitingForRequest) { - if (unprocessedData.size() >= 5) { - ByteArray requestID; - size_t i = 5; - size_t hostnameSize = unprocessedData[4]; - while (i < 5 + hostnameSize && i < unprocessedData.size()) { - requestID.push_back(unprocessedData[i]); - ++i; - } - // Skip the port: 2 byte large, one already skipped. Add one for comparison with size - i += 2; - if (i <= unprocessedData.size()) { - if (i != unprocessedData.size()) { - SWIFT_LOG(debug) << "Junk after authentication mechanism" << std::endl; - } - unprocessedData.clear(); - streamID = byteArrayToString(requestID); - bool hasBytestream = bytestreams->hasBytestream(streamID); - SafeByteArray result = createSafeByteArray("\x05", 1); - result.push_back(hasBytestream ? 0x0 : 0x4); - append(result, createByteArray("\x00\x03", 2)); - result.push_back(boost::numeric_cast<unsigned char>(requestID.size())); - append(result, concat(requestID, createByteArray("\x00\x00", 2))); - if (!hasBytestream) { - SWIFT_LOG(debug) << "Readstream or Wrtiestream with ID " << streamID << " not found!" << std::endl; - connection->write(result); - finish(boost::optional<FileTransferError>(FileTransferError::PeerError)); - } - else { - SWIFT_LOG(debug) << "Found stream. Sent OK." << std::endl; - connection->write(result); - state = ReadyForTransfer; - } - } - } - } + if (state == WaitingForAuthentication) { + if (unprocessedData.size() >= 2) { + size_t authCount = unprocessedData[1]; + size_t i = 2; + while (i < 2 + authCount && i < unprocessedData.size()) { + // Skip authentication mechanism + ++i; + } + if (i == 2 + authCount) { + // Authentication message is complete + if (i != unprocessedData.size()) { + SWIFT_LOG(debug) << "Junk after authentication mechanism" << std::endl; + } + unprocessedData.clear(); + connection->write(createSafeByteArray("\x05\x00", 2)); + state = WaitingForRequest; + } + } + } + else if (state == WaitingForRequest) { + if (unprocessedData.size() >= 5) { + ByteArray requestID; + size_t i = 5; + size_t hostnameSize = unprocessedData[4]; + while (i < 5 + hostnameSize && i < unprocessedData.size()) { + requestID.push_back(unprocessedData[i]); + ++i; + } + // Skip the port: 2 byte large, one already skipped. Add one for comparison with size + i += 2; + if (i <= unprocessedData.size()) { + if (i != unprocessedData.size()) { + SWIFT_LOG(debug) << "Junk after authentication mechanism" << std::endl; + } + unprocessedData.clear(); + streamID = byteArrayToString(requestID); + bool hasBytestream = bytestreams->hasBytestream(streamID); + SafeByteArray result = createSafeByteArray("\x05", 1); + result.push_back(hasBytestream ? 0x0 : 0x4); + append(result, createByteArray("\x00\x03", 2)); + result.push_back(boost::numeric_cast<unsigned char>(requestID.size())); + append(result, concat(requestID, createByteArray("\x00\x00", 2))); + if (!hasBytestream) { + SWIFT_LOG(debug) << "Readstream or Wrtiestream with ID " << streamID << " not found!" << std::endl; + connection->write(result); + finish(boost::optional<FileTransferError>(FileTransferError::PeerError)); + } + else { + SWIFT_LOG(debug) << "Found stream. Sent OK." << std::endl; + connection->write(result); + state = ReadyForTransfer; + } + } + } + } } void SOCKS5BytestreamServerSession::sendData() { - if (!readBytestream->isFinished()) { - try { - SafeByteArray dataToSend = createSafeByteArray(*readBytestream->read(boost::numeric_cast<size_t>(chunkSize))); - if (!dataToSend.empty()) { - connection->write(dataToSend); - onBytesSent(dataToSend.size()); - waitingForData = false; - } - else { - waitingForData = true; - } - } - catch (const BytestreamException&) { - finish(boost::optional<FileTransferError>(FileTransferError::PeerError)); - } - } - else { - finish(); - } + if (!readBytestream->isFinished()) { + try { + SafeByteArray dataToSend = createSafeByteArray(*readBytestream->read(boost::numeric_cast<size_t>(chunkSize))); + if (!dataToSend.empty()) { + connection->write(dataToSend); + onBytesSent(dataToSend.size()); + waitingForData = false; + } + else { + waitingForData = true; + } + } + catch (const BytestreamException&) { + finish(boost::optional<FileTransferError>(FileTransferError::PeerError)); + } + } + else { + finish(); + } } void SOCKS5BytestreamServerSession::finish(const boost::optional<FileTransferError>& error) { - SWIFT_LOG(debug) << "state: " << state << std::endl; - if (state == Finished) { - return; - } - - disconnectedConnection.disconnect(); - dataReadConnection.disconnect(); - dataWrittenConnection.disconnect(); - dataAvailableConnection.disconnect(); - readBytestream.reset(); - state = Finished; - onFinished(error); + SWIFT_LOG(debug) << "state: " << state << std::endl; + if (state == Finished) { + return; + } + + disconnectedConnection.disconnect(); + dataReadConnection.disconnect(); + dataWrittenConnection.disconnect(); + dataAvailableConnection.disconnect(); + readBytestream.reset(); + state = Finished; + onFinished(error); } } diff --git a/Swiften/FileTransfer/SOCKS5BytestreamServerSession.h b/Swiften/FileTransfer/SOCKS5BytestreamServerSession.h index ed5272f..c7e252c 100644 --- a/Swiften/FileTransfer/SOCKS5BytestreamServerSession.h +++ b/Swiften/FileTransfer/SOCKS5BytestreamServerSession.h @@ -6,78 +6,79 @@ #pragma once -#include <boost/shared_ptr.hpp> +#include <memory> + +#include <boost/signals2.hpp> #include <Swiften/Base/API.h> -#include <Swiften/Base/boost_bsignals.h> #include <Swiften/FileTransfer/FileTransferError.h> #include <Swiften/FileTransfer/ReadBytestream.h> #include <Swiften/FileTransfer/WriteBytestream.h> #include <Swiften/Network/Connection.h> namespace Swift { - class SOCKS5BytestreamRegistry; - - class SWIFTEN_API SOCKS5BytestreamServerSession { - public: - typedef boost::shared_ptr<SOCKS5BytestreamServerSession> ref; - - public: - enum State { - Initial, - WaitingForAuthentication, - WaitingForRequest, - ReadyForTransfer, - ReadingData, - WritingData, - Finished - }; - - SOCKS5BytestreamServerSession(boost::shared_ptr<Connection> connection, SOCKS5BytestreamRegistry* registry); - ~SOCKS5BytestreamServerSession(); - - void setChunkSize(int chunkSize) { - this->chunkSize = chunkSize; - } - - void start(); - void stop(); - - void startSending(boost::shared_ptr<ReadBytestream>); - void startReceiving(boost::shared_ptr<WriteBytestream>); - - HostAddressPort getAddressPort() const; - - boost::signal<void (boost::optional<FileTransferError>)> onFinished; - boost::signal<void (unsigned long long)> onBytesSent; - - const std::string& getStreamID() const { - return streamID; - } - - private: - void finish(const boost::optional<FileTransferError>& error = boost::optional<FileTransferError>()); - void process(); - void handleDataRead(boost::shared_ptr<SafeByteArray>); - void handleDisconnected(const boost::optional<Connection::Error>&); - void handleDataAvailable(); - void sendData(); - - private: - boost::shared_ptr<Connection> connection; - SOCKS5BytestreamRegistry* bytestreams; - ByteArray unprocessedData; - State state; - int chunkSize; - std::string streamID; - boost::shared_ptr<ReadBytestream> readBytestream; - boost::shared_ptr<WriteBytestream> writeBytestream; - bool waitingForData; - - boost::bsignals::connection disconnectedConnection; - boost::bsignals::connection dataReadConnection; - boost::bsignals::connection dataWrittenConnection; - boost::bsignals::connection dataAvailableConnection; - - }; + class SOCKS5BytestreamRegistry; + + class SWIFTEN_API SOCKS5BytestreamServerSession { + public: + typedef std::shared_ptr<SOCKS5BytestreamServerSession> ref; + + public: + enum State { + Initial, + WaitingForAuthentication, + WaitingForRequest, + ReadyForTransfer, + ReadingData, + WritingData, + Finished + }; + + SOCKS5BytestreamServerSession(std::shared_ptr<Connection> connection, SOCKS5BytestreamRegistry* registry); + ~SOCKS5BytestreamServerSession(); + + void setChunkSize(int chunkSize) { + this->chunkSize = chunkSize; + } + + void start(); + void stop(); + + void startSending(std::shared_ptr<ReadBytestream>); + void startReceiving(std::shared_ptr<WriteBytestream>); + + HostAddressPort getAddressPort() const; + + boost::signals2::signal<void (boost::optional<FileTransferError>)> onFinished; + boost::signals2::signal<void (unsigned long long)> onBytesSent; + + const std::string& getStreamID() const { + return streamID; + } + + private: + void finish(const boost::optional<FileTransferError>& error = boost::optional<FileTransferError>()); + void process(); + void handleDataRead(std::shared_ptr<SafeByteArray>); + void handleDisconnected(const boost::optional<Connection::Error>&); + void handleDataAvailable(); + void sendData(); + + private: + std::shared_ptr<Connection> connection; + SOCKS5BytestreamRegistry* bytestreams; + ByteArray unprocessedData; + State state; + int chunkSize; + std::string streamID; + std::shared_ptr<ReadBytestream> readBytestream; + std::shared_ptr<WriteBytestream> writeBytestream; + bool waitingForData; + + boost::signals2::connection disconnectedConnection; + boost::signals2::connection dataReadConnection; + boost::signals2::connection dataWrittenConnection; + boost::signals2::connection dataAvailableConnection; + + }; } diff --git a/Swiften/FileTransfer/StreamInitiationRequest.h b/Swiften/FileTransfer/StreamInitiationRequest.h index 7046eda..44e826c 100644 --- a/Swiften/FileTransfer/StreamInitiationRequest.h +++ b/Swiften/FileTransfer/StreamInitiationRequest.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2015 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ @@ -7,28 +7,27 @@ #pragma once #include <Swiften/Base/API.h> -#include <Swiften/Queries/GenericRequest.h> #include <Swiften/Elements/StreamInitiation.h> - +#include <Swiften/Queries/GenericRequest.h> namespace Swift { - class SWIFTEN_API StreamInitiationRequest : public GenericRequest<StreamInitiation> { - public: - typedef boost::shared_ptr<StreamInitiationRequest> ref; + class SWIFTEN_API StreamInitiationRequest : public GenericRequest<StreamInitiation> { + public: + typedef std::shared_ptr<StreamInitiationRequest> ref; - static ref create(const JID& jid, boost::shared_ptr<StreamInitiation> payload, IQRouter* router) { - return ref(new StreamInitiationRequest(jid, payload, router)); - } + static ref create(const JID& jid, std::shared_ptr<StreamInitiation> payload, IQRouter* router) { + return ref(new StreamInitiationRequest(jid, payload, router)); + } - static ref create(const JID& from, const JID& to, boost::shared_ptr<StreamInitiation> payload, IQRouter* router) { - return ref(new StreamInitiationRequest(from, to, payload, router)); - } + static ref create(const JID& from, const JID& to, std::shared_ptr<StreamInitiation> payload, IQRouter* router) { + return ref(new StreamInitiationRequest(from, to, payload, router)); + } - private: - StreamInitiationRequest(const JID& jid, boost::shared_ptr<StreamInitiation> payload, IQRouter* router) : GenericRequest<StreamInitiation>(IQ::Set, jid, payload, router) { - } + private: + StreamInitiationRequest(const JID& jid, std::shared_ptr<StreamInitiation> payload, IQRouter* router) : GenericRequest<StreamInitiation>(IQ::Set, jid, payload, router) { + } - StreamInitiationRequest(const JID& from, const JID& to, boost::shared_ptr<StreamInitiation> payload, IQRouter* router) : GenericRequest<StreamInitiation>(IQ::Set, from, to, payload, router) { - } - }; + StreamInitiationRequest(const JID& from, const JID& to, std::shared_ptr<StreamInitiation> payload, IQRouter* router) : GenericRequest<StreamInitiation>(IQ::Set, from, to, payload, router) { + } + }; } diff --git a/Swiften/FileTransfer/TransportSession.h b/Swiften/FileTransfer/TransportSession.h index c0560b7..dc6e59a 100644 --- a/Swiften/FileTransfer/TransportSession.h +++ b/Swiften/FileTransfer/TransportSession.h @@ -1,25 +1,26 @@ /* - * Copyright (c) 2013 Isode Limited. + * Copyright (c) 2013-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <boost/signals2.hpp> + #include <Swiften/Base/API.h> +#include <Swiften/Base/Override.h> #include <Swiften/FileTransfer/FileTransferError.h> -#include <Swiften/Base/boost_bsignals.h> namespace Swift { - class SWIFTEN_API TransportSession { - public: - virtual ~TransportSession(); + class SWIFTEN_API TransportSession { + public: + virtual ~TransportSession(); - virtual void start() = 0; - virtual void stop() = 0; + virtual void start() = 0; + virtual void stop() = 0; - boost::signal<void (size_t)> onBytesSent; - boost::signal<void (boost::optional<FileTransferError>)> onFinished; - }; + boost::signals2::signal<void (size_t)> onBytesSent; + boost::signals2::signal<void (boost::optional<FileTransferError>)> onFinished; + }; } diff --git a/Swiften/FileTransfer/UnitTest/DummyFileTransferManager.h b/Swiften/FileTransfer/UnitTest/DummyFileTransferManager.h index 26adb05..03e2476 100644 --- a/Swiften/FileTransfer/UnitTest/DummyFileTransferManager.h +++ b/Swiften/FileTransfer/UnitTest/DummyFileTransferManager.h @@ -4,46 +4,53 @@ * See Documentation/Licenses/BSD-simplified.txt for more information. */ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + #pragma once #include <string> -#include <boost/filesystem/path.hpp> + #include <boost/date_time/posix_time/posix_time.hpp> +#include <boost/filesystem/path.hpp> #include <Swiften/Base/Override.h> #include <Swiften/FileTransfer/FileTransferManager.h> namespace Swift { - class S5BProxyRequest; - class FileTransferOptions; - - class DummyFileTransferManager : public FileTransferManager { - public: - DummyFileTransferManager() : FileTransferManager() { - } - - virtual OutgoingFileTransfer::ref createOutgoingFileTransfer( - const JID&, - const boost::filesystem::path&, - const std::string&, - boost::shared_ptr<ReadBytestream>, - const FileTransferOptions&) SWIFTEN_OVERRIDE { - return OutgoingFileTransfer::ref(); - } - - virtual OutgoingFileTransfer::ref createOutgoingFileTransfer( - const JID&, - const std::string&, - const std::string&, - const boost::uintmax_t, - const boost::posix_time::ptime&, - boost::shared_ptr<ReadBytestream>, - const FileTransferOptions&) SWIFTEN_OVERRIDE { - return OutgoingFileTransfer::ref(); - } - - virtual void addS5BProxy(boost::shared_ptr<S5BProxyRequest>) { - } - - }; + class S5BProxyRequest; + class FileTransferOptions; + + class DummyFileTransferManager : public FileTransferManager { + public: + DummyFileTransferManager() : FileTransferManager() { + } + + virtual OutgoingFileTransfer::ref createOutgoingFileTransfer( + const JID&, + const boost::filesystem::path&, + const std::string&, + std::shared_ptr<ReadBytestream>, + const FileTransferOptions&) SWIFTEN_OVERRIDE { + return OutgoingFileTransfer::ref(); + } + + virtual OutgoingFileTransfer::ref createOutgoingFileTransfer( + const JID&, + const std::string&, + const std::string&, + const boost::uintmax_t, + const boost::posix_time::ptime&, + std::shared_ptr<ReadBytestream>, + const FileTransferOptions&) SWIFTEN_OVERRIDE { + return OutgoingFileTransfer::ref(); + } + + virtual void addS5BProxy(std::shared_ptr<S5BProxyRequest>) { + } + + }; } diff --git a/Swiften/FileTransfer/UnitTest/DummyFileTransferTransporterFactory.h b/Swiften/FileTransfer/UnitTest/DummyFileTransferTransporterFactory.h index 00a931f..5db3368 100644 --- a/Swiften/FileTransfer/UnitTest/DummyFileTransferTransporterFactory.h +++ b/Swiften/FileTransfer/UnitTest/DummyFileTransferTransporterFactory.h @@ -28,175 +28,175 @@ namespace Swift { class DummyFileTransferTransporter : public FileTransferTransporter { public: - enum Role { - Initiator, - Responder - }; + enum Role { + Initiator, + Responder + }; public: - DummyFileTransferTransporter( - const JID& initiator, - const JID& responder, - Role role, - SOCKS5BytestreamRegistry* s5bRegistry, - SOCKS5BytestreamServerManager* /* s5bServerManager */, - SOCKS5BytestreamProxiesManager* /* s5bProxy */, - IDGenerator* /* idGenerator */, - ConnectionFactory*, - TimerFactory*, - CryptoProvider* cryptoProvider, - IQRouter* iqRouter, - const FileTransferOptions& ftOptions) : initiator_(initiator), responder_(responder), role_(role), s5bRegistry_(s5bRegistry), crypto_(cryptoProvider), iqRouter_(iqRouter), ftOptions_(ftOptions) { - - } - - void initialize() { - s5bSessionID_ = s5bRegistry_->generateSessionID(); - } - - virtual void startGeneratingLocalCandidates() { - std::vector<JingleS5BTransportPayload::Candidate> candidates; - if (ftOptions_.isDirectAllowed()) { - JingleS5BTransportPayload::Candidate candidate; - candidate.cid = "123"; - candidate.priority = 1235; - candidates.push_back(candidate); - } - onLocalCandidatesGenerated(s5bSessionID_, candidates, getSOCKS5DstAddr()); - } - - virtual void stopGeneratingLocalCandidates() { - } - - virtual void addRemoteCandidates(const std::vector<JingleS5BTransportPayload::Candidate>&, const std::string&) { - } - - virtual void startTryingRemoteCandidates() { - onRemoteCandidateSelectFinished(s5bSessionID_, boost::optional<JingleS5BTransportPayload::Candidate>()); - } - - virtual void stopTryingRemoteCandidates() { - } - - virtual void startActivatingProxy(const JID& /* proxy */) { - } - - virtual void stopActivatingProxy() { - } - - virtual boost::shared_ptr<TransportSession> createIBBSendSession(const std::string& sessionID, unsigned int blockSize, boost::shared_ptr<ReadBytestream> stream) { - boost::shared_ptr<IBBSendSession> ibbSession = boost::make_shared<IBBSendSession>( - sessionID, initiator_, responder_, stream, iqRouter_); - ibbSession->setBlockSize(blockSize); - return boost::make_shared<IBBSendTransportSession>(ibbSession); - } - - virtual boost::shared_ptr<TransportSession> createIBBReceiveSession(const std::string& sessionID, unsigned long long size, boost::shared_ptr<WriteBytestream> stream) { - boost::shared_ptr<IBBReceiveSession> ibbSession = boost::make_shared<IBBReceiveSession>( - sessionID, initiator_, responder_, size, stream, iqRouter_); - return boost::make_shared<IBBReceiveTransportSession>(ibbSession); - } - - virtual boost::shared_ptr<TransportSession> createRemoteCandidateSession( - boost::shared_ptr<ReadBytestream>, const JingleS5BTransportPayload::Candidate& /* candidate */) { - return boost::shared_ptr<TransportSession>(); - } - - virtual boost::shared_ptr<TransportSession> createRemoteCandidateSession( - boost::shared_ptr<WriteBytestream>, const JingleS5BTransportPayload::Candidate& /* candidate */) { - return boost::shared_ptr<TransportSession>(); - } - - virtual boost::shared_ptr<TransportSession> createLocalCandidateSession( - boost::shared_ptr<ReadBytestream>, const JingleS5BTransportPayload::Candidate& /* candidate */) { - return boost::shared_ptr<TransportSession>(); - } - - virtual boost::shared_ptr<TransportSession> createLocalCandidateSession( - boost::shared_ptr<WriteBytestream>, const JingleS5BTransportPayload::Candidate& /* candidate */) { - return boost::shared_ptr<TransportSession>(); - } + DummyFileTransferTransporter( + const JID& initiator, + const JID& responder, + Role role, + SOCKS5BytestreamRegistry* s5bRegistry, + SOCKS5BytestreamServerManager* /* s5bServerManager */, + SOCKS5BytestreamProxiesManager* /* s5bProxy */, + IDGenerator* /* idGenerator */, + ConnectionFactory*, + TimerFactory*, + CryptoProvider* cryptoProvider, + IQRouter* iqRouter, + const FileTransferOptions& ftOptions) : initiator_(initiator), responder_(responder), role_(role), s5bRegistry_(s5bRegistry), crypto_(cryptoProvider), iqRouter_(iqRouter), ftOptions_(ftOptions) { + + } + + void initialize() { + s5bSessionID_ = s5bRegistry_->generateSessionID(); + } + + virtual void startGeneratingLocalCandidates() { + std::vector<JingleS5BTransportPayload::Candidate> candidates; + if (ftOptions_.isDirectAllowed()) { + JingleS5BTransportPayload::Candidate candidate; + candidate.cid = "123"; + candidate.priority = 1235; + candidates.push_back(candidate); + } + onLocalCandidatesGenerated(s5bSessionID_, candidates, getSOCKS5DstAddr()); + } + + virtual void stopGeneratingLocalCandidates() { + } + + virtual void addRemoteCandidates(const std::vector<JingleS5BTransportPayload::Candidate>&, const std::string&) { + } + + virtual void startTryingRemoteCandidates() { + onRemoteCandidateSelectFinished(s5bSessionID_, boost::optional<JingleS5BTransportPayload::Candidate>()); + } + + virtual void stopTryingRemoteCandidates() { + } + + virtual void startActivatingProxy(const JID& /* proxy */) { + } + + virtual void stopActivatingProxy() { + } + + virtual std::shared_ptr<TransportSession> createIBBSendSession(const std::string& sessionID, unsigned int blockSize, std::shared_ptr<ReadBytestream> stream) { + std::shared_ptr<IBBSendSession> ibbSession = std::make_shared<IBBSendSession>( + sessionID, initiator_, responder_, stream, iqRouter_); + ibbSession->setBlockSize(blockSize); + return std::make_shared<IBBSendTransportSession>(ibbSession); + } + + virtual std::shared_ptr<TransportSession> createIBBReceiveSession(const std::string& sessionID, unsigned long long size, std::shared_ptr<WriteBytestream> stream) { + std::shared_ptr<IBBReceiveSession> ibbSession = std::make_shared<IBBReceiveSession>( + sessionID, initiator_, responder_, size, stream, iqRouter_); + return std::make_shared<IBBReceiveTransportSession>(ibbSession); + } + + virtual std::shared_ptr<TransportSession> createRemoteCandidateSession( + std::shared_ptr<ReadBytestream>, const JingleS5BTransportPayload::Candidate& /* candidate */) { + return std::shared_ptr<TransportSession>(); + } + + virtual std::shared_ptr<TransportSession> createRemoteCandidateSession( + std::shared_ptr<WriteBytestream>, const JingleS5BTransportPayload::Candidate& /* candidate */) { + return std::shared_ptr<TransportSession>(); + } + + virtual std::shared_ptr<TransportSession> createLocalCandidateSession( + std::shared_ptr<ReadBytestream>, const JingleS5BTransportPayload::Candidate& /* candidate */) { + return std::shared_ptr<TransportSession>(); + } + + virtual std::shared_ptr<TransportSession> createLocalCandidateSession( + std::shared_ptr<WriteBytestream>, const JingleS5BTransportPayload::Candidate& /* candidate */) { + return std::shared_ptr<TransportSession>(); + } private: - std::string getSOCKS5DstAddr() const { - std::string result; - if (role_ == Initiator) { - result = getInitiatorCandidateSOCKS5DstAddr(); - } - else { - result = getResponderCandidateSOCKS5DstAddr(); - } - return result; - } - - std::string getInitiatorCandidateSOCKS5DstAddr() const { - return Hexify::hexify(crypto_->getSHA1Hash(createSafeByteArray(s5bSessionID_ + initiator_.toString() + responder_.toString()))); - } - - std::string getResponderCandidateSOCKS5DstAddr() const { - return Hexify::hexify(crypto_->getSHA1Hash(createSafeByteArray(s5bSessionID_ + responder_.toString() + initiator_.toString()))); - } + std::string getSOCKS5DstAddr() const { + std::string result; + if (role_ == Initiator) { + result = getInitiatorCandidateSOCKS5DstAddr(); + } + else { + result = getResponderCandidateSOCKS5DstAddr(); + } + return result; + } + + std::string getInitiatorCandidateSOCKS5DstAddr() const { + return Hexify::hexify(crypto_->getSHA1Hash(createSafeByteArray(s5bSessionID_ + initiator_.toString() + responder_.toString()))); + } + + std::string getResponderCandidateSOCKS5DstAddr() const { + return Hexify::hexify(crypto_->getSHA1Hash(createSafeByteArray(s5bSessionID_ + responder_.toString() + initiator_.toString()))); + } private: - JID initiator_; - JID responder_; - Role role_; - SOCKS5BytestreamRegistry* s5bRegistry_; - CryptoProvider* crypto_; - std::string s5bSessionID_; - IQRouter* iqRouter_; - FileTransferOptions ftOptions_; + JID initiator_; + JID responder_; + Role role_; + SOCKS5BytestreamRegistry* s5bRegistry_; + CryptoProvider* crypto_; + std::string s5bSessionID_; + IQRouter* iqRouter_; + FileTransferOptions ftOptions_; }; class DummyFileTransferTransporterFactory : public FileTransferTransporterFactory { public: - DummyFileTransferTransporterFactory( - SOCKS5BytestreamRegistry* s5bRegistry, - SOCKS5BytestreamServerManager* s5bServerManager, - SOCKS5BytestreamProxiesManager* s5bProxy, - IDGenerator* idGenerator, - ConnectionFactory* connectionFactory, - TimerFactory* timerFactory, - CryptoProvider* cryptoProvider, - IQRouter* iqRouter) : s5bRegistry_(s5bRegistry), s5bServerManager_(s5bServerManager), s5bProxy_(s5bProxy), idGenerator_(idGenerator), connectionFactory_(connectionFactory), timerFactory_(timerFactory), cryptoProvider_(cryptoProvider), iqRouter_(iqRouter) { - - } - - virtual ~DummyFileTransferTransporterFactory() { - } - - virtual FileTransferTransporter* createInitiatorTransporter(const JID& initiator, const JID& responder, const FileTransferOptions& options) { - DummyFileTransferTransporter* transporter = new DummyFileTransferTransporter( - initiator, - responder, - DummyFileTransferTransporter::Initiator, - s5bRegistry_, - s5bServerManager_, - s5bProxy_, - idGenerator_, - connectionFactory_, - timerFactory_, - cryptoProvider_, - iqRouter_, - options); - transporter->initialize(); - return transporter; - } - - virtual FileTransferTransporter* createResponderTransporter(const JID& /* initiator */, const JID& /* responder */, const std::string& /* s5bSessionID */, const FileTransferOptions& /* options */) { - return NULL; - } + DummyFileTransferTransporterFactory( + SOCKS5BytestreamRegistry* s5bRegistry, + SOCKS5BytestreamServerManager* s5bServerManager, + SOCKS5BytestreamProxiesManager* s5bProxy, + IDGenerator* idGenerator, + ConnectionFactory* connectionFactory, + TimerFactory* timerFactory, + CryptoProvider* cryptoProvider, + IQRouter* iqRouter) : s5bRegistry_(s5bRegistry), s5bServerManager_(s5bServerManager), s5bProxy_(s5bProxy), idGenerator_(idGenerator), connectionFactory_(connectionFactory), timerFactory_(timerFactory), cryptoProvider_(cryptoProvider), iqRouter_(iqRouter) { + + } + + virtual ~DummyFileTransferTransporterFactory() { + } + + virtual FileTransferTransporter* createInitiatorTransporter(const JID& initiator, const JID& responder, const FileTransferOptions& options) { + DummyFileTransferTransporter* transporter = new DummyFileTransferTransporter( + initiator, + responder, + DummyFileTransferTransporter::Initiator, + s5bRegistry_, + s5bServerManager_, + s5bProxy_, + idGenerator_, + connectionFactory_, + timerFactory_, + cryptoProvider_, + iqRouter_, + options); + transporter->initialize(); + return transporter; + } + + virtual FileTransferTransporter* createResponderTransporter(const JID& /* initiator */, const JID& /* responder */, const std::string& /* s5bSessionID */, const FileTransferOptions& /* options */) { + return nullptr; + } private: - SOCKS5BytestreamRegistry* s5bRegistry_; - SOCKS5BytestreamServerManager* s5bServerManager_; - SOCKS5BytestreamProxiesManager* s5bProxy_; - IDGenerator* idGenerator_; - ConnectionFactory* connectionFactory_; - TimerFactory* timerFactory_; - CryptoProvider* cryptoProvider_; - IQRouter* iqRouter_; + SOCKS5BytestreamRegistry* s5bRegistry_; + SOCKS5BytestreamServerManager* s5bServerManager_; + SOCKS5BytestreamProxiesManager* s5bProxy_; + IDGenerator* idGenerator_; + ConnectionFactory* connectionFactory_; + TimerFactory* timerFactory_; + CryptoProvider* cryptoProvider_; + IQRouter* iqRouter_; }; } diff --git a/Swiften/FileTransfer/UnitTest/IBBReceiveSessionTest.cpp b/Swiften/FileTransfer/UnitTest/IBBReceiveSessionTest.cpp index 41eb0ca..31f46de 100644 --- a/Swiften/FileTransfer/UnitTest/IBBReceiveSessionTest.cpp +++ b/Swiften/FileTransfer/UnitTest/IBBReceiveSessionTest.cpp @@ -1,185 +1,187 @@ /* - * Copyright (c) 2010 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ -#include <cppunit/extensions/HelperMacros.h> -#include <cppunit/extensions/TestFactoryRegistry.h> +#include <memory> #include <vector> + #include <boost/bind.hpp> -#include <boost/smart_ptr/make_shared.hpp> + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> #include <Swiften/Base/ByteArray.h> -#include <Swiften/FileTransfer/IBBReceiveSession.h> +#include <Swiften/Client/DummyStanzaChannel.h> #include <Swiften/FileTransfer/ByteArrayWriteBytestream.h> +#include <Swiften/FileTransfer/IBBReceiveSession.h> #include <Swiften/Queries/IQRouter.h> -#include <Swiften/Client/DummyStanzaChannel.h> using namespace Swift; class IBBReceiveSessionTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(IBBReceiveSessionTest); - CPPUNIT_TEST(testOpen); - CPPUNIT_TEST(testReceiveData); - CPPUNIT_TEST(testReceiveMultipleData); - CPPUNIT_TEST(testReceiveDataForOtherSession); - CPPUNIT_TEST(testReceiveDataOutOfOrder); - CPPUNIT_TEST(testReceiveLastData); - CPPUNIT_TEST(testReceiveClose); - CPPUNIT_TEST(testStopWhileActive); - CPPUNIT_TEST_SUITE_END(); - - public: - void setUp() { - stanzaChannel = new DummyStanzaChannel(); - iqRouter = new IQRouter(stanzaChannel); - finished = false; - bytestream = boost::make_shared<ByteArrayWriteBytestream>(); - } + CPPUNIT_TEST_SUITE(IBBReceiveSessionTest); + CPPUNIT_TEST(testOpen); + CPPUNIT_TEST(testReceiveData); + CPPUNIT_TEST(testReceiveMultipleData); + CPPUNIT_TEST(testReceiveDataForOtherSession); + CPPUNIT_TEST(testReceiveDataOutOfOrder); + CPPUNIT_TEST(testReceiveLastData); + CPPUNIT_TEST(testReceiveClose); + CPPUNIT_TEST(testStopWhileActive); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + stanzaChannel = new DummyStanzaChannel(); + iqRouter = new IQRouter(stanzaChannel); + finished = false; + bytestream = std::make_shared<ByteArrayWriteBytestream>(); + } - void tearDown() { - delete iqRouter; - delete stanzaChannel; - } - - void testOpen() { - boost::shared_ptr<IBBReceiveSession> testling(createSession("foo@bar.com/baz", "mysession")); - testling->start(); - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open")); + void tearDown() { + delete iqRouter; + delete stanzaChannel; + } + + void testOpen() { + std::shared_ptr<IBBReceiveSession> testling(createSession("foo@bar.com/baz", "mysession")); + testling->start(); + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open")); - CPPUNIT_ASSERT(stanzaChannel->isResultAtIndex(0, "id-open")); - CPPUNIT_ASSERT(!finished); - - testling->stop(); - } + CPPUNIT_ASSERT(stanzaChannel->isResultAtIndex(0, "id-open")); + CPPUNIT_ASSERT(!finished); + + testling->stop(); + } - void testReceiveData() { - boost::shared_ptr<IBBReceiveSession> testling(createSession("foo@bar.com/baz", "mysession")); - testling->start(); - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open")); - - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 0, createByteArray("abc")), "foo@bar.com/baz", "id-a")); - - CPPUNIT_ASSERT(stanzaChannel->isResultAtIndex(1, "id-a")); - CPPUNIT_ASSERT(createByteArray("abc") == bytestream->getData()); - CPPUNIT_ASSERT(!finished); - - testling->stop(); - } - - void testReceiveMultipleData() { - boost::shared_ptr<IBBReceiveSession> testling(createSession("foo@bar.com/baz", "mysession")); - testling->start(); - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open")); - - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 0, createByteArray("abc")), "foo@bar.com/baz", "id-a")); - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 1, createByteArray("def")), "foo@bar.com/baz", "id-b")); - - CPPUNIT_ASSERT(stanzaChannel->isResultAtIndex(2, "id-b")); - CPPUNIT_ASSERT(createByteArray("abcdef") == bytestream->getData()); - CPPUNIT_ASSERT(!finished); - - testling->stop(); - } - - void testReceiveDataForOtherSession() { - boost::shared_ptr<IBBReceiveSession> testling(createSession("foo@bar.com/baz", "mysession")); - testling->start(); - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open")); - - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("othersession", 0, createByteArray("abc")), "foo@bar.com/baz", "id-a")); - - CPPUNIT_ASSERT(stanzaChannel->isErrorAtIndex(1, "id-a")); - - testling->stop(); - } - - void testReceiveDataOutOfOrder() { - boost::shared_ptr<IBBReceiveSession> testling(createSession("foo@bar.com/baz", "mysession")); - testling->start(); - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open")); - - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 0, createByteArray("abc")), "foo@bar.com/baz", "id-a")); - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 0, createByteArray("def")), "foo@bar.com/baz", "id-b")); - - CPPUNIT_ASSERT(stanzaChannel->isErrorAtIndex(2, "id-b")); - CPPUNIT_ASSERT(finished); - CPPUNIT_ASSERT(error); - - testling->stop(); - } - - void testReceiveLastData() { - boost::shared_ptr<IBBReceiveSession> testling(createSession("foo@bar.com/baz", "mysession", 6)); - testling->start(); - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open")); - - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 0, createByteArray("abc")), "foo@bar.com/baz", "id-a")); - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 1, createByteArray("def")), "foo@bar.com/baz", "id-b")); - - CPPUNIT_ASSERT(stanzaChannel->isResultAtIndex(2, "id-b")); - CPPUNIT_ASSERT(createByteArray("abcdef") == bytestream->getData()); - CPPUNIT_ASSERT(finished); - CPPUNIT_ASSERT(!error); - - testling->stop(); - } - - void testReceiveClose() { - boost::shared_ptr<IBBReceiveSession> testling(createSession("foo@bar.com/baz", "mysession")); - testling->start(); - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open")); - - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBClose("mysession"), "foo@bar.com/baz", "id-close")); + void testReceiveData() { + std::shared_ptr<IBBReceiveSession> testling(createSession("foo@bar.com/baz", "mysession")); + testling->start(); + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open")); + + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 0, createByteArray("abc")), "foo@bar.com/baz", "id-a")); + + CPPUNIT_ASSERT(stanzaChannel->isResultAtIndex(1, "id-a")); + CPPUNIT_ASSERT(createByteArray("abc") == bytestream->getData()); + CPPUNIT_ASSERT(!finished); + + testling->stop(); + } + + void testReceiveMultipleData() { + std::shared_ptr<IBBReceiveSession> testling(createSession("foo@bar.com/baz", "mysession")); + testling->start(); + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open")); + + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 0, createByteArray("abc")), "foo@bar.com/baz", "id-a")); + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 1, createByteArray("def")), "foo@bar.com/baz", "id-b")); + + CPPUNIT_ASSERT(stanzaChannel->isResultAtIndex(2, "id-b")); + CPPUNIT_ASSERT(createByteArray("abcdef") == bytestream->getData()); + CPPUNIT_ASSERT(!finished); + + testling->stop(); + } + + void testReceiveDataForOtherSession() { + std::shared_ptr<IBBReceiveSession> testling(createSession("foo@bar.com/baz", "mysession")); + testling->start(); + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open")); + + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("othersession", 0, createByteArray("abc")), "foo@bar.com/baz", "id-a")); + + CPPUNIT_ASSERT(stanzaChannel->isErrorAtIndex(1, "id-a")); + + testling->stop(); + } + + void testReceiveDataOutOfOrder() { + std::shared_ptr<IBBReceiveSession> testling(createSession("foo@bar.com/baz", "mysession")); + testling->start(); + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open")); + + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 0, createByteArray("abc")), "foo@bar.com/baz", "id-a")); + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 0, createByteArray("def")), "foo@bar.com/baz", "id-b")); + + CPPUNIT_ASSERT(stanzaChannel->isErrorAtIndex(2, "id-b")); + CPPUNIT_ASSERT(finished); + CPPUNIT_ASSERT(error); + + testling->stop(); + } + + void testReceiveLastData() { + std::shared_ptr<IBBReceiveSession> testling(createSession("foo@bar.com/baz", "mysession", 6)); + testling->start(); + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open")); + + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 0, createByteArray("abc")), "foo@bar.com/baz", "id-a")); + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 1, createByteArray("def")), "foo@bar.com/baz", "id-b")); + + CPPUNIT_ASSERT(stanzaChannel->isResultAtIndex(2, "id-b")); + CPPUNIT_ASSERT(createByteArray("abcdef") == bytestream->getData()); + CPPUNIT_ASSERT(finished); + CPPUNIT_ASSERT(!error); + + testling->stop(); + } + + void testReceiveClose() { + std::shared_ptr<IBBReceiveSession> testling(createSession("foo@bar.com/baz", "mysession")); + testling->start(); + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open")); + + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBClose("mysession"), "foo@bar.com/baz", "id-close")); - CPPUNIT_ASSERT(finished); - CPPUNIT_ASSERT(error); + CPPUNIT_ASSERT(finished); + CPPUNIT_ASSERT(error); - testling->stop(); - } + testling->stop(); + } - void testStopWhileActive() { - boost::shared_ptr<IBBReceiveSession> testling(createSession("foo@bar.com/baz", "mysession")); - testling->start(); - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open")); + void testStopWhileActive() { + std::shared_ptr<IBBReceiveSession> testling(createSession("foo@bar.com/baz", "mysession")); + testling->start(); + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open")); - testling->stop(); + testling->stop(); - CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<IBB>(1, JID("foo@bar.com/baz"), IQ::Set)); - IBB::ref ibb = stanzaChannel->sentStanzas[1]->getPayload<IBB>(); - CPPUNIT_ASSERT_EQUAL(IBB::Close, ibb->getAction()); - CPPUNIT_ASSERT_EQUAL(std::string("mysession"), ibb->getStreamID()); - CPPUNIT_ASSERT(finished); - CPPUNIT_ASSERT(!error); - } + CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<IBB>(1, JID("foo@bar.com/baz"), IQ::Set)); + IBB::ref ibb = stanzaChannel->sentStanzas[1]->getPayload<IBB>(); + CPPUNIT_ASSERT_EQUAL(IBB::Close, ibb->getAction()); + CPPUNIT_ASSERT_EQUAL(std::string("mysession"), ibb->getStreamID()); + CPPUNIT_ASSERT(finished); + CPPUNIT_ASSERT(!error); + } - private: - IQ::ref createIBBRequest(IBB::ref ibb, const JID& from, const std::string& id) { - IQ::ref request = IQ::createRequest(IQ::Set, JID("baz@fum.com/dum"), id, ibb); - request->setFrom(from); - return request; - } + private: + IQ::ref createIBBRequest(IBB::ref ibb, const JID& from, const std::string& id) { + IQ::ref request = IQ::createRequest(IQ::Set, JID("baz@fum.com/dum"), id, ibb); + request->setFrom(from); + return request; + } - IBBReceiveSession* createSession(const std::string& from, const std::string& id, size_t size = 0x1000) { - IBBReceiveSession* session = new IBBReceiveSession(id, JID(from), JID(), size, bytestream, iqRouter); - session->onFinished.connect(boost::bind(&IBBReceiveSessionTest::handleFinished, this, _1)); - return session; - } + IBBReceiveSession* createSession(const std::string& from, const std::string& id, size_t size = 0x1000) { + IBBReceiveSession* session = new IBBReceiveSession(id, JID(from), JID(), size, bytestream, iqRouter); + session->onFinished.connect(boost::bind(&IBBReceiveSessionTest::handleFinished, this, _1)); + return session; + } - void handleFinished(boost::optional<FileTransferError> error) { - finished = true; - this->error = error; - } + void handleFinished(boost::optional<FileTransferError> error) { + finished = true; + this->error = error; + } - private: - DummyStanzaChannel* stanzaChannel; - IQRouter* iqRouter; - bool finished; - boost::optional<FileTransferError> error; - boost::shared_ptr<ByteArrayWriteBytestream> bytestream; + private: + DummyStanzaChannel* stanzaChannel; + IQRouter* iqRouter; + bool finished; + boost::optional<FileTransferError> error; + std::shared_ptr<ByteArrayWriteBytestream> bytestream; }; CPPUNIT_TEST_SUITE_REGISTRATION(IBBReceiveSessionTest); diff --git a/Swiften/FileTransfer/UnitTest/IBBSendSessionTest.cpp b/Swiften/FileTransfer/UnitTest/IBBSendSessionTest.cpp index eac52bf..f9057f8 100644 --- a/Swiften/FileTransfer/UnitTest/IBBSendSessionTest.cpp +++ b/Swiften/FileTransfer/UnitTest/IBBSendSessionTest.cpp @@ -1,230 +1,232 @@ /* - * Copyright (c) 2010 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ -#include <cppunit/extensions/HelperMacros.h> -#include <cppunit/extensions/TestFactoryRegistry.h> #include <vector> + #include <boost/bind.hpp> +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + #include <Swiften/Base/ByteArray.h> -#include <Swiften/FileTransfer/IBBSendSession.h> +#include <Swiften/Client/DummyStanzaChannel.h> #include <Swiften/FileTransfer/ByteArrayReadBytestream.h> +#include <Swiften/FileTransfer/IBBSendSession.h> #include <Swiften/Queries/IQRouter.h> -#include <Swiften/Client/DummyStanzaChannel.h> using namespace Swift; class IBBSendSessionTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(IBBSendSessionTest); - CPPUNIT_TEST(testStart); - CPPUNIT_TEST(testStart_ResponseStartsSending); - CPPUNIT_TEST(testResponseContinuesSending); - CPPUNIT_TEST(testRespondToAllFinishes); - CPPUNIT_TEST(testErrorResponseFinishesWithError); - CPPUNIT_TEST(testStopDuringSessionCloses); - CPPUNIT_TEST(testStopAfterFinishedDoesNotClose); - CPPUNIT_TEST(testDataStreamPauseStopsSendingData); - CPPUNIT_TEST(testDataStreamResumeAfterPauseSendsData); - CPPUNIT_TEST(testDataStreamResumeBeforePauseDoesNotSendData); - CPPUNIT_TEST(testDataStreamResumeAfterResumeDoesNotSendData); - - CPPUNIT_TEST_SUITE_END(); - - public: - void setUp() { - stanzaChannel = new DummyStanzaChannel(); - iqRouter = new IQRouter(stanzaChannel); - bytestream = boost::make_shared<ByteArrayReadBytestream>(createByteArray("abcdefg")); - finished = false; - } - - void tearDown() { - delete iqRouter; - delete stanzaChannel; - } - - void testStart() { - boost::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); - testling->setBlockSize(1234); - - testling->start(); - - CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(stanzaChannel->sentStanzas.size())); - CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<IBB>(0, JID("foo@bar.com/baz"), IQ::Set)); - IBB::ref ibb = stanzaChannel->sentStanzas[0]->getPayload<IBB>(); - CPPUNIT_ASSERT_EQUAL(IBB::Open, ibb->getAction()); - CPPUNIT_ASSERT_EQUAL(1234, ibb->getBlockSize()); - CPPUNIT_ASSERT_EQUAL(std::string("myid"), ibb->getStreamID()); - } - - void testStart_ResponseStartsSending() { - boost::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); - testling->setBlockSize(3); - testling->start(); - - stanzaChannel->onIQReceived(createIBBResult()); - - CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(stanzaChannel->sentStanzas.size())); - CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<IBB>(1, JID("foo@bar.com/baz"), IQ::Set)); - IBB::ref ibb = stanzaChannel->sentStanzas[1]->getPayload<IBB>(); - CPPUNIT_ASSERT_EQUAL(IBB::Data, ibb->getAction()); - CPPUNIT_ASSERT(createByteArray("abc") == ibb->getData()); - CPPUNIT_ASSERT_EQUAL(0, ibb->getSequenceNumber()); - CPPUNIT_ASSERT_EQUAL(std::string("myid"), ibb->getStreamID()); - } - - void testResponseContinuesSending() { - boost::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); - testling->setBlockSize(3); - testling->start(); - stanzaChannel->onIQReceived(createIBBResult()); - stanzaChannel->onIQReceived(createIBBResult()); - - CPPUNIT_ASSERT_EQUAL(3, static_cast<int>(stanzaChannel->sentStanzas.size())); - CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<IBB>(2, JID("foo@bar.com/baz"), IQ::Set)); - IBB::ref ibb = stanzaChannel->sentStanzas[2]->getPayload<IBB>(); - CPPUNIT_ASSERT_EQUAL(IBB::Data, ibb->getAction()); - CPPUNIT_ASSERT(createByteArray("def") == ibb->getData()); - CPPUNIT_ASSERT_EQUAL(1, ibb->getSequenceNumber()); - CPPUNIT_ASSERT_EQUAL(std::string("myid"), ibb->getStreamID()); - } - - void testRespondToAllFinishes() { - boost::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); - testling->setBlockSize(3); - testling->start(); - stanzaChannel->onIQReceived(createIBBResult()); - stanzaChannel->onIQReceived(createIBBResult()); - stanzaChannel->onIQReceived(createIBBResult()); - stanzaChannel->onIQReceived(createIBBResult()); - - CPPUNIT_ASSERT(finished); - CPPUNIT_ASSERT(!error); - } - - void testErrorResponseFinishesWithError() { - boost::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); - testling->setBlockSize(3); - testling->start(); - stanzaChannel->onIQReceived(IQ::createError(JID("baz@fum.com/foo"), stanzaChannel->sentStanzas[0]->getTo(), stanzaChannel->sentStanzas[0]->getID())); - - CPPUNIT_ASSERT(finished); - CPPUNIT_ASSERT(error); - } - - void testStopDuringSessionCloses() { - boost::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); - testling->setBlockSize(3); - testling->start(); - testling->stop(); - - CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(stanzaChannel->sentStanzas.size())); - CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<IBB>(1, JID("foo@bar.com/baz"), IQ::Set)); - IBB::ref ibb = stanzaChannel->sentStanzas[1]->getPayload<IBB>(); - CPPUNIT_ASSERT_EQUAL(IBB::Close, ibb->getAction()); - CPPUNIT_ASSERT_EQUAL(std::string("myid"), ibb->getStreamID()); - CPPUNIT_ASSERT(finished); - CPPUNIT_ASSERT(!error); - } - - void testStopAfterFinishedDoesNotClose() { - boost::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); - testling->setBlockSize(16); - testling->start(); - stanzaChannel->onIQReceived(createIBBResult()); - stanzaChannel->onIQReceived(createIBBResult()); - CPPUNIT_ASSERT(finished); - - testling->stop(); - - CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(stanzaChannel->sentStanzas.size())); - } - - void testDataStreamPauseStopsSendingData() { - boost::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); - bytestream->setDataComplete(false); - testling->setBlockSize(3); - testling->start(); - stanzaChannel->onIQReceived(createIBBResult()); - stanzaChannel->onIQReceived(createIBBResult()); - stanzaChannel->onIQReceived(createIBBResult()); - stanzaChannel->onIQReceived(createIBBResult()); - - CPPUNIT_ASSERT(!finished); - CPPUNIT_ASSERT(!error); - - CPPUNIT_ASSERT_EQUAL(4, static_cast<int>(stanzaChannel->sentStanzas.size())); - } - - void testDataStreamResumeAfterPauseSendsData() { - boost::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); - bytestream->setDataComplete(false); - testling->setBlockSize(3); - testling->start(); - stanzaChannel->onIQReceived(createIBBResult()); - stanzaChannel->onIQReceived(createIBBResult()); - stanzaChannel->onIQReceived(createIBBResult()); - stanzaChannel->onIQReceived(createIBBResult()); - - bytestream->addData(createByteArray("xyz")); - - CPPUNIT_ASSERT_EQUAL(5, static_cast<int>(stanzaChannel->sentStanzas.size())); - } - - void testDataStreamResumeBeforePauseDoesNotSendData() { - boost::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); - bytestream->setDataComplete(false); - testling->setBlockSize(3); - testling->start(); - stanzaChannel->onIQReceived(createIBBResult()); - - bytestream->addData(createByteArray("xyz")); - - CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(stanzaChannel->sentStanzas.size())); - } - - void testDataStreamResumeAfterResumeDoesNotSendData() { - boost::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); - bytestream->setDataComplete(false); - testling->setBlockSize(3); - testling->start(); - stanzaChannel->onIQReceived(createIBBResult()); - stanzaChannel->onIQReceived(createIBBResult()); - stanzaChannel->onIQReceived(createIBBResult()); - stanzaChannel->onIQReceived(createIBBResult()); - - bytestream->addData(createByteArray("xyz")); - bytestream->addData(createByteArray("xuv")); - - CPPUNIT_ASSERT_EQUAL(5, static_cast<int>(stanzaChannel->sentStanzas.size())); - } - - private: - IQ::ref createIBBResult() { - return IQ::createResult(JID("baz@fum.com/dum"), stanzaChannel->sentStanzas[stanzaChannel->sentStanzas.size()-1]->getTo(), stanzaChannel->sentStanzas[stanzaChannel->sentStanzas.size()-1]->getID(), boost::shared_ptr<IBB>()); - } - - private: - boost::shared_ptr<IBBSendSession> createSession(const std::string& to) { - boost::shared_ptr<IBBSendSession> session(new IBBSendSession("myid", JID(), JID(to), bytestream, iqRouter)); - session->onFinished.connect(boost::bind(&IBBSendSessionTest::handleFinished, this, _1)); - return session; - } - - void handleFinished(boost::optional<FileTransferError> error) { - finished = true; - this->error = error; - } - - private: - DummyStanzaChannel* stanzaChannel; - IQRouter* iqRouter; - bool finished; - boost::optional<FileTransferError> error; - boost::shared_ptr<ByteArrayReadBytestream> bytestream; + CPPUNIT_TEST_SUITE(IBBSendSessionTest); + CPPUNIT_TEST(testStart); + CPPUNIT_TEST(testStart_ResponseStartsSending); + CPPUNIT_TEST(testResponseContinuesSending); + CPPUNIT_TEST(testRespondToAllFinishes); + CPPUNIT_TEST(testErrorResponseFinishesWithError); + CPPUNIT_TEST(testStopDuringSessionCloses); + CPPUNIT_TEST(testStopAfterFinishedDoesNotClose); + CPPUNIT_TEST(testDataStreamPauseStopsSendingData); + CPPUNIT_TEST(testDataStreamResumeAfterPauseSendsData); + CPPUNIT_TEST(testDataStreamResumeBeforePauseDoesNotSendData); + CPPUNIT_TEST(testDataStreamResumeAfterResumeDoesNotSendData); + + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + stanzaChannel = new DummyStanzaChannel(); + iqRouter = new IQRouter(stanzaChannel); + bytestream = std::make_shared<ByteArrayReadBytestream>(createByteArray("abcdefg")); + finished = false; + } + + void tearDown() { + delete iqRouter; + delete stanzaChannel; + } + + void testStart() { + std::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); + testling->setBlockSize(1234); + + testling->start(); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(stanzaChannel->sentStanzas.size())); + CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<IBB>(0, JID("foo@bar.com/baz"), IQ::Set)); + IBB::ref ibb = stanzaChannel->sentStanzas[0]->getPayload<IBB>(); + CPPUNIT_ASSERT_EQUAL(IBB::Open, ibb->getAction()); + CPPUNIT_ASSERT_EQUAL(1234, ibb->getBlockSize()); + CPPUNIT_ASSERT_EQUAL(std::string("myid"), ibb->getStreamID()); + } + + void testStart_ResponseStartsSending() { + std::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); + testling->setBlockSize(3); + testling->start(); + + stanzaChannel->onIQReceived(createIBBResult()); + + CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(stanzaChannel->sentStanzas.size())); + CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<IBB>(1, JID("foo@bar.com/baz"), IQ::Set)); + IBB::ref ibb = stanzaChannel->sentStanzas[1]->getPayload<IBB>(); + CPPUNIT_ASSERT_EQUAL(IBB::Data, ibb->getAction()); + CPPUNIT_ASSERT(createByteArray("abc") == ibb->getData()); + CPPUNIT_ASSERT_EQUAL(0, ibb->getSequenceNumber()); + CPPUNIT_ASSERT_EQUAL(std::string("myid"), ibb->getStreamID()); + } + + void testResponseContinuesSending() { + std::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); + testling->setBlockSize(3); + testling->start(); + stanzaChannel->onIQReceived(createIBBResult()); + stanzaChannel->onIQReceived(createIBBResult()); + + CPPUNIT_ASSERT_EQUAL(3, static_cast<int>(stanzaChannel->sentStanzas.size())); + CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<IBB>(2, JID("foo@bar.com/baz"), IQ::Set)); + IBB::ref ibb = stanzaChannel->sentStanzas[2]->getPayload<IBB>(); + CPPUNIT_ASSERT_EQUAL(IBB::Data, ibb->getAction()); + CPPUNIT_ASSERT(createByteArray("def") == ibb->getData()); + CPPUNIT_ASSERT_EQUAL(1, ibb->getSequenceNumber()); + CPPUNIT_ASSERT_EQUAL(std::string("myid"), ibb->getStreamID()); + } + + void testRespondToAllFinishes() { + std::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); + testling->setBlockSize(3); + testling->start(); + stanzaChannel->onIQReceived(createIBBResult()); + stanzaChannel->onIQReceived(createIBBResult()); + stanzaChannel->onIQReceived(createIBBResult()); + stanzaChannel->onIQReceived(createIBBResult()); + + CPPUNIT_ASSERT(finished); + CPPUNIT_ASSERT(!error); + } + + void testErrorResponseFinishesWithError() { + std::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); + testling->setBlockSize(3); + testling->start(); + stanzaChannel->onIQReceived(IQ::createError(JID("baz@fum.com/foo"), stanzaChannel->sentStanzas[0]->getTo(), stanzaChannel->sentStanzas[0]->getID())); + + CPPUNIT_ASSERT(finished); + CPPUNIT_ASSERT(error); + } + + void testStopDuringSessionCloses() { + std::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); + testling->setBlockSize(3); + testling->start(); + testling->stop(); + + CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(stanzaChannel->sentStanzas.size())); + CPPUNIT_ASSERT(stanzaChannel->isRequestAtIndex<IBB>(1, JID("foo@bar.com/baz"), IQ::Set)); + IBB::ref ibb = stanzaChannel->sentStanzas[1]->getPayload<IBB>(); + CPPUNIT_ASSERT_EQUAL(IBB::Close, ibb->getAction()); + CPPUNIT_ASSERT_EQUAL(std::string("myid"), ibb->getStreamID()); + CPPUNIT_ASSERT(finished); + CPPUNIT_ASSERT(!error); + } + + void testStopAfterFinishedDoesNotClose() { + std::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); + testling->setBlockSize(16); + testling->start(); + stanzaChannel->onIQReceived(createIBBResult()); + stanzaChannel->onIQReceived(createIBBResult()); + CPPUNIT_ASSERT(finished); + + testling->stop(); + + CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(stanzaChannel->sentStanzas.size())); + } + + void testDataStreamPauseStopsSendingData() { + std::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); + bytestream->setDataComplete(false); + testling->setBlockSize(3); + testling->start(); + stanzaChannel->onIQReceived(createIBBResult()); + stanzaChannel->onIQReceived(createIBBResult()); + stanzaChannel->onIQReceived(createIBBResult()); + stanzaChannel->onIQReceived(createIBBResult()); + + CPPUNIT_ASSERT(!finished); + CPPUNIT_ASSERT(!error); + + CPPUNIT_ASSERT_EQUAL(4, static_cast<int>(stanzaChannel->sentStanzas.size())); + } + + void testDataStreamResumeAfterPauseSendsData() { + std::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); + bytestream->setDataComplete(false); + testling->setBlockSize(3); + testling->start(); + stanzaChannel->onIQReceived(createIBBResult()); + stanzaChannel->onIQReceived(createIBBResult()); + stanzaChannel->onIQReceived(createIBBResult()); + stanzaChannel->onIQReceived(createIBBResult()); + + bytestream->addData(createByteArray("xyz")); + + CPPUNIT_ASSERT_EQUAL(5, static_cast<int>(stanzaChannel->sentStanzas.size())); + } + + void testDataStreamResumeBeforePauseDoesNotSendData() { + std::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); + bytestream->setDataComplete(false); + testling->setBlockSize(3); + testling->start(); + stanzaChannel->onIQReceived(createIBBResult()); + + bytestream->addData(createByteArray("xyz")); + + CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(stanzaChannel->sentStanzas.size())); + } + + void testDataStreamResumeAfterResumeDoesNotSendData() { + std::shared_ptr<IBBSendSession> testling = createSession("foo@bar.com/baz"); + bytestream->setDataComplete(false); + testling->setBlockSize(3); + testling->start(); + stanzaChannel->onIQReceived(createIBBResult()); + stanzaChannel->onIQReceived(createIBBResult()); + stanzaChannel->onIQReceived(createIBBResult()); + stanzaChannel->onIQReceived(createIBBResult()); + + bytestream->addData(createByteArray("xyz")); + bytestream->addData(createByteArray("xuv")); + + CPPUNIT_ASSERT_EQUAL(5, static_cast<int>(stanzaChannel->sentStanzas.size())); + } + + private: + IQ::ref createIBBResult() { + return IQ::createResult(JID("baz@fum.com/dum"), stanzaChannel->sentStanzas[stanzaChannel->sentStanzas.size()-1]->getTo(), stanzaChannel->sentStanzas[stanzaChannel->sentStanzas.size()-1]->getID(), std::shared_ptr<IBB>()); + } + + private: + std::shared_ptr<IBBSendSession> createSession(const std::string& to) { + std::shared_ptr<IBBSendSession> session(new IBBSendSession("myid", JID(), JID(to), bytestream, iqRouter)); + session->onFinished.connect(boost::bind(&IBBSendSessionTest::handleFinished, this, _1)); + return session; + } + + void handleFinished(boost::optional<FileTransferError> error) { + finished = true; + this->error = error; + } + + private: + DummyStanzaChannel* stanzaChannel; + IQRouter* iqRouter; + bool finished; + boost::optional<FileTransferError> error; + std::shared_ptr<ByteArrayReadBytestream> bytestream; }; CPPUNIT_TEST_SUITE_REGISTRATION(IBBSendSessionTest); diff --git a/Swiften/FileTransfer/UnitTest/IncomingJingleFileTransferTest.cpp b/Swiften/FileTransfer/UnitTest/IncomingJingleFileTransferTest.cpp index 2fb39bb..72b933d 100644 --- a/Swiften/FileTransfer/UnitTest/IncomingJingleFileTransferTest.cpp +++ b/Swiften/FileTransfer/UnitTest/IncomingJingleFileTransferTest.cpp @@ -5,14 +5,13 @@ */ /* - * Copyright (c) 2013-2015 Isode Limited. + * Copyright (c) 2013-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #include <iostream> - -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> @@ -45,201 +44,200 @@ #include <Swiften/Queries/IQRouter.h> using namespace Swift; -using namespace boost; class IncomingJingleFileTransferTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(IncomingJingleFileTransferTest); - CPPUNIT_TEST(test_AcceptOnyIBBSendsSessionAccept); - CPPUNIT_TEST(test_OnlyIBBTransferReceiveWorks); - //CPPUNIT_TEST(test_AcceptFailingS5BFallsBackToIBB); - CPPUNIT_TEST_SUITE_END(); + CPPUNIT_TEST_SUITE(IncomingJingleFileTransferTest); + CPPUNIT_TEST(test_AcceptOnyIBBSendsSessionAccept); + CPPUNIT_TEST(test_OnlyIBBTransferReceiveWorks); + //CPPUNIT_TEST(test_AcceptFailingS5BFallsBackToIBB); + CPPUNIT_TEST_SUITE_END(); public: - shared_ptr<IncomingJingleFileTransfer> createTestling() { - JID ourJID("our@jid.org/full"); - return boost::make_shared<IncomingJingleFileTransfer>(ourJID, shared_ptr<JingleSession>(session), jingleContentPayload, ftTransporterFactory, timerFactory, crypto.get()); - } - - IQ::ref createIBBRequest(IBB::ref ibb, const JID& from, const std::string& id) { - IQ::ref request = IQ::createRequest(IQ::Set, JID("foo@bar.com/baz"), id, ibb); - request->setFrom(from); - return request; - } - - void setUp() { - crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); - eventLoop = new DummyEventLoop(); - resolver = new StaticDomainNameResolver(eventLoop); - session = boost::make_shared<FakeJingleSession>("foo@bar.com/baz", "mysession"); - jingleContentPayload = make_shared<JingleContentPayload>(); - // fakeRJTCSF = make_shared<FakeRemoteJingleTransportCandidateSelectorFactory>(); - // fakeLJTCF = make_shared<FakeLocalJingleTransportCandidateGeneratorFactory>(); - stanzaChannel = new DummyStanzaChannel(); - connectionFactory = new DummyConnectionFactory(eventLoop); - serverConnectionFactory = new DummyConnectionServerFactory(eventLoop); - iqRouter = new IQRouter(stanzaChannel); - bytestreamRegistry = new SOCKS5BytestreamRegistry(); - networkEnvironment = new PlatformNetworkEnvironment(); - natTraverser = new PlatformNATTraversalWorker(eventLoop); - bytestreamServerManager = new SOCKS5BytestreamServerManager(bytestreamRegistry, serverConnectionFactory, networkEnvironment, natTraverser); - idGenerator = new SimpleIDGenerator(); - timerFactory = new DummyTimerFactory(); - bytestreamProxy = new SOCKS5BytestreamProxiesManager(connectionFactory, timerFactory, resolver, iqRouter, "bar.com"); - ftTransporterFactory = new DefaultFileTransferTransporterFactory(bytestreamRegistry, bytestreamServerManager, bytestreamProxy, idGenerator, connectionFactory, timerFactory, crypto.get(), iqRouter); - } - - void tearDown() { - delete ftTransporterFactory; - delete bytestreamProxy; - delete timerFactory; - delete idGenerator; - delete bytestreamServerManager; - delete natTraverser; - delete networkEnvironment; - delete bytestreamRegistry; - delete iqRouter; - delete serverConnectionFactory; - delete connectionFactory; - delete stanzaChannel; - delete resolver; - delete eventLoop; - Log::setLogLevel(Log::error); - } - - // Tests whether IncomingJingleFileTransfer would accept a IBB only file transfer. - void test_AcceptOnyIBBSendsSessionAccept() { - //1. create your test incoming file transfer - shared_ptr<JingleFileTransferDescription> desc = make_shared<JingleFileTransferDescription>(); - desc->setFileInfo(JingleFileTransferFileInfo("foo.txt", "", 10)); - jingleContentPayload->addDescription(desc); - JingleIBBTransportPayload::ref tpRef = make_shared<JingleIBBTransportPayload>(); - tpRef->setSessionID("mysession"); - jingleContentPayload->addTransport(tpRef); - - shared_ptr<IncomingJingleFileTransfer> fileTransfer = createTestling(); - - //2. do 'accept' on a dummy writebytestream (you'll have to look if there already is one) - shared_ptr<ByteArrayWriteBytestream> byteStream = make_shared<ByteArrayWriteBytestream>(); - fileTransfer->accept(byteStream); - - // check whether accept has been called - getCall<FakeJingleSession::AcceptCall>(0); - } - - void test_OnlyIBBTransferReceiveWorks() { - //1. create your test incoming file transfer - shared_ptr<JingleFileTransferDescription> desc = make_shared<JingleFileTransferDescription>(); - desc->setFileInfo(JingleFileTransferFileInfo("file.txt", "", 10)); - jingleContentPayload->addDescription(desc); - JingleIBBTransportPayload::ref tpRef = make_shared<JingleIBBTransportPayload>(); - tpRef->setSessionID("mysession"); - jingleContentPayload->addTransport(tpRef); - - shared_ptr<IncomingJingleFileTransfer> fileTransfer = createTestling(); - - //2. do 'accept' on a dummy writebytestream (you'll have to look if there already is one) - shared_ptr<ByteArrayWriteBytestream> byteStream = make_shared<ByteArrayWriteBytestream>(); - fileTransfer->accept(byteStream); - - // check whether accept has been called - getCall<FakeJingleSession::AcceptCall>(0); - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open")); - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 0, createByteArray("abc")), "foo@bar.com/baz", "id-a")); - CPPUNIT_ASSERT(createByteArray("abc") == byteStream->getData()); - } - - void test_AcceptFailingS5BFallsBackToIBB() { - //1. create your test incoming file transfer - addFileTransferDescription(); - - // add SOCKS5BytestreamTransportPayload - JingleS5BTransportPayload::ref payLoad = addJingleS5BPayload(); - - shared_ptr<IncomingJingleFileTransfer> fileTransfer = createTestling(); - - //2. do 'accept' on a dummy writebytestream (you'll have to look if there already is one) - shared_ptr<ByteArrayWriteBytestream> byteStream = make_shared<ByteArrayWriteBytestream>(); - fileTransfer->accept(byteStream); - - // candidates are gathered - - // check whether accept has been called - FakeJingleSession::AcceptCall acceptCall = getCall<FakeJingleSession::AcceptCall>(0); - CPPUNIT_ASSERT_EQUAL(payLoad->getSessionID(), acceptCall.payload->getSessionID()); - - // check for candidate error - FakeJingleSession::InfoTransportCall infoTransportCall = getCall<FakeJingleSession::InfoTransportCall>(1); - JingleS5BTransportPayload::ref s5bPayload = dynamic_pointer_cast<JingleS5BTransportPayload>(infoTransportCall.payload); - CPPUNIT_ASSERT(s5bPayload->hasCandidateError()); - - // indicate transport replace (Romeo) - session->handleTransportReplaceReceived(getContentID(), addJingleIBBPayload()); - - FakeJingleSession::AcceptTransportCall acceptTransportCall = getCall<FakeJingleSession::AcceptTransportCall>(2); - - // send a bit of data - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open")); - stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 0, createByteArray("abc")), "foo@bar.com/baz", "id-a")); - CPPUNIT_ASSERT(createByteArray("abc") == byteStream->getData()); - } + std::shared_ptr<IncomingJingleFileTransfer> createTestling() { + JID ourJID("our@jid.org/full"); + return std::make_shared<IncomingJingleFileTransfer>(ourJID, std::shared_ptr<JingleSession>(session), jingleContentPayload, ftTransporterFactory, timerFactory, crypto.get()); + } + + IQ::ref createIBBRequest(IBB::ref ibb, const JID& from, const std::string& id) { + IQ::ref request = IQ::createRequest(IQ::Set, JID("foo@bar.com/baz"), id, ibb); + request->setFrom(from); + return request; + } + + void setUp() { + crypto = std::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); + eventLoop = new DummyEventLoop(); + resolver = new StaticDomainNameResolver(eventLoop); + session = std::make_shared<FakeJingleSession>("foo@bar.com/baz", "mysession"); + jingleContentPayload = std::make_shared<JingleContentPayload>(); + // fakeRJTCSF = std::make_shared<FakeRemoteJingleTransportCandidateSelectorFactory>(); + // fakeLJTCF = std::make_shared<FakeLocalJingleTransportCandidateGeneratorFactory>(); + stanzaChannel = new DummyStanzaChannel(); + connectionFactory = new DummyConnectionFactory(eventLoop); + serverConnectionFactory = new DummyConnectionServerFactory(eventLoop); + iqRouter = new IQRouter(stanzaChannel); + bytestreamRegistry = new SOCKS5BytestreamRegistry(); + networkEnvironment = new PlatformNetworkEnvironment(); + natTraverser = new PlatformNATTraversalWorker(eventLoop); + bytestreamServerManager = new SOCKS5BytestreamServerManager(bytestreamRegistry, serverConnectionFactory, networkEnvironment, natTraverser); + idGenerator = new SimpleIDGenerator(); + timerFactory = new DummyTimerFactory(); + bytestreamProxy = new SOCKS5BytestreamProxiesManager(connectionFactory, timerFactory, resolver, iqRouter, "bar.com"); + ftTransporterFactory = new DefaultFileTransferTransporterFactory(bytestreamRegistry, bytestreamServerManager, bytestreamProxy, idGenerator, connectionFactory, timerFactory, crypto.get(), iqRouter); + } + + void tearDown() { + delete ftTransporterFactory; + delete bytestreamProxy; + delete timerFactory; + delete idGenerator; + delete bytestreamServerManager; + delete natTraverser; + delete networkEnvironment; + delete bytestreamRegistry; + delete iqRouter; + delete serverConnectionFactory; + delete connectionFactory; + delete stanzaChannel; + delete resolver; + delete eventLoop; + Log::setLogLevel(Log::error); + } + + // Tests whether IncomingJingleFileTransfer would accept a IBB only file transfer. + void test_AcceptOnyIBBSendsSessionAccept() { + //1. create your test incoming file transfer + std::shared_ptr<JingleFileTransferDescription> desc = std::make_shared<JingleFileTransferDescription>(); + desc->setFileInfo(JingleFileTransferFileInfo("foo.txt", "", 10)); + jingleContentPayload->addDescription(desc); + JingleIBBTransportPayload::ref tpRef = std::make_shared<JingleIBBTransportPayload>(); + tpRef->setSessionID("mysession"); + jingleContentPayload->addTransport(tpRef); + + std::shared_ptr<IncomingJingleFileTransfer> fileTransfer = createTestling(); + + //2. do 'accept' on a dummy writebytestream (you'll have to look if there already is one) + std::shared_ptr<ByteArrayWriteBytestream> byteStream = std::make_shared<ByteArrayWriteBytestream>(); + fileTransfer->accept(byteStream); + + // check whether accept has been called + getCall<FakeJingleSession::AcceptCall>(0); + } + + void test_OnlyIBBTransferReceiveWorks() { + //1. create your test incoming file transfer + std::shared_ptr<JingleFileTransferDescription> desc = std::make_shared<JingleFileTransferDescription>(); + desc->setFileInfo(JingleFileTransferFileInfo("file.txt", "", 10)); + jingleContentPayload->addDescription(desc); + JingleIBBTransportPayload::ref tpRef = std::make_shared<JingleIBBTransportPayload>(); + tpRef->setSessionID("mysession"); + jingleContentPayload->addTransport(tpRef); + + std::shared_ptr<IncomingJingleFileTransfer> fileTransfer = createTestling(); + + //2. do 'accept' on a dummy writebytestream (you'll have to look if there already is one) + std::shared_ptr<ByteArrayWriteBytestream> byteStream = std::make_shared<ByteArrayWriteBytestream>(); + fileTransfer->accept(byteStream); + + // check whether accept has been called + getCall<FakeJingleSession::AcceptCall>(0); + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open")); + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 0, createByteArray("abc")), "foo@bar.com/baz", "id-a")); + CPPUNIT_ASSERT(createByteArray("abc") == byteStream->getData()); + } + + void test_AcceptFailingS5BFallsBackToIBB() { + //1. create your test incoming file transfer + addFileTransferDescription(); + + // add SOCKS5BytestreamTransportPayload + JingleS5BTransportPayload::ref payLoad = addJingleS5BPayload(); + + std::shared_ptr<IncomingJingleFileTransfer> fileTransfer = createTestling(); + + //2. do 'accept' on a dummy writebytestream (you'll have to look if there already is one) + std::shared_ptr<ByteArrayWriteBytestream> byteStream = std::make_shared<ByteArrayWriteBytestream>(); + fileTransfer->accept(byteStream); + + // candidates are gathered + + // check whether accept has been called + FakeJingleSession::AcceptCall acceptCall = getCall<FakeJingleSession::AcceptCall>(0); + CPPUNIT_ASSERT_EQUAL(payLoad->getSessionID(), acceptCall.payload->getSessionID()); + + // check for candidate error + FakeJingleSession::InfoTransportCall infoTransportCall = getCall<FakeJingleSession::InfoTransportCall>(1); + JingleS5BTransportPayload::ref s5bPayload = std::dynamic_pointer_cast<JingleS5BTransportPayload>(infoTransportCall.payload); + CPPUNIT_ASSERT(s5bPayload->hasCandidateError()); + + // indicate transport replace (Romeo) + session->handleTransportReplaceReceived(getContentID(), addJingleIBBPayload()); + + FakeJingleSession::AcceptTransportCall acceptTransportCall = getCall<FakeJingleSession::AcceptTransportCall>(2); + + // send a bit of data + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBOpen("mysession", 0x10), "foo@bar.com/baz", "id-open")); + stanzaChannel->onIQReceived(createIBBRequest(IBB::createIBBData("mysession", 0, createByteArray("abc")), "foo@bar.com/baz", "id-a")); + CPPUNIT_ASSERT(createByteArray("abc") == byteStream->getData()); + } #if 0 - void test_S5BTransferReceiveTest() { - addFileTransferDescription(); - JingleS5BTransportPayload::ref payLoad = addJingleS5BPayload(); - } + void test_S5BTransferReceiveTest() { + addFileTransferDescription(); + JingleS5BTransportPayload::ref payLoad = addJingleS5BPayload(); + } #endif private: - void addFileTransferDescription() { - shared_ptr<JingleFileTransferDescription> desc = make_shared<JingleFileTransferDescription>(); - desc->setFileInfo(JingleFileTransferFileInfo("file.txt", "", 10)); - jingleContentPayload->addDescription(desc); - } - - shared_ptr<JingleS5BTransportPayload> addJingleS5BPayload() { - JingleS5BTransportPayload::ref payLoad = make_shared<JingleS5BTransportPayload>(); - payLoad->setSessionID("mysession"); - jingleContentPayload->addTransport(payLoad); - return payLoad; - } - - shared_ptr<JingleIBBTransportPayload> addJingleIBBPayload() { - JingleIBBTransportPayload::ref payLoad = make_shared<JingleIBBTransportPayload>(); - payLoad->setSessionID("mysession"); - jingleContentPayload->addTransport(payLoad); - return payLoad; - } - - JingleContentID getContentID() const { - return JingleContentID(jingleContentPayload->getName(), jingleContentPayload->getCreator()); - } - - template <typename T> T getCall(int i) const { - size_t index = static_cast<size_t>(i); - CPPUNIT_ASSERT(index < session->calledCommands.size()); - T* cmd = boost::get<T>(&session->calledCommands[index]); - CPPUNIT_ASSERT(cmd); - return *cmd; - } + void addFileTransferDescription() { + std::shared_ptr<JingleFileTransferDescription> desc = std::make_shared<JingleFileTransferDescription>(); + desc->setFileInfo(JingleFileTransferFileInfo("file.txt", "", 10)); + jingleContentPayload->addDescription(desc); + } + + std::shared_ptr<JingleS5BTransportPayload> addJingleS5BPayload() { + JingleS5BTransportPayload::ref payLoad = std::make_shared<JingleS5BTransportPayload>(); + payLoad->setSessionID("mysession"); + jingleContentPayload->addTransport(payLoad); + return payLoad; + } + + std::shared_ptr<JingleIBBTransportPayload> addJingleIBBPayload() { + JingleIBBTransportPayload::ref payLoad = std::make_shared<JingleIBBTransportPayload>(); + payLoad->setSessionID("mysession"); + jingleContentPayload->addTransport(payLoad); + return payLoad; + } + + JingleContentID getContentID() const { + return JingleContentID(jingleContentPayload->getName(), jingleContentPayload->getCreator()); + } + + template <typename T> T getCall(int i) const { + size_t index = static_cast<size_t>(i); + CPPUNIT_ASSERT(index < session->calledCommands.size()); + T* cmd = boost::get<T>(&session->calledCommands[index]); + CPPUNIT_ASSERT(cmd); + return *cmd; + } private: - EventLoop* eventLoop; - boost::shared_ptr<CryptoProvider> crypto; - boost::shared_ptr<FakeJingleSession> session; - shared_ptr<JingleContentPayload> jingleContentPayload; -// shared_ptr<FakeRemoteJingleTransportCandidateSelectorFactory> fakeRJTCSF; -// shared_ptr<FakeLocalJingleTransportCandidateGeneratorFactory> fakeLJTCF; - FileTransferTransporterFactory* ftTransporterFactory; - SOCKS5BytestreamServerManager* bytestreamServerManager; - DummyStanzaChannel* stanzaChannel; - IQRouter* iqRouter; - SOCKS5BytestreamRegistry* bytestreamRegistry; - DummyConnectionFactory* connectionFactory; - DummyConnectionServerFactory* serverConnectionFactory; - SOCKS5BytestreamProxiesManager* bytestreamProxy; - DummyTimerFactory* timerFactory; - NetworkEnvironment* networkEnvironment; - NATTraverser* natTraverser; - IDGenerator* idGenerator; - DomainNameResolver* resolver; + EventLoop* eventLoop; + std::shared_ptr<CryptoProvider> crypto; + std::shared_ptr<FakeJingleSession> session; + std::shared_ptr<JingleContentPayload> jingleContentPayload; +// shared_ptr<FakeRemoteJingleTransportCandidateSelectorFactory> fakeRJTCSF; +// shared_ptr<FakeLocalJingleTransportCandidateGeneratorFactory> fakeLJTCF; + FileTransferTransporterFactory* ftTransporterFactory; + SOCKS5BytestreamServerManager* bytestreamServerManager; + DummyStanzaChannel* stanzaChannel; + IQRouter* iqRouter; + SOCKS5BytestreamRegistry* bytestreamRegistry; + DummyConnectionFactory* connectionFactory; + DummyConnectionServerFactory* serverConnectionFactory; + SOCKS5BytestreamProxiesManager* bytestreamProxy; + DummyTimerFactory* timerFactory; + NetworkEnvironment* networkEnvironment; + NATTraverser* natTraverser; + IDGenerator* idGenerator; + DomainNameResolver* resolver; }; CPPUNIT_TEST_SUITE_REGISTRATION(IncomingJingleFileTransferTest); diff --git a/Swiften/FileTransfer/UnitTest/OutgoingJingleFileTransferTest.cpp b/Swiften/FileTransfer/UnitTest/OutgoingJingleFileTransferTest.cpp index fee26d5..3f4d20f 100644 --- a/Swiften/FileTransfer/UnitTest/OutgoingJingleFileTransferTest.cpp +++ b/Swiften/FileTransfer/UnitTest/OutgoingJingleFileTransferTest.cpp @@ -11,10 +11,10 @@ */ #include <iostream> +#include <memory> #include <boost/bind.hpp> #include <boost/optional.hpp> -#include <boost/smart_ptr/make_shared.hpp> #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> @@ -52,232 +52,232 @@ using namespace Swift; class OutgoingJingleFileTransferTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(OutgoingJingleFileTransferTest); - CPPUNIT_TEST(test_SendSessionInitiateOnStart); - CPPUNIT_TEST(test_FallbackToIBBAfterFailingS5B); - CPPUNIT_TEST(test_ReceiveSessionTerminateAfterSessionInitiate); - CPPUNIT_TEST(test_DeclineEmitsFinishedStateCanceled); - CPPUNIT_TEST_SUITE_END(); - - class FTStatusHelper { - public: - FTStatusHelper() : finishedCalled(false), error(FileTransferError::UnknownError) { - } - - void handleFileTransferFinished(boost::optional<FileTransferError> error) { - finishedCalled = true; - if (error.is_initialized()) this->error = error.get().getType(); - } - - void handleFileTransferStatusChanged(FileTransfer::State fileTransferSTate) { - state = fileTransferSTate; - } - - public: - bool finishedCalled; - FileTransferError::Type error; - boost::optional<FileTransfer::State> state; - }; + CPPUNIT_TEST_SUITE(OutgoingJingleFileTransferTest); + CPPUNIT_TEST(test_SendSessionInitiateOnStart); + CPPUNIT_TEST(test_FallbackToIBBAfterFailingS5B); + CPPUNIT_TEST(test_ReceiveSessionTerminateAfterSessionInitiate); + CPPUNIT_TEST(test_DeclineEmitsFinishedStateCanceled); + CPPUNIT_TEST_SUITE_END(); + + class FTStatusHelper { + public: + FTStatusHelper() : finishedCalled(false), error(FileTransferError::UnknownError) { + } + + void handleFileTransferFinished(boost::optional<FileTransferError> error) { + finishedCalled = true; + if (error.is_initialized()) this->error = error.get().getType(); + } + + void handleFileTransferStatusChanged(FileTransfer::State fileTransferSTate) { + state = fileTransferSTate; + } + + public: + bool finishedCalled; + FileTransferError::Type error; + boost::optional<FileTransfer::State> state; + }; public: - boost::shared_ptr<OutgoingJingleFileTransfer> createTestling(const FileTransferOptions& options = FileTransferOptions().withAssistedAllowed(false).withDirectAllowed(false).withProxiedAllowed(false)) { - JID to("test@foo.com/bla"); - JingleFileTransferFileInfo fileInfo; - fileInfo.setDescription("some file"); - fileInfo.setName("test.bin"); - fileInfo.addHash(HashElement("sha-1", ByteArray())); - fileInfo.setSize(1024 * 1024); - return boost::shared_ptr<OutgoingJingleFileTransfer>(new OutgoingJingleFileTransfer( - to, - boost::shared_ptr<JingleSession>(fakeJingleSession), - stream, - ftTransportFactory, - timerFactory, - idGen, - fileInfo, - options, - crypto.get())); - } - - IQ::ref createIBBRequest(IBB::ref ibb, const JID& from, const std::string& id) { - IQ::ref request = IQ::createRequest(IQ::Set, JID("foo@bar.com/baz"), id, ibb); - request->setFrom(from); - return request; - } - - void setUp() { - crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); - fakeJingleSession = new FakeJingleSession("foo@bar.com/baz", "mysession"); - jingleContentPayload = boost::make_shared<JingleContentPayload>(); - stanzaChannel = new DummyStanzaChannel(); - iqRouter = new IQRouter(stanzaChannel); - eventLoop = new DummyEventLoop(); - timerFactory = new DummyTimerFactory(); - connectionFactory = new DummyConnectionFactory(eventLoop); - serverConnectionFactory = new DummyConnectionServerFactory(eventLoop); - s5bRegistry = new SOCKS5BytestreamRegistry(); - networkEnvironment = new PlatformNetworkEnvironment(); - natTraverser = new PlatformNATTraversalWorker(eventLoop); - bytestreamServerManager = new SOCKS5BytestreamServerManager(s5bRegistry, serverConnectionFactory, networkEnvironment, natTraverser); - - data.clear(); - for (int n=0; n < 1024 * 1024; ++n) { - data.push_back(34); - } - - stream = boost::make_shared<ByteArrayReadBytestream>(data); - - idGen = new IDGenerator(); - s5bProxy = new SOCKS5BytestreamProxiesManager(connectionFactory, timerFactory, resolver, iqRouter, "bar.com"); - ftTransportFactory = new DummyFileTransferTransporterFactory(s5bRegistry, bytestreamServerManager, s5bProxy, idGen, connectionFactory, timerFactory, crypto.get(), iqRouter); - } - - void tearDown() { - delete ftTransportFactory; - delete s5bProxy; - delete idGen; - delete bytestreamServerManager; - delete natTraverser; - delete networkEnvironment; - delete s5bRegistry; - delete serverConnectionFactory; - delete connectionFactory; - delete timerFactory; - delete eventLoop; - delete iqRouter; - delete stanzaChannel; - } - - - void test_SendSessionInitiateOnStart() { - boost::shared_ptr<OutgoingJingleFileTransfer> transfer = createTestling(); - transfer->start(); - - FakeJingleSession::InitiateCall call = getCall<FakeJingleSession::InitiateCall>(0); - JingleFileTransferDescription::ref description = boost::dynamic_pointer_cast<JingleFileTransferDescription>(call.description); - CPPUNIT_ASSERT(description); - CPPUNIT_ASSERT(static_cast<size_t>(1048576) == description->getFileInfo().getSize()); - - JingleIBBTransportPayload::ref transport = boost::dynamic_pointer_cast<JingleIBBTransportPayload>(call.payload); - CPPUNIT_ASSERT(transport); - } - - void test_FallbackToIBBAfterFailingS5B() { - boost::shared_ptr<OutgoingJingleFileTransfer> transfer = createTestling(FileTransferOptions().withAssistedAllowed(true).withDirectAllowed(true).withProxiedAllowed(true)); - transfer->start(); - - FakeJingleSession::InitiateCall call = getCall<FakeJingleSession::InitiateCall>(0); - - CPPUNIT_ASSERT(boost::dynamic_pointer_cast<JingleS5BTransportPayload>(call.payload)); - fakeJingleSession->handleSessionAcceptReceived(call.id, call.description, call.payload); - - // send candidate failure - JingleS5BTransportPayload::ref candidateFailurePayload = boost::make_shared<JingleS5BTransportPayload>(); - candidateFailurePayload->setCandidateError(true); - candidateFailurePayload->setSessionID(call.payload->getSessionID()); - fakeJingleSession->handleTransportInfoReceived(call.id, candidateFailurePayload); - - // no S5B candidates -> fallback to IBB - // call at position 1 is the candidate our candidate error - FakeJingleSession::ReplaceTransportCall replaceCall = getCall<FakeJingleSession::ReplaceTransportCall>(2); - - // accept transport replace - fakeJingleSession->handleTransportAcceptReceived(replaceCall.id, replaceCall.payload); - - IQ::ref iqOpenStanza = stanzaChannel->getStanzaAtIndex<IQ>(0); - CPPUNIT_ASSERT(iqOpenStanza); - IBB::ref ibbOpen = iqOpenStanza->getPayload<IBB>(); - CPPUNIT_ASSERT(ibbOpen); - CPPUNIT_ASSERT_EQUAL(IBB::Open, ibbOpen->getAction()); - } - - void test_ReceiveSessionTerminateAfterSessionInitiate() { - boost::shared_ptr<OutgoingJingleFileTransfer> transfer = createTestling(); - transfer->start(); - - getCall<FakeJingleSession::InitiateCall>(0); - - FTStatusHelper helper; - helper.finishedCalled = false; - transfer->onFinished.connect(bind(&FTStatusHelper::handleFileTransferFinished, &helper, _1)); - fakeJingleSession->handleSessionTerminateReceived(JinglePayload::Reason(JinglePayload::Reason::Busy)); - CPPUNIT_ASSERT_EQUAL(true, helper.finishedCalled); - CPPUNIT_ASSERT(FileTransferError::PeerError == helper.error); - } - - void test_DeclineEmitsFinishedStateCanceled() { - boost::shared_ptr<OutgoingJingleFileTransfer> transfer = createTestling(); - transfer->start(); - - getCall<FakeJingleSession::InitiateCall>(0); - - FTStatusHelper helper; - helper.finishedCalled = false; - transfer->onFinished.connect(bind(&FTStatusHelper::handleFileTransferFinished, &helper, _1)); - transfer->onStateChanged.connect(bind(&FTStatusHelper::handleFileTransferStatusChanged, &helper, _1)); - fakeJingleSession->handleSessionTerminateReceived(JinglePayload::Reason(JinglePayload::Reason::Decline)); - CPPUNIT_ASSERT_EQUAL(true, helper.finishedCalled); - CPPUNIT_ASSERT(FileTransferError::UnknownError == helper.error); - CPPUNIT_ASSERT_EQUAL(true, helper.state.is_initialized()); - CPPUNIT_ASSERT(FileTransfer::State::Canceled == helper.state.get().type); - } + std::shared_ptr<OutgoingJingleFileTransfer> createTestling(const FileTransferOptions& options = FileTransferOptions().withAssistedAllowed(false).withDirectAllowed(false).withProxiedAllowed(false)) { + JID to("test@foo.com/bla"); + JingleFileTransferFileInfo fileInfo; + fileInfo.setDescription("some file"); + fileInfo.setName("test.bin"); + fileInfo.addHash(HashElement("sha-1", ByteArray())); + fileInfo.setSize(1024 * 1024); + return std::shared_ptr<OutgoingJingleFileTransfer>(new OutgoingJingleFileTransfer( + to, + std::shared_ptr<JingleSession>(fakeJingleSession), + stream, + ftTransportFactory, + timerFactory, + idGen, + fileInfo, + options, + crypto.get())); + } + + IQ::ref createIBBRequest(IBB::ref ibb, const JID& from, const std::string& id) { + IQ::ref request = IQ::createRequest(IQ::Set, JID("foo@bar.com/baz"), id, ibb); + request->setFrom(from); + return request; + } + + void setUp() { + crypto = std::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); + fakeJingleSession = new FakeJingleSession("foo@bar.com/baz", "mysession"); + jingleContentPayload = std::make_shared<JingleContentPayload>(); + stanzaChannel = new DummyStanzaChannel(); + iqRouter = new IQRouter(stanzaChannel); + eventLoop = new DummyEventLoop(); + timerFactory = new DummyTimerFactory(); + connectionFactory = new DummyConnectionFactory(eventLoop); + serverConnectionFactory = new DummyConnectionServerFactory(eventLoop); + s5bRegistry = new SOCKS5BytestreamRegistry(); + networkEnvironment = new PlatformNetworkEnvironment(); + natTraverser = new PlatformNATTraversalWorker(eventLoop); + bytestreamServerManager = new SOCKS5BytestreamServerManager(s5bRegistry, serverConnectionFactory, networkEnvironment, natTraverser); + + data.clear(); + for (int n=0; n < 1024 * 1024; ++n) { + data.push_back(34); + } + + stream = std::make_shared<ByteArrayReadBytestream>(data); + + idGen = new IDGenerator(); + s5bProxy = new SOCKS5BytestreamProxiesManager(connectionFactory, timerFactory, resolver, iqRouter, "bar.com"); + ftTransportFactory = new DummyFileTransferTransporterFactory(s5bRegistry, bytestreamServerManager, s5bProxy, idGen, connectionFactory, timerFactory, crypto.get(), iqRouter); + } + + void tearDown() { + delete ftTransportFactory; + delete s5bProxy; + delete idGen; + delete bytestreamServerManager; + delete natTraverser; + delete networkEnvironment; + delete s5bRegistry; + delete serverConnectionFactory; + delete connectionFactory; + delete timerFactory; + delete eventLoop; + delete iqRouter; + delete stanzaChannel; + } + + + void test_SendSessionInitiateOnStart() { + std::shared_ptr<OutgoingJingleFileTransfer> transfer = createTestling(); + transfer->start(); + + FakeJingleSession::InitiateCall call = getCall<FakeJingleSession::InitiateCall>(0); + JingleFileTransferDescription::ref description = std::dynamic_pointer_cast<JingleFileTransferDescription>(call.description); + CPPUNIT_ASSERT(description); + CPPUNIT_ASSERT(static_cast<size_t>(1048576) == description->getFileInfo().getSize()); + + JingleIBBTransportPayload::ref transport = std::dynamic_pointer_cast<JingleIBBTransportPayload>(call.payload); + CPPUNIT_ASSERT(transport); + } + + void test_FallbackToIBBAfterFailingS5B() { + std::shared_ptr<OutgoingJingleFileTransfer> transfer = createTestling(FileTransferOptions().withAssistedAllowed(true).withDirectAllowed(true).withProxiedAllowed(true)); + transfer->start(); + + FakeJingleSession::InitiateCall call = getCall<FakeJingleSession::InitiateCall>(0); + + CPPUNIT_ASSERT(std::dynamic_pointer_cast<JingleS5BTransportPayload>(call.payload)); + fakeJingleSession->handleSessionAcceptReceived(call.id, call.description, call.payload); + + // send candidate failure + JingleS5BTransportPayload::ref candidateFailurePayload = std::make_shared<JingleS5BTransportPayload>(); + candidateFailurePayload->setCandidateError(true); + candidateFailurePayload->setSessionID(call.payload->getSessionID()); + fakeJingleSession->handleTransportInfoReceived(call.id, candidateFailurePayload); + + // no S5B candidates -> fallback to IBB + // call at position 1 is the candidate our candidate error + FakeJingleSession::ReplaceTransportCall replaceCall = getCall<FakeJingleSession::ReplaceTransportCall>(2); + + // accept transport replace + fakeJingleSession->handleTransportAcceptReceived(replaceCall.id, replaceCall.payload); + + IQ::ref iqOpenStanza = stanzaChannel->getStanzaAtIndex<IQ>(0); + CPPUNIT_ASSERT(iqOpenStanza); + IBB::ref ibbOpen = iqOpenStanza->getPayload<IBB>(); + CPPUNIT_ASSERT(ibbOpen); + CPPUNIT_ASSERT_EQUAL(IBB::Open, ibbOpen->getAction()); + } + + void test_ReceiveSessionTerminateAfterSessionInitiate() { + std::shared_ptr<OutgoingJingleFileTransfer> transfer = createTestling(); + transfer->start(); + + getCall<FakeJingleSession::InitiateCall>(0); + + FTStatusHelper helper; + helper.finishedCalled = false; + transfer->onFinished.connect(bind(&FTStatusHelper::handleFileTransferFinished, &helper, _1)); + fakeJingleSession->handleSessionTerminateReceived(JinglePayload::Reason(JinglePayload::Reason::Busy)); + CPPUNIT_ASSERT_EQUAL(true, helper.finishedCalled); + CPPUNIT_ASSERT(FileTransferError::PeerError == helper.error); + } + + void test_DeclineEmitsFinishedStateCanceled() { + std::shared_ptr<OutgoingJingleFileTransfer> transfer = createTestling(); + transfer->start(); + + getCall<FakeJingleSession::InitiateCall>(0); + + FTStatusHelper helper; + helper.finishedCalled = false; + transfer->onFinished.connect(bind(&FTStatusHelper::handleFileTransferFinished, &helper, _1)); + transfer->onStateChanged.connect(bind(&FTStatusHelper::handleFileTransferStatusChanged, &helper, _1)); + fakeJingleSession->handleSessionTerminateReceived(JinglePayload::Reason(JinglePayload::Reason::Decline)); + CPPUNIT_ASSERT_EQUAL(true, helper.finishedCalled); + CPPUNIT_ASSERT(FileTransferError::UnknownError == helper.error); + CPPUNIT_ASSERT_EQUAL(true, helper.state.is_initialized()); + CPPUNIT_ASSERT(FileTransfer::State::Canceled == helper.state.get().type); + } //TODO: some more testcases private: - void addFileTransferDescription() { - boost::shared_ptr<JingleFileTransferDescription> desc = boost::make_shared<JingleFileTransferDescription>(); - desc->setFileInfo(JingleFileTransferFileInfo()); - jingleContentPayload->addDescription(desc); - } - - boost::shared_ptr<JingleS5BTransportPayload> addJingleS5BPayload() { - JingleS5BTransportPayload::ref payLoad = boost::make_shared<JingleS5BTransportPayload>(); - payLoad->setSessionID("mysession"); - jingleContentPayload->addTransport(payLoad); - return payLoad; - } - - boost::shared_ptr<JingleIBBTransportPayload> addJingleIBBPayload() { - JingleIBBTransportPayload::ref payLoad = boost::make_shared<JingleIBBTransportPayload>(); - payLoad->setSessionID("mysession"); - jingleContentPayload->addTransport(payLoad); - return payLoad; - } - - JingleContentID getContentID() const { - return JingleContentID(jingleContentPayload->getName(), jingleContentPayload->getCreator()); - } - - template <typename T> T getCall(int i) const { - size_t index = static_cast<size_t>(i); - CPPUNIT_ASSERT(index < fakeJingleSession->calledCommands.size()); - T* cmd = boost::get<T>(&fakeJingleSession->calledCommands[index]); - CPPUNIT_ASSERT(cmd); - return *cmd; - } + void addFileTransferDescription() { + std::shared_ptr<JingleFileTransferDescription> desc = std::make_shared<JingleFileTransferDescription>(); + desc->setFileInfo(JingleFileTransferFileInfo()); + jingleContentPayload->addDescription(desc); + } + + std::shared_ptr<JingleS5BTransportPayload> addJingleS5BPayload() { + JingleS5BTransportPayload::ref payLoad = std::make_shared<JingleS5BTransportPayload>(); + payLoad->setSessionID("mysession"); + jingleContentPayload->addTransport(payLoad); + return payLoad; + } + + std::shared_ptr<JingleIBBTransportPayload> addJingleIBBPayload() { + JingleIBBTransportPayload::ref payLoad = std::make_shared<JingleIBBTransportPayload>(); + payLoad->setSessionID("mysession"); + jingleContentPayload->addTransport(payLoad); + return payLoad; + } + + JingleContentID getContentID() const { + return JingleContentID(jingleContentPayload->getName(), jingleContentPayload->getCreator()); + } + + template <typename T> T getCall(int i) const { + size_t index = static_cast<size_t>(i); + CPPUNIT_ASSERT(index < fakeJingleSession->calledCommands.size()); + T* cmd = boost::get<T>(&fakeJingleSession->calledCommands[index]); + CPPUNIT_ASSERT(cmd); + return *cmd; + } private: - std::vector<unsigned char> data; - boost::shared_ptr<ByteArrayReadBytestream> stream; - FakeJingleSession* fakeJingleSession; - boost::shared_ptr<JingleContentPayload> jingleContentPayload; - FileTransferTransporterFactory* ftTransportFactory; - SOCKS5BytestreamServerManager* bytestreamServerManager; - DummyStanzaChannel* stanzaChannel; - IQRouter* iqRouter; - IDGenerator* idGen; - EventLoop *eventLoop; - SOCKS5BytestreamRegistry* s5bRegistry; - SOCKS5BytestreamProxiesManager* s5bProxy; - DummyTimerFactory* timerFactory; - DummyConnectionFactory* connectionFactory; - DummyConnectionServerFactory* serverConnectionFactory; - boost::shared_ptr<CryptoProvider> crypto; - NetworkEnvironment* networkEnvironment; - NATTraverser* natTraverser; - DomainNameResolver* resolver; + std::vector<unsigned char> data; + std::shared_ptr<ByteArrayReadBytestream> stream; + FakeJingleSession* fakeJingleSession; + std::shared_ptr<JingleContentPayload> jingleContentPayload; + FileTransferTransporterFactory* ftTransportFactory; + SOCKS5BytestreamServerManager* bytestreamServerManager; + DummyStanzaChannel* stanzaChannel; + IQRouter* iqRouter; + IDGenerator* idGen; + EventLoop *eventLoop; + SOCKS5BytestreamRegistry* s5bRegistry; + SOCKS5BytestreamProxiesManager* s5bProxy; + DummyTimerFactory* timerFactory; + DummyConnectionFactory* connectionFactory; + DummyConnectionServerFactory* serverConnectionFactory; + std::shared_ptr<CryptoProvider> crypto; + NetworkEnvironment* networkEnvironment; + NATTraverser* natTraverser; + DomainNameResolver* resolver; }; CPPUNIT_TEST_SUITE_REGISTRATION(OutgoingJingleFileTransferTest); diff --git a/Swiften/FileTransfer/UnitTest/SOCKS5BytestreamClientSessionTest.cpp b/Swiften/FileTransfer/UnitTest/SOCKS5BytestreamClientSessionTest.cpp index a0f6033..290dda5 100644 --- a/Swiften/FileTransfer/UnitTest/SOCKS5BytestreamClientSessionTest.cpp +++ b/Swiften/FileTransfer/UnitTest/SOCKS5BytestreamClientSessionTest.cpp @@ -5,16 +5,17 @@ */ /* - * Copyright (c) 2015 Isode Limited. + * Copyright (c) 2015-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ +#include <memory> + #include <boost/bind.hpp> #include <boost/random/mersenne_twister.hpp> #include <boost/random/uniform_int.hpp> #include <boost/random/variate_generator.hpp> -#include <boost/smart_ptr/make_shared.hpp> #include <QA/Checker/IO.h> @@ -43,275 +44,271 @@ using namespace Swift; static boost::mt19937 randomGen; class SOCKS5BytestreamClientSessionTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(SOCKS5BytestreamClientSessionTest); - CPPUNIT_TEST(testForSessionReady); - CPPUNIT_TEST(testErrorHandlingHello); - CPPUNIT_TEST(testErrorHandlingRequest); - CPPUNIT_TEST(testWriteBytestream); - CPPUNIT_TEST(testReadBytestream); - CPPUNIT_TEST_SUITE_END(); + CPPUNIT_TEST_SUITE(SOCKS5BytestreamClientSessionTest); + CPPUNIT_TEST(testForSessionReady); + CPPUNIT_TEST(testErrorHandlingHello); + CPPUNIT_TEST(testErrorHandlingRequest); + CPPUNIT_TEST(testWriteBytestream); + CPPUNIT_TEST(testReadBytestream); + CPPUNIT_TEST_SUITE_END(); public: - SOCKS5BytestreamClientSessionTest() : destinationAddressPort(HostAddressPort(HostAddress("127.0.0.1"), 8888)) {} - - void setUp() { - crypto = boost::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); - destination = "092a44d859d19c9eed676b551ee80025903351c2"; - randomGen.seed(static_cast<unsigned int>(time(NULL))); - eventLoop = new DummyEventLoop(); - timerFactory = new DummyTimerFactory(); - connection = boost::make_shared<MockeryConnection>(failingPorts, true, eventLoop); - //connection->onDataSent.connect(boost::bind(&SOCKS5BytestreamServerSessionTest::handleDataWritten, this, _1)); - //stream1 = boost::make_shared<ByteArrayReadBytestream>(createByteArray("abcdefg"))); -// connection->onDataRead.connect(boost::bind(&SOCKS5BytestreamClientSessionTest::handleDataRead, this, _1)); - } - - void tearDown() { - //connection.reset(); - delete timerFactory; - delete eventLoop; - } - - void testForSessionReady() { - TestHelper helper; - connection->onDataSent.connect(boost::bind(&TestHelper::handleConnectionDataWritten, &helper, _1)); - - SOCKS5BytestreamClientSession::ref clientSession = boost::make_shared<SOCKS5BytestreamClientSession>(connection, destinationAddressPort, destination, timerFactory); - clientSession->onSessionReady.connect(boost::bind(&TestHelper::handleSessionReady, &helper, _1)); - - clientSession->start(); - eventLoop->processEvents(); - CPPUNIT_ASSERT(createByteArray("\x05\x01\x00", 3) == helper.unprocessedInput); - - helper.unprocessedInput.clear(); - serverRespondHelloOK(); - eventLoop->processEvents(); - CPPUNIT_ASSERT_EQUAL(createByteArray("\x05\x01\x00\x03", 4), createByteArray(&helper.unprocessedInput[0], 4)); - CPPUNIT_ASSERT_EQUAL(createByteArray(static_cast<char>(destination.size())), createByteArray(static_cast<char>(helper.unprocessedInput[4]))); - CPPUNIT_ASSERT_EQUAL(createByteArray(destination), createByteArray(&helper.unprocessedInput[5], destination.size())); - CPPUNIT_ASSERT_EQUAL(createByteArray("\x00", 1), createByteArray(&helper.unprocessedInput[5 + destination.size()], 1)); - - helper.unprocessedInput.clear(); - serverRespondRequestOK(); - eventLoop->processEvents(); - CPPUNIT_ASSERT_EQUAL(true, helper.sessionReadyCalled); - CPPUNIT_ASSERT_EQUAL(false, helper.sessionReadyError); - } - - void testErrorHandlingHello() { - TestHelper helper; - connection->onDataSent.connect(boost::bind(&TestHelper::handleConnectionDataWritten, &helper, _1)); - - SOCKS5BytestreamClientSession::ref clientSession = boost::make_shared<SOCKS5BytestreamClientSession>(connection, destinationAddressPort, destination, timerFactory); - clientSession->onSessionReady.connect(boost::bind(&TestHelper::handleSessionReady, &helper, _1)); - - clientSession->start(); - eventLoop->processEvents(); - CPPUNIT_ASSERT_EQUAL(createByteArray("\x05\x01\x00", 3), helper.unprocessedInput); - - helper.unprocessedInput.clear(); - serverRespondHelloAuthFail(); - eventLoop->processEvents(); - - CPPUNIT_ASSERT_EQUAL(true, helper.sessionReadyCalled); - CPPUNIT_ASSERT_EQUAL(true, helper.sessionReadyError); - CPPUNIT_ASSERT_EQUAL(true, connection->disconnectCalled); - } - - void testErrorHandlingRequest() { - TestHelper helper; - connection->onDataSent.connect(boost::bind(&TestHelper::handleConnectionDataWritten, &helper, _1)); - - SOCKS5BytestreamClientSession::ref clientSession = boost::make_shared<SOCKS5BytestreamClientSession>(connection, destinationAddressPort, destination, timerFactory); - clientSession->onSessionReady.connect(boost::bind(&TestHelper::handleSessionReady, &helper, _1)); - - clientSession->start(); - eventLoop->processEvents(); - CPPUNIT_ASSERT_EQUAL(createByteArray("\x05\x01\x00", 3), helper.unprocessedInput); - - helper.unprocessedInput.clear(); - serverRespondHelloOK(); - eventLoop->processEvents(); - CPPUNIT_ASSERT_EQUAL(createByteArray("\x05\x01\x00\x03", 4), createByteArray(&helper.unprocessedInput[0], 4)); - CPPUNIT_ASSERT_EQUAL(createByteArray(static_cast<char>(destination.size())), createByteArray(static_cast<char>(helper.unprocessedInput[4]))); - CPPUNIT_ASSERT_EQUAL(createByteArray(destination), createByteArray(&helper.unprocessedInput[5], destination.size())); - CPPUNIT_ASSERT_EQUAL(createByteArray("\x00", 1), createByteArray(&helper.unprocessedInput[5 + destination.size()], 1)); - - helper.unprocessedInput.clear(); - serverRespondRequestFail(); - eventLoop->processEvents(); - CPPUNIT_ASSERT_EQUAL(true, helper.sessionReadyCalled); - CPPUNIT_ASSERT_EQUAL(true, helper.sessionReadyError); - CPPUNIT_ASSERT_EQUAL(true, connection->disconnectCalled); - } - - void testWriteBytestream() { - TestHelper helper; - connection->onDataSent.connect(boost::bind(&TestHelper::handleConnectionDataWritten, &helper, _1)); - - SOCKS5BytestreamClientSession::ref clientSession = boost::make_shared<SOCKS5BytestreamClientSession>(connection, destinationAddressPort, destination, timerFactory); - clientSession->onSessionReady.connect(boost::bind(&TestHelper::handleSessionReady, &helper, _1)); - - clientSession->start(); - eventLoop->processEvents(); - - helper.unprocessedInput.clear(); - serverRespondHelloOK(); - eventLoop->processEvents(); - - helper.unprocessedInput.clear(); - serverRespondRequestOK(); - eventLoop->processEvents(); - CPPUNIT_ASSERT_EQUAL(true, helper.sessionReadyCalled); - CPPUNIT_ASSERT_EQUAL(false, helper.sessionReadyError); - - boost::shared_ptr<ByteArrayWriteBytestream> output = boost::make_shared<ByteArrayWriteBytestream>(); - clientSession->startReceiving(output); - - ByteArray transferData = generateRandomByteArray(1024); - connection->onDataRead(createSafeByteArrayRef(vecptr(transferData), transferData.size())); - CPPUNIT_ASSERT_EQUAL(transferData, output->getData()); - } - - void testReadBytestream() { - TestHelper helper; - connection->onDataSent.connect(boost::bind(&TestHelper::handleConnectionDataWritten, &helper, _1)); - - SOCKS5BytestreamClientSession::ref clientSession = boost::make_shared<SOCKS5BytestreamClientSession>(connection, destinationAddressPort, destination, timerFactory); - clientSession->onSessionReady.connect(boost::bind(&TestHelper::handleSessionReady, &helper, _1)); - - clientSession->start(); - eventLoop->processEvents(); - - helper.unprocessedInput.clear(); - serverRespondHelloOK(); - eventLoop->processEvents(); - - helper.unprocessedInput.clear(); - serverRespondRequestOK(); - eventLoop->processEvents(); - CPPUNIT_ASSERT_EQUAL(true, helper.sessionReadyCalled); - CPPUNIT_ASSERT_EQUAL(false, helper.sessionReadyError); - - helper.unprocessedInput.clear(); - ByteArray transferData = generateRandomByteArray(1024); - boost::shared_ptr<ByteArrayReadBytestream> input = boost::make_shared<ByteArrayReadBytestream>(transferData); - clientSession->startSending(input); - eventLoop->processEvents(); + SOCKS5BytestreamClientSessionTest() : destinationAddressPort(HostAddressPort(HostAddress::fromString("127.0.0.1").get(), 8888)) {} + + void setUp() { + crypto = std::shared_ptr<CryptoProvider>(PlatformCryptoProvider::create()); + destination = "092a44d859d19c9eed676b551ee80025903351c2"; + randomGen.seed(static_cast<unsigned int>(time(nullptr))); + eventLoop = std::unique_ptr<DummyEventLoop>(new DummyEventLoop()); + timerFactory = std::unique_ptr<DummyTimerFactory>(new DummyTimerFactory()); + connection = std::make_shared<MockeryConnection>(failingPorts, true, eventLoop.get()); + //connection->onDataSent.connect(boost::bind(&SOCKS5BytestreamServerSessionTest::handleDataWritten, this, _1)); + //stream1 = std::make_shared<ByteArrayReadBytestream>(createByteArray("abcdefg"))); +// connection->onDataRead.connect(boost::bind(&SOCKS5BytestreamClientSessionTest::handleDataRead, this, _1)); + } + + void tearDown() { + //connection.reset(); + } + + void testForSessionReady() { + TestHelper helper; + connection->onDataSent.connect(boost::bind(&TestHelper::handleConnectionDataWritten, &helper, _1)); + + SOCKS5BytestreamClientSession::ref clientSession = std::make_shared<SOCKS5BytestreamClientSession>(connection, destinationAddressPort, destination, timerFactory.get()); + clientSession->onSessionReady.connect(boost::bind(&TestHelper::handleSessionReady, &helper, _1)); + + clientSession->start(); + eventLoop->processEvents(); + CPPUNIT_ASSERT(createByteArray("\x05\x01\x00", 3) == helper.unprocessedInput); + + helper.unprocessedInput.clear(); + serverRespondHelloOK(); + eventLoop->processEvents(); + CPPUNIT_ASSERT_EQUAL(createByteArray("\x05\x01\x00\x03", 4), createByteArray(&helper.unprocessedInput[0], 4)); + CPPUNIT_ASSERT_EQUAL(createByteArray(static_cast<char>(destination.size())), createByteArray(static_cast<char>(helper.unprocessedInput[4]))); + CPPUNIT_ASSERT_EQUAL(createByteArray(destination), createByteArray(&helper.unprocessedInput[5], destination.size())); + CPPUNIT_ASSERT_EQUAL(createByteArray("\x00", 1), createByteArray(&helper.unprocessedInput[5 + destination.size()], 1)); + + helper.unprocessedInput.clear(); + serverRespondRequestOK(); + eventLoop->processEvents(); + CPPUNIT_ASSERT_EQUAL(true, helper.sessionReadyCalled); + CPPUNIT_ASSERT_EQUAL(false, helper.sessionReadyError); + } + + void testErrorHandlingHello() { + TestHelper helper; + connection->onDataSent.connect(boost::bind(&TestHelper::handleConnectionDataWritten, &helper, _1)); + + SOCKS5BytestreamClientSession::ref clientSession = std::make_shared<SOCKS5BytestreamClientSession>(connection, destinationAddressPort, destination, timerFactory.get()); + clientSession->onSessionReady.connect(boost::bind(&TestHelper::handleSessionReady, &helper, _1)); + + clientSession->start(); + eventLoop->processEvents(); + CPPUNIT_ASSERT_EQUAL(createByteArray("\x05\x01\x00", 3), helper.unprocessedInput); + + helper.unprocessedInput.clear(); + serverRespondHelloAuthFail(); + eventLoop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(true, helper.sessionReadyCalled); + CPPUNIT_ASSERT_EQUAL(true, helper.sessionReadyError); + CPPUNIT_ASSERT_EQUAL(true, connection->disconnectCalled); + } + + void testErrorHandlingRequest() { + TestHelper helper; + connection->onDataSent.connect(boost::bind(&TestHelper::handleConnectionDataWritten, &helper, _1)); + + SOCKS5BytestreamClientSession::ref clientSession = std::make_shared<SOCKS5BytestreamClientSession>(connection, destinationAddressPort, destination, timerFactory.get()); + clientSession->onSessionReady.connect(boost::bind(&TestHelper::handleSessionReady, &helper, _1)); + + clientSession->start(); + eventLoop->processEvents(); + CPPUNIT_ASSERT_EQUAL(createByteArray("\x05\x01\x00", 3), helper.unprocessedInput); + + helper.unprocessedInput.clear(); + serverRespondHelloOK(); + eventLoop->processEvents(); + CPPUNIT_ASSERT_EQUAL(createByteArray("\x05\x01\x00\x03", 4), createByteArray(&helper.unprocessedInput[0], 4)); + CPPUNIT_ASSERT_EQUAL(createByteArray(static_cast<char>(destination.size())), createByteArray(static_cast<char>(helper.unprocessedInput[4]))); + CPPUNIT_ASSERT_EQUAL(createByteArray(destination), createByteArray(&helper.unprocessedInput[5], destination.size())); + CPPUNIT_ASSERT_EQUAL(createByteArray("\x00", 1), createByteArray(&helper.unprocessedInput[5 + destination.size()], 1)); + + helper.unprocessedInput.clear(); + serverRespondRequestFail(); + eventLoop->processEvents(); + CPPUNIT_ASSERT_EQUAL(true, helper.sessionReadyCalled); + CPPUNIT_ASSERT_EQUAL(true, helper.sessionReadyError); + CPPUNIT_ASSERT_EQUAL(true, connection->disconnectCalled); + } + + void testWriteBytestream() { + TestHelper helper; + connection->onDataSent.connect(boost::bind(&TestHelper::handleConnectionDataWritten, &helper, _1)); + + SOCKS5BytestreamClientSession::ref clientSession = std::make_shared<SOCKS5BytestreamClientSession>(connection, destinationAddressPort, destination, timerFactory.get()); + clientSession->onSessionReady.connect(boost::bind(&TestHelper::handleSessionReady, &helper, _1)); + + clientSession->start(); + eventLoop->processEvents(); + + helper.unprocessedInput.clear(); + serverRespondHelloOK(); + eventLoop->processEvents(); + + helper.unprocessedInput.clear(); + serverRespondRequestOK(); + eventLoop->processEvents(); + CPPUNIT_ASSERT_EQUAL(true, helper.sessionReadyCalled); + CPPUNIT_ASSERT_EQUAL(false, helper.sessionReadyError); + + std::shared_ptr<ByteArrayWriteBytestream> output = std::make_shared<ByteArrayWriteBytestream>(); + clientSession->startReceiving(output); + + ByteArray transferData = generateRandomByteArray(1024); + connection->onDataRead(createSafeByteArrayRef(vecptr(transferData), transferData.size())); + CPPUNIT_ASSERT_EQUAL(transferData, output->getData()); + } + + void testReadBytestream() { + TestHelper helper; + connection->onDataSent.connect(boost::bind(&TestHelper::handleConnectionDataWritten, &helper, _1)); + + SOCKS5BytestreamClientSession::ref clientSession = std::make_shared<SOCKS5BytestreamClientSession>(connection, destinationAddressPort, destination, timerFactory.get()); + clientSession->onSessionReady.connect(boost::bind(&TestHelper::handleSessionReady, &helper, _1)); + + clientSession->start(); + eventLoop->processEvents(); + + helper.unprocessedInput.clear(); + serverRespondHelloOK(); + eventLoop->processEvents(); + + helper.unprocessedInput.clear(); + serverRespondRequestOK(); + eventLoop->processEvents(); + CPPUNIT_ASSERT_EQUAL(true, helper.sessionReadyCalled); + CPPUNIT_ASSERT_EQUAL(false, helper.sessionReadyError); + + helper.unprocessedInput.clear(); + ByteArray transferData = generateRandomByteArray(1024); + std::shared_ptr<ByteArrayReadBytestream> input = std::make_shared<ByteArrayReadBytestream>(transferData); + clientSession->startSending(input); + eventLoop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(createByteArray(vecptr(transferData), transferData.size()), helper.unprocessedInput); + } - CPPUNIT_ASSERT_EQUAL(createByteArray(vecptr(transferData), transferData.size()), helper.unprocessedInput); - } +private: + static ByteArray generateRandomByteArray(size_t len) { + boost::uniform_int<> dist(0, 255); + boost::variate_generator<boost::mt19937&, boost::uniform_int<> > randomByte(randomGen, dist); + ByteArray result(len); + for (size_t i=0; i < len; ++i ) { + result[i] = static_cast<unsigned char>(randomByte()); + } + return result; + } + + // Server responses + void serverRespondHelloOK() { + connection->onDataRead(createSafeByteArrayRef("\x05\00", 2)); + } + + void serverRespondHelloAuthFail() { + connection->onDataRead(createSafeByteArrayRef("\x05\xFF", 2)); + } + + void serverRespondRequestOK() { + std::shared_ptr<SafeByteArray> dataToSend = createSafeByteArrayRef("\x05\x00\x00\x03", 4); + append(*dataToSend, createSafeByteArray(static_cast<char>(destination.size()))); + append(*dataToSend, createSafeByteArray(destination)); + append(*dataToSend, createSafeByteArray("\x00", 1)); + connection->onDataRead(dataToSend); + } + + void serverRespondRequestFail() { + std::shared_ptr<SafeByteArray> correctData = createSafeByteArrayRef("\x05\x00\x00\x03", 4); + append(*correctData, createSafeByteArray(static_cast<char>(destination.size()))); + append(*correctData, createSafeByteArray(destination)); + append(*correctData, createSafeByteArray("\x00", 1)); + + std::shared_ptr<SafeByteArray> dataToSend; + //ByteArray failingData = Hexify::unhexify("8417947d1d305c72c11520ea7d2c6e787396705e72c312c6ccc3f66613d7cae1b91b7ab48e8b59a17d559c15fb51"); + //append(dataToSend, failingData); + //SWIFT_LOG(debug) << "hexed: " << Hexify::hexify(failingData) << std::endl; + do { + ByteArray rndArray = generateRandomByteArray(correctData->size()); + dataToSend = createSafeByteArrayRef(vecptr(rndArray), rndArray.size()); + } while (*dataToSend == *correctData); + connection->onDataRead(dataToSend); + } +private: + struct TestHelper { + TestHelper() : sessionReadyCalled(false), sessionReadyError(false) {} + ByteArray unprocessedInput; + bool sessionReadyCalled; + bool sessionReadyError; + void handleConnectionDataWritten(const SafeByteArray& data) { + append(unprocessedInput, data); + //SWIFT_LOG(debug) << "unprocessedInput (" << unprocessedInput.size() << "): " << Hexify::hexify(unprocessedInput) << std::endl; + } + + void handleSessionReady(bool error) { + sessionReadyCalled = true; + sessionReadyError = error; + } + }; -private: - static ByteArray generateRandomByteArray(size_t len) { - boost::uniform_int<> dist(0, 255); - boost::variate_generator<boost::mt19937&, boost::uniform_int<> > randomByte(randomGen, dist); - ByteArray result(len); - for (size_t i=0; i < len; ++i ) { - result[i] = static_cast<unsigned char>(randomByte()); - } - return result; - } - - // Server responses - void serverRespondHelloOK() { - connection->onDataRead(createSafeByteArrayRef("\x05\00", 2)); - } - - void serverRespondHelloAuthFail() { - connection->onDataRead(createSafeByteArrayRef("\x05\xFF", 2)); - } - - void serverRespondRequestOK() { - boost::shared_ptr<SafeByteArray> dataToSend = createSafeByteArrayRef("\x05\x00\x00\x03", 4); - append(*dataToSend, createSafeByteArray(static_cast<char>(destination.size()))); - append(*dataToSend, createSafeByteArray(destination)); - append(*dataToSend, createSafeByteArray("\x00", 1)); - connection->onDataRead(dataToSend); - } - - void serverRespondRequestFail() { - boost::shared_ptr<SafeByteArray> correctData = createSafeByteArrayRef("\x05\x00\x00\x03", 4); - append(*correctData, createSafeByteArray(static_cast<char>(destination.size()))); - append(*correctData, createSafeByteArray(destination)); - append(*correctData, createSafeByteArray("\x00", 1)); - - boost::shared_ptr<SafeByteArray> dataToSend; - //ByteArray failingData = Hexify::unhexify("8417947d1d305c72c11520ea7d2c6e787396705e72c312c6ccc3f66613d7cae1b91b7ab48e8b59a17d559c15fb51"); - //append(dataToSend, failingData); - //SWIFT_LOG(debug) << "hexed: " << Hexify::hexify(failingData) << std::endl; - do { - ByteArray rndArray = generateRandomByteArray(correctData->size()); - dataToSend = createSafeByteArrayRef(vecptr(rndArray), rndArray.size()); - } while (*dataToSend == *correctData); - connection->onDataRead(dataToSend); - } private: - struct TestHelper { - TestHelper() : sessionReadyCalled(false), sessionReadyError(false) {} - ByteArray unprocessedInput; - bool sessionReadyCalled; - bool sessionReadyError; + struct MockeryConnection : public Connection, public EventOwner, public std::enable_shared_from_this<MockeryConnection> { + public: + MockeryConnection(const std::vector<HostAddressPort>& failingPorts, bool isResponsive, EventLoop* eventLoop) : eventLoop(eventLoop), failingPorts(failingPorts), isResponsive(isResponsive), disconnectCalled(false) {} - void handleConnectionDataWritten(const SafeByteArray& data) { - append(unprocessedInput, data); - //SWIFT_LOG(debug) << "unprocessedInput (" << unprocessedInput.size() << "): " << Hexify::hexify(unprocessedInput) << std::endl; - } + void listen() { assert(false); } + void connect(const HostAddressPort& address) { + hostAddressPort = address; + if (isResponsive) { + bool fail = std::find(failingPorts.begin(), failingPorts.end(), address) != failingPorts.end(); + eventLoop->postEvent(boost::bind(boost::ref(onConnectFinished), fail)); + } + } - void handleSessionReady(bool error) { - sessionReadyCalled = true; - sessionReadyError = error; - } - }; + HostAddressPort getLocalAddress() const { return HostAddressPort(); } + HostAddressPort getRemoteAddress() const { return HostAddressPort(); } -private: - struct MockeryConnection : public Connection, public EventOwner, public boost::enable_shared_from_this<MockeryConnection> { - public: - MockeryConnection(const std::vector<HostAddressPort>& failingPorts, bool isResponsive, EventLoop* eventLoop) : eventLoop(eventLoop), failingPorts(failingPorts), isResponsive(isResponsive), disconnectCalled(false) {} - - void listen() { assert(false); } - void connect(const HostAddressPort& address) { - hostAddressPort = address; - if (isResponsive) { - bool fail = std::find(failingPorts.begin(), failingPorts.end(), address) != failingPorts.end(); - eventLoop->postEvent(boost::bind(boost::ref(onConnectFinished), fail)); - } - } - - HostAddressPort getLocalAddress() const { return HostAddressPort(); } - - HostAddressPort getRemoteAddress() const { return HostAddressPort(); } - - void disconnect() { - disconnectCalled = true; - } - - void write(const SafeByteArray& data) { - eventLoop->postEvent(boost::ref(onDataWritten), shared_from_this()); - onDataSent(data); - } - - boost::signal<void (const SafeByteArray&)> onDataSent; - - EventLoop* eventLoop; - boost::optional<HostAddressPort> hostAddressPort; - std::vector<HostAddressPort> failingPorts; - bool isResponsive; - bool disconnectCalled; - }; + void disconnect() { + disconnectCalled = true; + } + + void write(const SafeByteArray& data) { + eventLoop->postEvent(boost::ref(onDataWritten), shared_from_this()); + onDataSent(data); + } + + boost::signals2::signal<void (const SafeByteArray&)> onDataSent; + + EventLoop* eventLoop; + boost::optional<HostAddressPort> hostAddressPort; + std::vector<HostAddressPort> failingPorts; + bool isResponsive; + bool disconnectCalled; + }; private: - HostAddressPort destinationAddressPort; - std::string destination; - DummyEventLoop* eventLoop; - DummyTimerFactory* timerFactory; - boost::shared_ptr<MockeryConnection> connection; - const std::vector<HostAddressPort> failingPorts; - boost::shared_ptr<CryptoProvider> crypto; + HostAddressPort destinationAddressPort; + std::string destination; + std::unique_ptr<DummyEventLoop> eventLoop; + std::unique_ptr<DummyTimerFactory> timerFactory; + std::shared_ptr<MockeryConnection> connection; + const std::vector<HostAddressPort> failingPorts; + std::shared_ptr<CryptoProvider> crypto; }; CPPUNIT_TEST_SUITE_REGISTRATION(SOCKS5BytestreamClientSessionTest); diff --git a/Swiften/FileTransfer/UnitTest/SOCKS5BytestreamServerSessionTest.cpp b/Swiften/FileTransfer/UnitTest/SOCKS5BytestreamServerSessionTest.cpp index eb853a5..d419b8a 100644 --- a/Swiften/FileTransfer/UnitTest/SOCKS5BytestreamServerSessionTest.cpp +++ b/Swiften/FileTransfer/UnitTest/SOCKS5BytestreamServerSessionTest.cpp @@ -1,213 +1,213 @@ /* - * Copyright (c) 2010 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ -#include <Swiften/Base/ByteArray.h> +#include <boost/bind.hpp> #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> -#include <boost/bind.hpp> +#include <Swiften/Base/ByteArray.h> #include <Swiften/Base/Concat.h> -#include <Swiften/FileTransfer/SOCKS5BytestreamServerSession.h> +#include <Swiften/Base/StartStopper.h> +#include <Swiften/EventLoop/DummyEventLoop.h> #include <Swiften/FileTransfer/ByteArrayReadBytestream.h> #include <Swiften/FileTransfer/SOCKS5BytestreamRegistry.h> +#include <Swiften/FileTransfer/SOCKS5BytestreamServerSession.h> #include <Swiften/Network/DummyConnection.h> -#include <Swiften/EventLoop/DummyEventLoop.h> -#include <Swiften/Base/StartStopper.h> using namespace Swift; class SOCKS5BytestreamServerSessionTest : public CppUnit::TestFixture { - CPPUNIT_TEST_SUITE(SOCKS5BytestreamServerSessionTest); - CPPUNIT_TEST(testAuthenticate); - CPPUNIT_TEST(testAuthenticate_Chunked); - CPPUNIT_TEST(testRequest); - CPPUNIT_TEST(testRequest_UnknownBytestream); - CPPUNIT_TEST(testReceiveData); - CPPUNIT_TEST(testReceiveData_Chunked); - CPPUNIT_TEST(testDataStreamPauseStopsSendingData); - CPPUNIT_TEST(testDataStreamResumeAfterPauseSendsData); - CPPUNIT_TEST_SUITE_END(); - - public: - void setUp() { - receivedDataChunks = 0; - eventLoop = new DummyEventLoop(); - bytestreams = new SOCKS5BytestreamRegistry(); - connection = boost::make_shared<DummyConnection>(eventLoop); - connection->onDataSent.connect(boost::bind(&SOCKS5BytestreamServerSessionTest::handleDataWritten, this, _1)); - stream1 = boost::make_shared<ByteArrayReadBytestream>(createByteArray("abcdefg")); - finished = false; - } - - void tearDown() { - connection.reset(); - delete bytestreams; - delete eventLoop; - } - - void testAuthenticate() { - boost::shared_ptr<SOCKS5BytestreamServerSession> testling(createSession()); - StartStopper<SOCKS5BytestreamServerSession> stopper(testling.get()); - - receive(createSafeByteArray("\x05\x02\x01\x02")); - - CPPUNIT_ASSERT(createByteArray("\x05\x00", 2) == receivedData); - } - - void testAuthenticate_Chunked() { - boost::shared_ptr<SOCKS5BytestreamServerSession> testling(createSession()); - StartStopper<SOCKS5BytestreamServerSession> stopper(testling.get()); - - receive(createSafeByteArray("\x05\x02\x01")); - - CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(receivedData.size())); - receive(createSafeByteArray("\x01")); - CPPUNIT_ASSERT(createByteArray("\x05\x00", 2) == receivedData); - } - - void testRequest() { - boost::shared_ptr<SOCKS5BytestreamServerSession> testling(createSession()); - StartStopper<SOCKS5BytestreamServerSession> stopper(testling.get()); - bytestreams->setHasBytestream("abcdef", true); - authenticate(); - - ByteArray hostname(createByteArray("abcdef")); - receive(concat(createSafeByteArray("\x05\x01\x00\x03", 4), createSafeByteArray(static_cast<char>(hostname.size())), createSafeByteArray(hostname), createSafeByteArray("\x00\x00", 2))); - CPPUNIT_ASSERT(createByteArray("\x05\x00\x00\x03\x06\x61\x62\x63\x64\x65\x66\x00\x00", 13) == createByteArray(&receivedData[0], 13)); - } - - void testRequest_UnknownBytestream() { - boost::shared_ptr<SOCKS5BytestreamServerSession> testling(createSession()); - StartStopper<SOCKS5BytestreamServerSession> stopper(testling.get()); - authenticate(); - - ByteArray hostname(createByteArray("abcdef")); - receive(concat(createSafeByteArray("\x05\x01\x00\x03", 4), createSafeByteArray(static_cast<char>(hostname.size())), createSafeByteArray(hostname), createSafeByteArray("\x00\x00", 2))); - CPPUNIT_ASSERT(createByteArray("\x05\x04\x00\x03\x06\x61\x62\x63\x64\x65\x66\x00\x00", 13) == receivedData); - } - - void testReceiveData() { - boost::shared_ptr<SOCKS5BytestreamServerSession> testling(createSession()); - StartStopper<SOCKS5BytestreamServerSession> stopper(testling.get()); - bytestreams->setHasBytestream("abcdef", true); - authenticate(); - request("abcdef"); - eventLoop->processEvents(); - testling->startSending(stream1); - skipHeader("abcdef"); - eventLoop->processEvents(); - - CPPUNIT_ASSERT(createByteArray("abcdefg") == receivedData); - CPPUNIT_ASSERT_EQUAL(2, receivedDataChunks); - } - - void testReceiveData_Chunked() { - boost::shared_ptr<SOCKS5BytestreamServerSession> testling(createSession()); - testling->setChunkSize(3); - StartStopper<SOCKS5BytestreamServerSession> stopper(testling.get()); - bytestreams->setHasBytestream("abcdef", true); - authenticate(); - request("abcdef"); - eventLoop->processEvents(); - testling->startSending(stream1); - eventLoop->processEvents(); - skipHeader("abcdef"); - CPPUNIT_ASSERT(createByteArray("abcdefg") == receivedData); - CPPUNIT_ASSERT_EQUAL(4, receivedDataChunks); - } - - void testDataStreamPauseStopsSendingData() { - boost::shared_ptr<SOCKS5BytestreamServerSession> testling(createSession()); - testling->setChunkSize(3); - stream1->setDataComplete(false); - StartStopper<SOCKS5BytestreamServerSession> stopper(testling.get()); - bytestreams->setHasBytestream("abcdef", true); - authenticate(); - request("abcdef"); - eventLoop->processEvents(); - testling->startSending(stream1); - eventLoop->processEvents(); - skipHeader("abcdef"); - CPPUNIT_ASSERT(createByteArray("abcdefg") == receivedData); - CPPUNIT_ASSERT_EQUAL(4, receivedDataChunks); - - CPPUNIT_ASSERT(!finished); - CPPUNIT_ASSERT(!error); - } - - void testDataStreamResumeAfterPauseSendsData() { - boost::shared_ptr<SOCKS5BytestreamServerSession> testling(createSession()); - testling->setChunkSize(3); - stream1->setDataComplete(false); - StartStopper<SOCKS5BytestreamServerSession> stopper(testling.get()); - bytestreams->setHasBytestream("abcdef", true); - authenticate(); - request("abcdef"); - eventLoop->processEvents(); - testling->startSending(stream1); - eventLoop->processEvents(); - skipHeader("abcdef"); - - stream1->addData(createByteArray("xyz")); - eventLoop->processEvents(); - - CPPUNIT_ASSERT(createByteArray("abcdefgxyz") == receivedData); - CPPUNIT_ASSERT(!finished); - CPPUNIT_ASSERT(!error); - } - - private: - void receive(const SafeByteArray& data) { - connection->receive(data); - eventLoop->processEvents(); - } - - void authenticate() { - receive(createSafeByteArray("\x05\x02\x01\x02")); - receivedData.clear(); - receivedDataChunks = 0; - } - - void request(const std::string& hostname) { - receive(concat(createSafeByteArray("\x05\x01\x00\x03", 4), createSafeByteArray(static_cast<char>(hostname.size())), createSafeByteArray(hostname), createSafeByteArray("\x00\x00", 2))); - } - - void skipHeader(const std::string& hostname) { - size_t headerSize = 7 + hostname.size(); - receivedData = createByteArray(&receivedData[headerSize], receivedData.size() - headerSize); - } - - - void handleDataWritten(const SafeByteArray& data) { - receivedData.insert(receivedData.end(), data.begin(), data.end()); - receivedDataChunks++; - } - - private: - SOCKS5BytestreamServerSession* createSession() { - SOCKS5BytestreamServerSession* session = new SOCKS5BytestreamServerSession(connection, bytestreams); - session->onFinished.connect(boost::bind(&SOCKS5BytestreamServerSessionTest::handleFinished, this, _1)); - return session; - } - - void handleFinished(boost::optional<FileTransferError> error) { - finished = true; - this->error = error; - } - - private: - DummyEventLoop* eventLoop; - SOCKS5BytestreamRegistry* bytestreams; - boost::shared_ptr<DummyConnection> connection; - std::vector<unsigned char> receivedData; - int receivedDataChunks; - boost::shared_ptr<ByteArrayReadBytestream> stream1; - bool finished; - boost::optional<FileTransferError> error; + CPPUNIT_TEST_SUITE(SOCKS5BytestreamServerSessionTest); + CPPUNIT_TEST(testAuthenticate); + CPPUNIT_TEST(testAuthenticate_Chunked); + CPPUNIT_TEST(testRequest); + CPPUNIT_TEST(testRequest_UnknownBytestream); + CPPUNIT_TEST(testReceiveData); + CPPUNIT_TEST(testReceiveData_Chunked); + CPPUNIT_TEST(testDataStreamPauseStopsSendingData); + CPPUNIT_TEST(testDataStreamResumeAfterPauseSendsData); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + receivedDataChunks = 0; + eventLoop = new DummyEventLoop(); + bytestreams = new SOCKS5BytestreamRegistry(); + connection = std::make_shared<DummyConnection>(eventLoop); + connection->onDataSent.connect(boost::bind(&SOCKS5BytestreamServerSessionTest::handleDataWritten, this, _1)); + stream1 = std::make_shared<ByteArrayReadBytestream>(createByteArray("abcdefg")); + finished = false; + } + + void tearDown() { + connection.reset(); + delete bytestreams; + delete eventLoop; + } + + void testAuthenticate() { + std::shared_ptr<SOCKS5BytestreamServerSession> testling(createSession()); + StartStopper<SOCKS5BytestreamServerSession> stopper(testling.get()); + + receive(createSafeByteArray("\x05\x02\x01\x02")); + + CPPUNIT_ASSERT(createByteArray("\x05\x00", 2) == receivedData); + } + + void testAuthenticate_Chunked() { + std::shared_ptr<SOCKS5BytestreamServerSession> testling(createSession()); + StartStopper<SOCKS5BytestreamServerSession> stopper(testling.get()); + + receive(createSafeByteArray("\x05\x02\x01")); + + CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(receivedData.size())); + receive(createSafeByteArray("\x01")); + CPPUNIT_ASSERT(createByteArray("\x05\x00", 2) == receivedData); + } + + void testRequest() { + std::shared_ptr<SOCKS5BytestreamServerSession> testling(createSession()); + StartStopper<SOCKS5BytestreamServerSession> stopper(testling.get()); + bytestreams->setHasBytestream("abcdef", true); + authenticate(); + + ByteArray hostname(createByteArray("abcdef")); + receive(concat(createSafeByteArray("\x05\x01\x00\x03", 4), createSafeByteArray(static_cast<char>(hostname.size())), createSafeByteArray(hostname), createSafeByteArray("\x00\x00", 2))); + CPPUNIT_ASSERT(createByteArray("\x05\x00\x00\x03\x06\x61\x62\x63\x64\x65\x66\x00\x00", 13) == createByteArray(&receivedData[0], 13)); + } + + void testRequest_UnknownBytestream() { + std::shared_ptr<SOCKS5BytestreamServerSession> testling(createSession()); + StartStopper<SOCKS5BytestreamServerSession> stopper(testling.get()); + authenticate(); + + ByteArray hostname(createByteArray("abcdef")); + receive(concat(createSafeByteArray("\x05\x01\x00\x03", 4), createSafeByteArray(static_cast<char>(hostname.size())), createSafeByteArray(hostname), createSafeByteArray("\x00\x00", 2))); + CPPUNIT_ASSERT(createByteArray("\x05\x04\x00\x03\x06\x61\x62\x63\x64\x65\x66\x00\x00", 13) == receivedData); + } + + void testReceiveData() { + std::shared_ptr<SOCKS5BytestreamServerSession> testling(createSession()); + StartStopper<SOCKS5BytestreamServerSession> stopper(testling.get()); + bytestreams->setHasBytestream("abcdef", true); + authenticate(); + request("abcdef"); + eventLoop->processEvents(); + testling->startSending(stream1); + skipHeader("abcdef"); + eventLoop->processEvents(); + + CPPUNIT_ASSERT(createByteArray("abcdefg") == receivedData); + CPPUNIT_ASSERT_EQUAL(2, receivedDataChunks); + } + + void testReceiveData_Chunked() { + std::shared_ptr<SOCKS5BytestreamServerSession> testling(createSession()); + testling->setChunkSize(3); + StartStopper<SOCKS5BytestreamServerSession> stopper(testling.get()); + bytestreams->setHasBytestream("abcdef", true); + authenticate(); + request("abcdef"); + eventLoop->processEvents(); + testling->startSending(stream1); + eventLoop->processEvents(); + skipHeader("abcdef"); + CPPUNIT_ASSERT(createByteArray("abcdefg") == receivedData); + CPPUNIT_ASSERT_EQUAL(4, receivedDataChunks); + } + + void testDataStreamPauseStopsSendingData() { + std::shared_ptr<SOCKS5BytestreamServerSession> testling(createSession()); + testling->setChunkSize(3); + stream1->setDataComplete(false); + StartStopper<SOCKS5BytestreamServerSession> stopper(testling.get()); + bytestreams->setHasBytestream("abcdef", true); + authenticate(); + request("abcdef"); + eventLoop->processEvents(); + testling->startSending(stream1); + eventLoop->processEvents(); + skipHeader("abcdef"); + CPPUNIT_ASSERT(createByteArray("abcdefg") == receivedData); + CPPUNIT_ASSERT_EQUAL(4, receivedDataChunks); + + CPPUNIT_ASSERT(!finished); + CPPUNIT_ASSERT(!error); + } + + void testDataStreamResumeAfterPauseSendsData() { + std::shared_ptr<SOCKS5BytestreamServerSession> testling(createSession()); + testling->setChunkSize(3); + stream1->setDataComplete(false); + StartStopper<SOCKS5BytestreamServerSession> stopper(testling.get()); + bytestreams->setHasBytestream("abcdef", true); + authenticate(); + request("abcdef"); + eventLoop->processEvents(); + testling->startSending(stream1); + eventLoop->processEvents(); + skipHeader("abcdef"); + + stream1->addData(createByteArray("xyz")); + eventLoop->processEvents(); + + CPPUNIT_ASSERT(createByteArray("abcdefgxyz") == receivedData); + CPPUNIT_ASSERT(!finished); + CPPUNIT_ASSERT(!error); + } + + private: + void receive(const SafeByteArray& data) { + connection->receive(data); + eventLoop->processEvents(); + } + + void authenticate() { + receive(createSafeByteArray("\x05\x02\x01\x02")); + receivedData.clear(); + receivedDataChunks = 0; + } + + void request(const std::string& hostname) { + receive(concat(createSafeByteArray("\x05\x01\x00\x03", 4), createSafeByteArray(static_cast<char>(hostname.size())), createSafeByteArray(hostname), createSafeByteArray("\x00\x00", 2))); + } + + void skipHeader(const std::string& hostname) { + size_t headerSize = 7 + hostname.size(); + receivedData = createByteArray(&receivedData[headerSize], receivedData.size() - headerSize); + } + + + void handleDataWritten(const SafeByteArray& data) { + receivedData.insert(receivedData.end(), data.begin(), data.end()); + receivedDataChunks++; + } + + private: + SOCKS5BytestreamServerSession* createSession() { + SOCKS5BytestreamServerSession* session = new SOCKS5BytestreamServerSession(connection, bytestreams); + session->onFinished.connect(boost::bind(&SOCKS5BytestreamServerSessionTest::handleFinished, this, _1)); + return session; + } + + void handleFinished(boost::optional<FileTransferError> error) { + finished = true; + this->error = error; + } + + private: + DummyEventLoop* eventLoop; + SOCKS5BytestreamRegistry* bytestreams; + std::shared_ptr<DummyConnection> connection; + std::vector<unsigned char> receivedData; + int receivedDataChunks; + std::shared_ptr<ByteArrayReadBytestream> stream1; + bool finished; + boost::optional<FileTransferError> error; }; CPPUNIT_TEST_SUITE_REGISTRATION(SOCKS5BytestreamServerSessionTest); diff --git a/Swiften/FileTransfer/WriteBytestream.h b/Swiften/FileTransfer/WriteBytestream.h index 76237c4..5d9c3f8 100644 --- a/Swiften/FileTransfer/WriteBytestream.h +++ b/Swiften/FileTransfer/WriteBytestream.h @@ -6,27 +6,27 @@ #pragma once +#include <memory> #include <vector> -#include <boost/shared_ptr.hpp> +#include <boost/signals2.hpp> #include <Swiften/Base/API.h> -#include <Swiften/Base/boost_bsignals.h> namespace Swift { - class SWIFTEN_API WriteBytestream { - public: - typedef boost::shared_ptr<WriteBytestream> ref; + class SWIFTEN_API WriteBytestream { + public: + typedef std::shared_ptr<WriteBytestream> ref; - virtual ~WriteBytestream(); + virtual ~WriteBytestream(); - /** - * Write data from vector argument to bytestream. - * - * On success true is returned and \ref onWrite is called. On failure false is returned. - */ - virtual bool write(const std::vector<unsigned char>&) = 0; + /** + * Write data from vector argument to bytestream. + * + * On success true is returned and \ref onWrite is called. On failure false is returned. + */ + virtual bool write(const std::vector<unsigned char>&) = 0; - boost::signal<void (const std::vector<unsigned char>&)> onWrite; - }; + boost::signals2::signal<void (const std::vector<unsigned char>&)> onWrite; + }; } |