From dc259819a687fa9a6f9007ed15b443f737c5d473 Mon Sep 17 00:00:00 2001
From: dknn <yoann.blein@free.fr>
Date: Sun, 8 Jul 2012 22:23:27 +0200
Subject: Udp stuff


diff --git a/Swiften/Network/BoostNetworkFactories.cpp b/Swiften/Network/BoostNetworkFactories.cpp
index 488e519..0930075 100644
--- a/Swiften/Network/BoostNetworkFactories.cpp
+++ b/Swiften/Network/BoostNetworkFactories.cpp
@@ -14,6 +14,7 @@
 #include <Swiften/Network/NullNATTraverser.h>
 #include <Swiften/TLS/PlatformTLSFactories.h>
 #include <Swiften/Network/PlatformProxyProvider.h>
+#include <Swiften/Network/BoostUDPSocketFactory.h>
 
 namespace Swift {
 
@@ -30,6 +31,9 @@ BoostNetworkFactories::BoostNetworkFactories(EventLoop* eventLoop) : eventLoop(e
 	xmlParserFactory = new PlatformXMLParserFactory();
 	tlsFactories = new PlatformTLSFactories();
 	proxyProvider = new PlatformProxyProvider();
+#ifdef SWIFT_EXPERIMENTAL_FT
+	udpSocketFactory = new BoostUDPSocketFactory(ioServiceThread.getIOService(), eventLoop);
+#endif
 }
 
 BoostNetworkFactories::~BoostNetworkFactories() {
@@ -41,6 +45,9 @@ BoostNetworkFactories::~BoostNetworkFactories() {
 	delete domainNameResolver;
 	delete connectionFactory;
 	delete timerFactory;
+#ifdef SWIFT_EXPERIMENTAL_FT
+	delete udpSocketFactory;
+#endif
 }
 
 TLSContextFactory* BoostNetworkFactories::getTLSContextFactory() const {
diff --git a/Swiften/Network/BoostNetworkFactories.h b/Swiften/Network/BoostNetworkFactories.h
index 1968acd..2cca6dd 100644
--- a/Swiften/Network/BoostNetworkFactories.h
+++ b/Swiften/Network/BoostNetworkFactories.h
@@ -58,6 +58,11 @@ namespace Swift {
 				return eventLoop;
 			}
 
+			virtual UDPSocketFactory* getUDPSocketFactory() const {
+				return udpSocketFactory;
+			}
+
+
 		private:
 			BoostIOServiceThread ioServiceThread;
 			TimerFactory* timerFactory;
@@ -69,5 +74,6 @@ namespace Swift {
 			PlatformTLSFactories* tlsFactories;
 			ProxyProvider* proxyProvider;
 			EventLoop* eventLoop;
+			UDPSocketFactory* udpSocketFactory;
 	};
 }
diff --git a/Swiften/Network/BoostUDPSocket.cpp b/Swiften/Network/BoostUDPSocket.cpp
new file mode 100644
index 0000000..dff941f
--- /dev/null
+++ b/Swiften/Network/BoostUDPSocket.cpp
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2012 Yoann Blein
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include <Swiften/Network/BoostUDPSocket.h>
+
+#include <Swiften/Base/Log.h>
+#include <Swiften/Base/Algorithm.h>
+#include <Swiften/EventLoop/EventLoop.h>
+#include <Swiften/Base/ByteArray.h>
+#include <Swiften/Network/HostAddressPort.h>
+#include <Swiften/Base/SafeAllocator.h>
+
+#include <boost/bind.hpp>
+#include <boost/asio/placeholders.hpp>
+
+namespace Swift {
+
+static const size_t BUFFER_SIZE = 4096;
+
+// -----------------------------------------------------------------------------
+
+// A reference-counted non-modifiable buffer class.
+class SharedBuffer {
+	public:
+		SharedBuffer(const SafeByteArray& data) :
+			data_(new std::vector<char, SafeAllocator<char> >(data.begin(), data.end())),
+			buffer_(boost::asio::buffer(*data_)) {
+		}
+
+		// ConstBufferSequence requirements.
+		typedef boost::asio::const_buffer value_type;
+		typedef const boost::asio::const_buffer* const_iterator;
+		const boost::asio::const_buffer* begin() const { return &buffer_; }
+		const boost::asio::const_buffer* end() const { return &buffer_ + 1; }
+
+	private:
+		boost::shared_ptr< std::vector<char, SafeAllocator<char> > > data_;
+		boost::asio::const_buffer buffer_;
+};
+
+// -----------------------------------------------------------------------------
+
+BoostUDPSocket::BoostUDPSocket(boost::shared_ptr<boost::asio::io_service> ioService, EventLoop* eventLoop) :
+	eventLoop(eventLoop), ioService(ioService), socket_(*ioService), sending_(false)
+{
+}
+
+BoostUDPSocket::~BoostUDPSocket()
+{
+}
+
+void BoostUDPSocket::bind(int port)
+{
+	if (!socket_.is_open())
+		socket_.open(boost::asio::ip::udp::v4());
+	socket_.bind(boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), port));
+}
+
+void BoostUDPSocket::listen()
+{
+	if (!socket_.is_open())
+		socket_.open(boost::asio::ip::udp::v4());
+	doRead();
+}
+
+void BoostUDPSocket::connect(const HostAddressPort &address)
+{
+	if (!socket_.is_open())
+		socket_.open(boost::asio::ip::udp::v4());
+	socket_.connect(address.toEndpoint()); // TODO: handle errors
+	eventLoop->postEvent(boost::bind(boost::ref(onConnected)), shared_from_this());
+}
+
+void BoostUDPSocket::connectToFirstIncoming()
+{
+	boost::shared_ptr<SafeByteArray> buf = boost::make_shared<SafeByteArray>(1);
+	socket_.async_receive_from(
+				boost::asio::buffer(*buf),
+				remoteEndpoint_,
+				boost::bind(&BoostUDPSocket::handleFirstRead, shared_from_this(), boost::asio::placeholders::error));
+}
+
+void BoostUDPSocket::close() {
+	boost::system::error_code errorCode;
+	socket_.shutdown(boost::asio::ip::udp::socket::shutdown_send, errorCode);
+	socket_.close();
+}
+
+void BoostUDPSocket::send(const SafeByteArray& data)
+{
+	boost::lock_guard<boost::mutex> lock(sendMutex_);
+	if (!sending_) {
+		sending_ = true;
+		doSend(data);
+	} else {
+		append(sendQueue_, data);
+	}
+}
+
+void BoostUDPSocket::doSend(const SafeByteArray& data)
+{
+	socket_.async_send(SharedBuffer(data), boost::bind(&BoostUDPSocket::handleDataWritten, shared_from_this(), boost::asio::placeholders::error));
+}
+
+void BoostUDPSocket::doRead()
+{
+	readBuffer_ = boost::make_shared<SafeByteArray>(BUFFER_SIZE);
+	socket_.async_receive(
+				boost::asio::buffer(*readBuffer_),
+				boost::bind(&BoostUDPSocket::handleSocketRead, shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
+}
+
+void BoostUDPSocket::handleSocketRead(const boost::system::error_code& error, size_t bytesTransferred)
+{
+	SWIFT_LOG(debug) << "Socket read " << error << std::endl;
+	if (!error) {
+		readBuffer_->resize(bytesTransferred);
+		eventLoop->postEvent(boost::bind(boost::ref(onDataRead), readBuffer_), shared_from_this());
+		doRead();
+	}
+//	else if (/*error == boost::asio::error::eof ||*/ error == boost::asio::error::operation_aborted) {
+//		eventLoop->postEvent(boost::bind(boost::ref(onDisconnected), boost::optional<Error>()), shared_from_this());
+//	}
+//	else {
+//		eventLoop->postEvent(boost::bind(boost::ref(onDisconnected), ReadError), shared_from_this());
+	//	}
+}
+
+void BoostUDPSocket::handleFirstRead(const boost::system::error_code &error)
+{
+	if (!error) {
+		socket_.connect(remoteEndpoint_); // TODO: handle errors
+		eventLoop->postEvent(boost::bind(boost::ref(onConnected)), shared_from_this());
+	}
+}
+
+void BoostUDPSocket::handleDataWritten(const boost::system::error_code& error)
+{
+	SWIFT_LOG(debug) << "Data written " << error << std::endl;
+
+	//	if (!error) {
+	//		eventLoop->postEvent(boost::ref(onDataWritten), shared_from_this());
+	//	}
+	//	else if (/*error == boost::asio::error::eof || */error == boost::asio::error::operation_aborted) {
+	//		eventLoop->postEvent(boost::bind(boost::ref(onDisconnected), boost::optional<Error>()), shared_from_this());
+	//	}
+	//	else {
+	//		eventLoop->postEvent(boost::bind(boost::ref(onDisconnected), WriteError), shared_from_this());
+	//	}
+
+	boost::lock_guard<boost::mutex> lock(sendMutex_);
+	if (sendQueue_.empty()) {
+		sending_ = false;
+	} else {
+		doSend(sendQueue_);
+		sendQueue_.clear();
+	}
+}
+
+}
diff --git a/Swiften/Network/BoostUDPSocket.h b/Swiften/Network/BoostUDPSocket.h
new file mode 100644
index 0000000..5cc8b1d
--- /dev/null
+++ b/Swiften/Network/BoostUDPSocket.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2012 Yoann Blein
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+#include <Swiften/Network/UDPSocket.h>
+#include <Swiften/EventLoop/EventOwner.h>
+//#include <Swiften/Base/SafeByteArray.h>
+
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/ip/udp.hpp>
+#include <boost/enable_shared_from_this.hpp>
+#include <boost/thread/mutex.hpp>
+
+namespace boost {
+	class thread;
+	namespace system {
+		class error_code;
+	}
+}
+
+namespace Swift {
+	class EventLoop;
+	class HostAddressPort;
+
+	class BoostUDPSocket : public UDPSocket, public EventOwner, public boost::enable_shared_from_this<BoostUDPSocket> {
+		public:
+			typedef boost::shared_ptr<BoostUDPSocket> ref;
+
+			virtual ~BoostUDPSocket();
+
+			static ref create(boost::shared_ptr<boost::asio::io_service> ioService, EventLoop* eventLoop) {
+				return ref(new BoostUDPSocket(ioService, eventLoop));
+			}
+
+			virtual void bind(int port);
+			virtual void listen();
+			virtual void connect(const HostAddressPort& address);
+			virtual void connectToFirstIncoming();
+			virtual void send(const SafeByteArray& data);
+			virtual void close();
+
+			boost::asio::ip::udp::socket& getSocket() {
+				return socket_;
+			}
+
+		private:
+			BoostUDPSocket(boost::shared_ptr<boost::asio::io_service> ioService, EventLoop* eventLoop);
+
+			void handleSocketRead(const boost::system::error_code& error, size_t bytesTransferred);
+			void handleFirstRead(const boost::system::error_code& error);
+			void handleDataWritten(const boost::system::error_code& error);
+			void doRead();
+			void doSend(const SafeByteArray& data);
+
+		private:
+			EventLoop* eventLoop;
+			boost::shared_ptr<boost::asio::io_service> ioService;
+			boost::asio::ip::udp::socket socket_;
+			boost::shared_ptr<SafeByteArray> readBuffer_;
+			boost::mutex sendMutex_;
+			bool sending_;
+			SafeByteArray sendQueue_;
+			boost::asio::ip::udp::endpoint remoteEndpoint_;
+
+	};
+}
diff --git a/Swiften/Network/BoostUDPSocketFactory.cpp b/Swiften/Network/BoostUDPSocketFactory.cpp
new file mode 100644
index 0000000..6cd6949
--- /dev/null
+++ b/Swiften/Network/BoostUDPSocketFactory.cpp
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2012 Yoann Blein
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include <Swiften/Network/BoostUDPSocketFactory.h>
+
+#include <Swiften/Network/BoostUDPSocket.h>
+
+namespace Swift {
+
+BoostUDPSocketFactory::BoostUDPSocketFactory(boost::shared_ptr<boost::asio::io_service> ioService, EventLoop* eventLoop) : ioService(ioService), eventLoop(eventLoop) {
+}
+
+BoostUDPSocketFactory::~BoostUDPSocketFactory()
+{
+}
+
+boost::shared_ptr<UDPSocket> BoostUDPSocketFactory::createUDPSocket() {
+	return BoostUDPSocket::create(ioService, eventLoop);
+}
+
+}
diff --git a/Swiften/Network/BoostUDPSocketFactory.h b/Swiften/Network/BoostUDPSocketFactory.h
new file mode 100644
index 0000000..50dc588
--- /dev/null
+++ b/Swiften/Network/BoostUDPSocketFactory.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2012 Yoann Blein
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+#include <Swiften/Network/UDPSocketFactory.h>
+#include <boost/asio/io_service.hpp>
+#include <boost/shared_ptr.hpp>
+
+namespace Swift {
+	class BoostUDPSocket;
+	class EventLoop;
+
+	class BoostUDPSocketFactory : public UDPSocketFactory {
+		public:
+			BoostUDPSocketFactory(boost::shared_ptr<boost::asio::io_service> ioService, EventLoop* eventLoop);
+			virtual ~BoostUDPSocketFactory();
+
+			virtual boost::shared_ptr<UDPSocket> createUDPSocket();
+
+		private:
+			boost::shared_ptr<boost::asio::io_service> ioService;
+			EventLoop* eventLoop;
+	};
+}
diff --git a/Swiften/Network/HostAddressPort.cpp b/Swiften/Network/HostAddressPort.cpp
index e2e6012..0540e24 100644
--- a/Swiften/Network/HostAddressPort.cpp
+++ b/Swiften/Network/HostAddressPort.cpp
@@ -21,3 +21,8 @@ HostAddressPort::HostAddressPort(const boost::asio::ip::tcp::endpoint& endpoint)
 std::string HostAddressPort::toString() const {
 	return getAddress().toString() + ":" + boost::lexical_cast<std::string>(getPort());
 }
+
+boost::asio::ip::udp::endpoint HostAddressPort::toEndpoint() const
+{
+	return boost::asio::ip::udp::endpoint(boost::asio::ip::address::from_string(address_.toString()), port_);
+}
diff --git a/Swiften/Network/HostAddressPort.h b/Swiften/Network/HostAddressPort.h
index 68f3a1c..bf97bff 100644
--- a/Swiften/Network/HostAddressPort.h
+++ b/Swiften/Network/HostAddressPort.h
@@ -7,6 +7,7 @@
 #pragma once
 
 #include <boost/asio/ip/tcp.hpp>
+#include <boost/asio/ip/udp.hpp>
 
 #include <Swiften/Base/API.h>
 #include <Swiften/Network/HostAddress.h>
@@ -35,6 +36,8 @@ namespace Swift {
 			
 			std::string toString() const;
 
+			boost::asio::ip::udp::endpoint toEndpoint() const;
+
 		private:
 			HostAddress address_;
 			int port_;
diff --git a/Swiften/Network/NetworkFactories.h b/Swiften/Network/NetworkFactories.h
index c8009a6..eecb95c 100644
--- a/Swiften/Network/NetworkFactories.h
+++ b/Swiften/Network/NetworkFactories.h
@@ -17,6 +17,7 @@ namespace Swift {
 	class CertificateFactory;
 	class ProxyProvider;
 	class EventLoop;
+	class UDPSocketFactory;
 
 	/**
 	 * An interface collecting network factories.
@@ -34,5 +35,6 @@ namespace Swift {
 			virtual TLSContextFactory* getTLSContextFactory() const = 0;
 			virtual ProxyProvider* getProxyProvider() const = 0;
 			virtual EventLoop* getEventLoop() const = 0;
+			virtual UDPSocketFactory* getUDPSocketFactory() const = 0;
 	};
 }
diff --git a/Swiften/Network/SConscript b/Swiften/Network/SConscript
index b742bfe..648e969 100644
--- a/Swiften/Network/SConscript
+++ b/Swiften/Network/SConscript
@@ -73,7 +73,7 @@ else :
 objects = myenv.SwiftenObject(sourceList)
 
 if myenv["experimental"] :
-	# LibNATPMP classes
+  # LibNATPMP classes
 	natpmp_env = myenv.Clone()
 	natpmp_env.Append(CPPDEFINES = natpmp_env["LIBNATPMP_FLAGS"].get("INTERNAL_CPPDEFINES", []))
 	objects += natpmp_env.SwiftenObject([
@@ -89,5 +89,10 @@ if myenv["experimental"] :
 	objects += myenv.SwiftenObject([
 				"PlatformNATTraversalWorker.cpp",
 			])
+	# Screen sharing
+	objects += myenv.SwiftenObject([
+				"BoostUDPSocket.cpp",
+				"BoostUDPSocketFactory.cpp",
+			])
 
 swiften_env.Append(SWIFTEN_OBJECTS = [objects])
diff --git a/Swiften/Network/UDPSocket.h b/Swiften/Network/UDPSocket.h
new file mode 100644
index 0000000..ff324fd
--- /dev/null
+++ b/Swiften/Network/UDPSocket.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2012 Yoann Blein
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+#include <Swiften/Base/boost_bsignals.h>
+#include <Swiften/Base/SafeByteArray.h>
+
+namespace Swift {
+	class EventLoop;
+	class HostAddressPort;
+
+	class UDPSocket {
+		public:
+			typedef boost::shared_ptr<UDPSocket> ref;
+
+			virtual ~UDPSocket() {}
+
+			virtual void bind(int port) = 0;
+			virtual void listen() = 0;
+			virtual void connect(const HostAddressPort& address) = 0;
+			virtual void connectToFirstIncoming() = 0;
+			virtual void send(const SafeByteArray& data) = 0;
+			virtual void close() = 0;
+
+		public:
+			boost::signal<void (boost::shared_ptr<SafeByteArray>)> onDataRead;
+			boost::signal<void ()> onConnected;
+	};
+}
diff --git a/Swiften/Network/UDPSocketFactory.h b/Swiften/Network/UDPSocketFactory.h
new file mode 100644
index 0000000..33dd78c
--- /dev/null
+++ b/Swiften/Network/UDPSocketFactory.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2012 Yoann Blein
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+#include <boost/shared_ptr.hpp>
+
+namespace Swift {
+	class UDPSocket;
+
+	class UDPSocketFactory {
+		public:
+			virtual ~UDPSocketFactory();
+
+			virtual boost::shared_ptr<UDPSocket> createUDPSocket() = 0;
+	};
+}
-- 
cgit v0.10.2-6-g49f6