From 869c52b244c2d03313e9eda83fac05bf0fc3a619 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Sat, 29 Jan 2011 18:48:13 +0100
Subject: Added some experimental Jingle classes.


diff --git a/Swiften/Elements/JingleContent.h b/Swiften/Elements/JingleContent.h
new file mode 100644
index 0000000..bf419aa
--- /dev/null
+++ b/Swiften/Elements/JingleContent.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <vector>
+#include <boost/optional.hpp>
+
+#include <Swiften/Base/String.h>
+#include <Swiften/JID/JID.h>
+#include <Swiften/Elements/Payload.h>
+#include <Swiften/Elements/JingleDescription.h>
+#include <Swiften/Elements/JingleTransport.h>
+#include <Swiften/Base/foreach.h>
+
+namespace Swift {
+	class JingleContent : public Payload {
+		public:
+			typedef boost::shared_ptr<JingleContent> ref;
+
+			enum Creator {
+				InitiatorCreator,
+				ResponderCreator,
+			};
+
+			/*enum Senders {
+				NoSenders,
+				InitiatorSender,
+				ResponderSender,
+				BothSenders,
+			};*/
+
+			void setCreator(Creator creator) {
+				this->creator = creator;
+			}
+
+			void setName(const String& name) {
+				this->name = name;
+			}
+
+			const std::vector<JingleDescription::ref>& getDescriptions() const {
+				return descriptions;
+			}
+
+			void addDescription(JingleDescription::ref description) {
+				descriptions.push_back(description);
+			}
+
+			const std::vector<JingleTransport::ref>& getTransports() const {
+				return transports;
+			}
+
+			void addTransport(JingleTransport::ref transport) {
+				transports.push_back(transport);
+			}
+
+			template<typename T>
+			boost::shared_ptr<T> getDescription() const {
+				foreach (JingleDescription::ref i, descriptions) {
+					boost::shared_ptr<T> result(boost::dynamic_pointer_cast<T>(i));
+					if (result) {
+						return result;
+					}
+				}
+				return boost::shared_ptr<T>();
+			}
+
+			template<typename T>
+			boost::shared_ptr<T> getTransport() const {
+				foreach (JingleTransport::ref i, transports) {
+					boost::shared_ptr<T> result(boost::dynamic_pointer_cast<T>(i));
+					if (result) {
+						return result;
+					}
+				}
+				return boost::shared_ptr<T>();
+			}
+
+		private:
+			Creator creator;
+			String name;
+			//Senders senders;
+			std::vector<JingleDescription::ref> descriptions;
+			std::vector<JingleTransport::ref> transports;
+	};
+}
diff --git a/Swiften/Elements/JingleDescription.h b/Swiften/Elements/JingleDescription.h
new file mode 100644
index 0000000..775c0f7
--- /dev/null
+++ b/Swiften/Elements/JingleDescription.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2011 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/Elements/Payload.h>
+
+namespace Swift {
+	class JingleDescription : public Payload {
+		public:
+			typedef boost::shared_ptr<JingleDescription> ref;
+	};
+}
diff --git a/Swiften/Elements/JingleFileTransferDescription.h b/Swiften/Elements/JingleFileTransferDescription.h
new file mode 100644
index 0000000..19644bd
--- /dev/null
+++ b/Swiften/Elements/JingleFileTransferDescription.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2011 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/Elements/JingleDescription.h>
+#include <Swiften/Elements/StreamInitiationFileInfo.h>
+
+namespace Swift {
+	class JingleFileTransferDescription : public JingleDescription {
+		public:
+			typedef boost::shared_ptr<JingleFileTransferDescription> ref;
+
+			void setOffer(const StreamInitiationFileInfo& offer) {
+				this->offer = offer;
+			}
+
+			const boost::optional<StreamInitiationFileInfo>& getOffer() const {
+				return offer;
+			}
+
+		private:
+			boost::optional<StreamInitiationFileInfo> offer;
+	};
+}
diff --git a/Swiften/Elements/JingleIBBTransport.h b/Swiften/Elements/JingleIBBTransport.h
new file mode 100644
index 0000000..ca3ecc8
--- /dev/null
+++ b/Swiften/Elements/JingleIBBTransport.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <Swiften/Base/String.h>
+#include <Swiften/Elements/JingleTransport.h>
+
+namespace Swift {
+	class JingleIBBTransport : public JingleTransport {
+		public:
+			enum StanzaType {
+				IQStanza,
+				MessageStanza,
+			};
+
+			void setStanzaType(StanzaType stanzaType) {
+				this->stanzaType = stanzaType;
+			}
+
+			StanzaType getStanzaType() const {
+				return stanzaType;
+			}
+
+			void setSessionID(const String& id) {
+				sessionID = id;
+			}
+
+			const String& getSessionID() const {
+				return sessionID;
+			}
+
+			int getBlockSize() const {
+				return blockSize;
+			}
+
+			void setBlockSize(int blockSize) {
+				this->blockSize = blockSize;
+			}
+
+		private:
+			String sessionID;
+			int blockSize;
+			StanzaType stanzaType;
+	};
+}
diff --git a/Swiften/Elements/JinglePayload.h b/Swiften/Elements/JinglePayload.h
new file mode 100644
index 0000000..66b6d43
--- /dev/null
+++ b/Swiften/Elements/JinglePayload.h
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <vector>
+#include <boost/optional.hpp>
+
+#include <Swiften/Base/String.h>
+#include <Swiften/JID/JID.h>
+#include <Swiften/Elements/Payload.h>
+#include <Swiften/Elements/JingleContent.h>
+
+
+namespace Swift {
+	class JinglePayload : public Payload {
+		public:
+			typedef boost::shared_ptr<JinglePayload> ref;
+			struct Reason {
+					enum Type {
+						AlternativeSession,
+						Busy,
+						Cancel,
+						ConnectivityError,
+						Decline,
+						Expired,
+						FailedApplication,
+						FailedTransport,
+						GeneralError,
+						Gone,
+						IncompatibleParameters,
+						MediaError,
+						SecurityError,
+						Success,
+						Timeout,
+						UnsupportedApplications,
+						UnsupportedTransports
+					};
+					
+					Reason(Type type, const String& text = "") : type(type), text(text) {}
+					Type type;
+					String text;
+			};
+
+			enum Action {
+				ContentAccept,
+				ContentAdd,
+				ContentModify,
+				ContentReject,
+				ContentRemove,
+				DescriptionInfo,
+				SecurityInfo,
+				SessionAccept,
+				SessionInfo,
+				SessionInitiate,
+				SessionTerminate,
+				TransportAccept,
+				TransportInfo,
+				TransportReject,
+				TransportReplace
+			};
+
+			JinglePayload(Action action, const String& sessionID) : action(action), sessionID(sessionID) {
+			}
+
+			void setAction(Action action) {
+				this->action = action;
+			}
+
+			Action getAction() const {
+				return action;
+			}
+
+			void setInitiator(const JID& initiator) {
+				this->initiator = initiator;
+			}
+
+			const JID& getInitiator() const {
+				return initiator;
+			}
+
+			void setResponder(const JID& responder) {
+				this->responder = responder;
+			}
+
+			const JID& getResponder() const {
+				return responder;
+			}
+
+			void setSessionID(const String& id) {
+				sessionID = id;
+			}
+
+			const String& getSessionID() const {
+				return sessionID;
+			}
+
+			void addContent(JingleContent::ref content) {
+				this->contents.push_back(content);
+			}
+
+			const std::vector<JingleContent::ref> getContents() const {
+				return contents;
+			}
+
+			void setReason(const Reason& reason) {
+				this->reason = reason;
+			}
+
+			const boost::optional<Reason>& getReason() const {
+				return reason;
+			}
+
+		private:
+			Action action;
+			JID initiator;
+			JID responder;
+			String sessionID;
+			std::vector<JingleContent::ref> contents;
+			boost::optional<Reason> reason;
+	};
+}
diff --git a/Swiften/Elements/JingleS5BTransport.h b/Swiften/Elements/JingleS5BTransport.h
new file mode 100644
index 0000000..4522417
--- /dev/null
+++ b/Swiften/Elements/JingleS5BTransport.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <Swiften/Elements/JingleTransport.h>
+#include <Swiften/Elements/Bytestreams.h>
+
+namespace Swift {
+	class JingleS5BTransport : public JingleTransport {
+		public:
+			const Bytestreams& getInfo() const {
+				return info;
+			}
+
+			void setInfo(const Bytestreams& info) {
+				this->info = info;
+			}
+
+		private:
+			Bytestreams info;
+	};
+}
diff --git a/Swiften/Elements/JingleTransport.h b/Swiften/Elements/JingleTransport.h
new file mode 100644
index 0000000..ecd2a34
--- /dev/null
+++ b/Swiften/Elements/JingleTransport.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <Swiften/Elements/Payload.h>
+
+namespace Swift {
+	class JingleTransport : public Payload {
+	};
+}
diff --git a/Swiften/Elements/StreamInitiation.h b/Swiften/Elements/StreamInitiation.h
index 55b6b87..16dfd4d 100644
--- a/Swiften/Elements/StreamInitiation.h
+++ b/Swiften/Elements/StreamInitiation.h
@@ -12,20 +12,13 @@
 
 #include "Swiften/Base/String.h"
 #include "Swiften/Elements/Payload.h"
+#include <Swiften/Elements/StreamInitiationFileInfo.h>
 
 namespace Swift {
 	class StreamInitiation : public Payload {
 		public:
 			typedef boost::shared_ptr<StreamInitiation> ref;
 
-			struct FileInfo {
-				FileInfo(const String& name = "", const String& description = "", int size = -1) : name(name), description(description), size(size) {}
-
-				String name;
-				String description;
-				int size;
-			};
-
 			StreamInitiation() : isFileTransfer(true) {}
 
 			const String& getID() const {
@@ -36,11 +29,11 @@ namespace Swift {
 				this->id = id;
 			}
 
-			const boost::optional<FileInfo>& getFileInfo() const {
+			const boost::optional<StreamInitiationFileInfo>& getFileInfo() const {
 				return fileInfo;
 			}
 
-			void setFileInfo(const FileInfo& info) {
+			void setFileInfo(const StreamInitiationFileInfo& info) {
 				fileInfo = info;
 			}
 
@@ -71,7 +64,7 @@ namespace Swift {
 		private:
 			bool isFileTransfer;
 			String id;
-			boost::optional<FileInfo> fileInfo;
+			boost::optional<StreamInitiationFileInfo> fileInfo;
 			std::vector<String> providedMethods;
 			String requestedMethod;
 	};
diff --git a/Swiften/Elements/StreamInitiationFileInfo.h b/Swiften/Elements/StreamInitiationFileInfo.h
new file mode 100644
index 0000000..15b5a66
--- /dev/null
+++ b/Swiften/Elements/StreamInitiationFileInfo.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <Swiften/Base/String.h>
+
+namespace Swift {
+	struct StreamInitiationFileInfo {
+		StreamInitiationFileInfo(const String& name = "", const String& description = "", int size = -1) : name(name), description(description), size(size) {}
+
+		String name;
+		String description;
+		int size;
+	};
+}
diff --git a/Swiften/Examples/SendFile/.gitignore b/Swiften/Examples/SendFile/.gitignore
index f8b7625..b40e042 100644
--- a/Swiften/Examples/SendFile/.gitignore
+++ b/Swiften/Examples/SendFile/.gitignore
@@ -1 +1,2 @@
 SendFile
+ReceiveFile
diff --git a/Swiften/Examples/SendFile/ReceiveFile.cpp b/Swiften/Examples/SendFile/ReceiveFile.cpp
new file mode 100644
index 0000000..a6386cd
--- /dev/null
+++ b/Swiften/Examples/SendFile/ReceiveFile.cpp
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <boost/bind.hpp>
+#include <boost/filesystem.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+
+#include <Swiften/Client/Client.h>
+#include <Swiften/Network/BoostNetworkFactories.h>
+#include <Swiften/EventLoop/SimpleEventLoop.h>
+#include <Swiften/Client/ClientXMLTracer.h>
+#include <Swiften/FileTransfer/IncomingFileTransferManager.h>
+#include <Swiften/FileTransfer/FileWriteBytestream.h>
+#include <Swiften/Jingle/JingleSessionManager.h>
+
+using namespace Swift;
+
+SimpleEventLoop eventLoop;
+BoostNetworkFactories networkFactories(&eventLoop);
+
+int exitCode = 2;
+
+class FileReceiver {
+	public:
+		FileReceiver(const JID& jid, const String& password) : jid(jid), password(password), jingleSessionManager(NULL), incomingFileTransferManager(NULL) {
+			client = new Swift::Client(&eventLoop, &networkFactories, jid, password);
+			client->onConnected.connect(boost::bind(&FileReceiver::handleConnected, this));
+			client->onDisconnected.connect(boost::bind(&FileReceiver::handleDisconnected, this, _1));
+			//tracer = new ClientXMLTracer(client);
+		}
+
+		~FileReceiver() {
+			delete incomingFileTransferManager;
+			delete jingleSessionManager;
+			//delete tracer;
+			client->onDisconnected.disconnect(boost::bind(&FileReceiver::handleDisconnected, this, _1));
+			client->onConnected.disconnect(boost::bind(&FileReceiver::handleConnected, this));
+			delete client;
+		}
+
+		void start() {
+			client->connect();
+		}
+
+		void stop() {
+			foreach(const IncomingFileTransfer::ref transfer, incomingFileTransfers) {
+				//transfer->stop();
+			}
+			client->disconnect();
+		}
+
+	private:
+		void handleConnected() {
+			client->sendPresence(Presence::create());
+			jingleSessionManager = new JingleSessionManager(client->getIQRouter());
+			incomingFileTransferManager = new IncomingFileTransferManager(jingleSessionManager, client->getIQRouter());
+			incomingFileTransferManager->onIncomingFileTransfer.connect(boost::bind(&FileReceiver::handleIncomingFileTransfer, this, _1));
+		}
+
+		void handleIncomingFileTransfer(IncomingFileTransfer::ref transfer) {
+			incomingFileTransfers.push_back(transfer);
+			transfer->accept(boost::make_shared<FileWriteBytestream>("out"));
+			//transfer->onFinished.connect(boost::bind(&FileReceiver::handleFileTransferFinished, this, _1));
+			//transfer->start();
+		}
+
+		void handleDisconnected(const boost::optional<ClientError>&) {
+			std::cerr << "Error!" << std::endl;
+			exit(-1);
+		}
+
+		/*
+		void handleFileTransferFinished(const boost::optional<FileTransferError>& error) {
+			std::cout << "File transfer finished" << std::endl;
+			if (error) {
+				exit(-1);
+			}
+			else {
+				exit(0);
+			}
+		}*/
+
+		void exit(int code) {
+			exitCode = code;
+			stop();
+			eventLoop.stop();
+		}
+	
+	private:
+		JID jid;
+		String password;
+		Client* client;
+		ClientXMLTracer* tracer;
+		JingleSessionManager* jingleSessionManager;
+		IncomingFileTransferManager* incomingFileTransferManager;
+		std::vector<IncomingFileTransfer::ref> incomingFileTransfers;
+};
+
+
+int main(int argc, char* argv[]) {
+	if (argc != 3) {
+		std::cerr << "Usage: " << argv[0] << " <jid> <password>" << std::endl;
+		return -1;
+	}
+
+	JID jid(argv[1]);
+	FileReceiver fileReceiver(jid, String(argv[2]));
+	fileReceiver.start();
+
+	eventLoop.run();
+
+	return exitCode;
+}
diff --git a/Swiften/Examples/SendFile/SConscript b/Swiften/Examples/SendFile/SConscript
index 50cbe40..6986f22 100644
--- a/Swiften/Examples/SendFile/SConscript
+++ b/Swiften/Examples/SendFile/SConscript
@@ -10,4 +10,6 @@ myenv.MergeFlags(myenv.get("SQLITE_FLAGS", {}))
 myenv.MergeFlags(myenv.get("LIBXML_FLAGS", ""))
 myenv.MergeFlags(myenv.get("EXPAT_FLAGS", ""))
 myenv.MergeFlags(myenv["PLATFORM_FLAGS"])
-tester = myenv.Program("SendFile", ["SendFile.cpp"])
+
+myenv.Program("SendFile", ["SendFile.cpp"])
+myenv.Program("ReceiveFile", ["ReceiveFile.cpp"])
diff --git a/Swiften/FileTransfer/IncomingFileTransfer.cpp b/Swiften/FileTransfer/IncomingFileTransfer.cpp
index 1962724..238ccce 100644
--- a/Swiften/FileTransfer/IncomingFileTransfer.cpp
+++ b/Swiften/FileTransfer/IncomingFileTransfer.cpp
@@ -8,8 +8,16 @@
 
 namespace Swift {
 
-void IncomingFileTransfer::accept(WriteBytestream::ref) {
+IncomingFileTransfer::~IncomingFileTransfer() {
 
 }
 
+/*void IncomingFileTransfer::accept(WriteBytestream::ref) {
+
+}
+
+void IncomingFileTransfer::stop() {
+
+}*/
+
 }
diff --git a/Swiften/FileTransfer/IncomingFileTransfer.h b/Swiften/FileTransfer/IncomingFileTransfer.h
index d5e7a2f..4286ef0 100644
--- a/Swiften/FileTransfer/IncomingFileTransfer.h
+++ b/Swiften/FileTransfer/IncomingFileTransfer.h
@@ -16,6 +16,8 @@ namespace Swift {
 		public:
 			typedef boost::shared_ptr<IncomingFileTransfer> ref;
 
-			void accept(WriteBytestream::ref);
+			virtual ~IncomingFileTransfer();
+			
+			virtual void accept(WriteBytestream::ref) = 0;
 	};
 }
diff --git a/Swiften/FileTransfer/IncomingFileTransferManager.cpp b/Swiften/FileTransfer/IncomingFileTransferManager.cpp
new file mode 100644
index 0000000..5535840
--- /dev/null
+++ b/Swiften/FileTransfer/IncomingFileTransferManager.cpp
@@ -0,0 +1,46 @@
+/*
+ * 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/IncomingFileTransferManager.h>
+
+#include <boost/smart_ptr/make_shared.hpp>
+
+#include <Swiften/Elements/JingleDescription.h>
+#include <Swiften/Elements/JingleFileTransferDescription.h>
+#include <Swiften/Elements/JingleIBBTransport.h>
+#include <Swiften/Jingle/JingleSessionManager.h>
+#include <Swiften/FileTransfer/IncomingJingleFileTransfer.h>
+
+namespace Swift {
+
+IncomingFileTransferManager::IncomingFileTransferManager(JingleSessionManager* jingleSessionManager, IQRouter* router) : jingleSessionManager(jingleSessionManager), router(router) {
+	jingleSessionManager->addIncomingSessionHandler(this);
+}
+
+IncomingFileTransferManager::~IncomingFileTransferManager() {
+	jingleSessionManager->removeIncomingSessionHandler(this);
+}
+
+bool IncomingFileTransferManager::handleIncomingJingleSession(IncomingJingleSession::ref session) {
+	JingleContent::ref content = session->getContentWithDescription<JingleFileTransferDescription>();
+	if (content) {
+		// Check for supported transports
+		if (content->getTransport<JingleIBBTransport>()) {
+			IncomingJingleFileTransfer::ref transfer = boost::make_shared<IncomingJingleFileTransfer>(session);
+			onIncomingFileTransfer(transfer);
+		}
+		else {
+			session->terminate(JinglePayload::Reason::UnsupportedTransports);
+		}
+		return true;
+	}
+	else {
+		return false;
+	}
+}
+
+
+}
diff --git a/Swiften/FileTransfer/IncomingFileTransferManager.h b/Swiften/FileTransfer/IncomingFileTransferManager.h
index 41499e5..a54b5cd 100644
--- a/Swiften/FileTransfer/IncomingFileTransferManager.h
+++ b/Swiften/FileTransfer/IncomingFileTransferManager.h
@@ -8,11 +8,26 @@
 
 #include <boost/shared_ptr.hpp>
 
-#include "Swiften/Base/boost_bsignals.h"
+#include <Swiften/Base/boost_bsignals.h>
+#include <Swiften/FileTransfer/IncomingFileTransfer.h>
+#include <Swiften/Jingle/IncomingJingleSessionHandler.h>
 
 namespace Swift {
-	class IncomingFileTransferManager {
+	class IQRouter;
+	class JingleSessionManager;
+
+	class IncomingFileTransferManager : public IncomingJingleSessionHandler {
 		public:
+			IncomingFileTransferManager(JingleSessionManager* jingleSessionManager, IQRouter* router);
+			~IncomingFileTransferManager();
+
 			boost::signal<void (IncomingFileTransfer::ref)> onIncomingFileTransfer;
+
+		private:
+			bool handleIncomingJingleSession(IncomingJingleSession::ref session);
+
+		private:
+			JingleSessionManager* jingleSessionManager;
+			IQRouter* router;
 	};
 }
diff --git a/Swiften/FileTransfer/IncomingJingleFileTransfer.cpp b/Swiften/FileTransfer/IncomingJingleFileTransfer.cpp
new file mode 100644
index 0000000..cb2f65c
--- /dev/null
+++ b/Swiften/FileTransfer/IncomingJingleFileTransfer.cpp
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swiften/FileTransfer/IncomingJingleFileTransfer.h>
+
+namespace Swift {
+
+IncomingJingleFileTransfer::IncomingJingleFileTransfer(IncomingJingleSession::ref session) : session(session) {
+
+}
+
+void IncomingJingleFileTransfer::accept(WriteBytestream::ref stream) {
+	this->stream = stream;
+}
+
+}
diff --git a/Swiften/FileTransfer/IncomingJingleFileTransfer.h b/Swiften/FileTransfer/IncomingJingleFileTransfer.h
new file mode 100644
index 0000000..d69449e
--- /dev/null
+++ b/Swiften/FileTransfer/IncomingJingleFileTransfer.h
@@ -0,0 +1,27 @@
+/*
+ * 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/Jingle/IncomingJingleSession.h>
+#include <Swiften/FileTransfer/IncomingFileTransfer.h>
+
+namespace Swift {
+	class IncomingJingleFileTransfer : public IncomingFileTransfer {
+		public:
+			typedef boost::shared_ptr<IncomingJingleFileTransfer> ref;
+
+			IncomingJingleFileTransfer(IncomingJingleSession::ref session);
+
+			virtual void accept(WriteBytestream::ref);
+
+		private:
+			IncomingJingleSession::ref session;
+			WriteBytestream::ref stream;
+	};
+}
diff --git a/Swiften/FileTransfer/OutgoingFileTransfer.cpp b/Swiften/FileTransfer/OutgoingFileTransfer.cpp
index 4fa8d94..8e6f839 100644
--- a/Swiften/FileTransfer/OutgoingFileTransfer.cpp
+++ b/Swiften/FileTransfer/OutgoingFileTransfer.cpp
@@ -21,7 +21,7 @@ OutgoingFileTransfer::OutgoingFileTransfer(const String& id, const JID& from, co
 void OutgoingFileTransfer::start() {
 	StreamInitiation::ref streamInitiation(new StreamInitiation());
 	streamInitiation->setID(id);
-	streamInitiation->setFileInfo(StreamInitiation::FileInfo(name, description, size));
+	streamInitiation->setFileInfo(StreamInitiationFileInfo(name, description, size));
 	//streamInitiation->addProvidedMethod("http://jabber.org/protocol/bytestreams");
 	streamInitiation->addProvidedMethod("http://jabber.org/protocol/ibb");
 	StreamInitiationRequest::ref request = StreamInitiationRequest::create(to, streamInitiation, iqRouter);
diff --git a/Swiften/FileTransfer/SConscript b/Swiften/FileTransfer/SConscript
index d36e029..9f3234f 100644
--- a/Swiften/FileTransfer/SConscript
+++ b/Swiften/FileTransfer/SConscript
@@ -3,6 +3,8 @@ Import("swiften_env")
 sources = [
 		"OutgoingFileTransfer.cpp",
 		"IncomingFileTransfer.cpp",
+		"IncomingJingleFileTransfer.cpp",
+		"IncomingFileTransferManager.cpp",	
 		"ReadBytestream.cpp",
 		"WriteBytestream.cpp",
 		"FileReadBytestream.cpp",
diff --git a/Swiften/Jingle/IncomingJingleSession.cpp b/Swiften/Jingle/IncomingJingleSession.cpp
new file mode 100644
index 0000000..29155b8
--- /dev/null
+++ b/Swiften/Jingle/IncomingJingleSession.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/Jingle/IncomingJingleSession.h>
+
+namespace Swift {
+
+IncomingJingleSession::IncomingJingleSession(const String& id, const std::vector<JingleContent::ref>& contents) : JingleSession(id, contents) {
+
+}
+
+}
diff --git a/Swiften/Jingle/IncomingJingleSession.h b/Swiften/Jingle/IncomingJingleSession.h
new file mode 100644
index 0000000..222100f
--- /dev/null
+++ b/Swiften/Jingle/IncomingJingleSession.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2011 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/Jingle/JingleSession.h>
+
+namespace Swift {
+	class IncomingJingleSession : public JingleSession {
+		public:
+			IncomingJingleSession(const String& id, const std::vector<JingleContent::ref>& contents);
+
+			typedef boost::shared_ptr<IncomingJingleSession> ref;
+	};
+}
diff --git a/Swiften/Jingle/IncomingJingleSessionHandler.cpp b/Swiften/Jingle/IncomingJingleSessionHandler.cpp
new file mode 100644
index 0000000..d38118c
--- /dev/null
+++ b/Swiften/Jingle/IncomingJingleSessionHandler.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/Jingle/IncomingJingleSessionHandler.h>
+
+namespace Swift {
+
+IncomingJingleSessionHandler::~IncomingJingleSessionHandler() {
+}
+
+}
diff --git a/Swiften/Jingle/IncomingJingleSessionHandler.h b/Swiften/Jingle/IncomingJingleSessionHandler.h
new file mode 100644
index 0000000..5bf9237
--- /dev/null
+++ b/Swiften/Jingle/IncomingJingleSessionHandler.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <Swiften/Jingle/IncomingJingleSession.h>
+
+namespace Swift {
+	class IncomingJingleSessionHandler {
+		public:
+			virtual ~IncomingJingleSessionHandler();
+
+			virtual bool handleIncomingJingleSession(IncomingJingleSession::ref) = 0;
+	};
+}
diff --git a/Swiften/Jingle/JingleResponder.cpp b/Swiften/Jingle/JingleResponder.cpp
new file mode 100644
index 0000000..3dfc327
--- /dev/null
+++ b/Swiften/Jingle/JingleResponder.cpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swiften/Jingle/JingleResponder.h>
+
+#include <boost/smart_ptr/make_shared.hpp>
+
+#include <Swiften/Jingle/JingleSessionManager.h>
+#include <Swiften/Jingle/IncomingJingleSession.h>
+
+namespace Swift {
+
+JingleResponder::JingleResponder(JingleSessionManager* sessionManager, IQRouter* router) : SetResponder<JinglePayload>(router), sessionManager(sessionManager) {
+}
+
+bool JingleResponder::handleSetRequest(const JID& from, const JID&, const String& id, boost::shared_ptr<JinglePayload> payload) {
+	if (payload->getAction() == JinglePayload::SessionInitiate) {
+		if (sessionManager->getSession(from, payload->getSessionID())) {
+			// TODO: Add tie-break error
+			sendError(from, id, ErrorPayload::Conflict, ErrorPayload::Cancel);
+		}
+		else {
+			sendResponse(from, id, boost::shared_ptr<JinglePayload>());
+			IncomingJingleSession::ref session = boost::make_shared<IncomingJingleSession>(id, payload->getContents());
+			sessionManager->handleIncomingSession(from, session);
+		}
+	}
+	else {
+		JingleSession::ref session = sessionManager->getSession(from, payload->getSessionID());
+		if (session) {
+			session->handleIncomingAction(payload);
+			sendResponse(from, id, boost::shared_ptr<JinglePayload>());
+		}
+		else {
+			// TODO: Add jingle-specific error
+			sendError(from, id, ErrorPayload::ItemNotFound, ErrorPayload::Cancel);
+		}
+	}
+	return true;
+}
+
+}
diff --git a/Swiften/Jingle/JingleResponder.h b/Swiften/Jingle/JingleResponder.h
new file mode 100644
index 0000000..47dc90a
--- /dev/null
+++ b/Swiften/Jingle/JingleResponder.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <Swiften/Queries/SetResponder.h>
+#include <Swiften/Elements/JinglePayload.h>
+
+namespace Swift {
+	class IQRouter;
+	class JingleSessionManager;
+
+	class JingleResponder : public SetResponder<JinglePayload> {
+		public:
+			JingleResponder(JingleSessionManager* sessionManager, IQRouter* router);
+
+		private:
+			virtual bool handleSetRequest(const JID& from, const JID& to, const String& id, boost::shared_ptr<JinglePayload> payload);
+
+		private:
+			JingleSessionManager* sessionManager;
+	};
+}
diff --git a/Swiften/Jingle/JingleSession.cpp b/Swiften/Jingle/JingleSession.cpp
new file mode 100644
index 0000000..3dbb12a
--- /dev/null
+++ b/Swiften/Jingle/JingleSession.cpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swiften/Jingle/JingleSession.h>
+
+#include <boost/smart_ptr/make_shared.hpp>
+
+namespace Swift {
+
+JingleSession::JingleSession(const String& id, const std::vector<JingleContent::ref>& contents) : id(id), contents(contents) {
+
+}
+
+JingleSession::~JingleSession() {
+}
+
+void JingleSession::handleIncomingAction(JinglePayload::ref) {
+}
+
+void JingleSession::terminate(JinglePayload::Reason::Type reason) {
+	JinglePayload::ref payload = boost::make_shared<JinglePayload>(JinglePayload::SessionTerminate, id);
+	payload->setReason(JinglePayload::Reason(reason));
+	//onAction(payload)
+}
+
+
+}
diff --git a/Swiften/Jingle/JingleSession.h b/Swiften/Jingle/JingleSession.h
new file mode 100644
index 0000000..7ed86c2
--- /dev/null
+++ b/Swiften/Jingle/JingleSession.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2011 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/Base/String.h>
+#include <Swiften/Elements/JinglePayload.h>
+#include <Swiften/Elements/JingleContent.h>
+#include <Swiften/Base/foreach.h>
+
+namespace Swift {
+	class JingleSession {
+			friend class JingleResponder;
+		public:
+			typedef boost::shared_ptr<JingleSession> ref;
+
+			JingleSession(const String& id, const std::vector<JingleContent::ref>& contents);
+			virtual ~JingleSession();
+
+			String getID() const {
+				return id;
+			}
+
+			template<typename T>
+			JingleContent::ref getContentWithDescription() const {
+				foreach (JingleContent::ref content, contents) {
+					if (content->getDescription<T>()) {
+						return content;
+					}
+				}
+				return JingleContent::ref();
+			}
+
+			const std::vector<JingleContent::ref> getContents() const {
+				return contents;
+			}
+
+			void terminate(JinglePayload::Reason::Type reason);
+
+		private:
+			void handleIncomingAction(JinglePayload::ref);
+
+		private:
+			String id;
+			std::vector<JingleContent::ref> contents;
+	};
+}
diff --git a/Swiften/Jingle/JingleSessionManager.cpp b/Swiften/Jingle/JingleSessionManager.cpp
new file mode 100644
index 0000000..d8630cc
--- /dev/null
+++ b/Swiften/Jingle/JingleSessionManager.cpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2011 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swiften/Jingle/JingleSessionManager.h>
+#include <Swiften/Jingle/JingleResponder.h>
+#include <Swiften/Jingle/IncomingJingleSessionHandler.h>
+
+namespace Swift {
+
+JingleSessionManager::JingleSessionManager(IQRouter* router) : router(router) {
+	responder = new JingleResponder(this, router);
+}
+
+JingleSessionManager::~JingleSessionManager() {
+	delete responder;
+}
+
+JingleSession::ref JingleSessionManager::getSession(const JID& jid, const String& id) const {
+	SessionMap::const_iterator i = incomingSessions.find(JIDSession(jid, id));
+	return i != incomingSessions.end() ? i->second : JingleSession::ref();
+}
+
+void JingleSessionManager::addIncomingSessionHandler(IncomingJingleSessionHandler* handler) {
+	incomingSessionHandlers.push_back(handler);
+}
+
+void JingleSessionManager::removeIncomingSessionHandler(IncomingJingleSessionHandler* handler) {
+	incomingSessionHandlers.erase(std::remove(incomingSessionHandlers.begin(), incomingSessionHandlers.end(), handler), incomingSessionHandlers.end());
+}
+
+void JingleSessionManager::handleIncomingSession(const JID& from, IncomingJingleSession::ref session) {
+	incomingSessions.insert(std::make_pair(JIDSession(from, session->getID()), session));
+	foreach (IncomingJingleSessionHandler* handler, incomingSessionHandlers) {
+		if (handler->handleIncomingJingleSession(session)) {
+			return;
+		}
+	}
+	// TODO: Finish session
+}
+
+
+}
diff --git a/Swiften/Jingle/JingleSessionManager.h b/Swiften/Jingle/JingleSessionManager.h
new file mode 100644
index 0000000..ea4199d
--- /dev/null
+++ b/Swiften/Jingle/JingleSessionManager.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2011 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 <map>
+
+#include <Swiften/Base/boost_bsignals.h>
+#include <Swiften/Jingle/IncomingJingleSession.h>
+
+namespace Swift {
+	class IQRouter;
+	class JingleResponder;
+	class IncomingJingleSessionHandler;
+
+	class JingleSessionManager {
+			friend class JingleResponder;
+		public:
+			JingleSessionManager(IQRouter* router);
+			~JingleSessionManager();
+
+			JingleSession::ref getSession(const JID& jid, const String& id) const;
+
+			void addIncomingSessionHandler(IncomingJingleSessionHandler* handler);
+			void removeIncomingSessionHandler(IncomingJingleSessionHandler* handler);
+
+		protected:
+			void handleIncomingSession(const JID& from, IncomingJingleSession::ref);
+
+		private:
+			IQRouter* router;
+			JingleResponder* responder;
+			std::vector<IncomingJingleSessionHandler*> incomingSessionHandlers;
+			struct JIDSession {
+				JIDSession(const JID& jid, const String& session) : jid(jid), session(session) {}
+				bool operator<(const JIDSession& o) const {
+					return jid == o.jid ? session < o.session : jid < o.jid;
+				}
+				JID jid;
+				String session;
+			};
+			typedef std::map<JIDSession, JingleSession::ref> SessionMap;
+			SessionMap incomingSessions;
+	};
+}
diff --git a/Swiften/Jingle/SConscript b/Swiften/Jingle/SConscript
new file mode 100644
index 0000000..c1aadea
--- /dev/null
+++ b/Swiften/Jingle/SConscript
@@ -0,0 +1,11 @@
+Import("swiften_env")
+
+sources = [
+		"IncomingJingleSession.cpp",
+		"IncomingJingleSessionHandler.cpp",
+		"JingleSessionManager.cpp",	
+		"JingleResponder.cpp",
+		"JingleSession.cpp",
+	]
+
+swiften_env.Append(SWIFTEN_OBJECTS = swiften_env.StaticObject(sources))
diff --git a/Swiften/Parser/PayloadParsers/StreamInitiationParser.cpp b/Swiften/Parser/PayloadParsers/StreamInitiationParser.cpp
index 6e1082c..bf36321 100644
--- a/Swiften/Parser/PayloadParsers/StreamInitiationParser.cpp
+++ b/Swiften/Parser/PayloadParsers/StreamInitiationParser.cpp
@@ -36,7 +36,7 @@ void StreamInitiationParser::handleStartElement(const String& element, const Str
 	else if (level == PayloadLevel) {
 		if (element == "file") {
 			inFile = true;
-			currentFile = StreamInitiation::FileInfo();
+			currentFile = StreamInitiationFileInfo();
 			currentFile.name = attributes.getAttribute("name");
 			try {
 				currentFile.size = boost::lexical_cast<int>(attributes.getAttribute("size"));
diff --git a/Swiften/Parser/PayloadParsers/StreamInitiationParser.h b/Swiften/Parser/PayloadParsers/StreamInitiationParser.h
index f01567e..7a44651 100644
--- a/Swiften/Parser/PayloadParsers/StreamInitiationParser.h
+++ b/Swiften/Parser/PayloadParsers/StreamInitiationParser.h
@@ -36,7 +36,7 @@ namespace Swift {
 			FormParser* formParser;
 			bool inFile;
 			bool inFeature;
-			StreamInitiation::FileInfo currentFile;
+			StreamInitiationFileInfo currentFile;
 			String currentText;
 	};
 }
diff --git a/Swiften/SConscript b/Swiften/SConscript
index c325d03..36ebd0c 100644
--- a/Swiften/SConscript
+++ b/Swiften/SConscript
@@ -151,6 +151,7 @@ if env["SCONS_STAGE"] == "build" :
 			"EventLoop",
 			"Parser",
 			"JID",
+			"Jingle",
 			"Disco",
 			"VCards",
 			"Network",
diff --git a/Swiften/Serializer/PayloadSerializers/StreamInitiationSerializer.cpp b/Swiften/Serializer/PayloadSerializers/StreamInitiationSerializer.cpp
index 71702d0..0c7f593 100644
--- a/Swiften/Serializer/PayloadSerializers/StreamInitiationSerializer.cpp
+++ b/Swiften/Serializer/PayloadSerializers/StreamInitiationSerializer.cpp
@@ -35,7 +35,7 @@ String StreamInitiationSerializer::serializePayload(boost::shared_ptr<StreamInit
 	siElement.setAttribute("profile", FILE_TRANSFER_NS);
 
 	if (streamInitiation->getFileInfo()) {
-		StreamInitiation::FileInfo file = *streamInitiation->getFileInfo();
+		StreamInitiationFileInfo file = *streamInitiation->getFileInfo();
 		boost::shared_ptr<XMLElement> fileElement(new XMLElement("file", "http://jabber.org/protocol/si/profile/file-transfer"));
 		fileElement->setAttribute("name", file.name);
 		if (file.size != -1) {
diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/StreamInitiationSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/StreamInitiationSerializerTest.cpp
index 12c8485..e1a13b8 100644
--- a/Swiften/Serializer/PayloadSerializers/UnitTest/StreamInitiationSerializerTest.cpp
+++ b/Swiften/Serializer/PayloadSerializers/UnitTest/StreamInitiationSerializerTest.cpp
@@ -21,7 +21,7 @@ class StreamInitiationSerializerTest : public CppUnit::TestFixture{
 		void testSerialize_Request() {
 			StreamInitiationSerializer testling;
 			boost::shared_ptr<StreamInitiation> streamInitiation(new StreamInitiation());
-			StreamInitiation::FileInfo fileInfo("test.txt", "This is info about the file.", 1022);
+			StreamInitiationFileInfo fileInfo("test.txt", "This is info about the file.", 1022);
 			streamInitiation->setID("a0");
 			streamInitiation->setFileInfo(fileInfo);
 			streamInitiation->addProvidedMethod("http://jabber.org/protocol/bytestreams");
-- 
cgit v0.10.2-6-g49f6