diff options
7 files changed, 98 insertions, 38 deletions
diff --git a/Swiften/FileTransfer/IncomingFileTransferManager.cpp b/Swiften/FileTransfer/IncomingFileTransferManager.cpp index c1cc757..f5b95ec 100644 --- a/Swiften/FileTransfer/IncomingFileTransferManager.cpp +++ b/Swiften/FileTransfer/IncomingFileTransferManager.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. */ @@ -40,7 +40,7 @@ bool IncomingFileTransferManager::handleIncomingJingleSession( const std::vector<JingleContentPayload::ref>& contents, const JID& recipient) { if (JingleContentPayload::ref content = Jingle::getContentWithDescription<JingleFileTransferDescription>(contents)) { - if (content->getTransport<JingleS5BTransportPayload>()) { + if (content->getTransport<JingleS5BTransportPayload>() || content->getTransport<JingleIBBTransportPayload>()) { JingleFileTransferDescription::ref description = content->getDescription<JingleFileTransferDescription>(); if (description) { IncomingJingleFileTransfer::ref transfer = boost::make_shared<IncomingJingleFileTransfer>( diff --git a/Swiften/FileTransfer/IncomingJingleFileTransfer.cpp b/Swiften/FileTransfer/IncomingJingleFileTransfer.cpp index 8cb1cab..db17620 100644 --- a/Swiften/FileTransfer/IncomingJingleFileTransfer.cpp +++ b/Swiften/FileTransfer/IncomingJingleFileTransfer.cpp @@ -17,6 +17,7 @@ #include <Swiften/Elements/JingleFileTransferHash.h> #include <Swiften/Elements/JingleIBBTransportPayload.h> #include <Swiften/Elements/JingleS5BTransportPayload.h> +#include <Swiften/FileTransfer/FileTransferOptions.h> #include <Swiften/FileTransfer/FileTransferTransporter.h> #include <Swiften/FileTransfer/FileTransferTransporterFactory.h> #include <Swiften/FileTransfer/IncrementalBytestreamHashCalculator.h> @@ -82,7 +83,9 @@ void IncomingJingleFileTransfer::accept( writeStreamDataReceivedConnection = stream->onWrite.connect( boost::bind(&IncomingJingleFileTransfer::handleWriteStreamDataReceived, this, _1)); - if (JingleS5BTransportPayload::ref s5bTransport = initialContent->getTransport<JingleS5BTransportPayload>()) { + 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)); @@ -90,7 +93,7 @@ void IncomingJingleFileTransfer::accept( setState(GeneratingInitialLocalCandidates); transporter->startGeneratingLocalCandidates(); } - else if (JingleIBBTransportPayload::ref ibbTransport = initialContent->getTransport<JingleIBBTransportPayload>()) { + else if (ibbTransport && options.isInBandAllowed()) { SWIFT_LOG(debug) << "Got IBB transport as initial payload." << std::endl; setTransporter(transporterFactory->createResponderTransporter( getInitiator(), getResponder(), ibbTransport->getSessionID(), options)); @@ -103,8 +106,9 @@ void IncomingJingleFileTransfer::accept( session->sendAccept(getContentID(), initialContent->getDescriptions()[0], ibbTransport); } else { - // Can't happen, because the transfer would have been rejected automatically - assert(false); + // 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)); } } @@ -223,7 +227,7 @@ void IncomingJingleFileTransfer::handleWriteStreamDataReceived( void IncomingJingleFileTransfer::handleTransportReplaceReceived( const JingleContentID& content, JingleTransportPayload::ref transport) { SWIFT_LOG(debug) << std::endl; - if (state != WaitingForFallbackOrTerminate) { + if (state != WaitingForFallbackOrTerminate) { SWIFT_LOG(warning) << "Incorrect state" << std::endl; return; } diff --git a/Swiften/FileTransfer/OutgoingJingleFileTransfer.cpp b/Swiften/FileTransfer/OutgoingJingleFileTransfer.cpp index a72d5ef..2c43766 100644 --- a/Swiften/FileTransfer/OutgoingJingleFileTransfer.cpp +++ b/Swiften/FileTransfer/OutgoingJingleFileTransfer.cpp @@ -93,9 +93,15 @@ void OutgoingJingleFileTransfer::start() { return; } - setTransporter(transporterFactory->createInitiatorTransporter(getInitiator(), getResponder(), options)); - setInternalState(GeneratingInitialLocalCandidates); - transporter->startGeneratingLocalCandidates(); + 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() { @@ -124,6 +130,9 @@ void OutgoingJingleFileTransfer::handleSessionAcceptReceived( 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(); @@ -192,13 +201,24 @@ 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); - SWIFT_LOG(debug) << "\t" << "S5B candidate: " << candidate.hostPort.toString() << std::endl; + 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); diff --git a/Swiften/FileTransfer/SOCKS5BytestreamServerManager.cpp b/Swiften/FileTransfer/SOCKS5BytestreamServerManager.cpp index 7b97698..3b1be89 100644 --- a/Swiften/FileTransfer/SOCKS5BytestreamServerManager.cpp +++ b/Swiften/FileTransfer/SOCKS5BytestreamServerManager.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 Isode Limited. + * Copyright (c) 2012-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ @@ -192,6 +192,10 @@ void SOCKS5BytestreamServerManager::stop() { forwardPortRequest->stop(); forwardPortRequest.reset(); } + if (unforwardPortRequest) { + unforwardPortRequest->stop(); + unforwardPortRequest.reset(); + } if (server) { server->stop(); delete server; diff --git a/Swiften/FileTransfer/UnitTest/DummyFileTransferTransporterFactory.h b/Swiften/FileTransfer/UnitTest/DummyFileTransferTransporterFactory.h index 324404d..00a931f 100644 --- a/Swiften/FileTransfer/UnitTest/DummyFileTransferTransporterFactory.h +++ b/Swiften/FileTransfer/UnitTest/DummyFileTransferTransporterFactory.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. */ @@ -9,19 +9,20 @@ #include <string> #include <Swiften/Base/API.h> -#include <Swiften/StringCodecs/Hexify.h> #include <Swiften/Crypto/CryptoProvider.h> +#include <Swiften/FileTransfer/FileTransferOptions.h> #include <Swiften/FileTransfer/FileTransferTransporter.h> #include <Swiften/FileTransfer/FileTransferTransporterFactory.h> #include <Swiften/FileTransfer/IBBReceiveSession.h> #include <Swiften/FileTransfer/IBBReceiveTransportSession.h> -#include <Swiften/FileTransfer/IBBSendTransportSession.h> #include <Swiften/FileTransfer/IBBSendSession.h> +#include <Swiften/FileTransfer/IBBSendTransportSession.h> #include <Swiften/FileTransfer/SOCKS5BytestreamProxiesManager.h> #include <Swiften/FileTransfer/SOCKS5BytestreamRegistry.h> #include <Swiften/FileTransfer/SOCKS5BytestreamServerManager.h> #include <Swiften/FileTransfer/TransportSession.h> #include <Swiften/JID/JID.h> +#include <Swiften/StringCodecs/Hexify.h> namespace Swift { @@ -45,7 +46,7 @@ public: TimerFactory*, CryptoProvider* cryptoProvider, IQRouter* iqRouter, - const FileTransferOptions&) : initiator_(initiator), responder_(responder), role_(role), s5bRegistry_(s5bRegistry), crypto_(cryptoProvider), iqRouter_(iqRouter) { + const FileTransferOptions& ftOptions) : initiator_(initiator), responder_(responder), role_(role), s5bRegistry_(s5bRegistry), crypto_(cryptoProvider), iqRouter_(iqRouter), ftOptions_(ftOptions) { } @@ -55,6 +56,12 @@ public: 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()); } @@ -139,6 +146,7 @@ private: CryptoProvider* crypto_; std::string s5bSessionID_; IQRouter* iqRouter_; + FileTransferOptions ftOptions_; }; class DummyFileTransferTransporterFactory : public FileTransferTransporterFactory { diff --git a/Swiften/FileTransfer/UnitTest/OutgoingJingleFileTransferTest.cpp b/Swiften/FileTransfer/UnitTest/OutgoingJingleFileTransferTest.cpp index f3fe42e..fee26d5 100644 --- a/Swiften/FileTransfer/UnitTest/OutgoingJingleFileTransferTest.cpp +++ b/Swiften/FileTransfer/UnitTest/OutgoingJingleFileTransferTest.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. */ @@ -81,7 +81,7 @@ class OutgoingJingleFileTransferTest : public CppUnit::TestFixture { public: - boost::shared_ptr<OutgoingJingleFileTransfer> createTestling() { + 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"); @@ -96,7 +96,7 @@ public: timerFactory, idGen, fileInfo, - FileTransferOptions().withAssistedAllowed(false).withDirectAllowed(false).withProxiedAllowed(false), + options, crypto.get())); } @@ -159,16 +159,17 @@ public: CPPUNIT_ASSERT(description); CPPUNIT_ASSERT(static_cast<size_t>(1048576) == description->getFileInfo().getSize()); - JingleS5BTransportPayload::ref transport = boost::dynamic_pointer_cast<JingleS5BTransportPayload>(call.payload); + JingleIBBTransportPayload::ref transport = boost::dynamic_pointer_cast<JingleIBBTransportPayload>(call.payload); CPPUNIT_ASSERT(transport); } void test_FallbackToIBBAfterFailingS5B() { - boost::shared_ptr<OutgoingJingleFileTransfer> transfer = createTestling(); + 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 diff --git a/Swiften/QA/FileTransferTest/FileTransferTest.cpp b/Swiften/QA/FileTransferTest/FileTransferTest.cpp index 8597033..7a50e9f 100644 --- a/Swiften/QA/FileTransferTest/FileTransferTest.cpp +++ b/Swiften/QA/FileTransferTest/FileTransferTest.cpp @@ -49,7 +49,7 @@ enum Candidate { class FileTransferTest { public: - FileTransferTest(int senderCandidates, int receiverCandidates) : senderCandidates_(senderCandidates), senderIsDone_(false), receiverCandidates_(receiverCandidates), receiverIsDone_(false) { + FileTransferTest(int senderCandidates, int receiverCandidates) : senderCandidates_(senderCandidates), senderError_(FileTransferError::UnknownError), senderIsDone_(false), receiverCandidates_(receiverCandidates), receiverError_(FileTransferError::UnknownError), receiverIsDone_(false) { sender_ = boost::make_shared<Client>(JID(getenv("SWIFT_FILETRANSFERTEST_JID")), getenv("SWIFT_FILETRANSFERTEST_PASS"), networkFactories.get()); sender_->onDisconnected.connect(boost::bind(&FileTransferTest::handleSenderDisconnected, this, _1)); sender_->onConnected.connect(boost::bind(&FileTransferTest::handleSenderConnected, this)); @@ -108,6 +108,19 @@ class FileTransferTest { } void handleSenderConnected() { + DiscoInfo discoInfo; + discoInfo.addIdentity(DiscoInfo::Identity(CLIENT_NAME, "client", "pc")); + discoInfo.addFeature(DiscoInfo::JingleFeature); + discoInfo.addFeature(DiscoInfo::JingleFTFeature); + discoInfo.addFeature(DiscoInfo::Bytestream); + if (senderCandidates_ & InBandBytestream) { + discoInfo.addFeature(DiscoInfo::JingleTransportsIBBFeature); + } + if (senderCandidates_ & (S5B_Direct | S5B_Assisted | S5B_Proxied)) { + discoInfo.addFeature(DiscoInfo::JingleTransportsS5BFeature); + } + sender_->getDiscoManager()->setCapsNode(CLIENT_NODE); + sender_->getDiscoManager()->setDiscoInfo(discoInfo); sender_->sendPresence(Presence::create()); } @@ -119,8 +132,12 @@ class FileTransferTest { discoInfo.addFeature(DiscoInfo::JingleFeature); discoInfo.addFeature(DiscoInfo::JingleFTFeature); discoInfo.addFeature(DiscoInfo::Bytestream); - discoInfo.addFeature(DiscoInfo::JingleTransportsIBBFeature); - discoInfo.addFeature(DiscoInfo::JingleTransportsS5BFeature); + if (receiverCandidates_ & InBandBytestream) { + discoInfo.addFeature(DiscoInfo::JingleTransportsIBBFeature); + } + if (receiverCandidates_ & (S5B_Direct | S5B_Assisted | S5B_Proxied)) { + discoInfo.addFeature(DiscoInfo::JingleTransportsS5BFeature); + } receiver_->getDiscoManager()->setCapsNode(CLIENT_NODE); receiver_->getDiscoManager()->setDiscoInfo(discoInfo); receiver_->getPresenceSender()->sendPresence(Presence::create()); @@ -167,6 +184,8 @@ class FileTransferTest { outgoingFileTransfer_->start(); } else { std::cout << "ERROR: No outgoing file transfer returned." << std::endl; + receiverIsDone_ = true; + senderIsDone_ = true; endTest(); } } @@ -223,6 +242,9 @@ class FileTransferTest { timeOut_->onTick.connect(boost::bind(&FileTransferTest::endTest, this)); timeOut_->start(); } + else if (error) { + endTest(); + } } void run() { @@ -287,16 +309,17 @@ static bool runTest(int senderCandidates, int receiverCandidates) { testRun->run(); - if (testRun->isDone()) { - bool wasSuccessful = testRun->wasSuccessful(); - if (expectSuccess == wasSuccessful) { - success = true; - } else { - std::cout << "expected success: " << expectSuccess << ", wasSuccessful: " << wasSuccessful << std::endl; + bool wasSuccessful = testRun->wasSuccessful(); + if (expectSuccess == wasSuccessful) { + success = true; + } + else { + if (!testRun->isDone()) { + std::cout << "Test did not finish transfer. Sender candidates = " << senderCandidates << ", receiver candidates = " << receiverCandidates << "." << std::endl; } - } else { - std::cout << "Failed to run test! Sender candidates = " << senderCandidates << ", receiver candidates = " << receiverCandidates << "." << std::endl; } + std::cout << "expected success: " << expectSuccess << ", wasSuccessful: " << wasSuccessful << std::endl; + testRun.reset(); networkFactories.reset(); |