summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'Swiften/FileTransfer/IncomingJingleFileTransfer.cpp')
-rw-r--r--Swiften/FileTransfer/IncomingJingleFileTransfer.cpp14
1 files changed, 9 insertions, 5 deletions
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
@@ -1,49 +1,50 @@
/*
* Copyright (c) 2011-2016 Isode Limited.
* All rights reserved.
* See the COPYING file for more information.
*/
#include <Swiften/FileTransfer/IncomingJingleFileTransfer.h>
#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>
#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>
#include <Swiften/FileTransfer/TransportSession.h>
#include <Swiften/FileTransfer/WriteBytestream.h>
#include <Swiften/Jingle/JingleSession.h>
#include <Swiften/Network/TimerFactory.h>
#include <Swiften/Queries/GenericRequest.h>
#include <Swiften/StringCodecs/Base64.h>
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();
@@ -55,83 +56,86 @@ IncomingJingleFileTransfer::IncomingJingleFileTransfer(
boost::bind(&IncomingJingleFileTransfer::handleWaitOnHashTimerTicked, this));
}
IncomingJingleFileTransfer::~IncomingJingleFileTransfer() {
if (waitOnHashTimer) {
waitOnHashTimer->stop();
}
delete hashCalculator;
hashCalculator = NULL;
}
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));
- 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));
transporter->addRemoteCandidates(s5bTransport->getCandidates(), s5bTransport->getDstAddr());
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));
startTransferring(transporter->createIBBReceiveSession(
ibbTransport->getSessionID(),
description->getFileInfo().getSize(),
stream));
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));
}
}
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::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);
transporter->startTryingRemoteCandidates();
}
@@ -196,61 +200,61 @@ void IncomingJingleFileTransfer::checkIfAllDataReceived() {
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);
}
}
void IncomingJingleFileTransfer::handleWriteStreamDataReceived(
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) {
+ 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);
}
}
JingleContentID IncomingJingleFileTransfer::getContentID() const {
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()) {