changeset 381:9fd636045546

Socket: - Switch to template for addresses, - Rename Internet to Ip and add Ipv4 and Ipv6 as helpers, - Split Socket into several different classes.
author David Demelier <markand@malikania.fr>
date Tue, 23 Jun 2015 14:06:37 +0200
parents 06b0f405c58f
children 4b08afed634d
files C++/modules/Socket/Socket.cpp C++/modules/Socket/Socket.h C++/modules/Socket/SocketAddress.cpp C++/modules/Socket/SocketAddress.h C++/modules/Socket/SocketListener.cpp C++/modules/Socket/SocketListener.h C++/modules/Socket/SocketSsl.cpp C++/modules/Socket/SocketSsl.h C++/modules/Socket/SocketTcp.cpp C++/modules/Socket/SocketTcp.h C++/modules/Socket/SocketUdp.cpp C++/modules/Socket/SocketUdp.h C++/tests/Socket/main.cpp CMakeLists.txt
diffstat 14 files changed, 871 insertions(+), 751 deletions(-) [+]
line wrap: on
line diff
--- a/C++/modules/Socket/Socket.cpp	Fri Jun 19 13:56:12 2015 +0200
+++ b/C++/modules/Socket/Socket.cpp	Tue Jun 23 14:06:37 2015 +0200
@@ -26,16 +26,16 @@
  * -------------------------------------------------------- */
 
 #if defined(_WIN32)
-const Socket::Handle Socket::Invalid{INVALID_SOCKET};
-const int Socket::Error{SOCKET_ERROR};
+const Socket::Handle SocketAbstract::Invalid{INVALID_SOCKET};
+const int SocketAbstract::Error{SOCKET_ERROR};
 #else
-const int Socket::Invalid{-1};
-const int Socket::Error{-1};
+const int SocketAbstract::Invalid{-1};
+const int SocketAbstract::Error{-1};
 #endif
 
 #if defined(_WIN32)
 
-std::string Socket::syserror(int errn)
+std::string SocketAbstract::syserror(int errn)
 {
 	LPSTR str = nullptr;
 	std::string errmsg = "Unknown error";
@@ -58,16 +58,14 @@
 
 #else
 
-#include <cerrno>
-
-std::string Socket::syserror(int errn)
+std::string SocketAbstract::syserror(int errn)
 {
 	return strerror(errn);
 }
 
 #endif
 
-std::string Socket::syserror()
+std::string SocketAbstract::syserror()
 {
 #if defined(_WIN32)
 	return syserror(WSAGetLastError());
@@ -81,36 +79,36 @@
  * -------------------------------------------------------- */
 
 SocketError::SocketError(Code code, std::string function)
-	: m_code(code)
-	, m_function(std::move(function))
-	, m_error(Socket::syserror())
+	: m_code{code}
+	, m_function{std::move(function)}
+	, m_error{SocketAbstract::syserror()}
 {
 }
 
 SocketError::SocketError(Code code, std::string function, int error)
-	: m_code(code)
-	, m_function(std::move(function))
-	, m_error(Socket::syserror(error))
+	: m_code{code}
+	, m_function{std::move(function)}
+	, m_error{SocketAbstract::syserror(error)}
 {
 }
 
 SocketError::SocketError(Code code, std::string function, std::string error)
-	: m_code(code)
-	, m_function(std::move(function))
-	, m_error(std::move(error))
+	: m_code{code}
+	, m_function{std::move(function)}
+	, m_error{std::move(error)}
 {
 }
 
 /* --------------------------------------------------------
- * Socket class
+ * SocketAbstract class
  * -------------------------------------------------------- */
 
 #if defined(_WIN32)
-std::mutex Socket::s_mutex;
-std::atomic<bool> Socket::s_initialized{false};
+std::mutex SocketAbstract::s_mutex;
+std::atomic<bool> SocketAbstract::s_initialized{false};
 #endif
 
-Socket::Socket(int domain, int type, int protocol)
+SocketAbstract::SocketAbstract(int domain, int type, int protocol)
 {
 #if defined(_WIN32) && !defined(SOCKET_NO_WSA_INIT)
 	if (!s_initialized) {
@@ -121,13 +119,13 @@
 	m_handle = ::socket(domain, type, protocol);
 
 	if (m_handle == Invalid) {
-		throw SocketError(SocketError::System, "socket");
+		throw SocketError{SocketError::System, "socket"};
 	}
 
 	m_state = SocketState::Opened;
 }
 
-Socket::Socket(Socket &&other) noexcept
+SocketAbstract::SocketAbstract(SocketAbstract &&other) noexcept
 {
 	m_handle = other.m_handle;
 	m_state = other.m_state;
@@ -137,12 +135,14 @@
 	other.m_state = SocketState::Closed;
 }
 
-Socket::~Socket()
+SocketAbstract::~SocketAbstract()
 {
 	close();
 }
 
-std::unique_ptr<SocketAddress> Socket::address() const
+#if 0
+
+std::unique_ptr<SocketAddress> SocketAbstract::address() const
 {
 	socklen_t length;
 	sockaddr_storage ss;
@@ -153,7 +153,11 @@
 	return SocketAddress::decode(ss, length);
 }
 
-void Socket::bind(const std::unique_ptr<SocketAddress> &address)
+#endif
+
+#if 0
+
+void SocketAbstract::bind(const std::unique_ptr<SocketAddress> &address)
 {
 	const auto &sa = address->address();
 	const auto addrlen = address->length();
@@ -165,7 +169,9 @@
 	m_state = SocketState::Bound;
 }
 
-void Socket::close()
+#endif
+
+void SocketAbstract::close()
 {
 	if (m_state != SocketState::Closed) {
 #if defined(_WIN32)
@@ -173,12 +179,12 @@
 #else
 		::close(m_handle);
 #endif
-		m_handle = -1;
+		m_handle = Invalid;
 		m_state = SocketState::Closed;
 	}
 }
 
-void Socket::setBlockMode(bool block)
+void SocketAbstract::setBlockMode(bool block)
 {
 #if defined(O_NONBLOCK) && !defined(_WIN32)
 	int flags;
@@ -194,35 +200,55 @@
 	}
 
 	if (fcntl(m_handle, F_SETFL, flags) == Error) {
-		throw SocketError(SocketError::System, "setBlockMode");
+		throw SocketError{SocketError::System, "setBlockMode"};
 	}
 #else
 	unsigned long flags = (block) ? 0 : 1;
 
 	if (ioctlsocket(m_handle, FIONBIO, &flags) == Error) {
-		throw SocketError(SocketError::System, "setBlockMode");
+		throw SocketError{SocketError::System, "setBlockMode"};
 	}
 #endif
 }
 
-Socket &Socket::operator=(Socket &&other) noexcept
+SocketAbstract &SocketAbstract::operator=(SocketAbstract &&other) noexcept
 {
 	m_handle = other.m_handle;
 	m_state = other.m_state;
 
 	// Invalidate other
-	other.m_handle = -1;
+	other.m_handle = Invalid;
 	other.m_state = SocketState::Closed;
 
 	return *this;
 }
 
-bool operator==(const Socket &s1, const Socket &s2)
+bool operator==(const SocketAbstract &s1, const SocketAbstract &s2)
 {
 	return s1.handle() == s2.handle();
 }
 
-bool operator<(const Socket &s1, const Socket &s2)
+bool operator!=(const SocketAbstract &s1, const SocketAbstract &s2)
+{
+	return s1.handle() != s2.handle();
+}
+
+bool operator<(const SocketAbstract &s1, const SocketAbstract &s2)
 {
 	return s1.handle() < s2.handle();
 }
+
+bool operator>(const SocketAbstract &s1, const SocketAbstract &s2)
+{
+	return s1.handle() > s2.handle();
+}
+
+bool operator<=(const SocketAbstract &s1, const SocketAbstract &s2)
+{
+	return s1.handle() <= s2.handle();
+}
+
+bool operator>=(const SocketAbstract &s1, const SocketAbstract &s2)
+{
+	return s1.handle() >= s2.handle();
+}
--- a/C++/modules/Socket/Socket.h	Fri Jun 19 13:56:12 2015 +0200
+++ b/C++/modules/Socket/Socket.h	Tue Jun 23 14:06:37 2015 +0200
@@ -66,6 +66,10 @@
 
 class SocketAddress;
 
+/* --------------------------------------------------------
+ * Socket types and errors
+ * -------------------------------------------------------- */
+
 /**
  * @class SocketError
  * @brief Base class for sockets error
@@ -159,11 +163,15 @@
 	Timeout				///!< Timeout has occured in a waiting operation
 };
 
+/* --------------------------------------------------------
+ * Generic base sockets
+ * -------------------------------------------------------- */
+
 /**
  * @class Socket
  * @brief Base socket class for socket operations
  */
-class Socket {
+class SocketAbstract {
 public:
 	/* {{{ Portable types */
 
@@ -317,7 +325,7 @@
 	/**
 	 * This create an invalid socket.
 	 */	
-	inline Socket() noexcept
+	inline SocketAbstract() noexcept
 		: m_handle{Invalid}
 		, m_state{SocketState::Closed}
 	{
@@ -328,7 +336,7 @@
 	 *
 	 * @param handle the native descriptor
 	 */
-	inline Socket(Handle handle) noexcept
+	inline SocketAbstract(Handle handle) noexcept
 		: m_handle{handle}
 		, m_state{SocketState::Opened}
 	{
@@ -342,32 +350,24 @@
 	 * @param protocol the protocol
 	 * @throw SocketError on failures
 	 */
-	Socket(int domain, int type, int protocol);
+	SocketAbstract(int domain, int type, int protocol);
 
 	/**
 	 * Copy constructor deleted.
 	 */
-	Socket(const Socket &) = delete;
+	SocketAbstract(const SocketAbstract &) = delete;
 
 	/**
 	 * Transfer ownership from other to this.
 	 *
 	 * @param other the other socket
 	 */
-	Socket(Socket &&other) noexcept;
+	SocketAbstract(SocketAbstract &&other) noexcept;
 
 	/**
 	 * Default destructor.
 	 */
-	virtual ~Socket();
-
-	/**
-	 * Get the local name. This is a wrapper of getsockname().
-	 *
-	 * @return the address
-	 * @throw SocketError on failures
-	 */
-	std::unique_ptr<SocketAddress> address() const;
+	virtual ~SocketAbstract();
 
 	/**
 	 * Set an option for the socket.
@@ -381,11 +381,11 @@
 	inline void set(int level, int name, const Argument &arg)
 	{
 #if defined(_WIN32)
-		if (setsockopt(m_handle, level, name, (Socket::ConstArg)&arg, sizeof (arg)) == Error)
+		if (setsockopt(m_handle, level, name, (SocketAbstract::ConstArg)&arg, sizeof (arg)) == Error)
 #else
-		if (setsockopt(m_handle, level, name, (Socket::ConstArg)&arg, sizeof (arg)) < 0)
+		if (setsockopt(m_handle, level, name, (SocketAbstract::ConstArg)&arg, sizeof (arg)) < 0)
 #endif
-			throw SocketError(SocketError::System, "set");
+			throw SocketError{SocketError::System, "set"};
 	}
 
 	/**
@@ -402,11 +402,11 @@
 		socklen_t size = sizeof (result);
 
 #if defined(_WIN32)
-		if (getsockopt(m_handle, level, name, (Socket::Arg)&desired, &size) == Error)
+		if (getsockopt(m_handle, level, name, (SocketAbstract::Arg)&desired, &size) == Error)
 #else
-		if (getsockopt(m_handle, level, name, (Socket::Arg)&desired, &size) < 0)
+		if (getsockopt(m_handle, level, name, (SocketAbstract::Arg)&desired, &size) < 0)
 #endif
-			throw SocketError(SocketError::System, "get");
+			throw SocketError{SocketError::System, "get"};
 
 		std::memcpy(&result, &desired, size);
 
@@ -435,14 +435,6 @@
 	}
 
 	/**
-	 * Bind to an address.
-	 *
-	 * @param address the address
-	 * @throw SocketError on any error
-	 */
-	void bind(const std::unique_ptr<SocketAddress> &address);
-
-	/**
 	 * Set the blocking mode, if set to false, the socket will be marked
 	 * **non-blocking**.
 	 *
@@ -463,7 +455,7 @@
 	 *
 	 * @return *this
 	 */
-	Socket &operator=(const Socket &) = delete;
+	SocketAbstract &operator=(const SocketAbstract &) = delete;
 
 	/**
 	 * Transfer ownership from other to this. The other socket is left
@@ -472,9 +464,523 @@
 	 * @param other the other socket
 	 * @return this
 	 */
-	Socket &operator=(Socket &&other) noexcept;
+	SocketAbstract &operator=(SocketAbstract &&other) noexcept;
+};
+
+/**
+ * @class Socket
+ * @brief Generic socket implementation
+ *
+ * This class can be used to bind a socket and access its address.
+ *
+ * @see SocketAbstractTcp
+ * @see SocketAbstractUdp
+ */
+template <typename Address>
+class Socket : public SocketAbstract {
+public:
+	/**
+	 * Inherited constructors.
+	 */
+	using SocketAbstract::SocketAbstract;
+
+	/**
+	 * Bind to an address.
+	 *
+	 * @param address the address
+	 * @throw SocketError on any error
+	 */
+	inline void bind(const Address &address)
+	{
+		const auto &sa = address.address();
+		const auto addrlen = address.length();
+
+		if (::bind(m_handle, reinterpret_cast<const sockaddr *>(&sa), addrlen) == Error) {
+			throw SocketError{SocketError::System, "bind"};
+		}
+
+		m_state = SocketState::Bound;
+	}
+
+	/**
+	 * Get the local name. This is a wrapper of getsockname().
+	 *
+	 * @return the address
+	 * @throw SocketError on failures
+	 */
+	inline Address address() const
+	{
+		socklen_t length;
+		sockaddr_storage ss;
+
+		if (getsockname(m_handle, (sockaddr *)&ss, &length) == Error) {
+			throw SocketError{SocketError::System, "getsockname"};
+		}
+
+		return Address(ss, length);
+	}
+};
+
+/* --------------------------------------------------------
+ * TCP Sockets
+ * -------------------------------------------------------- */
+
+/**
+ * @class SocketAbstractTcp
+ * @brief Base class for TCP sockets
+ * @see SocketTcp
+ * @see SocketSsl
+ */
+template <typename Address>
+class SocketAbstractTcp : public Socket<Address> {
+public:
+	/**
+	 * Inherited constructors.
+	 */
+	using Socket<Address>::Socket;
+
+	/**
+	 * Construct a standard TCP socket. The type is automatically
+	 * set to SOCK_STREAM.
+	 *
+	 * @param domain the domain
+	 * @param protocol the protocol
+	 * @throw SocketError on error
+	 */
+	inline SocketAbstractTcp(int domain, int protocol)
+		: Socket<Address>(domain, SOCK_STREAM, protocol)
+	{
+	}
+
+	/**
+	 * Listen for pending connection.
+	 *
+	 * @param max the maximum number
+	 */
+	inline void listen(int max = 128)
+	{
+		if (::listen(Socket<Address>::m_handle, max) == SocketAbstract::Error) {
+			throw SocketError{SocketError::System, "listen"};
+		}
+	}
+
+	/**
+	 * Receive some data.
+	 *
+	 * @param data the destination buffer
+	 * @param length the buffer length
+	 * @throw SocketError on error
+	 */
+	virtual unsigned recv(void *data, unsigned length) = 0;
+
+	/**
+	 * Send some data.
+	 *
+	 * @param data the data buffer
+	 * @param length the buffer length
+	 * @throw SocketError on error
+	 */
+	virtual unsigned send(const void *data, unsigned length) = 0;
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @param count the number of bytes to receive
+	 * @return the string
+	 * @throw SocketError on error
+	 */
+	inline std::string recv(unsigned count)
+	{
+		std::string result;
+
+		result.resize(count);
+		auto n = recv(const_cast<char *>(result.data()), count);
+		result.resize(n);
+
+		return result;
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @param data the string to send
+	 * @return the number of bytes sent
+	 * @throw SocketError on error
+	 */
+	inline unsigned send(const std::string &data)
+	{
+		return send(data.c_str(), data.size());
+	}
+};
+
+/**
+ * @class SocketTcp
+ * @brief Standard implementation of TCP sockets
+ *
+ * This class is the basic implementation of TCP sockets.
+ */
+template <typename Address>
+class SocketTcp : public SocketAbstractTcp<Address> {
+public:
+	/**
+	 * Inherited constructors.
+	 */
+	using SocketAbstractTcp<Address>::SocketAbstractTcp;
+
+	/**
+	 * Connect to an end point.
+	 *
+	 * @param address the address
+	 * @throw SocketError on error
+	 */
+	void connect(const Address &address);
+
+	/**
+	 * Overloaded function.
+	 */
+	inline SocketTcp accept()
+	{
+		Address dummy;
+
+		return accept(dummy);
+	}
+
+	/**
+	 * Accept a clear TCP socket.
+	 *
+	 * @param info the client information
+	 * @return the socket
+	 * @throw SocketError on error
+	 */
+	SocketTcp accept(Address &info);
+
+	/**
+	 * @copydoc SocketAbstractTcp<Address>::recv
+	 */
+	using SocketAbstractTcp<Address>::recv;
+
+	/**
+	 * @copydoc SocketAbstractTcp<Address>::send
+	 */
+	using SocketAbstractTcp<Address>::send;
+
+	/**
+	 * @copydoc SocketAbstractTcp<Address>::recv
+	 */
+	unsigned recv(void *data, unsigned length) override;
+
+	/**
+	 * @copydoc SocketAbstractTcp<Address>::send
+	 */
+	unsigned send(const void *data, unsigned length) override;
 };
 
+template <typename Address>
+void SocketTcp<Address>::connect(const Address &address)
+{
+	if (SocketAbstract::m_state == SocketState::Connected) {
+		return;
+	}
+
+	auto &sa = address.address();
+	auto addrlen = address.length();
+
+	if (::connect(SocketAbstract::m_handle, reinterpret_cast<const sockaddr *>(&sa), addrlen) == SocketAbstract::Error) {
+		/*
+		 * Determine if the error comes from a non-blocking connect that cannot be
+		 * accomplished yet.
+		 */
+#if defined(_WIN32)
+		int error = WSAGetLastError();
+
+		if (error == WSAEWOULDBLOCK) {
+			throw SocketError{SocketError::WouldBlockWrite, "connect", error};
+		}
+
+		throw SocketError{SocketError::System, "connect", error};
+#else
+		if (errno == EINPROGRESS) {
+			throw SocketError{SocketError::WouldBlockWrite, "connect"};
+		}
+
+		throw SocketError{SocketError::System, "connect"};
+#endif
+	}
+
+	SocketAbstract::m_state = SocketState::Connected;
+}
+
+template <typename Address>
+unsigned SocketTcp<Address>::recv(void *data, unsigned dataLen)
+{
+	int nbread;
+
+	nbread = ::recv(SocketAbstract::m_handle, (SocketAbstract::Arg)data, dataLen, 0);
+	if (nbread == SocketAbstract::Error) {
+#if defined(_WIN32)
+		int error = WSAGetLastError();
+
+		if (error == WSAEWOULDBLOCK) {
+			throw SocketError{SocketError::WouldBlockRead, "recv", error};
+		}
+
+		throw SocketError{SocketError::System, "recv", error};
+#else
+		if (errno == EAGAIN || errno == EWOULDBLOCK) {
+			throw SocketError{SocketError::WouldBlockRead, "recv"};
+		}
+
+		throw SocketError{SocketError::System, "recv"};
+#endif
+	} else if (nbread == 0) {
+		SocketAbstract::m_state = SocketState::Closed;
+	}
+
+	return static_cast<unsigned>(nbread);
+}
+
+template <typename Address>
+unsigned SocketTcp<Address>::send(const void *data, unsigned length)
+{
+	int nbsent;
+
+	nbsent = ::send(SocketAbstract::m_handle, (SocketAbstract::ConstArg)data, length, 0);
+	if (nbsent == SocketAbstract::Error) {
+#if defined(_WIN32)
+		int error = WSAGetLastError();
+
+		if (error == WSAEWOULDBLOCK) {
+			throw SocketError{SocketError::WouldBlockWrite, "send", error};
+		}
+
+		throw SocketError{SocketError::System, "send", error};
+#else
+		if (errno == EAGAIN || errno == EWOULDBLOCK) {
+			throw SocketError{SocketError::WouldBlockWrite, "send"};
+		}
+
+		throw SocketError{SocketError::System, "send"};
+#endif
+	}
+
+	return static_cast<unsigned>(nbsent);
+}
+
+template <typename Address>
+SocketTcp<Address> SocketTcp<Address>::accept(Address &info)
+{
+	SocketAbstract::Handle handle;
+
+	// Store the information
+	sockaddr_storage address;
+	socklen_t addrlen;
+
+	addrlen = sizeof (sockaddr_storage);
+	handle = ::accept(SocketAbstract::m_handle, reinterpret_cast<sockaddr *>(&address), &addrlen);
+
+	if (handle == SocketAbstract::Invalid) {
+#if defined(_WIN32)
+		int error = WSAGetLastError();
+
+		if (error == WSAEWOULDBLOCK) {
+			throw SocketError{SocketError::WouldBlockRead, "accept", error};
+		}
+
+		throw SocketError{SocketError::System, "accept", error};
+#else
+		if (errno == EAGAIN || errno == EWOULDBLOCK) {
+			throw SocketError{SocketError::WouldBlockRead, "accept"};
+		}
+
+		throw SocketError{SocketError::System, "accept"};
+#endif
+	}
+
+	info = Address{address, addrlen};
+
+	return SocketTcp{handle};
+}
+
+/* --------------------------------------------------------
+ * UDP Sockets
+ * -------------------------------------------------------- */
+
+/**
+ * @class SocketAbstractUdp
+ * @brief Base class for UDP sockets
+ * @see SocketUdp
+ */
+template <typename Address>
+class SocketAbstractUdp : public Socket<Address> {
+public:
+	/**
+	 * Inherited constructors.
+	 */
+	using Socket<Address>::Socket;
+
+	/**
+	 * Construct a UDP socket. The type is automatically set to SOCK_DGRAM.
+	 *
+	 * @param domain the domain (e.g AF_INET)
+	 * @param protocol the protocol (usually 0)
+	 */
+	inline SocketAbstractUdp(int domain, int protocol)
+		: Socket<Address>(domain, SOCK_DGRAM, protocol)
+	{
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @param data the data
+	 * @param address the address
+	 * @return the number of bytes sent
+	 * @throw SocketError on error
+	 */
+	inline unsigned sendto(const std::string &data, const Address &address)
+	{
+		return sendto(data.c_str(), data.length(), address);
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @param data the data
+	 * @param info the client information
+	 * @return the string
+	 * @throw SocketError on error
+	 */
+	inline std::string recvfrom(unsigned count, Address &info)
+	{
+		std::string result;
+
+		result.resize(count);
+		auto n = recvfrom(const_cast<char *>(result.data()), count, info);
+		result.resize(n);
+
+		return result;
+	}
+
+	/**
+	 * Receive data from an end point.
+	 *
+	 * @param data the destination buffer
+	 * @param length the buffer length
+	 * @param info the client information
+	 * @return the number of bytes received
+	 * @throw SocketError on error
+	 */
+	virtual unsigned recvfrom(void *data, unsigned length, Address &info) = 0;
+
+	/**
+	 * Send data to an end point.
+	 *
+	 * @param data the buffer
+	 * @param length the buffer length
+	 * @param address the client address
+	 * @return the number of bytes sent
+	 * @throw SocketError on error
+	 */
+	virtual unsigned sendto(const void *data, unsigned length, const Address &address) = 0;
+};
+
+/**
+ * @class SocketUdp
+ * @brief Standard implementation of UDP sockets
+ *
+ * This class is the basic implementation of UDP sockets.
+ */
+template <typename Address>
+class SocketUdp : public SocketAbstractUdp<Address> {
+public:
+	/**
+	 * Inherited constructors.
+	 */
+	using SocketAbstractUdp<Address>::SocketAbstractUdp;
+
+	/**
+	 * @copydoc SocketAbstractUdp<Address>::recv
+	 */
+	using SocketAbstractUdp<Address>::recvfrom;
+
+	/**
+	 * @copydoc SocketAbstractUdp<Address>::send
+	 */
+	using SocketAbstractUdp<Address>::sendto;
+
+	/**
+	 * @copydoc SocketAbstractUdp<Address>::recvfrom
+	 */
+	unsigned recvfrom(void *data, unsigned length, Address &info) override;
+
+	/**
+	 * @copydoc SocketAbstractUdp<Address>::sendto
+	 */
+	unsigned sendto(const void *data, unsigned length, const Address &address) override;
+};
+
+template <typename Address>
+unsigned SocketUdp<Address>::recvfrom(void *data, unsigned length, Address &info)
+{
+	int nbread;
+
+	// Store information
+	sockaddr_storage address;
+	socklen_t addrlen;
+
+	addrlen = sizeof (struct sockaddr_storage);
+	nbread = ::recvfrom(SocketAbstract::m_handle, (SocketAbstract::Arg)data, length, 0, (sockaddr *)&address, &addrlen);
+
+	info = Address{address, addrlen};
+
+	if (nbread == SocketAbstract::Error) {
+#if defined(_WIN32)
+		int error = WSAGetLastError();
+
+		if (error == WSAEWOULDBLOCK) {
+			throw SocketError{SocketError::WouldBlockRead, "recvfrom", error};
+		}
+
+		throw SocketError{SocketError::System, "recvfrom", error};
+#else
+		if (errno == EAGAIN || errno == EWOULDBLOCK) {
+			throw SocketError{SocketError::WouldBlockRead, "recvfrom"};
+		}
+
+		throw SocketError{SocketError::System, "recvfrom"};
+#endif
+	}
+
+	return static_cast<unsigned>(nbread);
+}
+
+template <typename Address>
+unsigned SocketUdp<Address>::sendto(const void *data, unsigned length, const Address &info)
+{
+	int nbsent;
+
+	nbsent = ::sendto(SocketAbstract::m_handle, (SocketAbstract::ConstArg)data, length, 0, (const sockaddr *)&info.address(), info.length());
+	if (nbsent == SocketAbstract::Error) {
+#if defined(_WIN32)
+		int error = WSAGetLastError();
+
+		if (error == WSAEWOULDBLOCK) {
+			throw SocketError{SocketError::WouldBlockWrite, "sendto", error};
+		}
+
+		throw SocketError{SocketError::System, "sendto", error};
+#else
+		if (errno == EAGAIN || errno == EWOULDBLOCK) {
+			throw SocketError{SocketError::WouldBlockWrite, "sendto"};
+		}
+
+		throw SocketError{SocketError::System, "sendto"};
+#endif
+	}
+
+	return static_cast<unsigned>(nbsent);
+}
+
 /**
  * Compare two sockets.
  *
@@ -482,15 +988,51 @@
  * @param s2 the second socket
  * @return true if they equals
  */
-bool operator==(const Socket &s1, const Socket &s2);
+bool operator==(const SocketAbstract &s1, const SocketAbstract &s2);
 
 /**
- * Compare two sockets, ideal for putting in a std::map.
+ * Compare two sockets.
+ *
+ * @param s1 the first socket
+ * @param s2 the second socket
+ * @return true if they are different
+ */
+bool operator!=(const SocketAbstract &s1, const SocketAbstract &s2);
+
+/**
+ * Compare two sockets.
  *
  * @param s1 the first socket
  * @param s2 the second socket
  * @return true if s1 < s2
  */
-bool operator<(const Socket &s1, const Socket &s2);
+bool operator<(const SocketAbstract &s1, const SocketAbstract &s2);
+
+/**
+ * Compare two sockets.
+ *
+ * @param s1 the first socket
+ * @param s2 the second socket
+ * @return true if s1 > s2
+ */
+bool operator>(const SocketAbstract &s1, const SocketAbstract &s2);
+
+/**
+ * Compare two sockets.
+ *
+ * @param s1 the first socket
+ * @param s2 the second socket
+ * @return true if s1 <= s2
+ */
+bool operator<=(const SocketAbstract &s1, const SocketAbstract &s2);
+
+/**
+ * Compare two sockets.
+ *
+ * @param s1 the first socket
+ * @param s2 the second socket
+ * @return true if s1 >= s2
+ */
+bool operator>=(const SocketAbstract &s1, const SocketAbstract &s2);
 
 #endif // !_SOCKET_NG_H_
--- a/C++/modules/Socket/SocketAddress.cpp	Fri Jun 19 13:56:12 2015 +0200
+++ b/C++/modules/Socket/SocketAddress.cpp	Tue Jun 23 14:06:37 2015 +0200
@@ -22,30 +22,13 @@
 #include "Socket.h"
 #include "SocketAddress.h"
 
-std::unique_ptr<SocketAddress> SocketAddress::decode(const struct sockaddr_storage &ss, socklen_t length)
-{
-	switch (ss.ss_family) {
-	case AF_INET:
-	case AF_INET6:
-		return std::make_unique<address::Internet>(ss, length);
-#if !defined(_WIN32)
-	case AF_UNIX:
-		return std::make_unique<address::Unix>(ss, length);
-#endif
-	default:
-		break;
-	}
-
-	throw std::invalid_argument{"not a valid address type"};
-}
-
 namespace address {
 
 /* --------------------------------------------------------
- * Internet implementation
+ * Ip implementation
  * -------------------------------------------------------- */
 
-Internet::Internet(const std::string &host, unsigned port, int domain)
+Ip::Ip(const std::string &host, unsigned port, int domain)
 	: m_domain{domain}
 {
 	if (host == "*") {
@@ -83,7 +66,7 @@
 	}
 }
 
-Internet::Internet(const sockaddr_storage &ss, socklen_t length)
+Ip::Ip(const sockaddr_storage &ss, socklen_t length)
 	: m_domain{ss.ss_family}
 {
 	if (ss.ss_family == AF_INET6) {
@@ -93,21 +76,7 @@
 	}
 }
 
-socklen_t Internet::length() const noexcept
-{
-	return (m_domain == AF_INET6) ? sizeof (struct sockaddr_in6) : sizeof (struct sockaddr_in);
-}
-
-const sockaddr &Internet::address() const noexcept
-{
-	// Can't get a ternary operator to work here.
-	if (m_domain == AF_INET6)
-		return reinterpret_cast<const sockaddr &>(m_sin6);
-
-	return reinterpret_cast<const sockaddr &>(m_sin);
-}
-
-SocketAddressInfo Internet::info() const
+SocketAddressInfo Ip::info() const
 {
 	std::string type = (m_domain == AF_INET6) ? "ipv6" : "ipv4";
 	std::string port = std::to_string(m_domain == AF_INET6 ? ntohs(m_sin6.sin6_port) : ntohs(m_sin.sin_port));
@@ -134,29 +103,19 @@
 
 	// Copy the path
 	memset(m_sun.sun_path, 0, sizeof (m_sun.sun_path));
-	strncpy(m_sun.sun_path, path.c_str(), sizeof (m_sun.sun_path) - 1);
+	strncpy(m_sun.sun_path, m_path.c_str(), sizeof (m_sun.sun_path) - 1);
 
 	// Set the parameters
 	m_sun.sun_family = AF_UNIX;
 }
 
-Unix::Unix(const sockaddr_storage &ss, socklen_t)
-{
-	m_path = reinterpret_cast<const struct sockaddr_un &>(ss).sun_path;
-}
-
-socklen_t Unix::length() const noexcept
+Unix::Unix(const sockaddr_storage &ss, socklen_t length)
 {
-#if defined(SOCKET_HAVE_SUN_LEN)
-	return SUN_LEN(m_sun);
-#else
-	return sizeof (m_sun);
-#endif
-}
+	std::memcpy(&m_sun, &ss, length);
 
-const sockaddr &Unix::address() const noexcept
-{
-	return reinterpret_cast<const sockaddr &>(m_sun);
+	if (ss.ss_family == AF_UNIX) {
+		m_path = reinterpret_cast<const sockaddr_un &>(m_sun).sun_path;
+	}
 }
 
 SocketAddressInfo Unix::info() const
--- a/C++/modules/Socket/SocketAddress.h	Fri Jun 19 13:56:12 2015 +0200
+++ b/C++/modules/Socket/SocketAddress.h	Tue Jun 23 14:06:37 2015 +0200
@@ -29,7 +29,6 @@
  *			  compute the address size for a Unix address. Otherwise, sizeof is used.
  */
 
-
 #include <memory>
 #include <string>
 #include <unordered_map>
@@ -44,7 +43,6 @@
 #  include <netinet/in.h>
 #endif
 
-
 /**
  * Generic information table for an address.
  */
@@ -63,16 +61,6 @@
 class SocketAddress {
 public:
 	/**
-	 * Decode an address into the appropriate object. Useful for recvfrom, accept.
-	 *
-	 * @param ss the storage address
-	 * @param length the address length
-	 * @return the real object
-	 * @throw std::invalid_argument on error
-	 */
-	static std::unique_ptr<SocketAddress> decode(const struct sockaddr_storage &ss, socklen_t length);
-
-	/**
 	 * Default constructor.
 	 */
 	SocketAddress() = default;
@@ -81,39 +69,18 @@
 	 * Default destructor.
 	 */
 	virtual ~SocketAddress() = default;
-
-	/**
-	 * Get the address length
-	 *
-	 * @return the length
-	 */
-	virtual socklen_t length() const noexcept = 0;
-
-	/**
-	 * Get the address.
-	 *
-	 * @return the address
-	 */
-	virtual const sockaddr &address() const noexcept = 0;
-
-	/**
-	 * Get the information about the address.
-	 *
-	 * @return the information
-	 */
-	virtual SocketAddressInfo info() const = 0;
 };
 
 namespace address {
 
 /**
- * @class Internet
+ * @class Ip
  * @brief internet protocol connect class
  *
  * Create a connect address for internet protocol,
  * using getaddrinfo(3).
  */
-class Internet : public SocketAddress {
+class Ip : public SocketAddress {
 private:
 	union {
 		struct sockaddr_in m_sin;
@@ -124,6 +91,11 @@
 
 public:
 	/**
+	 * Default constructor.
+	 */
+	Ip() = default;
+
+	/**
 	 * Create an IPv4 or IPV6 end point.
 	 *
 	 * @param host the hostname
@@ -131,7 +103,7 @@
 	 * @param domain AF_INET or AF_INET6
 	 * @throw SocketError on error
 	 */
-	Internet(const std::string &host, unsigned port, int domain);
+	Ip(const std::string &host, unsigned port, int domain);
 
 	/**
 	 * Construct an internet address from a storage address.
@@ -139,22 +111,68 @@
 	 * @param ss the storage
 	 * @param length the length
 	 */
-	Internet(const struct sockaddr_storage &ss, socklen_t length);
+	Ip(const sockaddr_storage &ss, socklen_t length);
 
 	/**
 	 * @copydoc SocketAddress::length
 	 */
-	socklen_t length() const noexcept override;
+	socklen_t length() const noexcept
+	{
+		return (m_domain == AF_INET6) ? sizeof (sockaddr_in6) : sizeof (sockaddr_in);
+	}
 
 	/**
 	 * @copydoc SocketAddress::address
 	 */
-	const sockaddr &address() const noexcept override;
+	const sockaddr &address() const noexcept
+	{
+		// Can't get a ternary operator to work here.
+		if (m_domain == AF_INET6)
+			return reinterpret_cast<const sockaddr &>(m_sin6);
+
+		return reinterpret_cast<const sockaddr &>(m_sin);
+	}
 
 	/**
 	 * @copydoc SocketAddress::info
 	 */
-	SocketAddressInfo info() const override;
+	SocketAddressInfo info() const;
+};
+
+class Ipv6 : public Ip {
+public:
+	/**
+	 * Default constructor.
+	 */
+	Ipv6() = default;
+
+	inline Ipv6(const sockaddr_storage &ss, socklen_t length)
+		: Ip(ss, length)
+	{
+	}
+
+	inline Ipv6(const std::string &host, unsigned port)
+		: Ip(host, port, AF_INET6)
+	{
+	}
+};
+
+class Ipv4 : public Ip {
+public:
+	/**
+	 * Default constructor.
+	 */
+	Ipv4() = default;
+
+	inline Ipv4(const sockaddr_storage &ss, socklen_t length)
+		: Ip(ss, length)
+	{
+	}
+
+	inline Ipv4(const std::string &host, unsigned port)
+		: Ip(host, port, AF_INET)
+	{
+	}
 };
 
 #if !defined(_WIN32)
@@ -171,6 +189,8 @@
 	std::string m_path;
 
 public:
+	Unix() = default;
+
 	/**
 	 * Construct an address to a path.
 	 *
@@ -185,25 +205,35 @@
 	 * @param ss the storage
 	 * @param length the length
 	 */
-	Unix(const struct sockaddr_storage &ss, socklen_t length);
+	Unix(const sockaddr_storage &ss, socklen_t length);
 
 	/**
 	 * @copydoc SocketAddress::length
 	 */
-	socklen_t length() const noexcept override;
+	inline socklen_t length() const noexcept
+	{
+#if defined(SOCKET_HAVE_SUN_LEN)
+		return SUN_LEN(&m_sun);
+#else
+		return sizeof (m_sun);
+#endif
+	}
 
 	/**
 	 * @copydoc SocketAddress::address
 	 */
-	const sockaddr &address() const noexcept override;
+	inline const sockaddr &address() const noexcept
+	{
+		return reinterpret_cast<const sockaddr &>(m_sun);
+	}
 
 	/**
 	 * @copydoc SocketAddress::info
 	 */
-	SocketAddressInfo info() const override;
+	SocketAddressInfo info() const;
 };
 
-#endif // ! !_WIN32
+#endif // !_WIN32
 
 } // !address
 
--- a/C++/modules/Socket/SocketListener.cpp	Fri Jun 19 13:56:12 2015 +0200
+++ b/C++/modules/Socket/SocketListener.cpp	Tue Jun 23 14:06:37 2015 +0200
@@ -36,7 +36,7 @@
 	FD_ZERO(&readset);
 	FD_ZERO(&writeset);
 
-	Socket::Handle max = 0;
+	SocketAbstract::Handle max = 0;
 
 	for (const auto &s : table) {
 		if (s.second.second & SocketListener::Read) {
@@ -58,7 +58,7 @@
 	towait = (ms < 0) ? nullptr : &maxwait;
 
 	auto error = ::select(max + 1, &readset, &writeset, nullptr, towait);
-	if (error == Socket::Error) {
+	if (error == SocketAbstract::Error) {
 		throw SocketError(SocketError::System, "select");
 	}
 	if (error == 0) {
@@ -69,10 +69,10 @@
 
 	for (auto &c : table) {
 		if (FD_ISSET(c.first, &readset)) {
-			sockets.push_back(SocketStatus{c.second.first, SocketListener::Read});
+			sockets.push_back(SocketStatus{*c.second.first, SocketListener::Read});
 		}
 		if (FD_ISSET(c.first, &writeset)) {
-			sockets.push_back(SocketStatus{c.second.first, SocketListener::Write});
+			sockets.push_back(SocketStatus{*c.second.first, SocketListener::Write});
 		}
 	}
 
@@ -127,23 +127,23 @@
 	return flags;
 }
 
-void Poll::set(const SocketTable &, const std::shared_ptr<Socket> s, int flags, bool add)
+void Poll::set(const SocketTable &, SocketAbstract &s, int flags, bool add)
 {
 	if (add) {
-		m_fds.push_back(pollfd{s->handle(), topoll(flags), 0});
+		m_fds.push_back(pollfd{s.handle(), topoll(flags), 0});
 	} else {
 		auto it = std::find_if(m_fds.begin(), m_fds.end(), [&] (const struct pollfd &pfd) {
-			return pfd.fd == s->handle();
+			return pfd.fd == s.handle();
 		});
 
 		it->events |= topoll(flags);
 	}
 }
 
-void Poll::unset(const SocketTable &, const std::shared_ptr<Socket> s, int flags, bool remove)
+void Poll::unset(const SocketTable &, SocketAbstract &s, int flags, bool remove)
 {
 	auto it = std::find_if(m_fds.begin(), m_fds.end(), [&] (const struct pollfd &pfd) {
-		return pfd.fd == s->handle();
+		return pfd.fd == s.handle();
 	});
 
 	if (remove) {
@@ -166,7 +166,7 @@
 	std::vector<SocketStatus> sockets;
 	for (auto &fd : m_fds) {
 		if (fd.revents != 0) {
-			sockets.push_back(SocketStatus{table.at(fd.fd).first, toflags(fd.revents)});
+			sockets.push_back(SocketStatus{*table.at(fd.fd).first, toflags(fd.revents)});
 		}
 	}
 
@@ -209,16 +209,16 @@
 	return flags;
 }
 
-void Epoll::update(const std::shared_ptr<Socket> &sc, int op, int flags)
+void Epoll::update(SocketAbstract &sc, int op, int flags)
 {
 	struct epoll_event ev;
 
 	std::memset(&ev, 0, sizeof (struct epoll_event));
 
 	ev.events = flags;
-	ev.data.fd = sc->handle();
+	ev.data.fd = sc.handle();
 
-	if (epoll_ctl(m_handle, op, sc->handle(), &ev) < 0) {
+	if (epoll_ctl(m_handle, op, sc.handle(), &ev) < 0) {
 		throw SocketError{SocketError::System, "epoll_ctl"};
 	}
 }
@@ -239,7 +239,7 @@
 /*
  * Add a new epoll_event or just update it.
  */
-void Epoll::set(const SocketTable &, const std::shared_ptr<Socket> &sc, int flags, bool add)
+void Epoll::set(const SocketTable &, SocketAbstract &sc, int flags, bool add)
 {
 	update(sc, add ? EPOLL_CTL_ADD : EPOLL_CTL_MOD, toepoll(flags));
 
@@ -256,13 +256,13 @@
  * So we put the same flags that are currently effective and remove the
  * requested one.
  */
-void Epoll::unset(const SocketTable &table, const std::shared_ptr<Socket> &sc, int flags, bool remove)
+void Epoll::unset(const SocketTable &table, SocketAbstract &sc, int flags, bool remove)
 {
 	if (remove) {
 		update(sc, EPOLL_CTL_DEL, 0);
 		m_events.resize(m_events.size() - 1);
 	} else {
-		update(sc, EPOLL_CTL_MOD, table.at(sc->handle()).second & ~(toepoll(flags)));
+		update(sc, EPOLL_CTL_MOD, table.at(sc.handle()).second & ~(toepoll(flags)));
 	}
 }
 
@@ -279,7 +279,7 @@
 	}
 
 	for (int i = 0; i < ret; ++i) {
-		result.push_back(SocketStatus{table.at(m_events[i].data.fd).first, toflags(m_events[i].events)});
+		result.push_back(SocketStatus{*table.at(m_events[i].data.fd).first, toflags(m_events[i].events)});
 	}
 
 	return result;
@@ -306,18 +306,18 @@
 	close(m_handle);
 }
 
-void Kqueue::update(const std::shared_ptr<Socket> &sc, int filter, int flags)
+void Kqueue::update(SocketAbstract &sc, int filter, int flags)
 {
 	struct kevent ev;
 
-	EV_SET(&ev, sc->handle(), filter, flags, 0, 0, nullptr);
+	EV_SET(&ev, sc.handle(), filter, flags, 0, 0, nullptr);
 
 	if (kevent(m_handle, &ev, 1, nullptr, 0, nullptr) < 0) {
 		throw SocketError(SocketError::System, "kevent");
 	}
 }
 
-void Kqueue::set(const SocketTable &, const std::shared_ptr<Socket> &sc, int flags, bool add)
+void Kqueue::set(const SocketTable &, SocketAbstract &sc, int flags, bool add)
 {
 	if (flags & SocketListener::Read) {
 		update(sc, EVFILT_READ, EV_ADD | EV_ENABLE);
@@ -331,7 +331,7 @@
 	}
 }
 
-void Kqueue::unset(const SocketTable &, const std::shared_ptr<Socket> &sc, int flags, bool remove)
+void Kqueue::unset(const SocketTable &, SocketAbstract &sc, int flags, bool remove)
 {
 	if (flags & SocketListener::Read) {
 		update(sc, EVFILT_READ, EV_DELETE);
@@ -364,10 +364,10 @@
 	}
 
 	for (int i = 0; i < nevents; ++i) {
-		std::shared_ptr<Socket> sc = table.at(m_result[i].ident).first;
+		Socket *sc = table.at(m_result[i].ident).first;
 		int flags = m_result[i].filter == EVFILT_READ ? SocketListener::Read : SocketListener::Write;
 
-		sockets.push_back(SocketStatus{sc, flags});
+		sockets.push_back(SocketStatus{*sc, flags});
 	}
 
 	return sockets;
--- a/C++/modules/Socket/SocketListener.h	Fri Jun 19 13:56:12 2015 +0200
+++ b/C++/modules/Socket/SocketListener.h	Tue Jun 23 14:06:37 2015 +0200
@@ -105,15 +105,15 @@
  */
 class SocketStatus {
 public:
-	std::shared_ptr<Socket> socket;		//!< which socket is ready
-	int flags;				//!< the flags
+	SocketAbstract &socket;		//!< which socket is ready
+	int flags;			//!< the flags
 };
 
 /**
  * Table used in the socket listener to store which sockets have been
  * set in which directions.
  */
-using SocketTable = std::map<Socket::Handle, std::pair<std::shared_ptr<Socket>, int>>;
+using SocketTable = std::map<SocketAbstract::Handle, std::pair<SocketAbstract *, int>>;
 
 namespace backend {
 
@@ -136,12 +136,12 @@
 	/**
 	 * No-op, uses the SocketTable directly.
 	 */
-	inline void set(const SocketTable &, const std::shared_ptr<Socket> &, int, bool) noexcept {}
+	inline void set(const SocketTable &, SocketAbstract &, int, bool) noexcept {}
 
 	/**
 	 * No-op, uses the SocketTable directly.
 	 */
-	inline void unset(const SocketTable &, const std::shared_ptr<Socket> &, int, bool) noexcept {}
+	inline void unset(const SocketTable &, SocketAbstract &, int, bool) noexcept {}
 
 	std::vector<SocketStatus> wait(const SocketTable &table, int ms);
 };
@@ -163,8 +163,8 @@
 	int toflags(short &event) const noexcept;
 
 public:
-	void set(const SocketTable &, const std::shared_ptr<Socket> sc, int flags, bool add);
-	void unset(const SocketTable &, const std::shared_ptr<Socket> sc, int flags, bool remove);
+	void set(const SocketTable &, SocketAbstract &sc, int flags, bool add);
+	void unset(const SocketTable &, SocketAbstract &sc, int flags, bool remove);
 	std::vector<SocketStatus> wait(const SocketTable &, int ms);
 
 	/**
@@ -192,13 +192,13 @@
 
 	uint32_t toepoll(int flags) const noexcept;
 	int toflags(uint32_t events) const noexcept;
-	void update(const std::shared_ptr<Socket> &sc, int op, int flags);
+	void update(SocketAbstract &sc, int op, int flags);
 
 public:
 	Epoll();
 	~Epoll();
-	void set(const SocketTable &, const std::shared_ptr<Socket> &sc, int flags, bool add);
-	void unset(const SocketTable &, const std::shared_ptr<Socket> &sc, int flags, bool remove);
+	void set(const SocketTable &, SocketAbstract &sc, int flags, bool add);
+	void unset(const SocketTable &, SocketAbstract &sc, int flags, bool remove);
 	std::vector<SocketStatus> wait(const SocketTable &table, int ms);
 
 	/**
@@ -237,8 +237,8 @@
 	Kqueue();
 	~Kqueue();
 
-	void set(const SocketTable &, const std::shared_ptr<Socket> &sc, int flags, bool add);
-	void unset(const SocketTable &, const std::shared_ptr<Socket> &sc, int flags, bool remove);
+	void set(const SocketTable &, SocketAbstract &sc, int flags, bool add);
+	void unset(const SocketTable &, SocketAbstract &sc, int flags, bool remove);
 	std::vector<SocketStatus> wait(const SocketTable &, int ms);
 
 	/**
@@ -274,7 +274,7 @@
  * # Set
  *
  * @code
- * void set(const SocketTable &, const std::shared_ptr<Socket> &sc, int flags, bool add);
+ * void set(const SocketTable &, const SocketAbstract &sc, int flags, bool add);
  * @endcode
  *
  * This function, takes the socket to be added and the flags. The flags are
@@ -288,7 +288,7 @@
  * # Unset
  *
  * @code
- * void unset(const SocketTable &, const std::shared_ptr<Socket> &sc, int flags, bool remove);
+ * void unset(const SocketTable &, const SocketAbstract &sc, int flags, bool remove);
  * @endcode
  *
  * Like set, this function is only called if the flags are actually set and will
@@ -339,6 +339,8 @@
 	{
 	}
 
+#if 0
+
 	/**
 	 * Create a listener from a list of sockets.
 	 *
@@ -350,6 +352,7 @@
 			set(p.first, p.second);
 		}
 	}
+#endif
 
 	/**
 	 * Get the backend.
@@ -423,7 +426,7 @@
 	 * @param flags (may be OR'ed)
 	 * @throw SocketError if the backend failed to set
 	 */
-	void set(const std::shared_ptr<Socket> &sc, int flags);
+	void set(SocketAbstract &sc, int flags);
 
 	/**
 	 * Unset a socket from the listener, only the flags is removed
@@ -436,7 +439,7 @@
 	 * @param flags the flags (may be OR'ed)
 	 * @see remove
 	 */
-	void unset(const std::shared_ptr<Socket> &sc, int flags);
+	void unset(SocketAbstract &sc, int flags);
 
 	/**
 	 * Remove completely the socket from the listener.
@@ -445,7 +448,7 @@
 	 *
 	 * @param sc the socket
 	 */
-	inline void remove(std::shared_ptr<Socket> sc)
+	inline void remove(SocketAbstract &sc)
 	{
 		unset(sc, Read | Write);
 	}
@@ -519,13 +522,13 @@
 };
 
 template <typename Backend>
-void SocketListenerBase<Backend>::set(const std::shared_ptr<Socket> &sc, int flags)
+void SocketListenerBase<Backend>::set(SocketAbstract &sc, int flags)
 {
 	/* Invalid or useless flags */
 	if (flags == 0 || flags > 0x3)
 		return;
 
-	auto it = m_table.find(sc->handle());
+	auto it = m_table.find(sc.handle());
 
 	/*
 	 * Do not update the table if the backend failed to add
@@ -533,7 +536,7 @@
 	 */
 	if (it == m_table.end()) {
 		m_backend.set(m_table, sc, flags, true);
-		m_table.emplace(sc->handle(), std::make_pair(sc, flags));
+		m_table.emplace(sc.handle(), std::make_pair(std::addressof(sc), flags));
 	} else {
 		if ((flags & Read) && (it->second.second & Read)) {
 			flags &= ~(Read);
@@ -551,9 +554,9 @@
 }
 
 template <typename Backend>
-void SocketListenerBase<Backend>::unset(const std::shared_ptr<Socket> &sc, int flags)
+void SocketListenerBase<Backend>::unset(SocketAbstract &sc, int flags)
 {
-	auto it = m_table.find(sc->handle());
+	auto it = m_table.find(sc.handle());
 
 	/* Invalid or useless flags */
 	if (flags == 0 || flags > 0x3 || it == m_table.end())
--- a/C++/modules/Socket/SocketSsl.cpp	Fri Jun 19 13:56:12 2015 +0200
+++ b/C++/modules/Socket/SocketSsl.cpp	Tue Jun 23 14:06:37 2015 +0200
@@ -16,6 +16,8 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#if 0
+
 #include "SocketAddress.h"
 #include "SocketSsl.h"
 
@@ -165,3 +167,5 @@
 
 	return nbread;
 }
+
+#endif
--- a/C++/modules/Socket/SocketSsl.h	Fri Jun 19 13:56:12 2015 +0200
+++ b/C++/modules/Socket/SocketSsl.h	Tue Jun 23 14:06:37 2015 +0200
@@ -19,6 +19,8 @@
 #ifndef _SOCKET_SSL_NG_H_
 #define _SOCKET_SSL_NG_H_
 
+#if 0
+
 #include <cstdint>
 #include <atomic>
 #include <memory>
@@ -173,4 +175,6 @@
 	using SocketTcp::recv;
 };
 
+#endif
+
 #endif // !_SOCKET_SSL_NG_H_
--- a/C++/modules/Socket/SocketTcp.cpp	Fri Jun 19 13:56:12 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,156 +0,0 @@
-/*
- * SocketTcp.cpp -- portable C++ socket wrappers
- *
- * Copyright (c) 2013, 2014 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "SocketAddress.h"
-#include "SocketTcp.h"
-
-void SocketTcp::listen(int max)
-{
-	if (::listen(m_handle, max) == Error) {
-		throw SocketError(SocketError::System, "listen");
-	}
-}
-
-std::unique_ptr<SocketTcp> SocketTcp::accept()
-{
-	std::unique_ptr<SocketAddress> dummy;
-
-	return accept(dummy);
-}
-
-std::unique_ptr<SocketTcp> SocketTcp::accept(std::unique_ptr<SocketAddress> &info)
-{
-	Socket::Handle handle;
-
-	// Store the information
-	sockaddr_storage address;
-	socklen_t addrlen;
-
-	addrlen = sizeof (sockaddr_storage);
-	handle = ::accept(m_handle, reinterpret_cast<sockaddr *>(&address), &addrlen);
-
-	if (handle == Invalid) {
-#if defined(_WIN32)
-		int error = WSAGetLastError();
-
-		if (error == WSAEWOULDBLOCK) {
-			throw SocketError(SocketError::WouldBlockRead, "accept", error);
-		}
-
-		throw SocketError(SocketError::System, "accept", error);
-#else
-		if (errno == EAGAIN || errno == EWOULDBLOCK) {
-			throw SocketError(SocketError::WouldBlockRead, "accept");
-		}
-
-		throw SocketError(SocketError::System, "accept");
-#endif
-	}
-
-	info = SocketAddress::decode(address, addrlen);
-
-	return std::make_unique<SocketTcp>(handle);
-}
-
-void SocketTcp::connect(const std::unique_ptr<SocketAddress> &address)
-{
-	if (m_state == SocketState::Connected) {
-		return;
-	}
-
-	auto &sa = address->address();
-	auto addrlen = address->length();
-
-	if (::connect(m_handle, reinterpret_cast<const sockaddr *>(&sa), addrlen) == Error) {
-		/*
-		 * Determine if the error comes from a non-blocking connect that cannot be
-		 * accomplished yet.
-		 */
-#if defined(_WIN32)
-		int error = WSAGetLastError();
-
-		if (error == WSAEWOULDBLOCK) {
-			throw SocketError(SocketError::WouldBlockWrite, "connect", error);
-		}
-
-		throw SocketError(SocketError::System, "connect", error);
-#else
-		if (errno == EINPROGRESS) {
-			throw SocketError(SocketError::WouldBlockWrite, "connect");
-		}
-
-		throw SocketError(SocketError::System, "connect");
-#endif
-	}
-
-	m_state = SocketState::Connected;
-}
-
-unsigned SocketTcp::recv(void *data, unsigned dataLen)
-{
-	int nbread;
-
-	nbread = ::recv(m_handle, (Socket::Arg)data, dataLen, 0);
-	if (nbread == Error) {
-#if defined(_WIN32)
-		int error = WSAGetLastError();
-
-		if (error == WSAEWOULDBLOCK) {
-			throw SocketError(SocketError::WouldBlockRead, "recv", error);
-		}
-
-		throw SocketError(SocketError::System, "recv", error);
-#else
-		if (errno == EAGAIN || errno == EWOULDBLOCK) {
-			throw SocketError(SocketError::WouldBlockRead, "recv");
-		}
-
-		throw SocketError(SocketError::System, "recv");
-#endif
-	} else if (nbread == 0) {
-		m_state = SocketState::Closed;
-	}
-
-	return (unsigned)nbread;
-}
-
-unsigned SocketTcp::send(const void *data, unsigned length)
-{
-	int nbsent;
-
-	nbsent = ::send(m_handle, (Socket::ConstArg)data, length, 0);
-	if (nbsent == Error) {
-#if defined(_WIN32)
-		int error = WSAGetLastError();
-
-		if (error == WSAEWOULDBLOCK) {
-			throw SocketError(SocketError::WouldBlockWrite, "send", error);
-		}
-
-		throw SocketError(SocketError::System, "send", error);
-#else
-		if (errno == EAGAIN || errno == EWOULDBLOCK) {
-			throw SocketError(SocketError::WouldBlockWrite, "send");
-		}
-
-		throw SocketError(SocketError::System, "send");
-#endif
-	}
-
-	return (unsigned)nbsent;
-}
--- a/C++/modules/Socket/SocketTcp.h	Fri Jun 19 13:56:12 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,130 +0,0 @@
-/*
- * SocketTcp.h -- portable C++ socket wrappers
- *
- * Copyright (c) 2013, 2014 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _SOCKET_TCP_NG_H_
-#define _SOCKET_TCP_NG_H_
-
-#include <memory>
-
-#include "Socket.h"
-
-/**
- * @class SocketTcp
- * @brief End-user class for TCP sockets
- */
-class SocketTcp : public Socket {
-public:
-	/**
-	 * Inherited constructors.
-	 */
-	using Socket::Socket;
-
-	/**
-	 * Construct a standard TCP socket. The type is automatically
-	 * set to SOCK_STREAM.
-	 *
-	 * @param domain the domain
-	 * @param protocol the protocol
-	 * @throw SocketError on error
-	 */
-	inline SocketTcp(int domain, int protocol)
-		: Socket(domain, SOCK_STREAM, protocol)
-	{
-	}
-
-	/**
-	 * Listen for pending connection.
-	 *
-	 * @param max the maximum number
-	 */
-	virtual void listen(int max = 128);
-
-	/**
-	 * Accept a clear TCP socket without its address
-	 *
-	 * @return the socket
-	 * @throw SocketError on error
-	 */
-	std::unique_ptr<SocketTcp> accept();
-
-	/**
-	 * Accept a clear TCP socket.
-	 *
-	 * @param info the client information
-	 * @return the socket
-	 * @throw SocketError on error
-	 */
-	virtual std::unique_ptr<SocketTcp> accept(std::unique_ptr<SocketAddress> &info);
-
-	/**
-	 * Connect to an end point.
-	 *
-	 * @param address the address
-	 * @throw SocketError on error
-	 */
-	virtual void connect(const std::unique_ptr<SocketAddress> &address);
-
-	/**
-	 * Receive some data.
-	 *
-	 * @param data the destination buffer
-	 * @param length the buffer length
-	 * @throw SocketError on error
-	 */
-	virtual unsigned recv(void *data, unsigned length);
-
-	/**
-	 * Overloaded function.
-	 *
-	 * @param count the number of bytes to receive
-	 * @return the string
-	 * @throw SocketError on error
-	 */
-	inline std::string recv(unsigned count)
-	{
-		std::string result;
-
-		result.resize(count);
-		auto n = recv(const_cast<char *>(result.data()), count);
-		result.resize(n);
-
-		return result;
-	}
-
-	/**
-	 * Send some data.
-	 *
-	 * @param data the data to send
-	 * @param length the data length
-	 */
-	virtual unsigned send(const void *data, unsigned length);
-
-	/**
-	 * Overloaded function.
-	 *
-	 * @param data the string to send
-	 * @return the number of bytes sent
-	 * @throw SocketError on error
-	 */
-	inline unsigned send(const std::string &data)
-	{
-		return send(data.c_str(), data.size());
-	}
-};
-
-#endif // !_SOCKET_TCP_NG_H_
--- a/C++/modules/Socket/SocketUdp.cpp	Fri Jun 19 13:56:12 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,85 +0,0 @@
-/*
- * SocketUdp.cpp -- portable C++ socket wrappers
- *
- * Copyright (c) 2013, 2014 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "SocketAddress.h"
-#include "SocketUdp.h"
-
-SocketUdp::SocketUdp(int domain, int protocol)
-	: Socket(domain, SOCK_DGRAM, protocol)
-{
-}
-
-unsigned SocketUdp::recvfrom(void *data, unsigned length, std::unique_ptr<SocketAddress> &info)
-{
-	int nbread;
-
-	// Store information
-	sockaddr_storage address;
-	socklen_t addrlen;
-
-	addrlen = sizeof (struct sockaddr_storage);
-	nbread = ::recvfrom(m_handle, (Socket::Arg)data, length, 0, (sockaddr *)&address, &addrlen);
-
-	info = SocketAddress::decode(address, addrlen);
-
-	if (nbread == Error) {
-#if defined(_WIN32)
-		int error = WSAGetLastError();
-
-		if (error == WSAEWOULDBLOCK) {
-			throw SocketError(SocketError::WouldBlockRead, "recvfrom", error);
-		}
-
-		throw SocketError(SocketError::System, "recvfrom", error);
-#else
-		if (errno == EAGAIN || errno == EWOULDBLOCK) {
-			throw SocketError(SocketError::WouldBlockRead, "recvfrom");
-		}
-
-		throw SocketError(SocketError::System, "recvfrom");
-#endif
-	}
-
-	return (unsigned)nbread;
-}
-
-unsigned SocketUdp::sendto(const void *data, unsigned length, const std::unique_ptr<SocketAddress> &info)
-{
-	int nbsent;
-
-	nbsent = ::sendto(m_handle, (Socket::ConstArg)data, length, 0, (const sockaddr *)&info->address(), info->length());
-	if (nbsent == Error) {
-#if defined(_WIN32)
-		int error = WSAGetLastError();
-
-		if (error == WSAEWOULDBLOCK) {
-			throw SocketError(SocketError::WouldBlockWrite, "sendto", error);
-		}
-
-		throw SocketError(SocketError::System, "sendto", error);
-#else
-		if (errno == EAGAIN || errno == EWOULDBLOCK) {
-			throw SocketError(SocketError::WouldBlockWrite, "sendto");
-		}
-
-		throw SocketError(SocketError::System, "sendto");
-#endif
-	}
-
-	return (unsigned)nbsent;
-}
--- a/C++/modules/Socket/SocketUdp.h	Fri Jun 19 13:56:12 2015 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-/*
- * SocketUdp.h -- portable C++ socket wrappers
- *
- * Copyright (c) 2013, 2014 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _SOCKET_UDP_NG_H_
-#define _SOCKET_UDP_NG_H_
-
-#include "Socket.h"
-
-/**
- * @class SocketUdp
- * @brief UDP implementation for sockets
- */
-class SocketUdp : public Socket {
-public:
-	/**
-	 * Construct a UDP socket. The type is automatically set to SOCK_DGRAM.
-	 *
-	 * @param domain the domain (e.g AF_INET)
-	 * @param protocol the protocol (usually 0)
-	 */
-	SocketUdp(int domain, int protocol);
-
-	/**
-	 * Overloaded function.
-	 *
-	 * @param data the data
-	 * @param address the address
-	 * @return the number of bytes sent
-	 * @throw SocketError on error
-	 */
-	inline unsigned sendto(const std::string &data, const std::unique_ptr<SocketAddress> &address)
-	{
-		return sendto(data.c_str(), data.length(), address);
-	}
-
-	/**
-	 * Overloaded function.
-	 *
-	 * @param data the data
-	 * @param info the client information
-	 * @return the string
-	 * @throw SocketError on error
-	 */
-	inline std::string recvfrom(unsigned count, std::unique_ptr<SocketAddress> &info)
-	{
-		std::string result;
-
-		result.resize(count);
-		auto n = recvfrom(const_cast<char *>(result.data()), count, info);
-		result.resize(n);
-
-		return result;
-	}
-
-	/**
-	 * Receive data from an end point.
-	 *
-	 * @param data the destination buffer
-	 * @param length the buffer length
-	 * @param info the client information
-	 * @return the number of bytes received
-	 * @throw SocketError on error
-	 */
-	virtual unsigned recvfrom(void *data, unsigned length, std::unique_ptr<SocketAddress> &info);
-
-	/**
-	 * Send data to an end point.
-	 *
-	 * @param data the buffer
-	 * @param length the buffer length
-	 * @param address the client address
-	 * @return the number of bytes sent
-	 * @throw SocketError on error
-	 */
-	virtual unsigned sendto(const void *data, unsigned length, const std::unique_ptr<SocketAddress> &address);
-};
-
-#endif // !_SOCKET_UDP_NG_H_
--- a/C++/tests/Socket/main.cpp	Fri Jun 19 13:56:12 2015 +0200
+++ b/C++/tests/Socket/main.cpp	Tue Jun 23 14:06:37 2015 +0200
@@ -40,8 +40,8 @@
 
 class TcpServerTest : public testing::Test {
 protected:
-	SocketTcp m_server{AF_INET, 0};
-	SocketTcp m_client{AF_INET, 0};
+	SocketTcp<Ipv4> m_server{AF_INET, 0};
+	SocketTcp<Ipv4> m_client{AF_INET, 0};
 
 	std::thread m_tserver;
 	std::thread m_tclient;
@@ -64,7 +64,7 @@
 TEST_F(TcpServerTest, connect)
 {
 	m_tserver = std::thread([this] () {
-		m_server.bind(std::make_unique<Internet>("*", 16000, AF_INET));
+		m_server.bind(Ipv4{"*", 16000});
 
 		ASSERT_EQ(SocketState::Bound, m_server.state());
 
@@ -76,7 +76,7 @@
 	std::this_thread::sleep_for(100ms);
 
 	m_tclient = std::thread([this] () {
-		m_client.connect(std::make_unique<Internet>("127.0.0.1", 16000, AF_INET));
+		m_client.connect(Ipv4{"127.0.0.1", 16000});
 
 		ASSERT_EQ(SocketState::Connected, m_client.state());
 
@@ -87,21 +87,21 @@
 TEST_F(TcpServerTest, io)
 {
 	m_tserver = std::thread([this] () {
-		m_server.bind(std::make_unique<Internet>("*", 16000, AF_INET));
+		m_server.bind(Ipv4{"*", 16000});
 		m_server.listen();
 
 		auto client = m_server.accept();
-		auto msg = client->recv(512);
+		auto msg = client.recv(512);
 
 		ASSERT_EQ("hello world", msg);
 
-		client->send(msg);
+		client.send(msg);
 	});
 
 	std::this_thread::sleep_for(100ms);
 
 	m_tclient = std::thread([this] () {
-		m_client.connect(std::make_unique<Internet>("127.0.0.1", 16000, AF_INET));
+		m_client.connect(Ipv4{"127.0.0.1", 16000});
 		m_client.send("hello world");
 
 		ASSERT_EQ("hello world", m_client.recv(512));
@@ -114,8 +114,8 @@
 
 class UdpServerTest : public testing::Test {
 protected:
-	SocketUdp m_server{AF_INET, 0};
-	SocketUdp m_client{AF_INET, 0};
+	SocketUdp<Ipv4> m_server{AF_INET, 0};
+	SocketUdp<Ipv4> m_client{AF_INET, 0};
 
 	std::thread m_tserver;
 	std::thread m_tclient;
@@ -138,7 +138,7 @@
 TEST_F(UdpServerTest, io)
 {
 	m_tserver = std::thread([this] () {
-		std::unique_ptr<SocketAddress> info = std::make_unique<Internet>("*", 16000, AF_INET);
+		Ipv4 info{"*", 16000};
 
 		m_server.bind(info);
 		auto msg = m_server.recvfrom(512, info);
@@ -152,7 +152,7 @@
 	std::this_thread::sleep_for(100ms);
 
 	m_tclient = std::thread([this] () {
-		std::unique_ptr<SocketAddress> info = std::make_unique<Internet>("127.0.0.1", 16000, AF_INET);
+		Ipv4 info{"127.0.0.1", 16000};
 
 		m_client.sendto("hello world", info);
 
@@ -172,33 +172,40 @@
 	bool m_added{false};
 	int m_flags{0};
 
-	inline void set(const SocketTable &, const std::shared_ptr<Socket> &sc, int flags, bool add) noexcept
+	inline void set(const SocketTable &, SocketAbstract &sc, int flags, bool add) noexcept
 	{
 		m_callcount ++;
 		m_added = add;
 		m_flags |= flags;
 	}
 
-	inline void unset(const SocketTable &, const std::shared_ptr<Socket> &, int, bool) noexcept {}
+	inline void unset(const SocketTable &, SocketAbstract &, int, bool) noexcept
+	{
+	}
+
 	std::vector<SocketStatus> wait(const SocketTable &table, int ms) {}
 };
 
 class TestBackendSetFail {
 public:
-	inline void set(const SocketTable &, const std::shared_ptr<Socket> &, int, bool)
+	inline void set(const SocketTable &, SocketAbstract &, int, bool)
 	{
 		throw "fail";
 	}
 
-	inline void unset(const SocketTable &, const std::shared_ptr<Socket> &, int, bool) noexcept {}
+	inline void unset(const SocketTable &, const SocketAbstract &, int, bool) noexcept
+	{
+	}
+
 	std::vector<SocketStatus> wait(const SocketTable &table, int ms) {}
 };
 
 TEST(ListenerSet, initialAdd)
 {
 	SocketListenerBase<TestBackendSet> listener;
+	SocketAbstract s{0};
 
-	listener.set(std::make_shared<Socket>(0), SocketListener::Read);
+	listener.set(s, SocketListener::Read);
 
 	ASSERT_EQ(1U, listener.size());
 	ASSERT_EQ(1, listener.backend().m_callcount);
@@ -209,10 +216,10 @@
 TEST(ListenerSet, readThenWrite)
 {
 	SocketListenerBase<TestBackendSet> listener;
-	std::shared_ptr<Socket> sc = std::make_shared<Socket>(0);
+	SocketAbstract s{0};
 
-	listener.set(sc, SocketListener::Read);
-	listener.set(sc, SocketListener::Write);
+	listener.set(s, SocketListener::Read);
+	listener.set(s, SocketListener::Write);
 
 	ASSERT_EQ(1U, listener.size());
 	ASSERT_EQ(2, listener.backend().m_callcount);
@@ -223,9 +230,9 @@
 TEST(ListenerSet, allOneShot)
 {
 	SocketListenerBase<TestBackendSet> listener;
-	std::shared_ptr<Socket> sc = std::make_shared<Socket>(0);
+	SocketAbstract s{0};
 
-	listener.set(sc, SocketListener::Read | SocketListener::Write);
+	listener.set(s, SocketListener::Read | SocketListener::Write);
 
 	ASSERT_EQ(1U, listener.size());
 	ASSERT_EQ(1, listener.backend().m_callcount);
@@ -236,10 +243,10 @@
 TEST(ListenerSet, readTwice)
 {
 	SocketListenerBase<TestBackendSet> listener;
-	std::shared_ptr<Socket> sc = std::make_shared<Socket>(0);
+	SocketAbstract s{0};
 
-	listener.set(sc, SocketListener::Read);
-	listener.set(sc, SocketListener::Read);
+	listener.set(s, SocketListener::Read);
+	listener.set(s, SocketListener::Read);
 
 	ASSERT_EQ(1U, listener.size());
 	ASSERT_EQ(1, listener.backend().m_callcount);
@@ -250,9 +257,10 @@
 TEST(ListenerSet, failure)
 {
 	SocketListenerBase<TestBackendSetFail> listener;
+	SocketAbstract s{0};
 
 	try {
-		listener.set(std::make_shared<Socket>(0), SocketListener::Read);
+		listener.set(s, SocketListener::Read);
 		FAIL() << "exception expected";
 	} catch (...) {
 	}
@@ -271,41 +279,49 @@
 	int m_flags{0};
 	bool m_removal{false};
 
-	inline void set(const SocketTable &, const std::shared_ptr<Socket> &, int flags, bool) noexcept
+	inline void set(const SocketTable &, SocketAbstract &, int flags, bool) noexcept
 	{
 		m_isset = true;
 		m_flags |= flags;
 	}
 
-	inline void unset(const SocketTable &, const std::shared_ptr<Socket> &, int flags, bool remove) noexcept
+	inline void unset(const SocketTable &, SocketAbstract &, int flags, bool remove) noexcept
 	{
 		m_isunset = true;
 		m_flags &= ~(flags);
 		m_removal = remove;
 	}
 
-	std::vector<SocketStatus> wait(const SocketTable &table, int ms) {}
+	std::vector<SocketStatus> wait(const SocketTable &, int) noexcept
+	{
+		return {};
+	}
 };
 
 class TestBackendUnsetFail {
 public:
-	inline void set(const SocketTable &, const std::shared_ptr<Socket> &, int, bool) noexcept {}
+	inline void set(const SocketTable &, SocketAbstract &, int, bool) noexcept
+	{
+	}
 
-	inline void unset(const SocketTable &, const std::shared_ptr<Socket> &, int, bool)
+	inline void unset(const SocketTable &, SocketAbstract &, int, bool)
 	{
 		throw "fail";
 	}
 
-	std::vector<SocketStatus> wait(const SocketTable &table, int ms) {}
+	std::vector<SocketStatus> wait(const SocketTable &, int)
+	{
+		return {};
+	}
 };
 
 TEST(ListenerUnsetRemove, unset)
 {
 	SocketListenerBase<TestBackendUnset> listener;
-	std::shared_ptr<Socket> sc = std::make_shared<Socket>(0);
+	SocketAbstract s{0};
 
-	listener.set(sc, SocketListener::Read);
-	listener.unset(sc, SocketListener::Read);
+	listener.set(s, SocketListener::Read);
+	listener.unset(s, SocketListener::Read);
 
 	ASSERT_EQ(0U, listener.size());
 	ASSERT_TRUE(listener.backend().m_isset);
@@ -317,10 +333,10 @@
 TEST(ListenerUnsetRemove, unsetOne)
 {
 	SocketListenerBase<TestBackendUnset> listener;
-	std::shared_ptr<Socket> sc = std::make_shared<Socket>(0);
+	SocketAbstract s{0};
 
-	listener.set(sc, SocketListener::Read | SocketListener::Write);
-	listener.unset(sc, SocketListener::Read);
+	listener.set(s, SocketListener::Read | SocketListener::Write);
+	listener.unset(s, SocketListener::Read);
 
 	ASSERT_EQ(1U, listener.size());
 	ASSERT_TRUE(listener.backend().m_isset);
@@ -332,11 +348,11 @@
 TEST(ListenerUnsetRemove, unsetAll)
 {
 	SocketListenerBase<TestBackendUnset> listener;
-	std::shared_ptr<Socket> sc = std::make_shared<Socket>(0);
+	SocketAbstract s{0};
 
-	listener.set(sc, SocketListener::Read | SocketListener::Write);
-	listener.unset(sc, SocketListener::Read);
-	listener.unset(sc, SocketListener::Write);
+	listener.set(s, SocketListener::Read | SocketListener::Write);
+	listener.unset(s, SocketListener::Read);
+	listener.unset(s, SocketListener::Write);
 
 	ASSERT_EQ(0U, listener.size());
 	ASSERT_TRUE(listener.backend().m_isset);
@@ -348,10 +364,10 @@
 TEST(ListenerUnsetRemove, remove)
 {
 	SocketListenerBase<TestBackendUnset> listener;
-	std::shared_ptr<Socket> sc = std::make_shared<Socket>(0);
+	SocketAbstract s{0};
 
-	listener.set(sc, SocketListener::Read | SocketListener::Write);
-	listener.remove(sc);
+	listener.set(s, SocketListener::Read | SocketListener::Write);
+	listener.remove(s);
 
 	ASSERT_EQ(0U, listener.size());
 	ASSERT_TRUE(listener.backend().m_isset);
@@ -363,12 +379,12 @@
 TEST(ListenerUnsetRemove, failure)
 {
 	SocketListenerBase<TestBackendUnsetFail> listener;
-	std::shared_ptr<Socket> sc = std::make_shared<Socket>(0);
+	SocketAbstract s{0};
 
-	listener.set(sc, SocketListener::Read | SocketListener::Write);
+	listener.set(s, SocketListener::Read | SocketListener::Write);
 
 	try {
-		listener.remove(sc);
+		listener.remove(s);
 		FAIL() << "exception expected";
 	} catch (...) {
 	}
@@ -384,20 +400,20 @@
 class ListenerTest : public testing::Test {
 protected:
 	SocketListenerBase<backend::Select> m_listener;
-	std::shared_ptr<SocketTcp> m_masterTcp;
-	std::shared_ptr<SocketTcp> m_clientTcp;
+	SocketTcp<Ipv4> m_masterTcp;
+	SocketTcp<Ipv4> m_clientTcp;
 
 	std::thread m_tserver;
 	std::thread m_tclient;
 
 public:
 	ListenerTest()
-		: m_masterTcp{std::make_shared<SocketTcp>(AF_INET, 0)}
-		, m_clientTcp{std::make_shared<SocketTcp>(AF_INET, 0)}
+		: m_masterTcp{AF_INET, 0}
+		, m_clientTcp{AF_INET, 0}
 	{
-		m_masterTcp->set(SOL_SOCKET, SO_REUSEADDR, 1);
-		m_masterTcp->bind(std::make_unique<Internet>("*", 16000, AF_INET));
-		m_masterTcp->listen();
+		m_masterTcp.set(SOL_SOCKET, SO_REUSEADDR, 1);
+		m_masterTcp.bind(Ipv4{"*", 16000});
+		m_masterTcp.listen();
 	}
 
 	~ListenerTest()
@@ -417,8 +433,8 @@
 		try {
 			m_listener.set(m_masterTcp, SocketListener::Read);
 			m_listener.wait();
-			m_masterTcp->accept();
-			m_masterTcp->close();
+			m_masterTcp.accept();
+			m_masterTcp.close();
 		} catch (const std::exception &ex) {
 			FAIL() << ex.what();
 		}
@@ -427,7 +443,7 @@
 	std::this_thread::sleep_for(100ms);
 
 	m_tclient = std::thread([this] () {
-		m_clientTcp->connect(std::make_unique<Internet>("127.0.0.1", 16000, AF_INET));
+		m_clientTcp.connect(Ipv4{"127.0.0.1", 16000});
 	});
 }
 
@@ -438,9 +454,9 @@
 			m_listener.set(m_masterTcp, SocketListener::Read);
 			m_listener.wait();
 
-			auto sc = m_masterTcp->accept();
+			auto sc = m_masterTcp.accept();
 
-			ASSERT_EQ("hello", sc->recv(512));
+			ASSERT_EQ("hello", sc.recv(512));
 		} catch (const std::exception &ex) {
 			FAIL() << ex.what();
 		}
@@ -449,8 +465,8 @@
 	std::this_thread::sleep_for(100ms);
 
 	m_tclient = std::thread([this] () {
-		m_clientTcp->connect(std::make_unique<Internet>("127.0.0.1", 16000, AF_INET));
-		m_clientTcp->send("hello");
+		m_clientTcp.connect(Ipv4{"127.0.0.1", 16000});
+		m_clientTcp.send("hello");
 	});
 }
 
@@ -460,8 +476,8 @@
 
 class NonBlockingConnectTest : public testing::Test {
 protected:
-	SocketTcp m_server{AF_INET, 0};
-	SocketTcp m_client{AF_INET, 0};
+	SocketTcp<Ipv4> m_server{AF_INET, 0};
+	SocketTcp<Ipv4> m_client{AF_INET, 0};
 
 	std::thread m_tserver;
 	std::thread m_tclient;
@@ -487,8 +503,8 @@
 
 class TcpAcceptTest : public testing::Test {
 protected:
-	SocketTcp m_server{AF_INET, 0};
-	SocketTcp m_client{AF_INET, 0};
+	SocketTcp<Ipv4> m_server{AF_INET, 0};
+	SocketTcp<Ipv4> m_client{AF_INET, 0};
 
 	std::thread m_tserver;
 	std::thread m_tclient;
@@ -497,7 +513,7 @@
 	TcpAcceptTest()
 	{
 		m_server.set(SOL_SOCKET, SO_REUSEADDR, 1);
-		m_server.bind(std::make_unique<Internet>("*", 16000, AF_INET));
+		m_server.bind(Ipv4{"*", 16000});
 		m_server.listen();
 	}
 
@@ -516,8 +532,8 @@
 
 class TcpRecvTest : public testing::Test {
 protected:
-	SocketTcp m_server{AF_INET, 0};
-	SocketTcp m_client{AF_INET, 0};
+	SocketTcp<Ipv4> m_server{AF_INET, 0};
+	SocketTcp<Ipv4> m_client{AF_INET, 0};
 
 	std::thread m_tserver;
 	std::thread m_tclient;
@@ -526,7 +542,7 @@
 	TcpRecvTest()
 	{
 		m_server.set(SOL_SOCKET, SO_REUSEADDR, 1);
-		m_server.bind(std::make_unique<Internet>("*", 16000, AF_INET));
+		m_server.bind(Ipv4{"*", 16000});
 		m_server.listen();
 	}
 
@@ -544,13 +560,13 @@
 	m_tserver = std::thread([this] () {
 		auto client = m_server.accept();
 
-		ASSERT_EQ("hello", client->recv(32));
+		ASSERT_EQ("hello", client.recv(32));
 	});
 
 	std::this_thread::sleep_for(100ms);
 
 	m_tclient = std::thread([this] () {
-		m_client.connect(std::make_unique<Internet>("127.0.0.1", 16000, AF_INET));
+		m_client.connect(Ipv4{"127.0.0.1", 16000});
 		m_client.send("hello");
 		m_client.close();
 	});
@@ -560,6 +576,8 @@
  * Socket SSL
  * -------------------------------------------------------- */
 
+#if 0
+
 class SslTest : public testing::Test {
 protected:
 	SocketSsl client{AF_INET, 0};
@@ -592,6 +610,8 @@
 	}
 }
 
+#endif
+
 int main(int argc, char **argv)
 {
 	testing::InitGoogleTest(&argc, argv);
--- a/CMakeLists.txt	Fri Jun 19 13:56:12 2015 +0200
+++ b/CMakeLists.txt	Tue Jun 23 14:06:37 2015 +0200
@@ -363,10 +363,6 @@
 			${code_SOURCE_DIR}/C++/modules/Socket/SocketListener.h
 			${code_SOURCE_DIR}/C++/modules/Socket/SocketSsl.cpp
 			${code_SOURCE_DIR}/C++/modules/Socket/SocketSsl.h
-			${code_SOURCE_DIR}/C++/modules/Socket/SocketTcp.cpp
-			${code_SOURCE_DIR}/C++/modules/Socket/SocketTcp.h
-			${code_SOURCE_DIR}/C++/modules/Socket/SocketUdp.cpp
-			${code_SOURCE_DIR}/C++/modules/Socket/SocketUdp.h
 	)
 endif ()