summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'Swiften/FileTransfer/OutgoingJingleFileTransfer.cpp')
-rw-r--r--Swiften/FileTransfer/OutgoingJingleFileTransfer.cpp40
1 files changed, 30 insertions, 10 deletions
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
@@ -66,91 +66,100 @@ OutgoingJingleFileTransfer::OutgoingJingleFileTransfer(
// 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();
}
void OutgoingJingleFileTransfer::start() {
SWIFT_LOG(debug) << std::endl;
if (state != Initial) {
SWIFT_LOG(warning) << "Incorrect state" << std::endl;
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() {
terminate(JinglePayload::Reason::Cancel);
}
void OutgoingJingleFileTransfer::terminate(JinglePayload::Reason::Type reason) {
SWIFT_LOG(debug) << reason << std::endl;
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();
}
}
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));
}
}
void OutgoingJingleFileTransfer::handleTransportAcceptReceived(const JingleContentID&, JingleTransportPayload::ref transport) {
SWIFT_LOG(debug) << std::endl;
@@ -165,67 +174,78 @@ void OutgoingJingleFileTransfer::handleTransportAcceptReceived(const JingleConte
}
}
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& 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);
- 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);
}
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);
}
}
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();