diff options
author | Tobias Markmann <tm@ayena.de> | 2011-05-26 18:46:49 (GMT) |
---|---|---|
committer | Remko Tronçon <git@el-tramo.be> | 2011-09-25 17:42:32 (GMT) |
commit | 4f62e5ec4b42929fe3c1a68667e63cb1b7a35509 (patch) | |
tree | 0d19fac3f578dec00ccf3e58930312951e38de89 /Swift/Controllers/FileTransfer | |
parent | de660b763459cdd707876ec244b6866abca07fa2 (diff) | |
download | swift-contrib-4f62e5ec4b42929fe3c1a68667e63cb1b7a35509.zip swift-contrib-4f62e5ec4b42929fe3c1a68667e63cb1b7a35509.tar.bz2 |
Google Summer of Code 2011 Project: Adding support for Jingle File Transfers (XEP-0234), Jingle SOCKS5 Bytestreams Transport Method (XEP-0260), Jingle In-Band Bytestreams Transport Method (XEP-0261) and SOCKS5 Bytestreams (XEP-0065).
License: This patch is BSD-licensed, see http://www.opensource.org/licenses/bsd-license.php
Diffstat (limited to 'Swift/Controllers/FileTransfer')
8 files changed, 449 insertions, 0 deletions
diff --git a/Swift/Controllers/FileTransfer/FileTransferController.cpp b/Swift/Controllers/FileTransfer/FileTransferController.cpp new file mode 100644 index 0000000..afa907d --- /dev/null +++ b/Swift/Controllers/FileTransfer/FileTransferController.cpp @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2011 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include "FileTransferController.h" +#include "Swiften/FileTransfer/OutgoingJingleFileTransfer.h" +#include "Swiften/FileTransfer/FileTransferManager.h" +#include <Swiften/FileTransfer/FileReadBytestream.h> +#include <Swiften/Base/boost_bsignals.h> +#include <boost/bind.hpp> +#include "Swift/Controllers/UIInterfaces/ChatWindow.h" + +#include <boost/smart_ptr/make_shared.hpp> + +namespace Swift { + +FileTransferController::FileTransferController(const JID& receipient, const std::string& filename, FileTransferManager* fileTransferManager) : + sending(true), otherParty(receipient), filename(filename), ftManager(fileTransferManager), ftProgressInfo(0), chatWindow(0), currentState(FileTransfer::State::WaitingForStart) { + +} + +FileTransferController::FileTransferController(IncomingFileTransfer::ref transfer) : + sending(false), otherParty(transfer->getSender()), filename(transfer->filename), transfer(transfer), ftManager(0), ftProgressInfo(0), chatWindow(0), currentState(FileTransfer::State::WaitingForStart) { + +} + +FileTransferController::~FileTransferController() { + delete ftProgressInfo; +} + +const JID &FileTransferController::getOtherParty() const { + return otherParty; +} + +std::string FileTransferController::setChatWindow(ChatWindow* wnd, std::string nickname) { + chatWindow = wnd; + if (sending) { + uiID = wnd->addFileTransfer("me", true, filename, boost::filesystem::file_size(boost::filesystem::path(filename))); + } else { + uiID = wnd->addFileTransfer(nickname, false, filename, transfer->fileSizeInBytes); + } + return uiID; +} + +void FileTransferController::setReceipient(const JID& receipient) { + this->otherParty = receipient; +} + +bool FileTransferController::isIncoming() const { + return !sending; +} + +FileTransfer::State FileTransferController::getState() const { + return currentState; +} + +int FileTransferController::getProgress() const { + return ftProgressInfo ? ftProgressInfo->getPercentage() : 0; +} + +boost::uintmax_t FileTransferController::getSize() const { + if (transfer) { + return transfer->fileSizeInBytes; + } else { + return 0; + } +} + +void FileTransferController::start(std::string& description) { + std::cout << "FileTransferController::start" << std::endl; + fileReadStream = boost::make_shared<FileReadBytestream>(boost::filesystem::path(filename)); + OutgoingFileTransfer::ref outgoingTransfer = ftManager->createOutgoingFileTransfer(otherParty, boost::filesystem::path(filename), description, fileReadStream); + if (outgoingTransfer) { + ftProgressInfo = new FileTransferProgressInfo(outgoingTransfer->fileSizeInBytes); + ftProgressInfo->onProgressPercentage.connect(boost::bind(&FileTransferController::handleProgressPercentageChange, this, _1)); + outgoingTransfer->onStateChange.connect(boost::bind(&FileTransferController::handleFileTransferStateChange, this, _1)); + outgoingTransfer->onProcessedBytes.connect(boost::bind(&FileTransferProgressInfo::setBytesProcessed, ftProgressInfo, _1)); + outgoingTransfer->start(); + transfer = outgoingTransfer; + } else { + std::cerr << "File transfer not supported!" << std::endl; + } +} + +void FileTransferController::accept(std::string& file) { + std::cout << "FileTransferController::accept" << std::endl; + IncomingFileTransfer::ref incomingTransfer = boost::dynamic_pointer_cast<IncomingFileTransfer>(transfer); + if (incomingTransfer) { + fileWriteStream = boost::make_shared<FileWriteBytestream>(boost::filesystem::path(file)); + + ftProgressInfo = new FileTransferProgressInfo(transfer->fileSizeInBytes); + ftProgressInfo->onProgressPercentage.connect(boost::bind(&FileTransferController::handleProgressPercentageChange, this, _1)); + transfer->onStateChange.connect(boost::bind(&FileTransferController::handleFileTransferStateChange, this, _1)); + transfer->onProcessedBytes.connect(boost::bind(&FileTransferProgressInfo::setBytesProcessed, ftProgressInfo, _1)); + incomingTransfer->accept(fileWriteStream); + } else { + std::cerr << "Expected an incoming transfer in this situation!" << std::endl; + } +} + +void FileTransferController::cancel() { + if (transfer) { + transfer->cancel(); + } else { + chatWindow->setFileTransferStatus(uiID, ChatWindow::Canceled); + } +} + +void FileTransferController::handleFileTransferStateChange(FileTransfer::State state) { + currentState = state; + onStateChage(); + switch(state.state) { + case FileTransfer::State::Negotiating: + chatWindow->setFileTransferStatus(uiID, ChatWindow::Negotiating); + return; + case FileTransfer::State::Transferring: + chatWindow->setFileTransferStatus(uiID, ChatWindow::Transferring); + return; + case FileTransfer::State::Canceled: + chatWindow->setFileTransferStatus(uiID, ChatWindow::Canceled); + return; + case FileTransfer::State::Finished: + chatWindow->setFileTransferStatus(uiID, ChatWindow::Finished); + if (fileWriteStream) { + fileWriteStream->close(); + } + return; + case FileTransfer::State::Failed: + chatWindow->setFileTransferStatus(uiID, ChatWindow::FTFailed); + return; + case FileTransfer::State::WaitingForAccept: + chatWindow->setFileTransferStatus(uiID, ChatWindow::WaitingForAccept); + return; + case FileTransfer::State::WaitingForStart: + return; + } + std::cerr << "Unhandled FileTransfer::State!" << std::endl; +} + +void FileTransferController::handleProgressPercentageChange(int percentage) { + onProgressChange(); + chatWindow->setFileTransferProgress(uiID, percentage); +} + +} diff --git a/Swift/Controllers/FileTransfer/FileTransferController.h b/Swift/Controllers/FileTransfer/FileTransferController.h new file mode 100644 index 0000000..5d98468 --- /dev/null +++ b/Swift/Controllers/FileTransfer/FileTransferController.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2011 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <string> + +#include <boost/shared_ptr.hpp> + +#include <Swiften/JID/JID.h> +#include <Swiften/FileTransfer/FileTransfer.h> +#include <Swiften/FileTransfer/IncomingFileTransfer.h> +#include <Swiften/FileTransfer/FileReadBytestream.h> +#include <Swiften/FileTransfer/FileWriteBytestream.h> +#include <Swift/Controllers/FileTransfer/FileTransferProgressInfo.h> + +namespace Swift { + +class FileTransferManager; +class ChatWindow; + +class FileTransferController { +public: + /** + * For outgoing file transfers. It'll create a file transfer via FileTransferManager as soon as the descriptive information is available. + */ + FileTransferController(const JID&, const std::string&, FileTransferManager*); + + /** + * For incoming file transfers. + */ + FileTransferController(IncomingFileTransfer::ref transfer); + ~FileTransferController(); + + std::string setChatWindow(ChatWindow*, std::string nickname); + void setReceipient(const JID& otherParty); + + void start(std::string& description); + void accept(std::string& file); + void cancel(); + + const JID &getOtherParty() const; + bool isIncoming() const; + FileTransfer::State getState() const; + int getProgress() const; + boost::uintmax_t getSize() const; + + boost::signal<void ()> onStateChage; + boost::signal<void ()> onProgressChange; + +private: + void handleFileTransferStateChange(FileTransfer::State); + void handleProgressPercentageChange(int percentage); + +private: + bool sending; + JID otherParty; + std::string filename; + FileTransfer::ref transfer; + boost::shared_ptr<FileReadBytestream> fileReadStream; + boost::shared_ptr<FileWriteBytestream> fileWriteStream; + FileTransferManager* ftManager; + FileTransferProgressInfo* ftProgressInfo; + ChatWindow* chatWindow; + std::string uiID; + FileTransfer::State currentState; +}; + +} diff --git a/Swift/Controllers/FileTransfer/FileTransferOverview.cpp b/Swift/Controllers/FileTransfer/FileTransferOverview.cpp new file mode 100644 index 0000000..c3ffc5c --- /dev/null +++ b/Swift/Controllers/FileTransfer/FileTransferOverview.cpp @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2011 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include "FileTransferOverview.h" + +#include <boost/bind.hpp> +#include <Swiften/Base/boost_bsignals.h> + +#include <Swiften/FileTransfer/FileTransferManager.h> + +namespace Swift { + +FileTransferOverview::FileTransferOverview(FileTransferManager* ftm) : fileTransferManager(ftm) { + fileTransferManager->onIncomingFileTransfer.connect(boost::bind(&FileTransferOverview::handleIncomingFileTransfer, this, _1)); +} + +FileTransferOverview::~FileTransferOverview() { + +} + +void FileTransferOverview::sendFile(const JID& jid, const std::string& filename) { + FileTransferController* controller = new FileTransferController(jid, filename, fileTransferManager); + fileTransfers.push_back(controller); + + onNewFileTransferController(controller); +} + +void FileTransferOverview::handleIncomingFileTransfer(IncomingFileTransfer::ref transfer) { + FileTransferController* controller = new FileTransferController(transfer); + fileTransfers.push_back(controller); + onNewFileTransferController(controller); +} + +const std::vector<FileTransferController*>& FileTransferOverview::getFileTransfers() const { + return fileTransfers; +} + +} diff --git a/Swift/Controllers/FileTransfer/FileTransferOverview.h b/Swift/Controllers/FileTransfer/FileTransferOverview.h new file mode 100644 index 0000000..716666a --- /dev/null +++ b/Swift/Controllers/FileTransfer/FileTransferOverview.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2011 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <vector> + +#include "Swift/Controllers/FileTransfer/FileTransferController.h" + +#include <Swiften/Base/boost_bsignals.h> + +namespace Swift { + +class ChatsManager; +class FileTransferManager; + +class FileTransferOverview { +public: + FileTransferOverview(FileTransferManager*); + ~FileTransferOverview(); + + void sendFile(const JID&, const std::string&); + const std::vector<FileTransferController*>& getFileTransfers() const; + + boost::signal<void (FileTransferController*)> onNewFileTransferController; + +private: + void handleIncomingFileTransfer(IncomingFileTransfer::ref transfer); + +private: + std::vector<FileTransferController*> fileTransfers; + FileTransferManager *fileTransferManager; +}; + +} diff --git a/Swift/Controllers/FileTransfer/FileTransferProgressInfo.cpp b/Swift/Controllers/FileTransfer/FileTransferProgressInfo.cpp new file mode 100644 index 0000000..6d19fa1 --- /dev/null +++ b/Swift/Controllers/FileTransfer/FileTransferProgressInfo.cpp @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2011 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include "FileTransferProgressInfo.h" + +#include <Swiften/Base/Log.h> + +namespace Swift { + +FileTransferProgressInfo::FileTransferProgressInfo(boost::uintmax_t completeBytes) : completeBytes(completeBytes), completedBytes(0), percentage(0) { + onProgressPercentage(0); +} + +void FileTransferProgressInfo::setBytesProcessed(int processedBytes) { + int oldPercentage = int(double(completedBytes) / double(completeBytes) * 100.0); + completedBytes += processedBytes; + int newPercentage = int(double(completedBytes) / double(completeBytes) * 100.0); + if (oldPercentage != newPercentage) { + onProgressPercentage(newPercentage); + } + percentage = newPercentage; +} + +int FileTransferProgressInfo::getPercentage() const { + return percentage; +} + +} diff --git a/Swift/Controllers/FileTransfer/FileTransferProgressInfo.h b/Swift/Controllers/FileTransfer/FileTransferProgressInfo.h new file mode 100644 index 0000000..bb3c0fc --- /dev/null +++ b/Swift/Controllers/FileTransfer/FileTransferProgressInfo.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2011 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <Swiften/Base/boost_bsignals.h> + +namespace Swift { + +class FileTransferProgressInfo { +public: + FileTransferProgressInfo(boost::uintmax_t completeBytes); + +public: + void setBytesProcessed(int processedBytes); + + int getPercentage() const; + boost::signal<void (int)> onProgressPercentage; + +private: + boost::uintmax_t completeBytes; + boost::uintmax_t completedBytes; + int percentage; +}; + +} diff --git a/Swift/Controllers/FileTransfer/SOCKS5BytestreamProxyFinder.cpp b/Swift/Controllers/FileTransfer/SOCKS5BytestreamProxyFinder.cpp new file mode 100644 index 0000000..da0606c --- /dev/null +++ b/Swift/Controllers/FileTransfer/SOCKS5BytestreamProxyFinder.cpp @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2011 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include "SOCKS5BytestreamProxyFinder.h" + +#include <boost/smart_ptr/make_shared.hpp> +#include <boost/bind.hpp> + +#include <Swiften/Base/Log.h> +#include <Swiften/Elements/S5BProxyRequest.h> +#include <Swiften/Queries/GenericRequest.h> +#include <Swiften/Queries/IQRouter.h> + +namespace Swift { + +SOCKS5BytestreamProxyFinder::SOCKS5BytestreamProxyFinder(const JID& service, IQRouter *iqRouter) : iqRouter(iqRouter) { + serviceWalker = boost::make_shared<DiscoServiceWalker>(service, iqRouter); + serviceWalker->onServiceFound.connect(boost::bind(&SOCKS5BytestreamProxyFinder::handleServiceFound, this, _1, _2)); +} + +void SOCKS5BytestreamProxyFinder::start() { + serviceWalker->beginWalk(); +} + +void SOCKS5BytestreamProxyFinder::sendBytestreamQuery(const JID& jid) { + S5BProxyRequest::ref proxyRequest = boost::make_shared<S5BProxyRequest>(); + boost::shared_ptr<GenericRequest<S5BProxyRequest> > request = boost::make_shared<GenericRequest<S5BProxyRequest> >(IQ::Get, jid, proxyRequest, iqRouter); + request->onResponse.connect(boost::bind(&SOCKS5BytestreamProxyFinder::handleProxyResponse, this, _1, _2)); + request->send(); +} + +void SOCKS5BytestreamProxyFinder::handleServiceFound(const JID& jid, boost::shared_ptr<DiscoInfo> discoInfo) { + if (discoInfo->hasFeature(DiscoInfo::Bytestream)) { + sendBytestreamQuery(jid); + } +} + +void SOCKS5BytestreamProxyFinder::handleProxyResponse(boost::shared_ptr<S5BProxyRequest> request, ErrorPayload::ref error) { + if (error) { + SWIFT_LOG(debug) << "ERROR" << std::endl; + } else { + if (request) { + onProxyFound(request); + } else { + //assert(false); + } + } +} + +} diff --git a/Swift/Controllers/FileTransfer/SOCKS5BytestreamProxyFinder.h b/Swift/Controllers/FileTransfer/SOCKS5BytestreamProxyFinder.h new file mode 100644 index 0000000..1727a63 --- /dev/null +++ b/Swift/Controllers/FileTransfer/SOCKS5BytestreamProxyFinder.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2011 Tobias Markmann + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include <boost/shared_ptr.hpp> + +#include <Swift/Controllers/DiscoServiceWalker.h> +#include <Swiften/Network/HostAddressPort.h> +#include <Swiften/Elements/S5BProxyRequest.h> + +namespace Swift { + +class JID; +class IQRouter; + +class SOCKS5BytestreamProxyFinder { +public: + SOCKS5BytestreamProxyFinder(const JID& service, IQRouter *iqRouter); + void start(); + + boost::signal<void(boost::shared_ptr<S5BProxyRequest>)> onProxyFound; + +private: + void sendBytestreamQuery(const JID&); + + void handleServiceFound(const JID&, boost::shared_ptr<DiscoInfo>); + void handleProxyResponse(boost::shared_ptr<S5BProxyRequest>, ErrorPayload::ref); +private: + boost::shared_ptr<DiscoServiceWalker> serviceWalker; + IQRouter* iqRouter; + std::vector<boost::shared_ptr<GenericRequest<S5BProxyRequest> > > requests; +}; + +} |