From 63a8085f02218d2dd2b51acf29280624d6317610 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Mon, 1 Nov 2010 21:18:36 +0100
Subject: Added incoming IBB session.


diff --git a/Swiften/FileTransfer/FileTransferError.h b/Swiften/FileTransfer/FileTransferError.h
index b718927..6a6b454 100644
--- a/Swiften/FileTransfer/FileTransferError.h
+++ b/Swiften/FileTransfer/FileTransferError.h
@@ -13,6 +13,7 @@ namespace Swift {
 				UnknownError,
 				PeerError,
 				ReadError,
+				ClosedError,
 			};
 
 			FileTransferError(Type type = UnknownError) : type(type) {}
diff --git a/Swiften/FileTransfer/FileWriteBytestream.cpp b/Swiften/FileTransfer/FileWriteBytestream.cpp
new file mode 100644
index 0000000..b864b6f
--- /dev/null
+++ b/Swiften/FileTransfer/FileWriteBytestream.cpp
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <boost/filesystem/fstream.hpp>
+#include <cassert>
+
+#include "Swiften/FileTransfer/FileWriteBytestream.h"
+
+namespace Swift {
+
+FileWriteBytestream::FileWriteBytestream(const boost::filesystem::path& file) : file(file), stream(NULL) {
+}
+
+FileWriteBytestream::~FileWriteBytestream() {
+	if (stream) {
+		stream->close();
+		stream = NULL;
+	}
+}
+
+void FileWriteBytestream::write(const ByteArray& data) {
+	if (!stream) {
+		stream = new boost::filesystem::ofstream(file, std::ios_base::out|std::ios_base::binary);
+	}
+	assert(stream->good());
+	stream->write(data.getData(), data.getSize());
+}
+
+}
diff --git a/Swiften/FileTransfer/FileWriteBytestream.h b/Swiften/FileTransfer/FileWriteBytestream.h
new file mode 100644
index 0000000..c6f7b39
--- /dev/null
+++ b/Swiften/FileTransfer/FileWriteBytestream.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <boost/filesystem.hpp>
+#include <boost/filesystem/fstream.hpp>
+
+#include "Swiften/FileTransfer/WriteBytestream.h"
+
+namespace Swift {
+	class FileWriteBytestream : public WriteBytestream {
+		public:
+			FileWriteBytestream(const boost::filesystem::path& file);
+			~FileWriteBytestream();
+
+			virtual void write(const ByteArray&);
+
+		private:
+			boost::filesystem::path file;
+			boost::filesystem::ofstream* stream;
+	};
+}
diff --git a/Swiften/FileTransfer/IBBReceiveSession.cpp b/Swiften/FileTransfer/IBBReceiveSession.cpp
new file mode 100644
index 0000000..9eed21d
--- /dev/null
+++ b/Swiften/FileTransfer/IBBReceiveSession.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include "Swiften/FileTransfer/IBBReceiveSession.h"
+
+#include <boost/bind.hpp>
+
+#include "Swiften/Queries/IQRouter.h"
+#include "Swiften/FileTransfer/IBBRequest.h"
+#include "Swiften/FileTransfer/BytestreamException.h"
+
+namespace Swift {
+
+IBBReceiveSession::IBBReceiveSession(const String& id, const JID& from, size_t size, WriteBytestream::ref bytestream, IQRouter* router) : SetResponder<IBB>(router), id(id), from(from), size(size), bytestream(bytestream), router(router), sequenceNumber(0), active(false), receivedSize(0) {
+}
+
+IBBReceiveSession::~IBBReceiveSession() {
+}
+
+void IBBReceiveSession::start() {
+	active = true;
+}
+
+void IBBReceiveSession::stop() {
+	if (active && router->isAvailable()) {
+		IBBRequest::create(from, IBB::createIBBClose(id), router)->send();
+	}
+	finish(boost::optional<FileTransferError>());
+}
+
+void IBBReceiveSession::finish(boost::optional<FileTransferError> error) {
+	active = false;
+	onFinished(error);
+}
+
+bool IBBReceiveSession::handleSetRequest(const JID& from, const JID&, const String& id, IBB::ref ibb) {
+	if (from == this->from && ibb->getStreamID() == id) {
+		if (ibb->getAction() == IBB::Data) {
+			if (sequenceNumber == ibb->getSequenceNumber()) {
+				bytestream->write(ibb->getData());
+				receivedSize += ibb->getData().getSize();
+				if (receivedSize >= size) {
+					if (receivedSize > size) {
+						std::cerr << "Warning: Received more data than expected" << std::endl;
+					}
+					finish(boost::optional<FileTransferError>());
+				}
+			}
+			else {
+				sendError(from, id, ErrorPayload::NotAcceptable, ErrorPayload::Cancel);
+				finish(FileTransferError(FileTransferError::ClosedError));
+			}
+		}
+		else if (ibb->getAction() == IBB::Open) {
+			sendResponse(from, id, IBB::ref());
+		}
+		else if (ibb->getAction() == IBB::Close) {
+			sendResponse(from, id, IBB::ref());
+			finish(FileTransferError(FileTransferError::ClosedError));
+		}
+		return true;
+	}
+	return false;
+}
+
+}
diff --git a/Swiften/FileTransfer/IBBReceiveSession.h b/Swiften/FileTransfer/IBBReceiveSession.h
new file mode 100644
index 0000000..b2399b6
--- /dev/null
+++ b/Swiften/FileTransfer/IBBReceiveSession.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <boost/shared_ptr.hpp>
+#include <boost/optional.hpp>
+
+#include "Swiften/Base/boost_bsignals.h"
+#include "Swiften/FileTransfer/WriteBytestream.h"
+#include "Swiften/JID/JID.h"
+#include "Swiften/Elements/IBB.h"
+#include "Swiften/Elements/ErrorPayload.h"
+#include "Swiften/FileTransfer/FileTransferError.h"
+#include "Swiften/Queries/SetResponder.h"
+
+namespace Swift {
+	class IQRouter;
+
+	class IBBReceiveSession : public SetResponder<IBB> {
+		public:
+			IBBReceiveSession(const String& id, const JID& from, size_t size, WriteBytestream::ref bytestream, IQRouter* router);
+			~IBBReceiveSession();
+
+			void start();
+			void stop();
+
+			boost::signal<void (boost::optional<FileTransferError>)> onFinished;
+
+		private:
+			bool handleSetRequest(const JID& from, const JID& to, const String& id, IBB::ref payload);
+			void finish(boost::optional<FileTransferError>);
+
+		private:
+			String id;
+			JID from;
+			size_t size;
+			WriteBytestream::ref bytestream;
+			IQRouter* router;
+			int sequenceNumber;
+			bool active;
+			size_t receivedSize;
+	};
+}
diff --git a/Swiften/FileTransfer/IncomingFileTransfer.cpp b/Swiften/FileTransfer/IncomingFileTransfer.cpp
new file mode 100644
index 0000000..1962724
--- /dev/null
+++ b/Swiften/FileTransfer/IncomingFileTransfer.cpp
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include "Swiften/FileTransfer/IncomingFileTransfer.h"
+
+namespace Swift {
+
+void IncomingFileTransfer::accept(WriteBytestream::ref) {
+
+}
+
+}
diff --git a/Swiften/FileTransfer/IncomingFileTransfer.h b/Swiften/FileTransfer/IncomingFileTransfer.h
new file mode 100644
index 0000000..d5e7a2f
--- /dev/null
+++ b/Swiften/FileTransfer/IncomingFileTransfer.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <boost/shared_ptr.hpp>
+
+#include "Swiften/Base/boost_bsignals.h"
+#include "Swiften/FileTransfer/WriteBytestream.h"
+
+namespace Swift {
+	class IncomingFileTransfer {
+		public:
+			typedef boost::shared_ptr<IncomingFileTransfer> ref;
+
+			void accept(WriteBytestream::ref);
+	};
+}
diff --git a/Swiften/FileTransfer/IncomingFileTransferManager.h b/Swiften/FileTransfer/IncomingFileTransferManager.h
new file mode 100644
index 0000000..41499e5
--- /dev/null
+++ b/Swiften/FileTransfer/IncomingFileTransferManager.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <boost/shared_ptr.hpp>
+
+#include "Swiften/Base/boost_bsignals.h"
+
+namespace Swift {
+	class IncomingFileTransferManager {
+		public:
+			boost::signal<void (IncomingFileTransfer::ref)> onIncomingFileTransfer;
+	};
+}
diff --git a/Swiften/FileTransfer/SConscript b/Swiften/FileTransfer/SConscript
index f42dd88..d36e029 100644
--- a/Swiften/FileTransfer/SConscript
+++ b/Swiften/FileTransfer/SConscript
@@ -2,12 +2,16 @@ Import("swiften_env")
 
 sources = [
 		"OutgoingFileTransfer.cpp",
+		"IncomingFileTransfer.cpp",
 		"ReadBytestream.cpp",
+		"WriteBytestream.cpp",
 		"FileReadBytestream.cpp",
+		"FileWriteBytestream.cpp",
 		"SOCKS5BytestreamServer.cpp",
 		"SOCKS5BytestreamServerSession.cpp",
 		"SOCKS5BytestreamRegistry.cpp",
 		"IBBSendSession.cpp",
+		"IBBReceiveSession.cpp",
 	]
 
 swiften_env.Append(SWIFTEN_OBJECTS = swiften_env.StaticObject(sources))
diff --git a/Swiften/FileTransfer/WriteBytestream.cpp b/Swiften/FileTransfer/WriteBytestream.cpp
new file mode 100644
index 0000000..f1a5afc
--- /dev/null
+++ b/Swiften/FileTransfer/WriteBytestream.cpp
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include "Swiften/FileTransfer/WriteBytestream.h"
+
+namespace Swift {
+
+WriteBytestream::~WriteBytestream() {
+}
+
+}
diff --git a/Swiften/FileTransfer/WriteBytestream.h b/Swiften/FileTransfer/WriteBytestream.h
new file mode 100644
index 0000000..1dc791c
--- /dev/null
+++ b/Swiften/FileTransfer/WriteBytestream.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <boost/shared_ptr.hpp>
+
+#include "Swiften/Base/ByteArray.h"
+
+namespace Swift {
+	class WriteBytestream {
+		public:
+			typedef boost::shared_ptr<WriteBytestream> ref;
+
+			virtual ~WriteBytestream();
+
+			virtual void write(const ByteArray&) = 0;
+	};
+}
-- 
cgit v0.10.2-6-g49f6