From dc259819a687fa9a6f9007ed15b443f737c5d473 Mon Sep 17 00:00:00 2001 From: dknn 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 #include #include +#include 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 + +#include +#include +#include +#include +#include +#include + +#include +#include + +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 >(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 > > data_; + boost::asio::const_buffer buffer_; +}; + +// ----------------------------------------------------------------------------- + +BoostUDPSocket::BoostUDPSocket(boost::shared_ptr 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 buf = boost::make_shared(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 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(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()), 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()), shared_from_this()); + // } + // else { + // eventLoop->postEvent(boost::bind(boost::ref(onDisconnected), WriteError), shared_from_this()); + // } + + boost::lock_guard 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 +#include +//#include + +#include +#include +#include +#include + +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 { + public: + typedef boost::shared_ptr ref; + + virtual ~BoostUDPSocket(); + + static ref create(boost::shared_ptr 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 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 ioService; + boost::asio::ip::udp::socket socket_; + boost::shared_ptr 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 + +#include + +namespace Swift { + +BoostUDPSocketFactory::BoostUDPSocketFactory(boost::shared_ptr ioService, EventLoop* eventLoop) : ioService(ioService), eventLoop(eventLoop) { +} + +BoostUDPSocketFactory::~BoostUDPSocketFactory() +{ +} + +boost::shared_ptr 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 +#include +#include + +namespace Swift { + class BoostUDPSocket; + class EventLoop; + + class BoostUDPSocketFactory : public UDPSocketFactory { + public: + BoostUDPSocketFactory(boost::shared_ptr ioService, EventLoop* eventLoop); + virtual ~BoostUDPSocketFactory(); + + virtual boost::shared_ptr createUDPSocket(); + + private: + boost::shared_ptr 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(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 +#include #include #include @@ -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 +#include + +namespace Swift { + class EventLoop; + class HostAddressPort; + + class UDPSocket { + public: + typedef boost::shared_ptr 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)> onDataRead; + boost::signal 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 + +namespace Swift { + class UDPSocket; + + class UDPSocketFactory { + public: + virtual ~UDPSocketFactory(); + + virtual boost::shared_ptr createUDPSocket() = 0; + }; +} -- cgit v0.10.2-6-g49f6