changeset 473:5a9671dabb15

Socket: - Fix epoll which wrongly reset flags, - Fix wrongly use of SOCKET_DEFAULT_BACKEND, - Fix error in GCC using constexpr, switch to inline, - Add more documentation about non-blocking sockets, - Remove Socket::setBlockMode, - Start updating all doxygen comments, - Put back UDP.
author David Demelier <markand@malikania.fr>
date Thu, 05 Nov 2015 22:28:40 +0100
parents f8594d3394ab
children fb3158aca358
files C++/examples/Socket/blocking-accept.cpp C++/examples/Socket/blocking-connect.cpp C++/examples/Socket/non-blocking-accept.cpp C++/examples/Socket/non-blocking-connect.cpp C++/examples/Socket/stream-client.cpp C++/examples/Socket/stream-server.cpp C++/modules/Socket/Sockets.cpp C++/modules/Socket/Sockets.h C++/tests/Socket/main.cpp
diffstat 9 files changed, 456 insertions(+), 320 deletions(-) [+]
line wrap: on
line diff
--- a/C++/examples/Socket/blocking-accept.cpp	Thu Nov 05 16:42:23 2015 +0100
+++ b/C++/examples/Socket/blocking-accept.cpp	Thu Nov 05 22:28:40 2015 +0100
@@ -22,20 +22,21 @@
 int main()
 {
 #if defined(WITH_SSL)
-	net::SocketTls<net::Ipv4> master;
-	net::SocketTls<net::Ipv4> client{net::Invalid};
+	net::SocketTls<net::address::Ip> master;
+	net::SocketTls<net::address::Ip> client{net::Invalid};
 #else
-	net::SocketTcp<net::Ipv4> master;
-	net::SocketTcp<net::Ipv4> client{net::Invalid};
+	net::SocketTcp<net::address::Ip> master;
+	net::SocketTcp<net::address::Ip> client{net::Invalid};
 #endif
 
 	net::Listener<> listener;
 
 	try {
-		master.bind(net::Ipv4{"*", WITH_PORT});
+		master.set(net::option::SockReuseAddress{true});
+		master.bind(net::address::Ip{"*", WITH_PORT});
 		master.listen();
 
-		listener.set(master.handle(), net::FlagRead);
+		listener.set(master.handle(), net::Condition::Readable);
 		listener.wait(std::chrono::seconds(WITH_TIMEOUT));
 
 		client = master.accept(nullptr);
--- a/C++/examples/Socket/blocking-connect.cpp	Thu Nov 05 16:42:23 2015 +0100
+++ b/C++/examples/Socket/blocking-connect.cpp	Thu Nov 05 22:28:40 2015 +0100
@@ -28,14 +28,14 @@
 int main()
 {
 #if defined(WITH_SSL)
-	net::SocketTls<net::Ipv4> socket;
+	net::SocketTls<net::address::Ip> socket;
 #else
-	net::SocketTcp<net::Ipv4> socket;
+	net::SocketTcp<net::address::Ip> socket;
 #endif
 
 	try {
 		std::cout << "Trying to connect to " << WITH_HOST << ":" << WITH_PORT << std::endl;
-		socket.connect(net::Ipv4{WITH_HOST, WITH_PORT});
+		socket.connect(net::address::Ip{WITH_HOST, WITH_PORT});
 	} catch (const net::Error &error) {
 		std::cerr << "error: " << error.what() << std::endl;
 		std::exit(1);
--- a/C++/examples/Socket/non-blocking-accept.cpp	Thu Nov 05 16:42:23 2015 +0100
+++ b/C++/examples/Socket/non-blocking-accept.cpp	Thu Nov 05 22:28:40 2015 +0100
@@ -23,11 +23,11 @@
 int main()
 {
 #if defined(WITH_SSL)
-	net::SocketTls<net::Ipv4> master;
-	net::SocketTls<net::Ipv4> client{net::Invalid};
+	net::SocketTls<net::address::Ip> master;
+	net::SocketTls<net::address::Ip> client{net::Invalid};
 #else
-	net::SocketTcp<net::Ipv4> master;
-	net::SocketTcp<net::Ipv4> client{net::Invalid};
+	net::SocketTcp<net::address::Ip> master;
+	net::SocketTcp<net::address::Ip> client{net::Invalid};
 #endif
 
 	net::Listener<> listener;
@@ -35,11 +35,10 @@
 
 	// 1. Create the master socket for listening.
 	try {
-		master.bind(net::Ipv4{"*", WITH_PORT});
+		master.set(net::option::SockReuseAddress{true});
+		master.set(net::option::SockBlockMode{false});
+		master.bind(net::address::Ip{"*", WITH_PORT});
 		master.listen();
-
-		// Usually never needed, but for the example put everything as non-blocking.
-		master.setBlockMode(false);
 	} catch (const net::Error &error) {
 		std::cerr << "error: " << error.what() << std::endl;
 		std::exit(1);
@@ -48,22 +47,16 @@
 	while (client.state() != net::State::Accepted && timer.elapsed() < (WITH_TIMEOUT * 1000)) {
 		try {
 			if (client.state() == net::State::Closed) {
-				// 1. Wait for a pre-accept process.
-				listener.set(master.handle(), net::FlagRead);
+				// 2. Wait for a pre-accept process.
+				listener.set(master.handle(), net::Condition::Readable);
 				listener.wait(std::chrono::seconds(WITH_TIMEOUT));
 				client = master.accept(nullptr);
-				client.setBlockMode(false);
+				client.set(net::option::SockBlockMode{false});
 				listener.remove(master.handle());
 			} else {
-				// 2. Wait for the accept process to complete.
+				// 3. Wait for the accept process to complete.
 				listener.remove(client.handle());
-
-				if (client.state() == net::State::AcceptingRead) {
-					listener.set(client.handle(), net::FlagRead);
-				} else if (client.state() == net::State::AcceptingWrite) {
-					listener.set(client.handle(), net::FlagWrite);
-				}
-
+				listener.set(client.handle(), client.condition());
 				listener.wait(std::chrono::seconds(WITH_TIMEOUT));
 				client.accept();
 			}
--- a/C++/examples/Socket/non-blocking-connect.cpp	Thu Nov 05 16:42:23 2015 +0100
+++ b/C++/examples/Socket/non-blocking-connect.cpp	Thu Nov 05 22:28:40 2015 +0100
@@ -28,39 +28,33 @@
 int main()
 {
 #if defined(WITH_SSL)
-	net::SocketTls<net::Ipv4> socket;
+	net::SocketTls<net::address::Ip> socket;
 #else
-	net::SocketTcp<net::Ipv4> socket;
+	net::SocketTcp<net::address::Ip> socket;
 #endif
 
 	net::Listener<> listener;
 	ElapsedTimer timer;
 
-	socket.setBlockMode(false);
+	// 1. Set to non-blocking.
+	socket.set(net::option::SockBlockMode{false});
 
 	try {
 		std::cout << "Trying to connect to " << WITH_HOST << ":" << WITH_PORT << std::endl;
-		socket.connect(net::Ipv4{WITH_HOST, WITH_PORT});
+
+		// 2. Initial connection process.
+		socket.connect(net::address::Ip{WITH_HOST, WITH_PORT});
 
 		while (socket.state() != net::State::Connected) {
 			listener.remove(socket.handle());
 
-			if (socket.state() == net::State::ConnectingRead) {
-				listener.set(socket.handle(), net::FlagRead);
-			} else if (socket.state() == net::State::ConnectingWrite) {
-				listener.set(socket.handle(), net::FlagWrite);
-			}
-
+			// 2. Now complete by waiting for the appropriate condition.
+			listener.set(socket.handle(), socket.condition());
 			listener.wait(std::chrono::seconds(WITH_TIMEOUT));
 			socket.connect();
 		}
 	} catch (const net::Error &error) {
-		if (error.code() == net::Error::Timeout) {
-			std::cerr << "timeout while connecting" << std::endl;
-		} else {
-			std::cerr << "error: " << error.what() << std::endl;
-		}
-
+		std::cerr << "error: " << error.what() << std::endl;
 		std::exit(1);
 	}
 
--- a/C++/examples/Socket/stream-client.cpp	Thu Nov 05 16:42:23 2015 +0100
+++ b/C++/examples/Socket/stream-client.cpp	Thu Nov 05 22:28:40 2015 +0100
@@ -20,9 +20,9 @@
 #endif
 
 #if defined(WITH_SSL)
-using Client = net::StreamClient<net::Ipv4, net::Tls>;
+using Client = net::StreamClient<net::address::Ip, net::protocol::Tls>;
 #else
-using Client = net::StreamClient<net::Ipv4, net::Tcp>;
+using Client = net::StreamClient<net::address::Ip, net::protocol::Tcp>;
 #endif
 
 int main()
@@ -54,7 +54,7 @@
 		std::cout << "client: sent: " << data << std::endl;
 	});
 
-	client.connect(net::Ipv4{WITH_HOST, WITH_PORT});
+	client.connect(net::address::Ip{WITH_HOST, WITH_PORT});
 
 	while (connected) {
 		client.poll();
@@ -63,4 +63,4 @@
 	std::cout << "client: exiting" << std::endl;
 
 	return 0;
-}
\ No newline at end of file
+}
--- a/C++/examples/Socket/stream-server.cpp	Thu Nov 05 16:42:23 2015 +0100
+++ b/C++/examples/Socket/stream-server.cpp	Thu Nov 05 22:28:40 2015 +0100
@@ -15,26 +15,26 @@
 #endif
 
 #if defined(WITH_SSL)
-using Server = net::StreamServer<net::Ipv4, net::Tls>;
-using Connection = net::StreamConnection<net::Ipv4, net::Tls>;
+using Server = net::StreamServer<net::address::Ip, net::protocol::Tls>;
+using Connection = net::StreamConnection<net::address::Ip, net::protocol::Tls>;
 #else
-using Server = net::StreamServer<net::Ipv4, net::Tcp>;
-using Connection = net::StreamConnection<net::Ipv4, net::Tcp>;
+using Server = net::StreamServer<net::address::Ip, net::protocol::Tcp>;
+using Connection = net::StreamConnection<net::address::Ip, net::protocol::Tcp>;
 #endif
 
 int main()
 {
 #if defined(WITH_SSL)
-	net::Tls protocol;
+	net::protocol::Tls protocol;
 
 	protocol.setVerify(false);
 	protocol.setPrivateKey("test.key");
 	protocol.setCertificate("test.crt");
 	protocol.setMethod(net::ssl::Tlsv1);
 
-	Server server{std::move(protocol), net::Ipv4{"*", WITH_PORT}};
+	Server server{std::move(protocol), net::address::Ip{"*", WITH_PORT}};
 #else
-	Server server{net::Tcp{}, net::Ipv4{"*", WITH_PORT}};
+	Server server{net::protocol::Tcp{}, net::address::Ip{"*", WITH_PORT}};
 #endif
 
 	server.setConnectionHandler([] (const std::shared_ptr<Connection> &client) {
@@ -56,4 +56,4 @@
 	}
 
 	return 0;
-}
\ No newline at end of file
+}
--- a/C++/modules/Socket/Sockets.cpp	Thu Nov 05 16:42:23 2015 +0100
+++ b/C++/modules/Socket/Sockets.cpp	Thu Nov 05 22:28:40 2015 +0100
@@ -16,6 +16,8 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#define TIMEOUT_MSG "operation timeout"
+
 #include <algorithm>
 #include <atomic>
 #include <cstring>
@@ -130,6 +132,52 @@
 /* }}} */
 
 /*
+ * SSL stuff
+ * ------------------------------------------------------------------
+ */
+
+/* {{{ SSL initialization */
+
+#if !defined(SOCKET_NO_SSL)
+
+namespace ssl {
+
+namespace {
+
+std::mutex mutex;
+std::atomic<bool> initialized{false};
+
+} // !namespace
+
+void finish() noexcept
+{
+	ERR_free_strings();
+}
+
+void init() noexcept
+{
+	std::lock_guard<std::mutex> lock{mutex};
+
+	if (!initialized) {
+		initialized = true;
+
+		SSL_library_init();
+		SSL_load_error_strings();
+		OpenSSL_add_all_algorithms();
+
+#if !defined(SOCKET_NO_AUTO_SSL_INIT)
+		atexit(finish);
+#endif // SOCKET_NO_AUTO_SSL_INIT
+	}
+}
+
+} // !ssl
+
+#endif // SOCKET_NO_SSL
+
+/* }}} */
+
+/*
  * Error class
  * ------------------------------------------------------------------
  */
@@ -166,6 +214,8 @@
 
 /* {{{ Addresses */
 
+namespace address {
+
 /* Default domain */
 int Ip::m_default{AF_INET};
 
@@ -239,9 +289,9 @@
 
 #if !defined(_WIN32)
 
-Local::Local()
+Local::Local() noexcept
 {
-	std::memset(m_sun, 0, sizeof (sockaddr_un));
+	std::memset(&m_sun, 0, sizeof (sockaddr_un));
 }
 
 Local::Local(std::string path, bool rm) noexcept
@@ -272,6 +322,8 @@
 
 #endif // !_WIN32
 
+} // !address
+
 /* }}} */
 
 /*
@@ -316,7 +368,7 @@
 		throw Error{Error::System, "select"};
 	}
 	if (error == 0) {
-		throw Error{Error::Timeout, "select", "Timeout while listening"};
+		throw Error{Error::Timeout, "select", TIMEOUT_MSG};
 	}
 
 	std::vector<ListenerStatus> sockets;
@@ -335,6 +387,11 @@
 
 /* }}} */
 
+/*
+ * Poll
+ * ------------------------------------------------------------------
+ */
+
 /* {{{ Poll */
 
 /*
@@ -416,7 +473,7 @@
 {
 	auto result = poll(m_fds.data(), m_fds.size(), ms);
 	if (result == 0) {
-		throw Error{Error::Timeout, "select", "Timeout while listening"};
+		throw Error{Error::Timeout, "select", TIMEOUT_MSG};
 	}
 	if (result < 0) {
 		throw Error{Error::System, "poll"};
@@ -434,11 +491,15 @@
 
 #endif // !SOCKET_HAVE_POLL
 
+/* }}} */
+
 /*
  * Epoll implementation
  * ------------------------------------------------------------------
  */
 
+/* {{{ Epoll */
+
 #if defined(SOCKET_HAVE_EPOLL)
 
 uint32_t Epoll::toEpoll(Condition condition) const noexcept
@@ -497,14 +558,17 @@
 }
 
 /*
- * Add a new epoll_event or just update it.
+ * For set and unset, we need to apply the whole flags required, so if the socket
+ * was set to Connection::Readable and user add Connection::Writable, we must
+ * place both.
  */
-void Epoll::set(const ListenerTable &, Handle h, Condition condition, bool add)
+void Epoll::set(const ListenerTable &table, Handle sc, Condition condition, bool add)
 {
-	update(h, add ? EPOLL_CTL_ADD : EPOLL_CTL_MOD, toEpoll(condition));
-
 	if (add) {
+		update(sc, EPOLL_CTL_ADD, toEpoll(condition));
 		m_events.resize(m_events.size() + 1);
+	} else {
+		update(sc, EPOLL_CTL_MOD, toEpoll(table.at(sc) | condition));
 	}
 }
 
@@ -522,7 +586,7 @@
 		update(sc, EPOLL_CTL_DEL, 0);
 		m_events.resize(m_events.size() - 1);
 	} else {
-		update(sc, EPOLL_CTL_MOD, toEpoll(table.at(sc)) & ~(toEpoll(condition)));
+		update(sc, EPOLL_CTL_MOD, toEpoll(table.at(sc) & ~(condition)));
 	}
 }
 
@@ -532,7 +596,7 @@
 	std::vector<ListenerStatus> result;
 
 	if (ret == 0) {
-		throw Error{Error::Timeout, "epoll_wait"};
+		throw Error{Error::Timeout, "epoll_wait", TIMEOUT_MSG};
 	}
 	if (ret < 0) {
 		throw Error{Error::System, "epoll_wait"};
@@ -547,9 +611,14 @@
 
 #endif // !SOCKET_HAVE_EPOLL
 
-/* --------------------------------------------------------
+/* }}} */
+
+/*
  * Kqueue implementation
- * -------------------------------------------------------- */
+ * ------------------------------------------------------------------
+ */
+
+/* {{{ Kqueue */
 
 #if defined(SOCKET_HAVE_KQUEUE)
 
@@ -617,7 +686,7 @@
 	int nevents = kevent(m_handle, nullptr, 0, &m_result[0], m_result.capacity(), pts);
 
 	if (nevents == 0) {
-		throw Error{Error::Timeout, "kevent"};
+		throw Error{Error::Timeout, "kevent", TIMEOUT_MSG};
 	}
 	if (nevents < 0) {
 		throw Error{Error::System, "kevent"};
@@ -635,41 +704,6 @@
 
 #endif // !SOCKET_HAVE_KQUEUE
 
-#if !defined(SOCKET_NO_SSL)
-
-namespace ssl {
-
-namespace {
-
-std::mutex mutex;
-std::atomic<bool> initialized{false};
-
-} // !namespace
-
-void finish() noexcept
-{
-	ERR_free_strings();
-}
-
-void init() noexcept
-{
-	std::lock_guard<std::mutex> lock{mutex};
-
-	if (!initialized) {
-		initialized = true;
-
-		SSL_library_init();
-		SSL_load_error_strings();
-		OpenSSL_add_all_algorithms();
-
-#if !defined(SOCKET_NO_AUTO_SSL_INIT)
-		atexit(finish);
-#endif // SOCKET_NO_AUTO_SSL_INIT
-	}
-}
-
-} // !ssl
-
-#endif // SOCKET_NO_SSL
+/* }}} */
 
 } // !net
--- a/C++/modules/Socket/Sockets.h	Thu Nov 05 16:42:23 2015 +0100
+++ b/C++/modules/Socket/Sockets.h	Thu Nov 05 22:28:40 2015 +0100
@@ -93,24 +93,30 @@
  *
  * @note Do not rely on the value shown in doxygen.
  */
-#if !defined(SOCKET_DEFAULT_BACKEND)
-#  if defined(_WIN32)
+#if defined(_WIN32)
+#  if !defined(SOCKET_DEFAULT_BACKEND)
 #    if defined(SOCKET_HAVE_POLL)
 #      define SOCKET_DEFAULT_BACKEND Poll
 #    else
 #      define SOCKET_DEFAULT_BACKEND Select
 #    endif
-#  elif defined(__linux__)
-#    include <sys/epoll.h>
-   
+#  endif
+#elif defined(__linux__)
+#  include <sys/epoll.h>
+ 
+#  if !defined(SOCKET_DEFAULT_BACKEND)
 #    define SOCKET_DEFAULT_BACKEND Epoll
-#  elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__APPLE__)
-#    include <sys/types.h>
-#    include <sys/event.h>
-#    include <sys/time.h>
-   
+#  endif
+#elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__APPLE__)
+#  include <sys/types.h>
+#  include <sys/event.h>
+#  include <sys/time.h>
+ 
+#  if !defined(SOCKET_DEFAULT_BACKEND)
 #    define SOCKET_DEFAULT_BACKEND Kqueue
-#  else
+#  endif
+#else
+#  if !defined(SOCKET_DEFAULT_BACKEND)
 #    define SOCKET_DEFAULT_BACKEND Select
 #  endif
 #endif
@@ -255,6 +261,23 @@
 
 #endif
 
+#if !defined(SOCKET_NO_SSL)
+
+namespace ssl {
+
+/**
+ * @enum Method
+ * @brief Which OpenSSL method to use.
+ */
+enum Method {
+	Tlsv1,		//!< TLS v1.2 (recommended)
+	Sslv3		//!< SSLv3
+};
+
+} // !ssl
+
+#endif
+
 /* }}} */
 
 /*
@@ -542,7 +565,7 @@
  * @param v2 the second value
  * @return the new value
  */
-constexpr Condition &operator|=(Condition &v1, Condition v2) noexcept
+inline Condition &operator|=(Condition &v1, Condition v2) noexcept
 {
 	v1 = static_cast<Condition>(static_cast<int>(v1) | static_cast<int>(v2));
 
@@ -556,7 +579,7 @@
  * @param v2 the second value
  * @return the new value
  */
-constexpr Condition &operator&=(Condition &v1, Condition v2) noexcept
+inline Condition &operator&=(Condition &v1, Condition v2) noexcept
 {
 	v1 = static_cast<Condition>(static_cast<int>(v1) & static_cast<int>(v2));
 
@@ -570,7 +593,7 @@
  * @param v2 the second value
  * @return the new value
  */
-constexpr Condition &operator^=(Condition &v1, Condition v2) noexcept
+inline Condition &operator^=(Condition &v1, Condition v2) noexcept
 {
 	v1 = static_cast<Condition>(static_cast<int>(v1) ^ static_cast<int>(v2));
 
@@ -592,6 +615,13 @@
 /**
  * @class Socket
  * @brief Base socket class for socket operations.
+ *
+ * **Important:** When using non-blocking sockets, some considerations must be taken. See the implementation of the
+ * underlying protocol for more details.
+ *
+ * @see protocol::Tls
+ * @see protocol::Tcp
+ * @see protocol::Udp
  */
 template <typename Address, typename Protocol>
 class Socket {
@@ -618,11 +648,11 @@
 	 * @param type the type SOCK_*
 	 * @param protocol the protocol
 	 * @param iface the implementation
-	 * @throw Error on failures
+	 * @throw net::Error on errors
 	 * @post state is set to Open
 	 * @post handle is not set to Invalid
 	 */
-	Socket(int domain, int type, int protocol, Protocol iface = Protocol{})
+	Socket(int domain, int type, int protocol, Protocol iface = {})
 		: m_proto(std::move(iface))
 	{
 #if !defined(SOCKET_NO_AUTO_INIT)
@@ -647,6 +677,7 @@
 	 *
 	 * @param protocol the protocol
 	 * @param address which type of address
+	 * @throw net::Error on errors
 	 */
 	explicit inline Socket(Protocol protocol = {}, const Address &address = {})
 		: Socket{address.domain(), protocol.type(), 0, std::move(protocol)}
@@ -802,7 +833,7 @@
 	 * @param level the setting level
 	 * @param name the name
 	 * @param arg the value
-	 * @throw Error on error
+	 * @throw net::Error on errors
 	 */
 	template <typename Argument>
 	void set(int level, int name, const Argument &arg)
@@ -818,7 +849,7 @@
 	 * The object must have `set(Socket<Address, Protocol> &) const`.
 	 *
 	 * @param option the option
-	 * @throw Error on errors
+	 * @throw net::Error on errors
 	 */
 	template <typename Option>
 	inline void set(const Option &option)
@@ -831,7 +862,7 @@
 	 *
 	 * @param level the setting level
 	 * @param name the name
-	 * @throw Error on error
+	 * @throw net::Error on errors
 	 */
 	template <typename Argument>
 	Argument get(int level, int name)
@@ -855,7 +886,7 @@
 	 * returned from this function.
 	 *
 	 * @return the same value as get() in the option
-	 * @throw Error on errors
+	 * @throw net::Error on errors
 	 */
 	template <typename Option>
 	inline auto get() -> decltype(std::declval<Option>().get(*this))
@@ -875,47 +906,12 @@
 	}
 
 	/**
-	 * Set the blocking mode, if set to false, the socket will be marked
-	 * **non-blocking**.
-	 *
-	 * @param block set to false to mark **non-blocking**
-	 * @throw Error on any error
-	 * @deprecated see option::BlockMode and set()
-	 */
-	void setBlockMode(bool block)
-	{
-#if defined(O_NONBLOCK) && !defined(_WIN32)
-		int flags;
-
-		if ((flags = fcntl(m_handle, F_GETFL, 0)) == -1) {
-			flags = 0;
-		}
-
-		if (block) {
-			flags &= ~(O_NONBLOCK);
-		} else {
-			flags |= O_NONBLOCK;
-		}
-
-		if (fcntl(m_handle, F_SETFL, flags) == Failure) {
-			throw Error{Error::System, "setBlockMode"};
-		}
-#else
-		unsigned long flags = (block) ? 0 : 1;
-
-		if (ioctlsocket(m_handle, FIONBIO, &flags) == Failure) {
-			throw Error{Error::System, "setBlockMode"};
-		}
-#endif
-	}
-
-	/**
 	 * Bind using a native address.
 	 *
 	 * @param address the address
 	 * @param length the size
 	 * @pre state must not be Bound
-	 * @throw Error on errors
+	 * @throw net::Error on errors
 	 */
 	void bind(const sockaddr *address, socklen_t length)
 	{
@@ -932,7 +928,7 @@
 	 * Overload that takes an address.
 	 *
 	 * @param address the address
-	 * @throw Error on errors
+	 * @throw net::Error on errors
 	 */
 	inline void bind(const Address &address)
 	{
@@ -944,7 +940,7 @@
 	 *
 	 * @param max the maximum number
 	 * @pre state must be Bound
-	 * @throw Error on errors
+	 * @throw net::Error on errors
 	 */
 	inline void listen(int max = 128)
 	{
@@ -958,17 +954,15 @@
 	/**
 	 * Connect to the address.
 	 *
-	 * On non-blocking socket, if the connection cannot be established immediately then state is set to
-	 * State::Connecting, action is set to Action::Connect and condition is set to the required condition.
-	 *
-	 * User is then responsible of waiting for the condition to be checked and call the connect() overload
-	 * which takes 0 argument.
+	 * If connection cannot be established immediately, connect with no argument must be called again. See
+	 * the underlying protocol for more information.
 	 *
 	 * @pre state must be State::Open
 	 * @param address the address
 	 * @param length the the address length
-	 * @post if state is Connecting, action and condition are defined
-	 * @throw Error on errors
+	 * @throw net::Error on errors
+	 * @post state is set to State::Connecting or State::Connected
+	 * @note For non-blocking sockets, see the underlying protocol function for more details
 	 */
 	void connect(const sockaddr *address, socklen_t length)
 	{
@@ -996,13 +990,10 @@
 	}
 
 	/**
-	 * Continue the connection, only required with non-blocking sockets. Just like the initial connect() call,
-	 * this function can still be in progress.
+	 * Continue the connection, only required with non-blocking sockets.
 	 *
 	 * @pre state must be State::Connecting
-	 * @throw Error on errors
-	 * @post if connection is completed, state is set to State::Connected
-	 * @post if connection is still in progress, condition is set
+	 * @throw net::Error on errors
 	 */
 	void connect()
 	{
@@ -1020,16 +1011,15 @@
 	/**
 	 * Accept a new client. If there are no pending connection, throws an error.
 	 *
-	 * On non-blocking sockets, the client may not be completely accepted yet, if it's the case, the returned
-	 * socket state is set to State::Accepting and user is responsible of calling accept() on it when the required
-	 * condition is met.
+	 * If the client cannot be accepted immediately, the client is returned and accept with no arguments
+	 * must be called on it. See the underlying protocol for more information.
 	 *
 	 * @pre state must be State::Bound
 	 * @param info the address where to store client's information (optional)
 	 * @return the new socket
 	 * @throw Error on errors
-	 * @post the client socket state is either set to State::Accepting or State::Accepted
-	 * @post if the client state is set to State::Accepting, action and condition are defined
+	 * @post returned client's state is set to State::Accepting or State::Accepted
+	 * @note For non-blocking sockets, see the underlying protocol function for more details
 	 */
 	Socket<Address, Protocol> accept(Address *info)
 	{
@@ -1109,17 +1099,17 @@
 	/**
 	 * Receive some data.
 	 *
-	 * If the operation cannot be complete immediately, 0 is returned, action() is set to Action::Receive and
-	 * condition is set to Condition::Readableable or Condition::Writable, the user then must wait for the
-	 * appropriate condition and repeat the recv() call.
+	 * If the operation cannot be complete immediately, 0 is returned and user must call the function
+	 * again when ready. See the underlying protocol for more information.
 	 *
-	 * If action() is set to None and result is set to 0, disconnection occured.
+	 * If action is set to Action::None and result is set to 0, disconnection occured.
 	 *
 	 * @param data the destination buffer
 	 * @param length the buffer length
-	 * @pre action() must not be Action::Send
+	 * @pre action must not be Action::Send
 	 * @return the number of bytes received or 0
 	 * @throw Error on error
+	 * @note For non-blocking sockets, see the underlying protocol function for more details
 	 */
 	unsigned recv(void *data, unsigned length)
 	{
@@ -1155,15 +1145,17 @@
 	}
 
 	/**
-	 * Send some data. Just like recv(), the operation may not succeed immediately and requires to be
-	 * repeated.
+	 * Send some data.
+	 *
+	 * If the operation cannot be complete immediately, 0 is returned and user must call the function
+	 * again when ready. See the underlying protocol for more information.
 	 *
 	 * @param data the data buffer
 	 * @param length the buffer length
 	 * @return the number of bytes sent or 0
 	 * @pre action() must not be Flag::Receive
 	 * @throw Error on error
-	 * @see recv
+	 * @note For non-blocking sockets, see the underlying protocol function for more details
 	 */
 	unsigned send(const void *data, unsigned length)
 	{
@@ -1192,20 +1184,37 @@
 		return send(data.c_str(), data.size());
 	}
 
-#if 0
-
 	/**
 	 * Send data to an end point.
 	 *
+	 * If the operation cannot be complete immediately, 0 is returned and user must call the function
+	 * again when ready. See the underlying protocol for more information.
+	 *
 	 * @param data the buffer
 	 * @param length the buffer length
 	 * @param address the client address
+	 * @param addrlen the address length
 	 * @return the number of bytes sent
-	 * @throw Error on error
+	 * @throw net::Error on errors
+	 * @note For non-blocking sockets, see the underlying protocol function for more details
+	 */
+	inline unsigned sendto(const void *data, unsigned length, const sockaddr *address, socklen_t addrlen)
+	{
+		return m_proto.sendto(*this, data, length, address, addrlen);
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @param data the buffer
+	 * @param length the buffer length
+	 * @param address the destination
+	 * @return the number of bytes sent
+	 * @throw net::Error on errors
 	 */
 	inline unsigned sendto(const void *data, unsigned length, const Address &address)
 	{
-		return m_proto.sendto(*this, data, length, address);
+		return sendto(data, length, address.address(), address.length());
 	}
 
 	/**
@@ -1214,7 +1223,7 @@
 	 * @param data the data
 	 * @param address the address
 	 * @return the number of bytes sent
-	 * @throw Error on error
+	 * @throw net:;Error on errors
 	 */
 	inline unsigned sendto(const std::string &data, const Address &address)
 	{
@@ -1224,17 +1233,43 @@
 	/**
 	 * Receive data from an end point.
 	 *
+	 * If the operation cannot be complete immediately, 0 is returned and user must call the function
+	 * again when ready. See the underlying protocol for more information.
+	 *
 	 * @param data the destination buffer
 	 * @param length the buffer length
-	 * @param info the client information
+	 * @param address the address destination
+	 * @param addrlen the address length (in/out)
 	 * @return the number of bytes received
-	 * @throw Error on error
+	 * @throw net::Error on errors
+	 * @note For non-blocking sockets, see the underlying protocol function for more details
+	 */
+	inline unsigned recvfrom(void *data, unsigned length, sockaddr *address, socklen_t *addrlen)
+	{
+		return m_proto.recvfrom(*this, data, length, address, addrlen);
+	}
+
+	/**
+	 * Overloaded function.
+	 *
+	 * @param data the destination buffer
+	 * @param length the buffer length
+	 * @param info the address destination
+	 * @return the number of bytes received
+	 * @throw net::Error on errors
 	 */
 	inline unsigned recvfrom(void *data, unsigned length, Address *info = nullptr)
 	{
-		Address dummy;
-
-		return m_proto.recvfrom(*this, data, length, info == nullptr ? dummy : *info);
+		sockaddr_storage storage;
+		socklen_t addrlen = sizeof (sockaddr_storage);
+
+		auto n = recvfrom(data, length, reinterpret_cast<sockaddr *>(&storage), &addrlen);
+
+		if (info && n != 0) {
+			*info = Address{&storage, addrlen};
+		}
+
+		return n;
 	}
 
 	/**
@@ -1243,9 +1278,9 @@
 	 * @param count the maximum number of bytes to receive
 	 * @param info the client information
 	 * @return the string
-	 * @throw Error on error
+	 * @throw net::Error on errors
 	 */
-	inline std::string recvfrom(unsigned count, Address *info = nullptr)
+	std::string recvfrom(unsigned count, Address *info = nullptr)
 	{
 		std::string result;
 
@@ -1256,8 +1291,6 @@
 		return result;
 	}
 
-#endif
-
 	/**
 	 * Close the socket.
 	 *
@@ -1403,12 +1436,19 @@
  */
 namespace option {
 
+/*
+ * Options for socket
+ * ------------------------------------------------------------------
+ */
+
+/* {{{ Options for socket */
+
 /**
- * @class BlockMode
+ * @class SockBlockMode
  * @brief Set or get the blocking-mode for a socket.
  * @warning On Windows, it's not possible to check if the socket is blocking or not.
  */
-class BlockMode {
+class SockBlockMode {
 public:
 	/**
 	 * Set to false if you want non-blocking socket.
@@ -1473,6 +1513,116 @@
 };
 
 /**
+ * @class SockReuseAddress
+ * @brief Reuse address, must be used before calling Socket::bind
+ */
+class SockReuseAddress {
+public:
+	/**
+	 * Set to true if you want to set the SOL_SOCKET/SO_REUSEADDR option.
+	 */
+	bool value{true};
+
+	/**
+	 * Set the option.
+	 *
+	 * @param sc the socket
+	 * @throw Error on errors
+	 */
+	template <typename Address, typename Protocol>
+	inline void set(Socket<Address, Protocol> &sc) const
+	{
+		sc.set(SOL_SOCKET, SO_REUSEADDR, value ? 1 : 0);
+	}
+
+	/**
+	 * Get the option.
+	 *
+	 * @return the value
+	 * @throw Error on errors
+	 */
+	template <typename Address, typename Protocol>
+	inline bool get(Socket<Address, Protocol> &sc) const
+	{
+		return static_cast<bool>(sc.template get<int>(SOL_SOCKET, SO_REUSEADDR));
+	}
+};
+
+/**
+ * @class SockSendBuffer
+ * @brief Set or get the output buffer.
+ */
+class SockSendBuffer {
+public:
+	/**
+	 * Set to the buffer size.
+	 */
+	int value{2048};
+
+	/**
+	 * Set the option.
+	 *
+	 * @param sc the socket
+	 * @throw Error on errors
+	 */
+	template <typename Address, typename Protocol>
+	inline void set(Socket<Address, Protocol> &sc) const
+	{
+		sc.set(SOL_SOCKET, SO_SNDBUF, value);
+	}
+
+	/**
+	 * Get the option.
+	 *
+	 * @return the value
+	 * @throw Error on errors
+	 */
+	template <typename Address, typename Protocol>
+	inline int get(Socket<Address, Protocol> &sc) const
+	{
+		return sc.template get<int>(SOL_SOCKET, SO_SNDBUF);
+	}
+};
+
+/**
+ * @class SockReceiveBuffer
+ * @brief Set or get the input buffer.
+ */
+class SockReceiveBuffer {
+public:
+	/**
+	 * Set to the buffer size.
+	 */
+	int value{2048};
+
+	/**
+	 * Set the option.
+	 *
+	 * @param sc the socket
+	 * @throw Error on errors
+	 */
+	template <typename Address, typename Protocol>
+	inline void set(Socket<Address, Protocol> &sc) const
+	{
+		sc.set(SOL_SOCKET, SO_RCVBUF, value);
+	}
+
+	/**
+	 * Get the option.
+	 *
+	 * @return the value
+	 * @throw Error on errors
+	 */
+	template <typename Address, typename Protocol>
+	inline int get(Socket<Address, Protocol> &sc) const
+	{
+		return sc.template get<int>(SOL_SOCKET, SO_RCVBUF);
+	}
+};
+
+/* }}} */
+
+/**
  * @class TcpNoDelay
  * @brief Set this option if you want to disable nagle's algorithm.
  */
@@ -1504,43 +1654,7 @@
 	template <typename Address, typename Protocol>
 	inline bool get(Socket<Address, Protocol> &sc) const
 	{
-		return static_cast<bool>(sc.get<int>(IPPROTO_TCP, TCP_NODELAY));
-	}
-};
-
-/**
- * @class ReuseAddress
- * @brief Reuse address, must be used before calling Socket::bind
- */
-class ReuseAddress {
-public:
-	/**
-	 * Set to true if you want to set the SOL_SOCKET/SO_REUSEADDR option.
-	 */
-	bool value{true};
-
-	/**
-	 * Set the option.
-	 *
-	 * @param sc the socket
-	 * @throw Error on errors
-	 */
-	template <typename Address, typename Protocol>
-	inline void set(Socket<Address, Protocol> &sc) const
-	{
-		sc.set(SOL_SOCKET, SO_REUSEADDR, value ? 1 : 0);
-	}
-
-	/**
-	 * Get the option.
-	 *
-	 * @return the value
-	 * @throw Error on errors
-	 */
-	template <typename Address, typename Protocol>
-	inline bool get(Socket<Address, Protocol> &sc) const
-	{
-		return static_cast<bool>(sc.get<int>(SOL_SOCKET, SO_REUSEADDR));
+		return static_cast<bool>(sc.template get<int>(IPPROTO_TCP, TCP_NODELAY));
 	}
 };
 
@@ -1579,7 +1693,7 @@
 	template <typename Address, typename Protocol>
 	inline bool get(Socket<Address, Protocol> &sc) const
 	{
-		return static_cast<bool>(sc.get<int>(IPPROTO_IPV6, IPV6_V6ONLY));
+		return static_cast<bool>(sc.template get<int>(IPPROTO_IPV6, IPV6_V6ONLY));
 	}
 };
 
@@ -1598,6 +1712,11 @@
 /* {{{ Addresses */
 
 /**
+ * Set of predefined addresses.
+ */
+namespace address {
+
+/**
  * @class Ip
  * @brief Base class for IPv6 and IPv4, you can use it if you don't know in advance if you'll use IPv6 or IPv4.
  */
@@ -1799,6 +1918,8 @@
 
 #endif // !_WIN32
 
+} // !address
+
 /* }}} */
 
 /*
@@ -1812,6 +1933,11 @@
 
 /* {{{ Protocols */
 
+/**
+ * Set of predefined protocols.
+ */
+namespace protocol {
+
 /* {{{ Tcp */
 
 /**
@@ -1997,6 +2123,7 @@
 			int error = WSAGetLastError();
 
 			if (error == WSAEWOULDBLOCK) {
+				nbread = 0;
 				sc.setCondition(Condition::Readable);
 			} else {
 				sc.setState(State::Disconnected);
@@ -2069,8 +2196,6 @@
 
 /* {{{ Udp */
 
-#if 0
-
 /**
  * @class Udp
  * @brief Clear UDP type.
@@ -2084,7 +2209,7 @@
 	 *
 	 * @return SOCK_DGRAM
 	 */
-	inline int type() noexcept
+	inline int type() const noexcept
 	{
 		return SOCK_DGRAM;
 	}
@@ -2101,40 +2226,43 @@
 	/**
 	 * Receive data from an end point.
 	 *
+	 * If the socket is marked non-blocking and no data is available, 0 is returned and condition is set to
+	 * Condition::Readable.
+	 *
+	 * If the socket is blocking, this functions blocks until some data is available or if an error occurs.
+	 *
 	 * @param sc the socket
 	 * @param data the destination buffer
 	 * @param length the buffer length
-	 * @param info the client information
+	 * @param address the address
+	 * @param addrlen the initial address length
 	 * @return the number of bytes received
 	 * @throw Error on error
 	 */
 	template <typename Address>
-	unsigned recvfrom(Socket<Address, Udp> &sc, void *data, unsigned length, Address &info)
+	unsigned recvfrom(Socket<Address, Udp> &sc, void *data, unsigned length, sockaddr *address, socklen_t *addrlen)
 	{
 		int nbread;
 
-		/* Store information */
-		sockaddr_storage address;
-		socklen_t addrlen = sizeof (sockaddr_storage);
-
-		nbread = ::recvfrom(sc.handle(), (Arg)data, length, 0, reinterpret_cast<sockaddr *>(&address), &addrlen);
-		info = Address{&address, addrlen};
+		nbread = ::recvfrom(sc.handle(), (Arg)data, length, 0, address, addrlen);
 
 		if (nbread == Failure) {
 #if defined(_WIN32)
 			int error = WSAGetLastError();
 
 			if (error == WSAEWOULDBLOCK) {
-				throw Error{Error::WouldBlockRead, "recvfrom", error};
+				nbread = 0;
+				sc.setCondition(Condition::Readable);
+			} else {
+				throw Error{Error::System, "recvfrom"};
 			}
-
-			throw Error{Error::System, "recvfrom", error};
 #else
 			if (errno == EAGAIN || errno == EWOULDBLOCK) {
-				throw Error{Error::WouldBlockRead, "recvfrom"};
+				nbread = 0;
+				sc.setCondition(Condition::Readable);
+			} else {
+				throw Error{Error::System, "recvfrom"};
 			}
-
-			throw Error{Error::System, "recvfrom"};
 #endif
 		}
 
@@ -2144,34 +2272,42 @@
 	/**
 	 * Send data to an end point.
 	 *
+	 * If the socket is marked non-blocking and the operation would block, then 0 is returned and condition is set to
+	 * Condition::Writable.
+	 *
+	 * If the socket is blocking, this functions blocks until the data has been sent.
+	 *
 	 * @param sc the socket
 	 * @param data the buffer
 	 * @param length the buffer length
 	 * @param address the client address
+	 * @param addrlen the adderss length
 	 * @return the number of bytes sent
 	 * @throw Error on error
 	 */
 	template <typename Address>
-	unsigned sendto(Socket<Address, Udp> &sc, const void *data, unsigned length, const Address &address)
+	unsigned sendto(Socket<Address, Udp> &sc, const void *data, unsigned length, const sockaddr *address, socklen_t addrlen)
 	{
 		int nbsent;
 
-		nbsent = ::sendto(sc.handle(), (ConstArg)data, length, 0, address.address(), address.length());
+		nbsent = ::sendto(sc.handle(), (ConstArg)data, length, 0, address, addrlen);
 		if (nbsent == Failure) {
 #if defined(_WIN32)
 			int error = WSAGetLastError();
 
 			if (error == WSAEWOULDBLOCK) {
-				throw Error{Error::WouldBlockWrite, "sendto", error};
+				nbsent = 0;
+				sc.setCondition(Condition::Writable);
+			} else {
+				throw Error{Error::System, "sendto", error};
 			}
-
-			throw Error{Error::System, "sendto", error};
 #else
 			if (errno == EAGAIN || errno == EWOULDBLOCK) {
-				throw Error{Error::WouldBlockWrite, "sendto"};
+				nbsent = 0;
+				sc.setCondition(Condition::Writable);
+			} else {
+				throw Error{Error::System, "sendto"};
 			}
-
-			throw Error{Error::System, "sendto"};
 #endif
 		}
 
@@ -2179,27 +2315,12 @@
 	}
 };
 
-#endif
-
 /* }}} */
 
 /* {{{ Tls */
 
 #if !defined(SOCKET_NO_SSL)
 
-namespace ssl {
-
-/**
- * @enum Method
- * @brief Which OpenSSL method to use.
- */
-enum Method {
-	Tlsv1,		//!< TLS v1.2 (recommended)
-	Sslv3		//!< SSLv3
-};
-
-} // !ssl
-
 /**
  * @class Tls
  * @brief OpenSSL secure layer for TCP.
@@ -2329,7 +2450,7 @@
 	Tls()
 	{
 #if !defined(SOCKET_NO_SSL_AUTO_INIT)
-		ssl::init();
+		::net::ssl::init();
 #endif
 	}
 
@@ -2564,7 +2685,7 @@
 			auto no = SSL_get_error(m_ssl.get(), nbsent);
 
 			if (no == SSL_ERROR_WANT_READ || no == SSL_ERROR_WANT_WRITE) {
-				nbread = 0
+				nbsent = 0;
 				updateStates(sc, sc.state(), Action::Send, no);
 			} else {
 				throw Error{Error::System, "send", error(no)};
@@ -2579,6 +2700,8 @@
 
 /* }}} */
 
+} // !protocol
+
 /* }}} */
 
 /*
@@ -2596,31 +2719,32 @@
  * Helper to create TCP sockets.
  */
 template <typename Address>
-using SocketTcp = Socket<Address, Tcp>;
+using SocketTcp = Socket<Address, protocol::Tcp>;
 
 /**
  * Helper to create TCP/IP sockets.
  */
-using SocketTcpIp = Socket<Ip, Tcp>;
+using SocketTcpIp = Socket<address::Ip, protocol::Tcp>;
 
 #if !defined(_WIN32)
 
 /**
  * Helper to create TCP/Local sockets.
  */
-using SocketTcpLocal = Socket<Local, Tcp>;
+using SocketTcpLocal = Socket<address::Local, protocol::Tcp>;
 
 #endif
 
-#if 0
-
 /**
  * Helper to create UDP sockets.
  */
 template <typename Address>
-using SocketUdp = Socket<Address, Udp>;
-
-#endif
+using SocketUdp = Socket<Address, protocol::Udp>;
+
+/**
+ * Helper to create UDP/IP sockets.
+ */
+using SocketUdpIp = Socket<address::Ip, protocol::Udp>;
 
 #if !defined(SOCKET_NO_SSL)
 
@@ -2628,12 +2752,12 @@
  * Helper to create OpenSSL TCP sockets.
  */
 template <typename Address>
-using SocketTls = Socket<Address, Tls>;
+using SocketTls = Socket<Address, protocol::Tls>;
 
 /**
  * Helper to create OpenSSL TCP/Ip sockets.
  */
-using SocketTlsIp = Socket<Ip, Tls>;
+using SocketTlsIp = Socket<address::Ip, protocol::Tls>;
 
 #endif // !SOCKET_NO_SSL
 
@@ -3243,7 +3367,7 @@
 	StreamConnection(Socket<Address, Protocol> s)
 		: m_socket{std::move(s)}
 	{
-		m_socket.setBlockMode(false);
+		m_socket.set(net::option::SockBlockMode{false});
 	}
 
 	/**
@@ -3387,12 +3511,7 @@
 		assert(client->socket().action() != Action::None);
 
 		m_listener.remove(client->socket().handle());
-
-		if (client->socket().condition() == Condition::Readable) {
-			m_listener.set(client->socket().handle(), Condition::Readable);
-		} else {
-			m_listener.set(client->socket().handle(), Condition::Writable);
-		}
+		m_listener.set(client->socket().handle(), client->socket().condition());
 	}
 
 	/*
@@ -3725,12 +3844,7 @@
 		assert(m_socket.action() != Action::None);
 
 		m_listener.remove(m_socket.handle());
-
-		if (m_socket.condition() == Condition::Readable) {
-			m_listener.set(m_socket.handle(), Condition::Readable);
-		} else {
-			m_listener.set(m_socket.handle(), Condition::Writable);
-		}
+		m_listener.set(m_socket.handle(), m_socket.condition());
 	}
 
 	/*
@@ -3777,8 +3891,8 @@
 				 * At this step, it is possible that we were completing a receive operation, in this
 				 * case the write flag may be removed, add it if required.
 				 */
-				if (!m_output.empty()) {
-					m_listener.set(m_socket.handle(), Condition::Writable);
+				if (m_output.empty()) {
+					m_listener.unset(m_socket.handle(), Condition::Writable);
 				}
 
 				m_onRead(received);
@@ -3841,7 +3955,7 @@
 	StreamClient(Protocol protocol = {}, const Address &address = {})
 		: m_socket{std::move(protocol), address}
 	{
-		m_socket.setBlockMode(false);
+		m_socket.set(net::option::SockBlockMode{false});
 		m_listener.set(m_socket.handle(), Condition::Readable);
 	}
 
--- a/C++/tests/Socket/main.cpp	Thu Nov 05 16:42:23 2015 +0100
+++ b/C++/tests/Socket/main.cpp	Thu Nov 05 22:28:40 2015 +0100
@@ -27,6 +27,10 @@
 #include <Sockets.h>
 
 using namespace net;
+using namespace net::address;
+using namespace net::option;
+using namespace net::protocol;
+
 using namespace std::literals::chrono_literals;
 
 /*
@@ -39,11 +43,11 @@
 	SocketTcpIp s;
 
 	try {
-		s.set(option::ReuseAddress{true});
-		ASSERT_TRUE(s.get<option::ReuseAddress>());
+		s.set(option::SockReuseAddress{true});
+		ASSERT_TRUE(s.get<option::SockReuseAddress>());
 
-		s.set(option::ReuseAddress{false});
-		ASSERT_FALSE(s.get<option::ReuseAddress>());
+		s.set(option::SockReuseAddress{false});
+		ASSERT_FALSE(s.get<option::SockReuseAddress>());
 	} catch (const std::exception &ex) {
 		FAIL() << ex.what();
 	}
@@ -66,7 +70,7 @@
 
 TEST(Options, v6only)
 {
-	SocketTcpIp s;
+	SocketTcpIp s{Tcp{}, Ip{Ip::v6}};
 
 	try {
 		s.set(option::Ipv6Only{true});
@@ -151,8 +155,6 @@
  * UDP tests
  * -------------------------------------------------------- */
 
-#if 0
-
 class UdpServerTest : public testing::Test {
 protected:
 	SocketUdp<Ip> m_server;
@@ -204,8 +206,6 @@
 	});
 }
 
-#endif
-
 /* --------------------------------------------------------
  * Listener: set function
  * -------------------------------------------------------- */
@@ -533,7 +533,7 @@
 public:
 	NonBlockingConnectTest()
 	{
-		m_client.setBlockMode(false);
+		m_client.set(SockBlockMode{false});
 	}
 
 	~NonBlockingConnectTest()