summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTobias Markmann <tm@ayena.de>2011-05-26 18:46:49 (GMT)
committerRemko Tronçon <git@el-tramo.be>2011-09-25 17:42:32 (GMT)
commit4f62e5ec4b42929fe3c1a68667e63cb1b7a35509 (patch)
tree0d19fac3f578dec00ccf3e58930312951e38de89 /Swift/Controllers/FileTransfer
parentde660b763459cdd707876ec244b6866abca07fa2 (diff)
downloadswift-4f62e5ec4b42929fe3c1a68667e63cb1b7a35509.zip
swift-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')
-rw-r--r--Swift/Controllers/FileTransfer/FileTransferController.cpp147
-rw-r--r--Swift/Controllers/FileTransfer/FileTransferController.h72
-rw-r--r--Swift/Controllers/FileTransfer/FileTransferOverview.cpp41
-rw-r--r--Swift/Controllers/FileTransfer/FileTransferOverview.h38
-rw-r--r--Swift/Controllers/FileTransfer/FileTransferProgressInfo.cpp31
-rw-r--r--Swift/Controllers/FileTransfer/FileTransferProgressInfo.h29
-rw-r--r--Swift/Controllers/FileTransfer/SOCKS5BytestreamProxyFinder.cpp53
-rw-r--r--Swift/Controllers/FileTransfer/SOCKS5BytestreamProxyFinder.h38
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;
+};
+
+}