Daniele Bartolini 11 лет назад
Родитель
Сommit
96c2cbb979
1 измененных файлов с 241 добавлено и 477 удалено
  1. 241 477
      engine/core/network/socket.h

+ 241 - 477
engine/core/network/socket.h

@@ -60,58 +60,68 @@ namespace crown
 
 struct ConnectResult
 {
-	enum { NO_ERROR, REFUSED, TIMEOUT, UNKNOWN } error;
+	enum { NO_ERROR, BAD_SOCKET, REFUSED, TIMEOUT, UNKNOWN } error;
 };
 
 struct ReadResult
 {
-	enum { NO_ERROR, REMOTE_CLOSED, TIMEOUT, UNKNOWN } error;
+	enum { NO_ERROR, BAD_SOCKET, REMOTE_CLOSED, TIMEOUT, UNKNOWN } error;
 	size_t bytes_read;
 };
 
 struct WriteResult
 {
-	enum { NO_ERROR, REMOTE_CLOSED, TIMEOUT, UNKNOWN } error;
+	enum { NO_ERROR, BAD_SOCKET, REMOTE_CLOSED, TIMEOUT, UNKNOWN } error;
 	size_t bytes_wrote;
 };
 
 struct AcceptResult
 {
-	enum { NO_ERROR, NO_CONNECTION, UNKNOWN } error;
+	enum { NO_ERROR, BAD_SOCKET, NO_CONNECTION, UNKNOWN } error;
 };
 
 struct TCPSocket
 {
 	//-----------------------------------------------------------------------------
 	TCPSocket()
+#if CROWN_PLATFORM_POSIX
 		: m_socket(0)
+#elif CROWN_PLATFORM_WINDOWS
+		: m_socket(INVALID_SOCKET)
+#endif
 	{
 	}
 
 	//-----------------------------------------------------------------------------
-	TCPSocket(int socket)
-		: m_socket(socket)
+	void open()
 	{
+#if CROWN_PLATFORM_POSIX
+		m_socket = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+		CE_ASSERT(m_socket >= 0, "socket: errno = %d", errno);
+#elif CROWN_PLATFORM_WINDOWS
+		m_socket = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+		CE_ASSERT(m_socket >= 0, "socket: WSAGetLastError = %d", WSAGetLastError());
+#endif
 	}
 
 	//-----------------------------------------------------------------------------
-	ConnectResult connect(const NetAddress& destination, uint16_t port)
+	ConnectResult connect(const NetAddress& ip, uint16_t port)
 	{
 		close();
-		m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
-		CE_ASSERT(m_socket >= 0, "socket: errno = %d", errno);
+		open();
+
+		ConnectResult cr;
+		cr.error = ConnectResult::NO_ERROR;
 
+#if CROWN_PLATFORM_POSIX
 		sockaddr_in addr_in;
 		addr_in.sin_family = AF_INET;
-		addr_in.sin_addr.s_addr = htonl(destination.address());
-		addr_in.sin_port = htons(port);
+		addr_in.sin_addr.s_addr = htonl(ip.address());
+		addr_in.sin_port = ::htons(port);
 
-		int res = ::connect(m_socket, (const sockaddr*)&addr_in, sizeof(sockaddr_in));
+		int err = ::connect(m_socket, (const sockaddr*)&addr_in, sizeof(sockaddr_in));
 
-		ConnectResult cr;
-		cr.error = ConnectResult::NO_ERROR;
-
-		if (res == 0)
+		if (err == 0)
 			return cr;
 
 		if (errno == ECONNREFUSED)
@@ -122,143 +132,159 @@ struct TCPSocket
 			cr.error = ConnectResult::UNKNOWN;
 
 		return cr;
+#elif CROWN_PLATFORM_WINDOWS
+		sockaddr_in addr_in;
+		addr_in.sin_family = AF_INET;
+		addr_in.sin_addr.s_addr = ::htonl(ip.address());
+		addr_in.sin_port = ::htons(port);
+
+		int err = ::connect(m_socket, (const sockaddr*)&addr_in, sizeof(sockaddr_in));
+
+		if (err == 0)
+			return cr;
+
+		int wsaerr = WSAGetLastError();
+		if (wsaerr == WSAECONNREFUSED)
+			cr.error = ConnectResult::REFUSED;
+		else if (wsaerr == WSAETIMEDOUT)
+			cr.error = ConnectResult::TIMEOUT;
+		else
+			cr.error = ConnectResult::UNKNOWN;
+
+		return cr;
+#endif
 	}
 
 	//-----------------------------------------------------------------------------
 	bool bind(uint16_t port)
 	{
 		close();
-		m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
-		CE_ASSERT(m_socket >= 0, "socket: errno = %d", errno);
-
+		open();
+		set_resuse_address(true);
+#if CROWN_PLATFORM_POSIX
 		sockaddr_in address;
 		address.sin_family = AF_INET;
 		address.sin_addr.s_addr = htonl(INADDR_ANY);
 		address.sin_port = htons(port);
 
-		set_resuse_address(true);
-		int bind_ret = ::bind(m_socket, (const sockaddr*) &address, sizeof(sockaddr_in));
-		CE_ASSERT(bind_ret != -1, "bind: errno = %d", errno);
-		CE_UNUSED(bind_ret);
+		int err = ::bind(m_socket, (const sockaddr*) &address, sizeof(sockaddr_in));
+		CE_ASSERT(err == 0, "bind: errno = %d", errno);
+		CE_UNUSED(err);
+		return true;
+#elif CROWN_PLATFORM_WINDOWS
+		sockaddr_in address;
+		address.sin_family = AF_INET;
+		address.sin_addr.s_addr = htonl(INADDR_ANY);
+		address.sin_port = htons(port);
 
+		int err = ::bind(m_socket, (const sockaddr*) &address, sizeof(sockaddr_in));
+		CE_ASSERT(err == 0, "bind: WSAGetLastError = %d", WSAGetLastError());
+		CE_UNUSED(err);
 		return true;
+#endif
 	}
 
 	//-----------------------------------------------------------------------------
 	void listen(uint32_t max)
 	{
-		int listen_ret = ::listen(m_socket, max);
-		CE_ASSERT(listen_ret != -1, "listen: errno = %d", errno);
-		CE_UNUSED(listen_ret);
+#if CROWN_PLATFORM_POSIX
+		int err = ::listen(m_socket, max);
+		CE_ASSERT(err == 0, "listen: errno = %d", errno);
+		CE_UNUSED(err);
+#elif CROWN_PLATFORM_WINDOWS
+		int err = ::listen(m_socket, max);
+		CE_ASSERT(err == 0, "listen: WSAGetLastError = %d", WSAGetLastError());
+		CE_UNUSED(err);
+#endif
 	}
 
-	//-----------------------------------------------------------------------------
-	AcceptResult accept_nonblock(TCPSocket& c)
+	AcceptResult accept_internal(TCPSocket& c)
 	{
-		set_blocking(false);
+		AcceptResult ar;
+		ar.error = AcceptResult::NO_ERROR;
 
-		sockaddr_in client;
-		size_t client_size = sizeof(client);
-		int sock = ::accept(m_socket, (sockaddr*) &client, (socklen_t*) &client_size);
+#if CROWN_PLATFORM_POSIX
+		int err = ::accept(m_socket, NULL, NULL);
+
+		if (err >= 0)
+			c.m_socket = err;
+		else if (err == -1 && errno == EBADF)
+			ar.error = AcceptResult::BAD_SOCKET;
+		else if (err == -1 && (errno == EAGAIN || errno == EWOULDBLOCK))
+			ar.error = AcceptResult::NO_CONNECTION;
+		else
+			ar.error = AcceptResult::UNKNOWN;
 
-		AcceptResult result;
-		if (sock == -1 && (errno == EAGAIN || errno == EWOULDBLOCK))
-		{
-			result.error = AcceptResult::NO_CONNECTION;
-		}
-		else if (sock == -1)
+		return ar;
+#elif CROWN_PLATFORM_WINDOWS
+		int err = ::accept(m_socket, NULL, NULL);
+
+		if (err != INVALID_SOCKET)
 		{
-			result.error = AcceptResult::UNKNOWN;
+			c.m_socket = err;
+			return ar;
 		}
+
+		int wsaerr = WSAGetLastError();
+		if (wsaerr == WSAEWOULDBLOCK))
+			ar.error = AcceptResult::NO_CONNECTION;
 		else
-		{
-			result.error = AcceptResult::NO_ERROR;
-			c.m_socket = sock;
-		}
+			ar.error = AcceptResult::UNKNOWN;
 
-		return result;
+		return ar;
+#endif		
+	}
+
+	//-----------------------------------------------------------------------------
+	AcceptResult accept_nonblock(TCPSocket& c)
+	{
+		set_blocking(false);
+		return accept_internal(c);
 	}
 
 	//-----------------------------------------------------------------------------
 	AcceptResult accept(TCPSocket& c)
 	{
 		set_blocking(true);
-
-		sockaddr_in client;
-		size_t client_size = sizeof(client);
-
-		int sock = ::accept(m_socket, (sockaddr*) &client, (socklen_t*) &client_size);
-
-		AcceptResult result;
-		if (sock == -1)
-		{
-			result.error = AcceptResult::UNKNOWN;
-		}
-		else
-		{
-			result.error = AcceptResult::NO_ERROR;
-			c.m_socket = sock;
-		}
-
-		return result;
+		return accept_internal(c);
 	}
 
 	//-----------------------------------------------------------------------------
 	void close()
 	{
+#if CROWN_PLATFORM_POSIX
 		if (m_socket != 0)
 		{
 			::close(m_socket);
 			m_socket = 0;
 		}
-	}
-
-	//-----------------------------------------------------------------------------
-	ReadResult read_nonblock(void* data, size_t size)
-	{
-		set_blocking(false);
-		ssize_t read_bytes = ::read(m_socket, (char*) data, size);
-
-		ReadResult rr;
-		if (read_bytes == -1 && (errno == EAGAIN || errno == EWOULDBLOCK))
-		{
-			rr.error = ReadResult::NO_ERROR;
-			rr.bytes_read = 0;
-		}
-		else if (read_bytes == -1 && errno == ETIMEDOUT)
-		{
-			rr.error = ReadResult::TIMEOUT;
-		}
-		else if (read_bytes == 0)
-		{
-			rr.error = ReadResult::REMOTE_CLOSED;
-		}
-		else
+#elif CROWN_PLATFORM_WINDOWS
+		if (m_socket != INVALID_SOCKET)
 		{
-			rr.error = ReadResult::NO_ERROR;
-			rr.bytes_read = read_bytes;
+			::closesocket(m_socket);
+			m_socket = INVALID_SOCKET;
 		}
-
-		return rr;
+#endif
 	}
 
-	//-----------------------------------------------------------------------------
-	ReadResult read(void* data, size_t size)
+	ReadResult read_internal(void* data, size_t size)
 	{
-		set_blocking(true);
+		ReadResult rr;
+		rr.error = ReadResult::NO_ERROR;
+		rr.bytes_read = 0;
 
-		// Ensure all data is read
+#if CROWN_PLATFORM_POSIX
 		char* buf = (char*) data;
 		size_t to_read = size;
-		ReadResult rr;
-		rr.bytes_read = 0;
-		rr.error = ReadResult::NO_ERROR;
 
 		while (to_read > 0)
 		{
-			ssize_t read_bytes = ::read(m_socket, buf, to_read);
+			ssize_t read_bytes = ::recv(m_socket, buf, to_read, 0);
 
-			if (read_bytes == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) continue;
+			if (read_bytes == -1 && (errno == EAGAIN || errno == EWOULDBLOCK))
+			{
+				return rr;
+			}
 			else if (read_bytes == -1 && errno == ETIMEDOUT)
 			{
 				rr.error = ReadResult::TIMEOUT;
@@ -275,74 +301,81 @@ struct TCPSocket
 			rr.bytes_read += read_bytes;
 		}
 
-		rr.error = ReadResult::NO_ERROR;
 		return rr;
+#elif CROWN_PLATFORM_WINDOWS
+		char* buf = (char*) data;
+		size_t to_read = size;
+
+		while (to_read > 0)
+		{
+			int read_bytes = ::recv(m_socket, buf, to_read, 0);
+
+			if (read_bytes == SOCKET_ERROR && WSAGetLastError() == WSAEWOULDBLOCK)
+				return rr;
+			else if (read_bytes == SOCKET_ERROR && WSAGetLastError() == WSAETIMEDOUT)
+			{
+				rr.error = ReadResult::TIMEOUT;
+				return rr;
+			}
+			else if (read_bytes == 0)
+			{
+				rr.error = ReadResult::REMOTE_CLOSED;
+				return rr;
+			}
+
+			buf += read_bytes;
+			to_read -= read_bytes;
+			result.bytes_read += read_bytes;
+		}
+
+		return rr;
+#endif
 	}
 
 	//-----------------------------------------------------------------------------
-	WriteResult write_nonblock(const void* data, size_t size)
+	ReadResult read_nonblock(void* data, size_t size)
 	{
 		set_blocking(false);
-		ssize_t bytes_wrote = ::send(m_socket, data, size, 0);
-
-		WriteResult wr;
-		if (bytes_wrote == -1 && (errno == EAGAIN || errno == EWOULDBLOCK))
-		{
-			wr.error = WriteResult::NO_ERROR;
-			wr.bytes_wrote = 0;
-		}
-		else if (bytes_wrote == -1 && errno == ETIMEDOUT)
-		{
-			wr.error = WriteResult::TIMEOUT;
-		}
-		else if (bytes_wrote == 0)
-		{
-			wr.error = WriteResult::REMOTE_CLOSED;
-		}
-		else
-		{
-			wr.error = WriteResult::UNKNOWN;
-		}
-
-		return wr;
+		return read_internal(data, size);
 	}
 
 	//-----------------------------------------------------------------------------
-	WriteResult write(const void* data, size_t size)
+	ReadResult read(void* data, size_t size)
 	{
 		set_blocking(true);
+		return read_internal(data, size);
+	}
 
-		const char* buf = (const char*) data;
-		size_t to_send = size;
+	WriteResult write_internal(const void* data, size_t size)
+	{
 		WriteResult wr;
-		wr.bytes_wrote = 0;
 		wr.error = WriteResult::NO_ERROR;
+		wr.bytes_wrote = 0;
+
+#if CROWN_PLATFORM_POSIX
+		const char* buf = (const char*) data;
+		size_t to_send = size;
 
-		// Ensure all data is sent
 		while (to_send > 0)
 		{
 			ssize_t bytes_wrote = ::send(m_socket, (const char*) buf, to_send, 0);
 
-			// Check for errors
-			if (bytes_wrote == -1)
+			if (bytes_wrote == -1 && (errno == EAGAIN || errno == EWOULDBLOCK))
+				return wr;
+			else if (bytes_wrote == -1 && errno == ETIMEDOUT)
+			{
+				wr.error = WriteResult::TIMEOUT;
+				return wr;
+			}
+			else if (bytes_wrote == 0)
+			{
+				wr.error = WriteResult::REMOTE_CLOSED;
+				return wr;
+			}
+			else
 			{
-				switch (errno)
-				{
-					case EAGAIN:
-					{
-						continue;
-					}
-					case ETIMEDOUT:
-					{
-						wr.error = WriteResult::TIMEOUT;
-						return wr;
-					}
-					default:
-					{
-						wr.error = WriteResult::UNKNOWN;
-						return wr;
-					}
-				}
+				wr.error = WriteResult::UNKNOWN;
+				return wr;
 			}
 
 			buf += bytes_wrote;
@@ -350,385 +383,116 @@ struct TCPSocket
 			wr.bytes_wrote += bytes_wrote;
 		}
 
-		wr.error = WriteResult::NO_ERROR;
 		return wr;
-	}
-
-	//-----------------------------------------------------------------------------
-	void set_blocking(bool blocking)
-	{
-		int flags = fcntl(m_socket, F_GETFL, 0);
-		fcntl(m_socket, F_SETFL, blocking ? (flags & ~O_NONBLOCK) : O_NONBLOCK);
-	}
-
-	//-----------------------------------------------------------------------------
-	void set_resuse_address(bool reuse)
-	{
-		int optval = (int) reuse;
-		setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
-	}
-
-	//-----------------------------------------------------------------------------
-	void set_timeout(uint32_t seconds)
-	{
-		struct timeval timeout;
-		timeout.tv_sec = seconds;
-		timeout.tv_usec = 0;
-		int res;
-		res = setsockopt (m_socket, SOL_SOCKET, SO_RCVTIMEO, (char*) &timeout, sizeof(timeout));
-		CE_ASSERT(res == 0, "setsockopt: errno: %d", errno);
-		res = setsockopt (m_socket, SOL_SOCKET, SO_SNDTIMEO, (char*) &timeout, sizeof(timeout));
-		CE_ASSERT(res == 0, "setsockopt: errno: %d", errno);
-	}
-
-private:
-
-	int m_socket;
-};
-
-
-/*
-class TCPSocket
-{
-public:
-	//-----------------------------------------------------------------------------
-	TCPSocket()
-		: m_socket(0)
-	{
-	}
-
-	//-----------------------------------------------------------------------------
-	TCPSocket(int socket)
-		: m_socket(socket)
-	{
-	}
-
-	//-----------------------------------------------------------------------------
-	bool connect(const NetAddress& destination, uint16_t port)
-	{
-		m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
-
-		CE_ASSERT(m_socket > 0, "Failed to create socket");
-
-		sockaddr_in address;
-		address.sin_family = AF_INET;
-		address.sin_addr.s_addr = ::htonl(destination.address());
-		address.sin_port = ::htons(port);
-
-		if (::connect(m_socket, (const sockaddr*)&address, sizeof(sockaddr_in)) < 0)
-		{
-			os::printf("Failed to connect socket\n");
-			close();
-			return false;
-		}
-
-		return true;
-	}
-
-	//-----------------------------------------------------------------------------
-	void close()
-	{
-		if (m_socket != 0)
-		{
-			::closesocket(m_socket);
-			m_socket = 0;
-		}
-	}
-
-	//-----------------------------------------------------------------------------
-	ReadResult read_nonblock(void* data, size_t size)
-	{
-		set_blocking(false);
-		int read_bytes = ::recv(m_socket, (char*) data, size, 0);
-
-		ReadResult result;
-		if (read_bytes == SOCKET_ERROR && (errno == WSAEWOULDBLOCK))
-		{
-			result.error = ReadResult::NO_ERROR;
-			result.bytes_read = 0;
-		}
-		else if (read_bytes == SOCKET_ERROR && errno == WSAETIMEDOUT)
-		{
-			result.error = ReadResult::TIMEOUT;
-		}
-		else if (read_bytes == SOCKET_ERROR)
-		{
-			result.error = ReadResult::UNKNOWN;
-		}
-		else if (read_bytes == 0)
-		{
-			result.error = ReadResult::REMOTE_CLOSED;
-		}
-		else
-		{
-			result.error = ReadResult::NO_ERROR;
-			result.bytes_read = read_bytes;
-		}
-
-		return result;
-	}
-
-	//-----------------------------------------------------------------------------
-	ReadResult read(void* data, size_t size)
-	{
-		set_blocking(true);
-
-		// Ensure all data is read
-		char* buf = (char*) data;
-		size_t to_read = size;
-		ReadResult result;
-		result.bytes_read = 0;
-		result.error = ReadResult::NO_ERROR;
+#elif CROWN_PLATFORM_WINDOWS
+		const char* buf = (const char*) data;
+		size_t to_send = size;
 
-		while (to_read > 0)
+		while (to_send > 0)
 		{
-			int read_bytes = recv(m_socket, buf, to_read, 0);
+			ssize_t bytes_wrote = ::send(m_socket, (const char*) buf, to_send, 0);
 
-			if (read_bytes == SOCKET_ERROR && (errno == WSAEWOULDBLOCK)) continue;
-			else if (read_bytes == SOCKET_ERROR && errno == WSAETIMEDOUT)
+			if (bytes_wrote == SOCKET_ERROR && WSAGetLastError() == WSAEWOULDBLOCK)
 			{
-				result.error = ReadResult::TIMEOUT;
-				return result;
+				return wr;
 			}
-			else if (read_bytes == 0)
+			else if (bytes_wrote == SOCKET_ERROR && WSAGetLastError() == WSAETIMEDOUT)
 			{
-				result.error = ReadResult::REMOTE_CLOSED;
-				return result;
+				wr.error = WriteResult::TIMEOUT;
+				return wr;
+			}
+			else if (bytes_wrote == 0)
+			{
+				wr.error = WriteResult::REMOTE_CLOSED;
+				return wr;
+			}
+			else
+			{
+				wr.error = WriteResult::UNKNOWN;
+				return wr;
 			}
 
-			buf += read_bytes;
-			to_read -= read_bytes;
-			result.bytes_read += read_bytes;
+			buf += bytes_wrote;
+			to_send -= bytes_wrote;
+			wr.bytes_wrote += bytes_wrote;
 		}
 
-		result.error = ReadResult::NO_ERROR;
-		return result;
+		return wr;
+#endif
 	}
 
 	//-----------------------------------------------------------------------------
 	WriteResult write_nonblock(const void* data, size_t size)
 	{
 		set_blocking(false);
-		int bytes_wrote = ::send(m_socket, (char*)data, size, 0);
-
-		WriteResult result;
-		if (bytes_wrote == SOCKET_ERROR && (errno == WSAEWOULDBLOCK))
-		{
-			result.error = WriteResult::NO_ERROR;
-			result.bytes_wrote = 0;
-		}
-		else if (bytes_wrote == SOCKET_ERROR && errno == WSAETIMEDOUT)
-		{
-			result.error = WriteResult::TIMEOUT;
-		}
-		else if (bytes_wrote == 0)
-		{
-			result.error = WriteResult::REMOTE_CLOSED;
-		}
-		else
-		{
-			result.error = WriteResult::UNKNOWN;
-		}
-
-		return result;
+		return write_internal(data, size);
 	}
 
 	//-----------------------------------------------------------------------------
 	WriteResult write(const void* data, size_t size)
 	{
 		set_blocking(true);
-
-		const char* buf = (const char*) data;
-		size_t to_send = size;
-		WriteResult result;
-		result.bytes_wrote = 0;
-		result.error = WriteResult::NO_ERROR;
-
-		// Ensure all data is sent
-		while (to_send > 0)
-		{
-			int bytes_wrote = ::send(m_socket, (const char*) buf, to_send, 0);
-
-			// Check for errors
-			if (bytes_wrote == SOCKET_ERROR)
-			{
-				switch (errno)
-				{
-					case WSAEWOULDBLOCK:
-					{
-						continue;
-					}
-					case WSAETIMEDOUT:
-					{
-						result.error = WriteResult::TIMEOUT;
-						return result;
-					}
-					default:
-					{
-						result.error = WriteResult::UNKNOWN;
-						return result;
-					}
-				}
-			}
-
-			buf += bytes_wrote;
-			to_send -= bytes_wrote;
-			result.bytes_wrote += bytes_wrote;
-		}
-
-		result.error = WriteResult::NO_ERROR;
-		return result;
+		return write_internal(data, size);
 	}
 
 	//-----------------------------------------------------------------------------
 	void set_blocking(bool blocking)
 	{
-		//Warning! Blocking sockets under windows seem to have some drawback, see http://www.sockets.com/winsock.htm#IoctlSocket
+#if CROWN_PLATFORM_POSIX
+		int flags = fcntl(m_socket, F_GETFL, 0);
+		fcntl(m_socket, F_SETFL, blocking ? (flags & ~O_NONBLOCK) : O_NONBLOCK);
+#elif CROWN_PLATFORM_WINDOWS
+		//Warning! http://www.sockets.com/winsock.htm#IoctlSocket
 		u_long non_blocking = blocking ? 0 : 1;
 		ioctlsocket(m_socket, FIONBIO, &non_blocking);
+#endif
 	}
 
 	//-----------------------------------------------------------------------------
 	void set_resuse_address(bool reuse)
 	{
+#if CROWN_PLATFORM_POSIX
 		int optval = (int) reuse;
-		setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, (char*)&optval, sizeof(optval));
+		int err = setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
+		CE_ASSERT(err == 0, "setsockopt: errno = %d", errno);
+#elif CROWN_PLATFORM_WINDOWS
+		int optval = (int) reuse;
+		int err = setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
+		CE_ASSERT(err == 0, "setsockopt: WSAGetLastError = %d", WSAGetLastError());
+#endif
 	}
 
 	//-----------------------------------------------------------------------------
 	void set_timeout(uint32_t seconds)
 	{
+#if CROWN_PLATFORM_POSIX
 		struct timeval timeout;
 		timeout.tv_sec = seconds;
 		timeout.tv_usec = 0;
-		int res;
-		res = setsockopt (m_socket, SOL_SOCKET, SO_RCVTIMEO, (char*) &timeout, sizeof(timeout));
-		CE_ASSERT(res == 0, "Failed to set timeout on socket: errno: %d", errno);
-		res = setsockopt (m_socket, SOL_SOCKET, SO_SNDTIMEO, (char*) &timeout, sizeof(timeout));
-		CE_ASSERT(res == 0, "Failed to set timeout on socket: errno: %d", errno);
-	}
-
-public:
-
-	SOCKET m_socket;
-};
-
-class TCPServer
-{
-public:
-
-	//-----------------------------------------------------------------------------
-	bool open(uint16_t port)
-	{
-		m_server.m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
-		CE_ASSERT(m_server.m_socket > 0, "Failed to create socket");
-
-		m_server.set_resuse_address(true);
-
-		// Bind socket
-		sockaddr_in address;
-		address.sin_family = AF_INET;
-		address.sin_addr.s_addr = htonl(INADDR_ANY);
-		address.sin_port = htons(port);
-
-		int bind_ret = bind(m_server.m_socket, (const sockaddr*) &address, sizeof(sockaddr_in));
-		CE_ASSERT(bind_ret != -1, "Failed to bind socket: errno: %d", errno);
-
-		return true;
-	}
-
-	//-----------------------------------------------------------------------------
-	void close()
-	{
-		m_server.close();
-	}
-
-	//-----------------------------------------------------------------------------
-	void listen(uint32_t max)
-	{
-		int listen_ret = ::listen(m_server.m_socket, max);
-		CE_ASSERT(listen_ret != -1, "Failed to listen on socket: errno: %d", errno);
-	}
-
-	//-----------------------------------------------------------------------------
-	AcceptResult accept_nonblock(TCPSocket& c)
-	{
-		m_server.set_blocking(false);
-
-		sockaddr_in client;
-		size_t client_size = sizeof(client);
-		int sock = ::accept(m_server.m_socket, (sockaddr*) &client, (int*) &client_size);
-
-		AcceptResult result;
-		if (sock == SOCKET_ERROR && (errno == WSAEWOULDBLOCK))
-		{
-			result.error = AcceptResult::NO_CONNECTION;
-		}
-		else if (sock == SOCKET_ERROR)
-		{
-			result.error = AcceptResult::UNKNOWN;
-		}
-		else
-		{
-			result.error = AcceptResult::NO_ERROR;
-			c.m_socket = sock;
-		}
-
-		return result;
-	}
-
-	//-----------------------------------------------------------------------------
-	AcceptResult accept(TCPSocket& c)
-	{
-		m_server.set_blocking(true);
-
-		sockaddr_in client;
-		size_t client_size = sizeof(client);
-
-		int sock = ::accept(m_server.m_socket, (sockaddr*) &client, (int*) &client_size);
-
-		AcceptResult result;
-		if (sock == SOCKET_ERROR)
-		{
-			result.error = AcceptResult::UNKNOWN;
-		}
-		else
-		{
-			result.error = AcceptResult::NO_ERROR;
-			c.m_socket = sock;
-		}
-
-		return result;
-	}
-
-	//-----------------------------------------------------------------------------
-	ReadResult read_nonblock(void* data, size_t size)
-	{
-		return m_server.read_nonblock(data, size);
-	}
-
-	//-----------------------------------------------------------------------------
-	ReadResult read(void* data, size_t size)
-	{
-		return m_server.read(data, size);
-	}
-
-	//-----------------------------------------------------------------------------
-	WriteResult write_nonblock(void* data, size_t size)
-	{
-		return m_server.write_nonblock(data, size);
-	}
-
-	//-----------------------------------------------------------------------------
-	WriteResult write(const void* data, size_t size)
-	{
-		return m_server.write(data, size);
+		int err;
+		err = setsockopt (m_socket, SOL_SOCKET, SO_RCVTIMEO, (char*) &timeout, sizeof(timeout));
+		CE_ASSERT(err == 0, "setsockopt: errno: %d", errno);
+		err = setsockopt (m_socket, SOL_SOCKET, SO_SNDTIMEO, (char*) &timeout, sizeof(timeout));
+		CE_ASSERT(err == 0, "setsockopt: errno: %d", errno);
+#elif CROWN_PLATFORM_WINDOWS
+		struct timeval timeout;
+		timeout.tv_sec = seconds;
+		timeout.tv_usec = 0;
+		int err;
+		err = setsockopt (m_socket, SOL_SOCKET, SO_RCVTIMEO, (char*) &timeout, sizeof(timeout));
+		CE_ASSERT(err == 0, "setsockopt: WSAGetLastError: %d", WSAGetLastError());
+		err = setsockopt (m_socket, SOL_SOCKET, SO_SNDTIMEO, (char*) &timeout, sizeof(timeout));
+		CE_ASSERT(err == 0, "setsockopt: WSAGetLastError: %d", WSAGetLastError());
+#endif
 	}
 
 private:
 
-	TCPSocket m_server;
+#if CROWN_PLATFORM_POSIX
+	int m_socket;
+#elif CROWN_PLATFORM_WINDOWS
+	SOCKET m_socket;
+#endif
 };
-*/
 
 } // namespace crown