<commit_before>/* Copyright 2010 <NAME>

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License. */

/** @file Socket.cpp
	@brief */

#include <string>
#include <cassert>
#include <utility>
#include <sstream>

#ifdef KNET_USE_BOOST
#include <boost/thread/thread.hpp>
#endif

#include "kNet/DebugMemoryLeakCheck.h"

#include "kNet/Network.h"

#include "kNet/Socket.h"
#include "kNet/NetworkLogging.h"
#include "kNet/EventArray.h"

using namespace std;

#ifdef UNIX
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/tcp.h>
#endif

#ifdef WIN32
const int numConcurrentReceiveBuffers = 4;
const int numConcurrentSendBuffers = 4;
#endif

namespace kNet
{

std::string SocketTransportLayerToString(SocketTransportLayer transport)
{
	switch(transport)
	{
	case SocketOverUDP: return "UDP";
	case SocketOverTCP: return "TCP";
	default:
		{
			std::stringstream ss;
			ss << "Invalid SocketTransportLayer (" << (int)transport << ")!";
			return ss.str();
		}
	}
}

SocketTransportLayer StringToSocketTransportLayer(const char *str)
{
	if (!str)
		return InvalidTransportLayer;
	if (!_stricmp(str, "tcp") || !_stricmp(str, "SocketOverTCP"))
		return SocketOverTCP;
	if (!_stricmp(str, "udp") || !_stricmp(str, "SocketOverUDP"))
		return SocketOverUDP;
	return InvalidTransportLayer;
}


std::string SocketTypeToString(SocketType type)
{
	switch(type)
	{
	case ServerListenSocket: return "Server listen socket";
	case ServerClientSocket: return "Server client socket";
	case ClientSocket: return "Client socket";
	default:
		{
			std::stringstream ss;
			ss << "Invalid SocketType (" << (int)type << ")!";
			return ss.str();
		}
	}
}

Socket::Socket()
:connectSocket(INVALID_SOCKET),
writeOpen(false),
readOpen(false),
transport(InvalidTransportLayer),
type(InvalidSocketType)
#ifdef WIN32
,queuedReceiveBuffers(numConcurrentReceiveBuffers)
,queuedSendBuffers(numConcurrentSendBuffers)
#endif
{
	localEndPoint.Reset();
	remoteEndPoint.Reset();
}

Socket::~Socket()
{
	// We cannot Close() the socket here, since the same underlying BSD SOCKET handle can be shared
	// between multiple Socket objects. We rely instead to non-RAII behavior and manually remembering to 
	// Close().
#ifdef WIN32
	FreeOverlappedTransferBuffers();
#endif
}

Socket::Socket(SOCKET connection, const EndPoint &localEndPoint_, const char *localHostName_,
	const EndPoint &remoteEndPoint_, const char *remoteHostName_, 
	SocketTransportLayer transport_, SocketType type_, size_t maxSendSize_)
:connectSocket(connection), localEndPoint(localEndPoint_), localHostName(localHostName_),
remoteEndPoint(remoteEndPoint_), remoteHostName(remoteHostName_), 
transport(transport_), type(type_), maxSendSize(maxSendSize_),
writeOpen(true), readOpen(true)
#ifdef WIN32
,queuedReceiveBuffers(numConcurrentReceiveBuffers)
,queuedSendBuffers(numConcurrentSendBuffers)
#endif
{
	SetSendBufferSize(512 * 1024);
	SetReceiveBufferSize(512 * 1024);
	udpPeerAddress = remoteEndPoint.ToSockAddrIn();
}

Socket::Socket(const Socket &rhs)
#ifdef WIN32
:queuedReceiveBuffers(numConcurrentReceiveBuffers)
,queuedSendBuffers(numConcurrentSendBuffers)
#endif
{
	*this = rhs;
}

Socket &Socket::operator=(const Socket &rhs)
{
#ifdef WIN32
	// We would be losing data if Socket is copied from old to new when data is present in the receive buffers,
	// since the receive buffers are not moved or copied to the new Socket.
	assert(queuedReceiveBuffers.Size() == 0);
#endif

	if (this == &rhs)
		return *this;

	connectSocket = rhs.connectSocket;
	localEndPoint = rhs.localEndPoint;
	localHostName = rhs.localHostName;
	remoteEndPoint = rhs.remoteEndPoint;
	remoteHostName = rhs.remoteHostName;
	transport = rhs.transport;
	type = rhs.type;
	maxSendSize = rhs.maxSendSize;
	writeOpen = rhs.writeOpen;
	readOpen = rhs.readOpen;
	udpPeerAddress = rhs.udpPeerAddress;

	return *this;
}

bool Socket::Connected() const
{
	return connectSocket != INVALID_SOCKET;
}

OverlappedTransferBuffer *AllocateOverlappedTransferBuffer(int bytes)
{
	OverlappedTransferBuffer *buffer = new OverlappedTransferBuffer;
	memset(buffer, 0, sizeof(OverlappedTransferBuffer));
	buffer->buffer.buf = new char[bytes];
	buffer->buffer.len = bytes;
#ifdef WIN32
	buffer->overlapped.hEvent = WSACreateEvent();
	if (buffer->overlapped.hEvent == WSA_INVALID_EVENT)
	{
		LOG(LogError, "Socket.cpp:AllocateOverlappedTransferBuffer: WSACreateEvent failed!");
		delete[] buffer->buffer.buf;
		delete buffer;
		return 0;
	}
#endif

	return buffer;
}

void DeleteOverlappedTransferBuffer(OverlappedTransferBuffer *buffer)
{
	if (!buffer)
		return;
	delete[] buffer->buffer.buf;
#ifdef WIN32
	BOOL success = WSACloseEvent(buffer->overlapped.hEvent);
	if (success == FALSE)
		LOG(LogError, "Socket.cpp:DeleteOverlappedTransferBuffer: WSACloseEvent failed!");
	buffer->overlapped.hEvent = WSA_INVALID_EVENT;
#endif
	delete buffer;
}

void Socket::SetSendBufferSize(int bytes)
{
	socklen_t len = sizeof(bytes);
	if (setsockopt(connectSocket, SOL_SOCKET, SO_SNDBUF, (char*)&bytes, len))
		LOG(LogError, "Socket::SetSendBufferSize: setsockopt failed with error %s!", Network::GetLastErrorString().c_str());
}

void Socket::SetReceiveBufferSize(int bytes)
{
	socklen_t len = sizeof(bytes);
	if (setsockopt(connectSocket, SOL_SOCKET, SO_RCVBUF, (char*)&bytes, len))
		LOG(LogError, "Socket::SetReceiveBufferSize: setsockopt failed with error %s!", Network::GetLastErrorString().c_str());
}

int Socket::SendBufferSize() const
{
	int bytes = 0;
	socklen_t len = sizeof(bytes);
	if (getsockopt(connectSocket, SOL_SOCKET, SO_SNDBUF, (char*)&bytes, &len))
	{
		LOG(LogError, "Socket::SendBufferSize: getsockopt failed with error %s!", Network::GetLastErrorString().c_str());
		return 0;
	}
	return bytes;
}

int Socket::ReceiveBufferSize() const
{
	int bytes = 0;
	socklen_t len = sizeof(bytes);
	if (getsockopt(connectSocket, SOL_SOCKET, SO_RCVBUF, (char*)&bytes, &len))
	{
		LOG(LogError, "Socket::ReceiveBufferSize: getsockopt failed with error %s!", Network::GetLastErrorString().c_str());
		return 0;
	}

	return bytes;
}

#ifdef WIN32
void Socket::EnqueueNewReceiveBuffer(OverlappedTransferBuffer *buffer)
{
	if (!readOpen || queuedReceiveBuffers.CapacityLeft() == 0 || IsUDPSlaveSocket())
	{
		DeleteOverlappedTransferBuffer(buffer); // buffer may be a zero pointer, but that is alright.
		return;
	}

	if (!buffer)
	{
		const int receiveBufferSize = 16384; // This is best to be at least 9K (the largest size of jumbo datagrams commonly supported)
		buffer = AllocateOverlappedTransferBuffer(receiveBufferSize);
		if (!buffer)
		{
			LOG(LogError, "Socket::EnqueueNewReceiveBuffer: Call to AllocateOverlappedTransferBuffer failed!");
			return;
		}
	}

	if (WSAResetEvent(buffer->overlapped.hEvent) != TRUE)
		LOG(LogError, "Socket::EnqueueNewReceiveBuffer: WSAResetEvent failed!");

	unsigned long flags = 0;
	int ret;

	if (IsUDPServerSocket())
	{
		buffer->fromLen = sizeof(buffer->from);
		ret = WSARecvFrom(connectSocket, &buffer->buffer, 1, (LPDWORD)&buffer->bytesContains, &flags, (sockaddr*)&buffer->from, &buffer->fromLen, &buffer->overlapped, 0);
	}
	else
	{
		ret = WSARecv(connectSocket, &buffer->buffer, 1, (LPDWORD)&buffer->bytesContains, &flags, &buffer->overlapped, 0);
	}

	int error = (ret == 0) ? 0 : Network::GetLastError();
	if (ret == 0 || (ret == SOCKET_ERROR && error == WSA_IO_PENDING)) // If ret is not 0, ret == SOCKET_ERROR according to MSDN. http://msdn.microsoft.com/en-us/library/ms741688(VS.85).aspx
	{
		if (ret == 0 && buffer->bytesContains == 0)
		{
			if (IsUDPServerSocket())
				LOG(LogError, "Unexpected: Received a message of 0 bytes on a UDP server socket!");

			LOG(LogInfo, "Socket::EnqueueNewReceiveBuffer: Received 0 bytes from the network. Read connection closed in socket %s.", ToString().c_str());
			readOpen = false;
			DeleteOverlappedTransferBuffer(buffer);
			return;
		}
		// Return value 0: The operation completed and we have received new data. Push it to a queue for the user to receive.
		// WSA_IO_PENDING: The operation was successfully enqueued.
		bool success = queuedReceiveBuffers.Insert(buffer);
		if (!success)
		{
			LOG(LogError, "Socket::EnqueueNewReceiveBuffer: queuedReceiveBuffers.Insert(buffer); failed!");
			DeleteOverlappedTransferBuffer(buffer);
		}
	}
	else if (error == WSAEDISCON)
	{
		if (IsUDPServerSocket())
			LOG(LogError, "Unexpected: Received WSAEDISCON on a UDP server socket!");

		LOG(LogError, "Socket::EnqueueNewReceivebuffer: WSAEDISCON. Connection closed in socket %s.", ToString().c_str());
		readOpen = false;
		///\todo Should do writeOpen = false; here as well?
		DeleteOverlappedTransferBuffer(buffer);
		return;
	}
	else
	{
		if (error != WSAEWOULDBLOCK && error != 0)
		{
			LOG(LogError, "Socket::EnqueueNewReceiveBuffer: %s for overlapped socket %s failed! Error: %s.", IsUDPServerSocket() ? "WSARecvFrom" : "WSARecv", ToString().c_str(), Network::GetErrorString(error).c_str());

			// We never close the server socket as a reaction on any error, since an error on one client could shut down
			// the whole server for all clients. This check is mainly here to ignore the 10054 error (WSAECONNRESET) which
			// is returned when UDP clients give back a ICMP Host Unreachable message, but since there may be other
			// client-specific errors, we don't explicitly check for the 10054 case only.
			if (!IsUDPServerSocket())
			{
				LOG(LogError, "Socket::EnqueueNewReceiveBuffer: Closing down socket.",  Network::GetErrorString(error).c_str());
				readOpen = false;
				writeOpen = false;
				Close();
			}
		}

		DeleteOverlappedTransferBuffer(buffer); // We failed to queue the buffer, free it up immediately to avoid leaking memory.
		return;
	}
}
#endif

void DumpBuffer(const char *description, const char *data, int size)
{
	printf("%s (%d bytes): ", description, size);
	for(int i = 0; i < min(size, 50); ++i)
		printf("%02X ", (unsigned int)(unsigned char)data[i]);
	printf("\n");
}

size_t Socket::Receive(char *dst, size_t maxBytes, EndPoint *endPoint)
{
	assert(dst);
	assert(maxBytes > 0);
	if (maxBytes == 0)
		return 0;

	if (connectSocket == INVALID_SOCKET)
		return 0;

	if (!readOpen)
		return 0;

	if (IsUDPSlaveSocket()) // UDP slave sockets are never read directly. Instead the UDP server socket reads all client data.
		return 0; // So, if we accidentally come here to read a UDP slave socket, act as if it never received any data.

	if (IsUDPServerSocket())
	{
		sockaddr_in from;
		socklen_t fromLen = sizeof(from);
		int numBytesRead = recvfrom(connectSocket, dst, maxBytes, 0, (sockaddr*)&from, &fromLen);
		if (numBytesRead == KNET_SOCKET_ERROR)
		{
			int error = Network::GetLastError();
			if (error != KNET_EWOULDBLOCK && error != 0)
				LOG(LogError, "Socket::Receive: recvfrom failed: %s in socket %s", Network::GetErrorString(error).c_str(), ToString().c_str());

			return 0;
		}
		if (numBytesRead > 0)
			LOG(LogData, "recvfrom (%d) in socket %s", numBytesRead, ToString().c_str());

		if (endPoint)
			*endPoint = EndPoint::FromSockAddrIn(from);

		return numBytesRead;
	}

	// If we reach here, this socket is a tcp connection socket (server->client or client->server), or a udp client->server socket.

	int ret = recv(connectSocket, dst, maxBytes, 0);

	if (ret > 0)
	{
		LOG(LogData, "Received %d bytes of data from socket 0x%X.", ret, (unsigned int)connectSocket);
		return (size_t)ret;
	}
	else if (ret == 0)
	{
		LOG(LogInfo, "Socket::Receive: Received 0 bytes from network. Read-connection closed to socket %s.", ToString().c_str());
		readOpen = false;
		return 0;
	}
	else
	{
		int error = Network::GetLastError();
		if (error != KNET_EWOULDBLOCK && error != 0)
		{
			LOG(LogError, "Socket::Receive: recv failed in socket %s. Error %s", ToString().c_str(), Network::GetErrorString(error).c_str());

			// We never close the server socket as a reaction on any error, since an error on one client could shut down
			// the whole server for all clients. This check is mainly here to ignore the 10054 error (WSAECONNRESET) which
			// is returned when UDP clients give back a ICMP Host Unreachable message, but since there may be other
			// client-specific errors, we don't explicitly check for the 10054 case only.
			if (!IsUDPServerSocket())
			{
				readOpen = false;
				writeOpen = false;
				Close();
			}
		}
		return 0;
	}
}

bool Socket::IsOverlappedReceiveReady() const
{
	if (IsUDPSlaveSocket()) // UDP slave sockets are never read directly. For these sockets, act as if they're never ready for reads.
		return false;

#ifdef WIN32
	if (queuedReceiveBuffers.Size() == 0)
		return false;
	return Event((*queuedReceiveBuffers.Front())->overlapped.hEvent, EventWaitRead).Test();
#else
	if (!readOpen)
		return false;

	EventArray ea;
	ea.AddEvent(Event(connectSocket, EventWaitRead));
	return ea.Wait(0) == 0;
#endif
}

Event Socket::GetOverlappedReceiveEvent()
{
	if (IsUDPSlaveSocket()) // UDP slave sockets are never read directly. For these sockets, return a null event that never fires.
		return Event();

#ifdef WIN32
	if (readOpen)
	{
		/// Prime the receive buffers to the full capacity if they weren't so yet.
		const int capacityLeft = queuedReceiveBuffers.CapacityLeft();
		for(int i = 0; i < capacityLeft; ++i)
			EnqueueNewReceiveBuffer();
	}

	if (queuedReceiveBuffers.Size() == 0)
		return Event();

	OverlappedTransferBuffer *receivedData = *queuedReceiveBuffers.Front();
	assert(receivedData);

	return Event(receivedData->overlapped.hEvent, EventWaitRead);
#else
	return Event(connectSocket, EventWaitRead);
#endif
}

Event Socket::GetOverlappedSendEvent()
{
	if (!writeOpen)
		return Event();

#ifdef WIN32
	if (queuedSendBuffers.Size() == 0)
		return Event();

	OverlappedTransferBuffer *sentData = *queuedSendBuffers.Front();
	assert(sentData);

	return Event(sentData->overlapped.hEvent, EventWaitWrite);
#else
	return Event(connectSocket, EventWaitWrite);
#endif
}

OverlappedTransferBuffer *Socket::BeginReceive()
{
	// UDP 'slave socket' is a socket descriptor on the server side that is a copy of the single UDP server listen socket.
	// The slave sockets don't receive data directly, but the server socket is used instead to receive data for them.
	if (IsUDPSlaveSocket())
	{
#ifdef WIN32
		assert(queuedReceiveBuffers.Size() == 0); // We shouldn't ever have queued a single receive buffer for this Socket.
#endif
		return 0; // If we happen to come here, act as if the socket never received any data.
	}

#ifdef WIN32
	if (readOpen)
	{
		// Insert new empty receive buffers to the Overlapped Transfer receive queue until we have a full capacity queue primed.
		const int capacityLeft = queuedReceiveBuffers.CapacityLeft();
		for(int i = 0; i < capacityLeft; ++i)
			EnqueueNewReceiveBuffer();
	}

	if (queuedReceiveBuffers.Size() == 0)
		return 0;

	OverlappedTransferBuffer *receivedData = *queuedReceiveBuffers.Front();
	DWORD flags = 0;
	BOOL ret = WSAGetOverlappedResult(connectSocket, &receivedData->overlapped, (LPDWORD)&receivedData->bytesContains, FALSE, &flags);
	int error = (ret == TRUE) ? 0 : Network::GetLastError();
	if (ret == TRUE)
	{
		queuedReceiveBuffers.PopFront();

		// Successfully receiving zero bytes with overlapped sockets means the same as recv() of 0 bytes,
		// peer has closed the write connection (but can still recv() until we also close the write connection).
		if (receivedData->bytesContains == 0)
		{
			DeleteOverlappedTransferBuffer(receivedData);
			if (readOpen)
				LOG(LogInfo, "Socket::BeginReceive: Received 0 bytes from the network. Read connection closed in socket %s.", ToString().c_str());
			readOpen = false;
			if (IsUDPServerSocket())
				LOG(LogError, "Socket::BeginReceive: UDP server socket transitioned to readOpen==false!");
			return 0;
		}

		return receivedData;
	}
	else if (error == WSAEDISCON)
	{
		queuedReceiveBuffers.PopFront();
		DeleteOverlappedTransferBuffer(receivedData);
		if (readOpen || writeOpen)
			LOG(LogError, "Socket::BeginReceive: WSAEDISCON. Bidirectionally closing connection in socket %s.", ToString().c_str());
		if (IsUDPServerSocket())
			LOG(LogError, "Socket::BeginReceive: Unexpected: Received WSAEDISCON on UDP server socket!");
		Close();
		return 0;
	}
	else if (error != WSA_IO_INCOMPLETE)
	{
		queuedReceiveBuffers.PopFront();
		if (readOpen || writeOpen)
			if (!(IsUDPServerSocket() && error == 10054)) // If we are running both UDP server and client on localhost, we can receive 10054 (Peer closed connection) on the server side, in which case, we ignore this error print.
				LOG(LogError, "Socket::BeginReceive: WSAGetOverlappedResult failed with code %d when reading from an overlapped socket! Reason: %s.", error, Network::GetErrorString(error).c_str());
		DeleteOverlappedTransferBuffer(receivedData);
		// Mark this socket closed, unless the read error was on a UDP server socket, in which case we must ignore
		// the read error on this buffer (an error on a single client connection cannot shut down the whole server!)
		if (!IsUDPServerSocket() && (readOpen || writeOpen))
		{
			LOG(LogError, "Socket::BeginReceive: Closing socket due to read error!");
			Close();
		}
	}
	return 0;
#else
	if (!readOpen)
		return 0;

	const int receiveBufferSize = 4096;
	OverlappedTransferBuffer *buffer = AllocateOverlappedTransferBuffer(receiveBufferSize);
	EndPoint source;
	buffer->bytesContains = Receive(buffer->buffer.buf, buffer->buffer.len, &source);
	if (buffer->bytesContains > 0)
	{
		buffer->fromLen = sizeof(buffer->from);
		buffer->from = source.ToSockAddrIn();
		return buffer;
	}
	else
	{
		// Did not get any data. Delete the buffer immediately.
		DeleteOverlappedTransferBuffer(buffer);
		return 0;
	}
#endif
}

void Socket::EndReceive(OverlappedTransferBuffer *buffer)
{
#ifdef WIN32
	if (readOpen)
	{
		EnqueueNewReceiveBuffer(buffer);
		return;
	}
#endif

	DeleteOverlappedTransferBuffer(buffer);
}

void Socket::Disconnect()
{
	if (connectSocket == INVALID_SOCKET)
		return;

	LOG(LogVerbose, "Socket::Disconnect(), this: %p.", this);

	if (transport == SocketOverTCP)
	{
		int result = shutdown(connectSocket, SD_SEND);
		if (result == KNET_SOCKET_ERROR)
			LOG(LogError, "Socket::Disconnect(): TCP socket shutdown(SD_SEND) failed: %s in socket %s.", Network::GetLastErrorString().c_str(), ToString().c_str());
		else
			LOG(LogInfo, "Socket::Disconnect(): TCP socket shutdown(SD_SEND) succeeded on socket %s.", ToString().c_str());
	}

	writeOpen = false;
}

void Socket::Close()
{
	if (connectSocket == INVALID_SOCKET)
	{
		assert(!readOpen && !writeOpen);
		return;
	}

	LOG(LogInfo, "Socket::Close(): Closing socket %s.", ToString().c_str());

	if (!IsUDPSlaveSocket())
	{
		// For UDP client sockets on the server side, the same SOCKET object is shared by 
		// all other client sockets and the UDP server socket. For those sockets, the UDP server socket is the owner
		// of the socket object, so the clients cannot close their sockets, as closing one would close them all.

		int result = shutdown(connectSocket, SD_BOTH);
		if (result == KNET_SOCKET_ERROR)
			LOG(LogError, "Socket::Close(): Socket shutdown(SD_BOTH) failed: %s in socket %s.", Network::GetLastErrorString().c_str(), ToString().c_str());
		else
			LOG(LogInfo, "Socket::Close(): Socket shutdown(SD_BOTH) succeeded on socket %s.", ToString().c_str());

		result = closesocket(connectSocket);
		if (result == KNET_SOCKET_ERROR)
			LOG(LogError, "Socket::Close(): closesocket() failed: %s in socket %s.", Network::GetLastErrorString().c_str(), ToString().c_str());
	}

	connectSocket = INVALID_SOCKET;
	localEndPoint.Reset();
	localHostName = "";
	remoteEndPoint.Reset();
	remoteHostName = "";
	transport = InvalidTransportLayer;
	type = InvalidSocketType;
	readOpen = false;
	writeOpen = false;

#ifdef WIN32
	FreeOverlappedTransferBuffers();
#endif
}

#ifdef WIN32
void Socket::FreeOverlappedTransferBuffers()
{
	LOG(LogVerbose, "Socket::FreeOverlappedTransferBuffers(), this: %p.", this);
/// \todo Use CancelIo to tear-down commited OverlappedTransferBuffers before freeing data. http://msdn.microsoft.com/en-us/library/aa363792(VS.85).aspx
	while(queuedReceiveBuffers.Size() > 0)
		DeleteOverlappedTransferBuffer(queuedReceiveBuffers.TakeFront());

	while(queuedSendBuffers.Size() > 0)
		DeleteOverlappedTransferBuffer(queuedSendBuffers.TakeFront());
}
#endif

void Socket::SetBlocking(bool isBlocking)
{
	if (connectSocket == INVALID_SOCKET)
		return;

	u_long nonBlocking = (isBlocking == false) ? 1 : 0;
#ifdef WIN32
	if (ioctlsocket(connectSocket, FIONBIO, &nonBlocking))
		LOG(LogError, "Socket::SetBlocking: ioctlsocket failed with error %s!", Network::GetLastErrorString().c_str());
#else
	int flags = fcntl(connectSocket, F_GETFL, 0);
	fcntl(connectSocket, F_SETFL, flags | O_NONBLOCK);
#endif
}

/// @return True on success, false otherwise.
bool Socket::Send(const char *data, size_t numBytes)
{
	if (connectSocket == INVALID_SOCKET)
	{
		LOG(LogError, "Trying to send a datagram to INVALID_SOCKET!");
		return false;
	}

	// Server listen sockets are *not* for sending data. They only accept incoming connections.
	if (type == ServerListenSocket)
	{
		LOG(LogError, "Trying to send data through a server listen socket!");
		return false;
	}

	if (!writeOpen)
	{
		LOG(LogError, "Trying to send data to a socket that is not open for writing!");
		return false;
	}

	int bytesSent = 0;
	if (transport == SocketOverUDP)
		bytesSent = sendto(connectSocket, data, numBytes, 0, (sockaddr*)&udpPeerAddress, sizeof(udpPeerAddress));
	else
		bytesSent = send(connectSocket, data, numBytes, 0);

	if (bytesSent == numBytes)
	{
		LOG(LogData, "Socket::EndSend: Sent out %d bytes to socket %s.", bytesSent, ToString().c_str());
		return true;
	}
	else if (bytesSent > 0) // Managed to send some data, but not all bytes.
	{
		assert(transport == SocketOverTCP); // Only TCP sockets should ever succeed 'partially'.
		// Our Socket::Send tries to guarantee that either all or nothing of the data is sent. We don't want
		// to report back to the upper layer that only part of the data was successfully sent. So, try to
		// re-issue the remainining bytes, but now in blocking mode, so we can wait for the rest of the data to
		// be sent.
		const int socketWriteTimeout = 5000; // msecs.
		bool waitSuccess = WaitForSendReady(socketWriteTimeout);
		if (!waitSuccess)<commit_msg>Fixed the error "Socket::Send() failed! Error: Socket is already connected(56)." on Mac when using UDP connetions.<commit_after>/* Copyright 2010 <NAME>

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License. */

/** @file Socket.cpp
	@brief */

#include <string>
#include <cassert>
#include <utility>
#include <sstream>

#ifdef KNET_USE_BOOST
#include <boost/thread/thread.hpp>
#endif

#include "kNet/DebugMemoryLeakCheck.h"

#include "kNet/Network.h"

#include "kNet/Socket.h"
#include "kNet/NetworkLogging.h"
#include "kNet/EventArray.h"

using namespace std;

#ifdef UNIX
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/tcp.h>
#endif

#ifdef WIN32
const int numConcurrentReceiveBuffers = 4;
const int numConcurrentSendBuffers = 4;
#endif

namespace kNet
{

std::string SocketTransportLayerToString(SocketTransportLayer transport)
{
	switch(transport)
	{
	case SocketOverUDP: return "UDP";
	case SocketOverTCP: return "TCP";
	default:
		{
			std::stringstream ss;
			ss << "Invalid SocketTransportLayer (" << (int)transport << ")!";
			return ss.str();
		}
	}
}

SocketTransportLayer StringToSocketTransportLayer(const char *str)
{
	if (!str)
		return InvalidTransportLayer;
	if (!_stricmp(str, "tcp") || !_stricmp(str, "SocketOverTCP"))
		return SocketOverTCP;
	if (!_stricmp(str, "udp") || !_stricmp(str, "SocketOverUDP"))
		return SocketOverUDP;
	return InvalidTransportLayer;
}


std::string SocketTypeToString(SocketType type)
{
	switch(type)
	{
	case ServerListenSocket: return "Server listen socket";
	case ServerClientSocket: return "Server client socket";
	case ClientSocket: return "Client socket";
	default:
		{
			std::stringstream ss;
			ss << "Invalid SocketType (" << (int)type << ")!";
			return ss.str();
		}
	}
}

Socket::Socket()
:connectSocket(INVALID_SOCKET),
writeOpen(false),
readOpen(false),
transport(InvalidTransportLayer),
type(InvalidSocketType)
#ifdef WIN32
,queuedReceiveBuffers(numConcurrentReceiveBuffers)
,queuedSendBuffers(numConcurrentSendBuffers)
#endif
{
	localEndPoint.Reset();
	remoteEndPoint.Reset();
}

Socket::~Socket()
{
	// We cannot Close() the socket here, since the same underlying BSD SOCKET handle can be shared
	// between multiple Socket objects. We rely instead to non-RAII behavior and manually remembering to 
	// Close().
#ifdef WIN32
	FreeOverlappedTransferBuffers();
#endif
}

Socket::Socket(SOCKET connection, const EndPoint &localEndPoint_, const char *localHostName_,
	const EndPoint &remoteEndPoint_, const char *remoteHostName_, 
	SocketTransportLayer transport_, SocketType type_, size_t maxSendSize_)
:connectSocket(connection), localEndPoint(localEndPoint_), localHostName(localHostName_),
remoteEndPoint(remoteEndPoint_), remoteHostName(remoteHostName_), 
transport(transport_), type(type_), maxSendSize(maxSendSize_),
writeOpen(true), readOpen(true)
#ifdef WIN32
,queuedReceiveBuffers(numConcurrentReceiveBuffers)
,queuedSendBuffers(numConcurrentSendBuffers)
#endif
{
	SetSendBufferSize(512 * 1024);
	SetReceiveBufferSize(512 * 1024);
	udpPeerAddress = remoteEndPoint.ToSockAddrIn();
}

Socket::Socket(const Socket &rhs)
#ifdef WIN32
:queuedReceiveBuffers(numConcurrentReceiveBuffers)
,queuedSendBuffers(numConcurrentSendBuffers)
#endif
{
	*this = rhs;
}

Socket &Socket::operator=(const Socket &rhs)
{
#ifdef WIN32
	// We would be losing data if Socket is copied from old to new when data is present in the receive buffers,
	// since the receive buffers are not moved or copied to the new Socket.
	assert(queuedReceiveBuffers.Size() == 0);
#endif

	if (this == &rhs)
		return *this;

	connectSocket = rhs.connectSocket;
	localEndPoint = rhs.localEndPoint;
	localHostName = rhs.localHostName;
	remoteEndPoint = rhs.remoteEndPoint;
	remoteHostName = rhs.remoteHostName;
	transport = rhs.transport;
	type = rhs.type;
	maxSendSize = rhs.maxSendSize;
	writeOpen = rhs.writeOpen;
	readOpen = rhs.readOpen;
	udpPeerAddress = rhs.udpPeerAddress;

	return *this;
}

bool Socket::Connected() const
{
	return connectSocket != INVALID_SOCKET;
}

OverlappedTransferBuffer *AllocateOverlappedTransferBuffer(int bytes)
{
	OverlappedTransferBuffer *buffer = new OverlappedTransferBuffer;
	memset(buffer, 0, sizeof(OverlappedTransferBuffer));
	buffer->buffer.buf = new char[bytes];
	buffer->buffer.len = bytes;
#ifdef WIN32
	buffer->overlapped.hEvent = WSACreateEvent();
	if (buffer->overlapped.hEvent == WSA_INVALID_EVENT)
	{
		LOG(LogError, "Socket.cpp:AllocateOverlappedTransferBuffer: WSACreateEvent failed!");
		delete[] buffer->buffer.buf;
		delete buffer;
		return 0;
	}
#endif

	return buffer;
}

void DeleteOverlappedTransferBuffer(OverlappedTransferBuffer *buffer)
{
	if (!buffer)
		return;
	delete[] buffer->buffer.buf;
#ifdef WIN32
	BOOL success = WSACloseEvent(buffer->overlapped.hEvent);
	if (success == FALSE)
		LOG(LogError, "Socket.cpp:DeleteOverlappedTransferBuffer: WSACloseEvent failed!");
	buffer->overlapped.hEvent = WSA_INVALID_EVENT;
#endif
	delete buffer;
}

void Socket::SetSendBufferSize(int bytes)
{
	socklen_t len = sizeof(bytes);
	if (setsockopt(connectSocket, SOL_SOCKET, SO_SNDBUF, (char*)&bytes, len))
		LOG(LogError, "Socket::SetSendBufferSize: setsockopt failed with error %s!", Network::GetLastErrorString().c_str());
}

void Socket::SetReceiveBufferSize(int bytes)
{
	socklen_t len = sizeof(bytes);
	if (setsockopt(connectSocket, SOL_SOCKET, SO_RCVBUF, (char*)&bytes, len))
		LOG(LogError, "Socket::SetReceiveBufferSize: setsockopt failed with error %s!", Network::GetLastErrorString().c_str());
}

int Socket::SendBufferSize() const
{
	int bytes = 0;
	socklen_t len = sizeof(bytes);
	if (getsockopt(connectSocket, SOL_SOCKET, SO_SNDBUF, (char*)&bytes, &len))
	{
		LOG(LogError, "Socket::SendBufferSize: getsockopt failed with error %s!", Network::GetLastErrorString().c_str());
		return 0;
	}
	return bytes;
}

int Socket::ReceiveBufferSize() const
{
	int bytes = 0;
	socklen_t len = sizeof(bytes);
	if (getsockopt(connectSocket, SOL_SOCKET, SO_RCVBUF, (char*)&bytes, &len))
	{
		LOG(LogError, "Socket::ReceiveBufferSize: getsockopt failed with error %s!", Network::GetLastErrorString().c_str());
		return 0;
	}

	return bytes;
}

#ifdef WIN32
void Socket::EnqueueNewReceiveBuffer(OverlappedTransferBuffer *buffer)
{
	if (!readOpen || queuedReceiveBuffers.CapacityLeft() == 0 || IsUDPSlaveSocket())
	{
		DeleteOverlappedTransferBuffer(buffer); // buffer may be a zero pointer, but that is alright.
		return;
	}

	if (!buffer)
	{
		const int receiveBufferSize = 16384; // This is best to be at least 9K (the largest size of jumbo datagrams commonly supported)
		buffer = AllocateOverlappedTransferBuffer(receiveBufferSize);
		if (!buffer)
		{
			LOG(LogError, "Socket::EnqueueNewReceiveBuffer: Call to AllocateOverlappedTransferBuffer failed!");
			return;
		}
	}

	if (WSAResetEvent(buffer->overlapped.hEvent) != TRUE)
		LOG(LogError, "Socket::EnqueueNewReceiveBuffer: WSAResetEvent failed!");

	unsigned long flags = 0;
	int ret;

	if (IsUDPServerSocket())
	{
		buffer->fromLen = sizeof(buffer->from);
		ret = WSARecvFrom(connectSocket, &buffer->buffer, 1, (LPDWORD)&buffer->bytesContains, &flags, (sockaddr*)&buffer->from, &buffer->fromLen, &buffer->overlapped, 0);
	}
	else
	{
		ret = WSARecv(connectSocket, &buffer->buffer, 1, (LPDWORD)&buffer->bytesContains, &flags, &buffer->overlapped, 0);
	}

	int error = (ret == 0) ? 0 : Network::GetLastError();
	if (ret == 0 || (ret == SOCKET_ERROR && error == WSA_IO_PENDING)) // If ret is not 0, ret == SOCKET_ERROR according to MSDN. http://msdn.microsoft.com/en-us/library/ms741688(VS.85).aspx
	{
		if (ret == 0 && buffer->bytesContains == 0)
		{
			if (IsUDPServerSocket())
				LOG(LogError, "Unexpected: Received a message of 0 bytes on a UDP server socket!");

			LOG(LogInfo, "Socket::EnqueueNewReceiveBuffer: Received 0 bytes from the network. Read connection closed in socket %s.", ToString().c_str());
			readOpen = false;
			DeleteOverlappedTransferBuffer(buffer);
			return;
		}
		// Return value 0: The operation completed and we have received new data. Push it to a queue for the user to receive.
		// WSA_IO_PENDING: The operation was successfully enqueued.
		bool success = queuedReceiveBuffers.Insert(buffer);
		if (!success)
		{
			LOG(LogError, "Socket::EnqueueNewReceiveBuffer: queuedReceiveBuffers.Insert(buffer); failed!");
			DeleteOverlappedTransferBuffer(buffer);
		}
	}
	else if (error == WSAEDISCON)
	{
		if (IsUDPServerSocket())
			LOG(LogError, "Unexpected: Received WSAEDISCON on a UDP server socket!");

		LOG(LogError, "Socket::EnqueueNewReceivebuffer: WSAEDISCON. Connection closed in socket %s.", ToString().c_str());
		readOpen = false;
		///\todo Should do writeOpen = false; here as well?
		DeleteOverlappedTransferBuffer(buffer);
		return;
	}
	else
	{
		if (error != WSAEWOULDBLOCK && error != 0)
		{
			LOG(LogError, "Socket::EnqueueNewReceiveBuffer: %s for overlapped socket %s failed! Error: %s.", IsUDPServerSocket() ? "WSARecvFrom" : "WSARecv", ToString().c_str(), Network::GetErrorString(error).c_str());

			// We never close the server socket as a reaction on any error, since an error on one client could shut down
			// the whole server for all clients. This check is mainly here to ignore the 10054 error (WSAECONNRESET) which
			// is returned when UDP clients give back a ICMP Host Unreachable message, but since there may be other
			// client-specific errors, we don't explicitly check for the 10054 case only.
			if (!IsUDPServerSocket())
			{
				LOG(LogError, "Socket::EnqueueNewReceiveBuffer: Closing down socket.",  Network::GetErrorString(error).c_str());
				readOpen = false;
				writeOpen = false;
				Close();
			}
		}

		DeleteOverlappedTransferBuffer(buffer); // We failed to queue the buffer, free it up immediately to avoid leaking memory.
		return;
	}
}
#endif

void DumpBuffer(const char *description, const char *data, int size)
{
	printf("%s (%d bytes): ", description, size);
	for(int i = 0; i < min(size, 50); ++i)
		printf("%02X ", (unsigned int)(unsigned char)data[i]);
	printf("\n");
}

size_t Socket::Receive(char *dst, size_t maxBytes, EndPoint *endPoint)
{
	assert(dst);
	assert(maxBytes > 0);
	if (maxBytes == 0)
		return 0;

	if (connectSocket == INVALID_SOCKET)
		return 0;

	if (!readOpen)
		return 0;

	if (IsUDPSlaveSocket()) // UDP slave sockets are never read directly. Instead the UDP server socket reads all client data.
		return 0; // So, if we accidentally come here to read a UDP slave socket, act as if it never received any data.

	if (IsUDPServerSocket())
	{
		sockaddr_in from;
		socklen_t fromLen = sizeof(from);
		int numBytesRead = recvfrom(connectSocket, dst, maxBytes, 0, (sockaddr*)&from, &fromLen);
		if (numBytesRead == KNET_SOCKET_ERROR)
		{
			int error = Network::GetLastError();
			if (error != KNET_EWOULDBLOCK && error != 0)
				LOG(LogError, "Socket::Receive: recvfrom failed: %s in socket %s", Network::GetErrorString(error).c_str(), ToString().c_str());

			return 0;
		}
		if (numBytesRead > 0)
			LOG(LogData, "recvfrom (%d) in socket %s", numBytesRead, ToString().c_str());

		if (endPoint)
			*endPoint = EndPoint::FromSockAddrIn(from);

		return numBytesRead;
	}

	// If we reach here, this socket is a tcp connection socket (server->client or client->server), or a udp client->server socket.

	int ret = recv(connectSocket, dst, maxBytes, 0);

	if (ret > 0)
	{
		LOG(LogData, "Received %d bytes of data from socket 0x%X.", ret, (unsigned int)connectSocket);
		return (size_t)ret;
	}
	else if (ret == 0)
	{
		LOG(LogInfo, "Socket::Receive: Received 0 bytes from network. Read-connection closed to socket %s.", ToString().c_str());
		readOpen = false;
		return 0;
	}
	else
	{
		int error = Network::GetLastError();
		if (error != KNET_EWOULDBLOCK && error != 0)
		{
			LOG(LogError, "Socket::Receive: recv failed in socket %s. Error %s", ToString().c_str(), Network::GetErrorString(error).c_str());

			// We never close the server socket as a reaction on any error, since an error on one client could shut down
			// the whole server for all clients. This check is mainly here to ignore the 10054 error (WSAECONNRESET) which
			// is returned when UDP clients give back a ICMP Host Unreachable message, but since there may be other
			// client-specific errors, we don't explicitly check for the 10054 case only.
			if (!IsUDPServerSocket())
			{
				readOpen = false;
				writeOpen = false;
				Close();
			}
		}
		return 0;
	}
}

bool Socket::IsOverlappedReceiveReady() const
{
	if (IsUDPSlaveSocket()) // UDP slave sockets are never read directly. For these sockets, act as if they're never ready for reads.
		return false;

#ifdef WIN32
	if (queuedReceiveBuffers.Size() == 0)
		return false;
	return Event((*queuedReceiveBuffers.Front())->overlapped.hEvent, EventWaitRead).Test();
#else
	if (!readOpen)
		return false;

	EventArray ea;
	ea.AddEvent(Event(connectSocket, EventWaitRead));
	return ea.Wait(0) == 0;
#endif
}

Event Socket::GetOverlappedReceiveEvent()
{
	if (IsUDPSlaveSocket()) // UDP slave sockets are never read directly. For these sockets, return a null event that never fires.
		return Event();

#ifdef WIN32
	if (readOpen)
	{
		/// Prime the receive buffers to the full capacity if they weren't so yet.
		const int capacityLeft = queuedReceiveBuffers.CapacityLeft();
		for(int i = 0; i < capacityLeft; ++i)
			EnqueueNewReceiveBuffer();
	}

	if (queuedReceiveBuffers.Size() == 0)
		return Event();

	OverlappedTransferBuffer *receivedData = *queuedReceiveBuffers.Front();
	assert(receivedData);

	return Event(receivedData->overlapped.hEvent, EventWaitRead);
#else
	return Event(connectSocket, EventWaitRead);
#endif
}

Event Socket::GetOverlappedSendEvent()
{
	if (!writeOpen)
		return Event();

#ifdef WIN32
	if (queuedSendBuffers.Size() == 0)
		return Event();

	OverlappedTransferBuffer *sentData = *queuedSendBuffers.Front();
	assert(sentData);

	return Event(sentData->overlapped.hEvent, EventWaitWrite);
#else
	return Event(connectSocket, EventWaitWrite);
#endif
}

OverlappedTransferBuffer *Socket::BeginReceive()
{
	// UDP 'slave socket' is a socket descriptor on the server side that is a copy of the single UDP server listen socket.
	// The slave sockets don't receive data directly, but the server socket is used instead to receive data for them.
	if (IsUDPSlaveSocket())
	{
#ifdef WIN32
		assert(queuedReceiveBuffers.Size() == 0); // We shouldn't ever have queued a single receive buffer for this Socket.
#endif
		return 0; // If we happen to come here, act as if the socket never received any data.
	}

#ifdef WIN32
	if (readOpen)
	{
		// Insert new empty receive buffers to the Overlapped Transfer receive queue until we have a full capacity queue primed.
		const int capacityLeft = queuedReceiveBuffers.CapacityLeft();
		for(int i = 0; i < capacityLeft; ++i)
			EnqueueNewReceiveBuffer();
	}

	if (queuedReceiveBuffers.Size() == 0)
		return 0;

	OverlappedTransferBuffer *receivedData = *queuedReceiveBuffers.Front();
	DWORD flags = 0;
	BOOL ret = WSAGetOverlappedResult(connectSocket, &receivedData->overlapped, (LPDWORD)&receivedData->bytesContains, FALSE, &flags);
	int error = (ret == TRUE) ? 0 : Network::GetLastError();
	if (ret == TRUE)
	{
		queuedReceiveBuffers.PopFront();

		// Successfully receiving zero bytes with overlapped sockets means the same as recv() of 0 bytes,
		// peer has closed the write connection (but can still recv() until we also close the write connection).
		if (receivedData->bytesContains == 0)
		{
			DeleteOverlappedTransferBuffer(receivedData);
			if (readOpen)
				LOG(LogInfo, "Socket::BeginReceive: Received 0 bytes from the network. Read connection closed in socket %s.", ToString().c_str());
			readOpen = false;
			if (IsUDPServerSocket())
				LOG(LogError, "Socket::BeginReceive: UDP server socket transitioned to readOpen==false!");
			return 0;
		}

		return receivedData;
	}
	else if (error == WSAEDISCON)
	{
		queuedReceiveBuffers.PopFront();
		DeleteOverlappedTransferBuffer(receivedData);
		if (readOpen || writeOpen)
			LOG(LogError, "Socket::BeginReceive: WSAEDISCON. Bidirectionally closing connection in socket %s.", ToString().c_str());
		if (IsUDPServerSocket())
			LOG(LogError, "Socket::BeginReceive: Unexpected: Received WSAEDISCON on UDP server socket!");
		Close();
		return 0;
	}
	else if (error != WSA_IO_INCOMPLETE)
	{
		queuedReceiveBuffers.PopFront();
		if (readOpen || writeOpen)
			if (!(IsUDPServerSocket() && error == 10054)) // If we are running both UDP server and client on localhost, we can receive 10054 (Peer closed connection) on the server side, in which case, we ignore this error print.
				LOG(LogError, "Socket::BeginReceive: WSAGetOverlappedResult failed with code %d when reading from an overlapped socket! Reason: %s.", error, Network::GetErrorString(error).c_str());
		DeleteOverlappedTransferBuffer(receivedData);
		// Mark this socket closed, unless the read error was on a UDP server socket, in which case we must ignore
		// the read error on this buffer (an error on a single client connection cannot shut down the whole server!)
		if (!IsUDPServerSocket() && (readOpen || writeOpen))
		{
			LOG(LogError, "Socket::BeginReceive: Closing socket due to read error!");
			Close();
		}
	}
	return 0;
#else
	if (!readOpen)
		return 0;

	const int receiveBufferSize = 4096;
	OverlappedTransferBuffer *buffer = AllocateOverlappedTransferBuffer(receiveBufferSize);
	EndPoint source;
	buffer->bytesContains = Receive(buffer->buffer.buf, buffer->buffer.len, &source);
	if (buffer->bytesContains > 0)
	{
		buffer->fromLen = sizeof(buffer->from);
		buffer->from = source.ToSockAddrIn();
		return buffer;
	}
	else
	{
		// Did not get any data. Delete the buffer immediately.
		DeleteOverlappedTransferBuffer(buffer);
		return 0;
	}
#endif
}

void Socket::EndReceive(OverlappedTransferBuffer *buffer)
{
#ifdef WIN32
	if (readOpen)
	{
		EnqueueNewReceiveBuffer(buffer);
		return;
	}
#endif

	DeleteOverlappedTransferBuffer(buffer);
}

void Socket::Disconnect()
{
	if (connectSocket == INVALID_SOCKET)
		return;

	LOG(LogVerbose, "Socket::Disconnect(), this: %p.", this);

	if (transport == SocketOverTCP)
	{
		int result = shutdown(connectSocket, SD_SEND);
		if (result == KNET_SOCKET_ERROR)
			LOG(LogError, "Socket::Disconnect(): TCP socket shutdown(SD_SEND) failed: %s in socket %s.", Network::GetLastErrorString().c_str(), ToString().c_str());
		else
			LOG(LogInfo, "Socket::Disconnect(): TCP socket shutdown(SD_SEND) succeeded on socket %s.", ToString().c_str());
	}

	writeOpen = false;
}

void Socket::Close()
{
	if (connectSocket == INVALID_SOCKET)
	{
		assert(!readOpen && !writeOpen);
		return;
	}

	LOG(LogInfo, "Socket::Close(): Closing socket %s.", ToString().c_str());

	if (!IsUDPSlaveSocket())
	{
		// For UDP client sockets on the server side, the same SOCKET object is shared by 
		// all other client sockets and the UDP server socket. For those sockets, the UDP server socket is the owner
		// of the socket object, so the clients cannot close their sockets, as closing one would close them all.

		int result = shutdown(connectSocket, SD_BOTH);
		if (result == KNET_SOCKET_ERROR)
			LOG(LogError, "Socket::Close(): Socket shutdown(SD_BOTH) failed: %s in socket %s.", Network::GetLastErrorString().c_str(), ToString().c_str());
		else
			LOG(LogInfo, "Socket::Close(): Socket shutdown(SD_BOTH) succeeded on socket %s.", ToString().c_str());

		result = closesocket(connectSocket);
		if (result == KNET_SOCKET_ERROR)
			LOG(LogError, "Socket::Close(): closesocket() failed: %s in socket %s.", Network::GetLastErrorString().c_str(), ToString().c_str());
	}

	connectSocket = INVALID_SOCKET;
	localEndPoint.Reset();
	localHostName = "";
	remoteEndPoint.Reset();
	remoteHostName = "";
	transport = InvalidTransportLayer;
	type = InvalidSocketType;
	readOpen = false;
	writeOpen = false;

#ifdef WIN32
	FreeOverlappedTransferBuffers();
#endif
}

#ifdef WIN32
void Socket::FreeOverlappedTransferBuffers()
{
	LOG(LogVerbose, "Socket::FreeOverlappedTransferBuffers(), this: %p.", this);
/// \todo Use CancelIo to tear-down commited OverlappedTransferBuffers before freeing data. http://msdn.microsoft.com/en-us/library/aa363792(VS.85).aspx
	while(queuedReceiveBuffers.Size() > 0)
		DeleteOverlappedTransferBuffer(queuedReceiveBuffers.TakeFront());

	while(queuedSendBuffers.Size() > 0)
		DeleteOverlappedTransferBuffer(queuedSendBuffers.TakeFront());
}
#endif

void Socket::SetBlocking(bool isBlocking)
{
	if (connectSocket == INVALID_SOCKET)
		return;

	u_long nonBlocking = (isBlocking == false) ? 1 : 0;
#ifdef WIN32
	if (ioctlsocket(connectSocket, FIONBIO, &nonBlocking))
		LOG(LogError, "Socket::SetBlocking: ioctlsocket failed with error %s!", Network::GetLastErrorString().c_str());
#else
	int flags = fcntl(connectSocket, F_GETFL, 0);
	fcntl(connectSocket, F_SETFL, flags | O_NONBLOCK);
#endif
}

/// @return True on success, false otherwise.
bool Socket::Send(const char *data, size_t numBytes)
{
	if (connectSocket == INVALID_SOCKET)
	{
		LOG(LogError, "Trying to send a datagram to INVALID_SOCKET!");
		return false;
	}

	// Server listen sockets are *not* for sending data. They only accept incoming connections.
	if (type == ServerListenSocket)
	{
		LOG(LogError, "Trying to send data through a server listen socket!");
		return false;
	}

	if (!writeOpen)
	{
		LOG(LogError, "Trying to send data to a socket that is not open for writing!");
		return false;
	}

	int bytesSent = 0;
	// sendto() to a connected socket causes EISCONN on OSX, so avoid it for client UDP sockets
	if (transport == SocketOverUDP && type != ClientSocket)
		bytesSent = sendto(connectSocket, data, numBytes, 0, (sockaddr*)&udpPeerAddress, sizeof(udpPeerAddress));
	else
		bytesSent = send(connectSocket, data, numBytes, 0);

	if (bytesSent == numBytes)
	{
		LOG(LogData, "Socket::EndSend: Sent out %d bytes to socket %s.", bytesSent, ToString().c_str());
		return true;
	}
	else if (bytesSent > 0) // Managed to send some data, but not all bytes.
	{
		assert(transport == SocketOverTCP); // Only TCP sockets should ever succeed 'partially'.
		// Our Socket::Send tries to guarantee that either all or nothing of the data is sent. We don't want
		// to report back to the upper layer that only part of the data was successfully sent. So, try to
		// re-issue the remainining bytes, but now in blocking mode, so we can wait for the rest of the data to
		// be sent.
		const int socketWriteTimeout = 5000; // msecs.
		bool waitSuccess = WaitForSendReady(socketWriteTimeout);
		if (!waitSuccess)
{'fraction_non_alphanumeric': 0.11934722768383799, 'fraction_numerical': 0.008651199370821865, 'mean_word_length': 4.963392391870766, 'pattern_counts': {'":': 0, '<': 53, '<?xml version=': 0, '>': 109, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5473060', 'n_tokens_mistral': 15866, 'n_tokens_neox': 14565, 'n_words': 4400}