diff options
Diffstat (limited to 'Swiften/FileTransfer/IncomingJingleFileTransfer.cpp')
| -rw-r--r-- | Swiften/FileTransfer/IncomingJingleFileTransfer.cpp | 152 | 
1 files changed, 151 insertions, 1 deletions
| diff --git a/Swiften/FileTransfer/IncomingJingleFileTransfer.cpp b/Swiften/FileTransfer/IncomingJingleFileTransfer.cpp index cb2f65c..904b53e 100644 --- a/Swiften/FileTransfer/IncomingJingleFileTransfer.cpp +++ b/Swiften/FileTransfer/IncomingJingleFileTransfer.cpp @@ -6,14 +6,164 @@  #include <Swiften/FileTransfer/IncomingJingleFileTransfer.h> +#include <boost/bind.hpp> +#include <boost/smart_ptr/make_shared.hpp> + +#include <Swiften/FileTransfer/RemoteJingleTransportCandidateSelectorFactory.h> +#include <Swiften/FileTransfer/LocalJingleTransportCandidateGeneratorFactory.h> +#include <Swiften/FileTransfer/JingleIncomingIBBTransport.h> +#include <Swiften/Elements/JingleIBBTransportPayload.h> +#include <Swiften/Elements/JingleS5BTransportPayload.h> +#include <Swiften/FileTransfer/RemoteJingleTransportCandidateSelector.h> +#include <Swiften/FileTransfer/LocalJingleTransportCandidateGenerator.h> +  namespace Swift { -IncomingJingleFileTransfer::IncomingJingleFileTransfer(IncomingJingleSession::ref session) : session(session) { +IncomingJingleFileTransfer::IncomingJingleFileTransfer( +		JingleSession::ref session, +		JingleContentPayload::ref content, +		RemoteJingleTransportCandidateSelectorFactory* candidateSelectorFactory, +		LocalJingleTransportCandidateGeneratorFactory* candidateGeneratorFactory, +		IQRouter* router) : +			session(session), +			router(router), +			initialContent(content), +			contentID(content->getName(), content->getCreator()), +			state(Initial), +			remoteTransportCandidateSelectFinished(false), +			localTransportCandidateSelectFinished(false) { +	 +	candidateSelector = candidateSelectorFactory->createCandidateSelector(); +	candidateSelector->onRemoteTransportCandidateSelectFinished.connect(boost::bind(&IncomingJingleFileTransfer::handleRemoteTransportCandidateSelectFinished, this, _1)); + +	candidateGenerator = candidateGeneratorFactory->createCandidateGenerator(); +	candidateGenerator->onLocalTransportCandidatesGenerated.connect(boost::bind(&IncomingJingleFileTransfer::handleLocalTransportCandidatesGenerated, this, _1)); + +	session->onTransportInfoReceived.connect(boost::bind(&IncomingJingleFileTransfer::handleTransportInfoReceived, this, _1, _2)); +	session->onTransportReplaceReceived.connect(boost::bind(&IncomingJingleFileTransfer::handleTransportReplaceReceived, this, _1, _2)); +	session->onSessionTerminateReceived.connect(boost::bind(&IncomingJingleFileTransfer::handleSessionTerminateReceived, this)); + +	description = initialContent->getDescription<JingleFileTransferDescription>(); +	assert(description); +} + +IncomingJingleFileTransfer::~IncomingJingleFileTransfer() { +	session->onSessionTerminateReceived.disconnect(boost::bind(&IncomingJingleFileTransfer::handleSessionTerminateReceived, this)); +	session->onTransportReplaceReceived.disconnect(boost::bind(&IncomingJingleFileTransfer::handleTransportReplaceReceived, this, _1, _2)); +	session->onTransportInfoReceived.disconnect(boost::bind(&IncomingJingleFileTransfer::handleTransportInfoReceived, this, _1, _2)); + +	candidateGenerator->onLocalTransportCandidatesGenerated.disconnect(boost::bind(&IncomingJingleFileTransfer::handleLocalTransportCandidatesGenerated, this, _1)); +	delete candidateGenerator; +	candidateSelector->onRemoteTransportCandidateSelectFinished.disconnect(boost::bind(&IncomingJingleFileTransfer::handleRemoteTransportCandidateSelectFinished, this, _1)); +	delete candidateSelector;  }  void IncomingJingleFileTransfer::accept(WriteBytestream::ref stream) { +	assert(!stream);  	this->stream = stream; + +	if (JingleIBBTransportPayload::ref ibbTransport = initialContent->getTransport<JingleIBBTransportPayload>()) { +		setActiveTransport(createIBBTransport(ibbTransport)); +		session->accept(); +	} +	else if (JingleS5BTransportPayload::ref s5bTransport = initialContent->getTransport<JingleS5BTransportPayload>()) { +		state = CreatingInitialTransports; +		candidateSelector->addRemoteTransportCandidates(s5bTransport); +		candidateGenerator->generateLocalTransportCandidates(); +	} +	else { +		assert(false); +	} +} + + +void IncomingJingleFileTransfer::handleLocalTransportCandidatesGenerated(JingleTransportPayload::ref candidates) { +	if (state == CreatingInitialTransports) { +		if (!candidates) { +			localTransportCandidateSelectFinished = true; +		} +		session->accept(candidates); +		state = NegotiatingTransport; +		candidateSelector->selectCandidate(); +	} +} + + +void IncomingJingleFileTransfer::handleRemoteTransportCandidateSelectFinished(JingleTransportPayload::ref transport) { +	remoteTransportCandidateSelectFinished = true; +	selectedRemoteTransportCandidate = transport; +	session->sendTransportInfo(contentID, transport); +	checkCandidateSelected(); +} + +void IncomingJingleFileTransfer::checkCandidateSelected() { +	if (localTransportCandidateSelectFinished && remoteTransportCandidateSelectFinished) { +		if (candidateGenerator->isActualCandidate(selectedLocalTransportCandidate) && candidateSelector->isActualCandidate(selectedRemoteTransportCandidate)) { +			if (candidateGenerator->getPriority(selectedLocalTransportCandidate) > candidateSelector->getPriority(selectedRemoteTransportCandidate)) { +				setActiveTransport(candidateGenerator->selectTransport(selectedLocalTransportCandidate)); +			} +			else { +				setActiveTransport(candidateSelector->selectTransport(selectedRemoteTransportCandidate)); +			} +		} +		else if (candidateSelector->isActualCandidate(selectedRemoteTransportCandidate)) { +			setActiveTransport(candidateSelector->selectTransport(selectedRemoteTransportCandidate)); +		} +		else if (candidateGenerator->isActualCandidate(selectedLocalTransportCandidate)) { +			setActiveTransport(candidateGenerator->selectTransport(selectedLocalTransportCandidate)); +		} +		else { +			state = WaitingForFallbackOrTerminate; +		} +	} +} + +void IncomingJingleFileTransfer::setActiveTransport(JingleTransport::ref transport) { +	state = Transferring; +	activeTransport = transport; +	activeTransport->onDataReceived.connect(boost::bind(&IncomingJingleFileTransfer::handleTransportDataReceived, this, _1)); +	activeTransport->start(); +} + +void IncomingJingleFileTransfer::handleSessionTerminateReceived() { +	// TODO +	state = Terminated; +} + +void IncomingJingleFileTransfer::handleTransportDataReceived(const std::vector<unsigned char>& data) { +	stream->write(data); +} + + +void IncomingJingleFileTransfer::handleTransportInfoReceived(const JingleContentID&, JingleTransportPayload::ref transport) { +	localTransportCandidateSelectFinished = true; +	selectedLocalTransportCandidate = transport; +	if (candidateGenerator->isActualCandidate(transport)) { +		candidateSelector->setMinimumPriority(candidateGenerator->getPriority(transport)); +	} +	checkCandidateSelected(); +} + +void IncomingJingleFileTransfer::handleTransportReplaceReceived(const JingleContentID& content, JingleTransportPayload::ref transport) { +	if (JingleIBBTransportPayload::ref ibbTransport = boost::dynamic_pointer_cast<JingleIBBTransportPayload>(transport)) { +		setActiveTransport(createIBBTransport(ibbTransport)); +		session->acceptTransport(content, transport); +	} +	else { +		session->rejectTransport(content, transport); +	} +} + +void IncomingJingleFileTransfer::stopActiveTransport() { +	if (activeTransport) { +		activeTransport->stop(); +		activeTransport->onDataReceived.disconnect(boost::bind(&IncomingJingleFileTransfer::handleTransportDataReceived, this, _1)); +	} +} + +JingleIncomingIBBTransport::ref IncomingJingleFileTransfer::createIBBTransport(JingleIBBTransportPayload::ref ibbTransport) { +	return boost::make_shared<JingleIncomingIBBTransport>(session->getInitiator(), ibbTransport->getSessionID(), description->getOffer()->size, router);  }  } | 
 Swift
 Swift