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