13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*-------------------------------------------------------------------------
23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * drawElements Utility Library
33c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * ----------------------------
43c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
53c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Copyright 2014 The Android Open Source Project
63c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
73c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Licensed under the Apache License, Version 2.0 (the "License");
83c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * you may not use this file except in compliance with the License.
93c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * You may obtain a copy of the License at
103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *      http://www.apache.org/licenses/LICENSE-2.0
123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Unless required by applicable law or agreed to in writing, software
143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * distributed under the License is distributed on an "AS IS" BASIS,
153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * See the License for the specific language governing permissions and
173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * limitations under the License.
183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*!
203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \file
213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Socket abstraction.
223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deSocket.h"
253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deMemory.h"
263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deMutex.h"
273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#if (DE_OS == DE_OS_WIN32)
293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#	define DE_USE_WINSOCK
303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#elif (DE_OS == DE_OS_UNIX) || (DE_OS == DE_OS_OSX) || (DE_OS == DE_OS_IOS) || (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_SYMBIAN)
313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#	define DE_USE_BERKELEY_SOCKETS
323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#else
333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#	error Implement deSocket for your OS.
343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif
353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/* Common utilities. */
373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
383c827367444ee418f129b2c238299f49d3264554Jarkko Poyryconst char* deGetSocketResultName (deSocketResult result)
393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (result)
413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case DE_SOCKETRESULT_SUCCESS:				return "DE_SOCKETRESULT_SUCCESS";
433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case DE_SOCKETRESULT_WOULD_BLOCK:			return "DE_SOCKETRESULT_WOULD_BLOCK";
443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case DE_SOCKETRESULT_CONNECTION_CLOSED:		return "DE_SOCKETRESULT_CONNECTION_CLOSED";
453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case DE_SOCKETRESULT_CONNECTION_TERMINATED:	return "DE_SOCKETRESULT_CONNECTION_TERMINATED";
463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case DE_SOCKETRESULT_ERROR:					return "DE_SOCKETRESULT_ERROR";
473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:									return DE_NULL;
483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
513c827367444ee418f129b2c238299f49d3264554Jarkko Poyryconst char* deGetSocketFamilyName (deSocketFamily family)
523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (family)
543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case DE_SOCKETFAMILY_INET4:		return "DE_SOCKETFAMILY_INET4";
563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case DE_SOCKETFAMILY_INET6:		return "DE_SOCKETFAMILY_INET6";
573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:						return DE_NULL;
583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#if defined(DE_USE_WINSOCK) || defined(DE_USE_BERKELEY_SOCKETS)
623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/* Common deSocketAddress implementation. */
643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
653c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct deSocketAddress_s
663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	char*				host;
683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int					port;
693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deSocketFamily		family;
703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deSocketType		type;
713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deSocketProtocol	protocol;
723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
743c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeSocketAddress* deSocketAddress_create (void)
753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deSocketAddress* addr = (deSocketAddress*)deCalloc(sizeof(deSocketAddress));
773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!addr)
783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return addr;
793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Sane defaults. */
813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addr->family	= DE_SOCKETFAMILY_INET4;
823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addr->type		= DE_SOCKETTYPE_STREAM;
833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	addr->protocol	= DE_SOCKETPROTOCOL_TCP;
843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return addr;
863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
883c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeBool deSocketAddress_setFamily (deSocketAddress* address, deSocketFamily family)
893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	address->family = family;
913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return DE_TRUE;
923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
943c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeSocketFamily deSocketAddress_getFamily (const deSocketAddress* address)
953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return address->family;
973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
993c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid deSocketAddress_destroy (deSocketAddress* address)
1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deFree(address->host);
1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deFree(address);
1033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1053c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeBool deSocketAddress_setPort (deSocketAddress* address, int port)
1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	address->port = port;
1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return DE_TRUE;
1093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint deSocketAddress_getPort (const deSocketAddress* address)
1123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return address->port;
1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1163c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeBool deSocketAddress_setHost (deSocketAddress* address, const char* host)
1173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (address->host)
1193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deFree(address->host);
1213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		address->host = DE_NULL;
1223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	address->host = deStrdup(host);
1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return address->host != DE_NULL;
1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyryconst char* deSocketAddress_getHost (const deSocketAddress* address)
1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return address->host;
1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1343c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeBool deSocketAddress_setType (deSocketAddress* address, deSocketType type)
1353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	address->type = type;
1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return DE_TRUE;
1383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1403c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeSocketType deSocketAddress_getType (const deSocketAddress* address)
1413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return address->type;
1433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1453c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeBool deSocketAddress_setProtocol (deSocketAddress* address, deSocketProtocol protocol)
1463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	address->protocol = protocol;
1483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return DE_TRUE;
1493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1513c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeSocketProtocol deSocketAddress_getProtocol (const deSocketAddress* address)
1523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return address->protocol;
1543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif
1573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#if defined(DE_USE_WINSOCK)
1593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* WinSock spesific. */
1613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#	include <WinSock2.h>
1623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#	include <WinDef.h>
1633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1643c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic deBool initWinsock (void)
1653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	WSADATA wsaData;
1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
1683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_FALSE;
1693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return DE_TRUE;
1713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#elif defined(DE_USE_BERKELEY_SOCKETS)
1743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Berkeley Socket includes. */
1763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#	include <sys/socket.h>
1773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#	include <netinet/in.h>
1783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#	include <netinet/tcp.h>
1793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#	include <arpa/inet.h>
1803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#	include <netdb.h>
1813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#	include <unistd.h>
1823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#	include <fcntl.h>
1833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#	include <errno.h>
1843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif
1863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/* Socket type. */
1883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#if defined(DE_USE_WINSOCK)
1893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* \note SOCKET is unsigned type! */
1903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef SOCKET					deSocketHandle;
1913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#	define DE_INVALID_SOCKET_HANDLE	INVALID_SOCKET
1923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#else
1933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	typedef int						deSocketHandle;
1943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#	define DE_INVALID_SOCKET_HANDLE	-1
1953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif
1963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1973c827367444ee418f129b2c238299f49d3264554Jarkko PoyryDE_INLINE deBool deSocketHandleIsValid (deSocketHandle handle)
1983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return handle != DE_INVALID_SOCKET_HANDLE;
2003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#if defined(DE_USE_WINSOCK) || defined(DE_USE_BERKELEY_SOCKETS)
2033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/* Shared berkeley and winsock implementation. */
2053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2063c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct deSocket_s
2073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deSocketHandle			handle;
2093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deMutex					stateLock;
2113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	volatile deSocketState	state;
2123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	volatile deUint32		openChannels;
2133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
2143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/* Common socket functions. */
2163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2173c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int deSocketFamilyToBsdProtocolFamily (deSocketFamily family)
2183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (family)
2203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case DE_SOCKETFAMILY_INET4:	return PF_INET;
2223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case DE_SOCKETFAMILY_INET6:	return PF_INET6;
2233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
2243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(DE_FALSE);
2253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return 0;
2263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2293c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int deSocketTypeToBsdType (deSocketType type)
2303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (type)
2323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case DE_SOCKETTYPE_STREAM:		return SOCK_STREAM;
2343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case DE_SOCKETTYPE_DATAGRAM:	return SOCK_DGRAM;
2353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
2363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(DE_FALSE);
2373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return 0;
2383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2413c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int deSocketProtocolToBsdProtocol (deSocketProtocol protocol)
2423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (protocol)
2443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case DE_SOCKETPROTOCOL_TCP:	return IPPROTO_TCP;
2463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case DE_SOCKETPROTOCOL_UDP:	return IPPROTO_UDP;
2473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
2483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(DE_FALSE);
2493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return 0;
2503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2533c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic deBool deSocketAddressToBsdAddress (const deSocketAddress* address, struct sockaddr* bsdAddr, int* bsdAddrSize, deSocketFamily* family)
2543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deBool			hasHost		= address->host != DE_NULL;
2563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint8			hostAddr[16];	/*!< Binary representation. */
2573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deMemset(bsdAddr, 0, sizeof(struct sockaddr));
2593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	*family = address->family;
2613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* If host is supplied, use gethostbyname() to determine actual family. */
2633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (hasHost)
2643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		struct hostent* host = gethostbyname(address->host);
2663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!host)
2683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return DE_FALSE;
2693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (host->h_addrtype == AF_INET)
2713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			*family = DE_SOCKETFAMILY_INET4;
2723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (host->h_addrtype == AF_INET6)
2733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			*family = DE_SOCKETFAMILY_INET6;
2743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
2753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return DE_FALSE;
2763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT((host->h_addrtype == AF_INET && host->h_length == 4) ||
2783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				  (host->h_addrtype == AF_INET6 && host->h_length == 16));
2793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		/* Use first address. */
2813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (host->h_addr_list[0] != 0)
2823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deMemcpy(hostAddr, host->h_addr_list[0], host->h_length);
2833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
2843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return DE_FALSE;
2853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (*family == DE_SOCKETFAMILY_INET4)
2883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		struct sockaddr_in* addr4 = (struct sockaddr_in*)bsdAddr;
2903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		addr4->sin_port		= htons((deUint16)address->port);
2923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		addr4->sin_family	= AF_INET;
2933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (hasHost)
2953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deMemcpy(&addr4->sin_addr, hostAddr, 4);
2963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
2973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			addr4->sin_addr.s_addr = INADDR_ANY;
2983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		*bsdAddrSize = sizeof(struct sockaddr_in);
3003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_TRUE;
3013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (*family == DE_SOCKETFAMILY_INET6)
3033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(!"TODO");
3053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_FALSE;
3063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
3083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_FALSE;
3093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3113c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid deBsdAddressToSocketAddress (deSocketAddress* address, const struct sockaddr* bsdAddr, int addrLen)
3123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Decode client address info. */
3143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (bsdAddr->sa_family == AF_INET)
3153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const struct sockaddr_in* addr4 = (const struct sockaddr_in*)bsdAddr;
3173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(addrLen >= (int)sizeof(struct sockaddr_in));
3183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_UNREF(addrLen);
3193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deSocketAddress_setFamily(address, DE_SOCKETFAMILY_INET4);
3213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deSocketAddress_setPort(address, ntohs(addr4->sin_port));
3223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#if defined(DE_USE_WINSOCK)
3243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deSocketAddress_setHost(address, inet_ntoa(addr4->sin_addr));
3253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#else
3263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
3273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			char buf[16];
3283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			inet_ntop(AF_INET, &addr4->sin_addr, buf, sizeof(buf));
3293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deSocketAddress_setHost(address, buf);
3303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
3313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif
3323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
3343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(DE_FALSE);
3353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3373c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeSocket* deSocket_create (void)
3383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deSocket* sock = (deSocket*)deCalloc(sizeof(deSocket));
3403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!sock)
3413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return sock;
3423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#if defined(DE_USE_WINSOCK)
3443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Make sure WSA is up. */
3453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!initWinsock())
3463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return 0;
3473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif
3483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	sock->stateLock	= deMutex_create(0);
3503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	sock->handle	= DE_INVALID_SOCKET_HANDLE;
3513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	sock->state		= DE_SOCKETSTATE_CLOSED;
3523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return sock;
3543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3563c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid deSocket_destroy (deSocket* sock)
3573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (sock->state != DE_SOCKETSTATE_CLOSED)
3593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deSocket_close(sock);
3603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deMutex_destroy(sock->stateLock);
3623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deFree(sock);
3633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3653c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeSocketState deSocket_getState (const deSocket* sock)
3663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return sock->state;
3683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3703c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeUint32 deSocket_getOpenChannels (const deSocket* sock)
3713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return sock->openChannels;
3733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3753c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeBool deSocket_setFlags (deSocket* sock, deUint32 flags)
3763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deSocketHandle fd = sock->handle;
3783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (sock->state == DE_SOCKETSTATE_CLOSED)
3803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_FALSE;
3813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Keepalive. */
3833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int mode = (flags & DE_SOCKET_KEEPALIVE) ? 1 : 0;
3853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (const char*)&mode, sizeof(mode)) != 0)
3863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return DE_FALSE;
3873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Nodelay. */
3903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int mode = (flags & DE_SOCKET_NODELAY) ? 1 : 0;
3923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (const char*)&mode, sizeof(mode)) != 0)
3933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return DE_FALSE;
3943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Non-blocking. */
3973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#if defined(DE_USE_WINSOCK)
3993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		u_long mode = (flags & DE_SOCKET_NONBLOCKING) ? 1 : 0;
4003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (ioctlsocket(fd, FIONBIO, &mode) != 0)
4013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return DE_FALSE;
4023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#else
4033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int oldFlags	= fcntl(fd, F_GETFL, 0);
4043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int newFlags	= (flags & DE_SOCKET_NONBLOCKING) ? (oldFlags | O_NONBLOCK) : (oldFlags & ~O_NONBLOCK);
4053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (fcntl(fd, F_SETFL, newFlags) != 0)
4063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return DE_FALSE;
4073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif
4083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Close on exec. */
4113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#if defined(DE_USE_BERKELEY_SOCKETS)
4133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int oldFlags = fcntl(fd, F_GETFD, 0);
4143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int newFlags = (flags & DE_SOCKET_CLOSE_ON_EXEC) ? (oldFlags | FD_CLOEXEC) : (oldFlags & ~FD_CLOEXEC);
4153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (fcntl(fd, F_SETFD, newFlags) != 0)
4163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return DE_FALSE;
4173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif
4183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return DE_TRUE;
4213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4233c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeBool deSocket_listen (deSocket* sock, const deSocketAddress* address)
4243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int			backlogSize	= 4;
4263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	struct sockaddr		bsdAddr;
4273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int					bsdAddrLen;
4283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deSocketFamily		family;
4293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (sock->state != DE_SOCKETSTATE_CLOSED)
4313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_FALSE;
4323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Resolve address. */
4343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!deSocketAddressToBsdAddress(address, &bsdAddr, &bsdAddrLen, &family))
4353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_FALSE;
4363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Create socket. */
4383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	sock->handle = socket(deSocketFamilyToBsdProtocolFamily(family), deSocketTypeToBsdType(address->type), deSocketProtocolToBsdProtocol(address->protocol));
4393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!deSocketHandleIsValid(sock->handle))
4403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_FALSE;
4413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	sock->state = DE_SOCKETSTATE_DISCONNECTED;
4433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Allow re-using address. */
4453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int reuseVal = 1;
4473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		setsockopt(sock->handle, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuseVal, (int)sizeof(reuseVal));
4483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Bind to address. */
4513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (bind(sock->handle, &bsdAddr, bsdAddrLen) != 0)
4523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deSocket_close(sock);
4543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_FALSE;
4553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Start listening. */
4583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (listen(sock->handle, backlogSize) != 0)
4593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deSocket_close(sock);
4613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_FALSE;
4623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	sock->state = DE_SOCKETSTATE_LISTENING;
4653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return DE_TRUE;
4673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4693c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeSocket* deSocket_accept (deSocket* sock, deSocketAddress* clientAddress)
4703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deSocketHandle		newFd	= DE_INVALID_SOCKET_HANDLE;
4723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deSocket*			newSock	= DE_NULL;
4733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	struct sockaddr		addr;
4743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int					addrLen	= (int)sizeof(addr);
4753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deMemset(&addr, 0, sizeof(addr));
4773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#if defined(DE_USE_WINSOCK)
4793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	newFd = accept(sock->handle, (struct sockaddr*)&addr, &addrLen);
4803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#else
4813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	newFd = accept(sock->handle, (struct sockaddr*)&addr, (socklen_t*)&addrLen);
4823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif
4833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!deSocketHandleIsValid(newFd))
4843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_NULL;
4853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	newSock = (deSocket*)deCalloc(sizeof(deSocket));
4873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!newSock)
4883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#if defined(DE_USE_WINSOCK)
4903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		closesocket(newFd);
4913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#else
4923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		close(newFd);
4933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif
4943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_NULL;
4953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	newSock->stateLock		= deMutex_create(0);
4983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	newSock->handle			= newFd;
4993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	newSock->state			= DE_SOCKETSTATE_CONNECTED;
5003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	newSock->openChannels	= DE_SOCKETCHANNEL_BOTH;
5013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (clientAddress)
5033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deBsdAddressToSocketAddress(clientAddress, &addr, addrLen);
5043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return newSock;
5063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5083c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeBool deSocket_connect (deSocket* sock, const deSocketAddress* address)
5093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	struct sockaddr		bsdAddr;
5113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int					bsdAddrLen;
5123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deSocketFamily		family;
5133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Resolve address. */
5153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!deSocketAddressToBsdAddress(address, &bsdAddr, &bsdAddrLen, &family))
5163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_FALSE;
5173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Create socket. */
5193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	sock->handle = socket(deSocketFamilyToBsdProtocolFamily(family), deSocketTypeToBsdType(address->type), deSocketProtocolToBsdProtocol(address->protocol));
5203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!deSocketHandleIsValid(sock->handle))
5213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_FALSE;
5223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Connect. */
5243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (connect(sock->handle, &bsdAddr, bsdAddrLen) != 0)
5253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_FALSE;
5263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	sock->state			= DE_SOCKETSTATE_CONNECTED;
5283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	sock->openChannels	= DE_SOCKETCHANNEL_BOTH;
5293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return DE_TRUE;
5313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5333c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeBool deSocket_shutdown (deSocket* sock, deUint32 channels)
5343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32 closedChannels = 0;
5363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deMutex_lock(sock->stateLock);
5383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (sock->state == DE_SOCKETSTATE_DISCONNECTED ||
5403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		sock->state == DE_SOCKETSTATE_CLOSED)
5413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deMutex_unlock(sock->stateLock);
5433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_FALSE;
5443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(channels != 0 && (channels & ~DE_SOCKETCHANNEL_BOTH) == 0);
5473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Don't attempt to close already closed channels on partially open socket. */
5493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	channels &= sock->openChannels;
5503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (channels == 0)
5523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deMutex_unlock(sock->stateLock);
5543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_FALSE;
5553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#if defined(DE_USE_WINSOCK)
5583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int how = 0;
5603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if ((channels & DE_SOCKETCHANNEL_BOTH) == DE_SOCKETCHANNEL_BOTH)
5623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			how = SD_BOTH;
5633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (channels & DE_SOCKETCHANNEL_SEND)
5643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			how = SD_SEND;
5653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (channels & DE_SOCKETCHANNEL_RECEIVE)
5663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			how = SD_RECEIVE;
5673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (shutdown(sock->handle, how) == 0)
5693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			closedChannels = channels;
5703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
5713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
5723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int err = WSAGetLastError();
5733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			/* \note Due to asynchronous behavior certain errors are perfectly ok. */
5753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (err == WSAECONNABORTED || err == WSAECONNRESET || err == WSAENOTCONN)
5763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				closedChannels = DE_SOCKETCHANNEL_BOTH;
5773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
5783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
5793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				deMutex_unlock(sock->stateLock);
5803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return DE_FALSE;
5813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
5823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
5833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#else
5853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int how = 0;
5873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if ((channels & DE_SOCKETCHANNEL_BOTH) == DE_SOCKETCHANNEL_BOTH)
5893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			how = SHUT_RDWR;
5903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (channels & DE_SOCKETCHANNEL_SEND)
5913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			how = SHUT_WR;
5923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (channels & DE_SOCKETCHANNEL_RECEIVE)
5933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			how = SHUT_RD;
5943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (shutdown(sock->handle, how) == 0)
5963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			closedChannels = channels;
5973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
5983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
5993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (errno == ENOTCONN)
6003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				closedChannels = DE_SOCKETCHANNEL_BOTH;
6013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
6023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
6033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				deMutex_unlock(sock->stateLock);
6043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return DE_FALSE;
6053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
6063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
6073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif
6093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	sock->openChannels &= ~closedChannels;
6113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (sock->openChannels == 0)
6123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		sock->state = DE_SOCKETSTATE_DISCONNECTED;
6133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deMutex_unlock(sock->stateLock);
6153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return DE_TRUE;
6163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6183c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeBool deSocket_close (deSocket* sock)
6193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deMutex_lock(sock->stateLock);
6213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (sock->state == DE_SOCKETSTATE_CLOSED)
6233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deMutex_unlock(sock->stateLock);
6253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_FALSE;
6263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#if !defined(DE_USE_WINSOCK)
6293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (sock->state == DE_SOCKETSTATE_LISTENING)
6303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		/* There can be a thread blockin in accept(). Release it by calling shutdown. */
6323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		shutdown(sock->handle, SHUT_RDWR);
6333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif
6353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#if defined(DE_USE_WINSOCK)
6373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (closesocket(sock->handle) != 0)
6383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_FALSE;
6393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#else
6403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (close(sock->handle) != 0)
6413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_FALSE;
6423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif
6433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	sock->state			= DE_SOCKETSTATE_CLOSED;
6443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	sock->handle		= DE_INVALID_SOCKET_HANDLE;
6453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	sock->openChannels	= 0;
6463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deMutex_unlock(sock->stateLock);
6483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return DE_TRUE;
6493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6513c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic deSocketResult mapSendRecvResult (int numBytes)
6523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (numBytes > 0)
6543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_SOCKETRESULT_SUCCESS;
6553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (numBytes == 0)
6563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_SOCKETRESULT_CONNECTION_CLOSED;
6573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
6583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
6593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		/* Other errors. */
6603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#if defined(DE_USE_WINSOCK)
6613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		int	error = WSAGetLastError();
6623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		switch (error)
6633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
6643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case WSAEWOULDBLOCK:	return DE_SOCKETRESULT_WOULD_BLOCK;
6653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case WSAENETDOWN:
6663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case WSAENETRESET:
6673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case WSAECONNABORTED:
6683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case WSAECONNRESET:		return DE_SOCKETRESULT_CONNECTION_TERMINATED;
6693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			default:				return DE_SOCKETRESULT_ERROR;
6703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
6713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#else
6723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		switch (errno)
6733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
6743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case EAGAIN:		return DE_SOCKETRESULT_WOULD_BLOCK;
6753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case ECONNABORTED:
6763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case ECONNRESET:	return DE_SOCKETRESULT_CONNECTION_TERMINATED;
6773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			default:			return DE_SOCKETRESULT_ERROR;
6783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
6793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif
6803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6833c827367444ee418f129b2c238299f49d3264554Jarkko PoyryDE_INLINE void deSocket_setChannelsClosed (deSocket* sock, deUint32 channels)
6843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deMutex_lock(sock->stateLock);
6863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	sock->openChannels &= ~channels;
6883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (sock->openChannels == 0)
6893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		sock->state = DE_SOCKETSTATE_DISCONNECTED;
6903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deMutex_unlock(sock->stateLock);
6923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6943c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeSocketResult deSocket_send (deSocket* sock, const void* buf, int bufSize, int* numSentPtr)
6953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int				numSent	= (int)send(sock->handle, (const char*)buf, bufSize, 0);
6973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deSocketResult	result	= mapSendRecvResult(numSent);
6983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (numSentPtr)
7003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		*numSentPtr = numSent;
7013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Update state. */
7033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (result == DE_SOCKETRESULT_CONNECTION_CLOSED)
7043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deSocket_setChannelsClosed(sock, DE_SOCKETCHANNEL_SEND);
7053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (result == DE_SOCKETRESULT_CONNECTION_TERMINATED)
7063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deSocket_setChannelsClosed(sock, DE_SOCKETCHANNEL_BOTH);
7073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return result;
7093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7113c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeSocketResult deSocket_receive (deSocket* sock, void* buf, int bufSize, int* numReceivedPtr)
7123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int				numRecv	= (int)recv(sock->handle, (char*)buf, bufSize, 0);
7143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deSocketResult	result	= mapSendRecvResult(numRecv);
7153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (numReceivedPtr)
7173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		*numReceivedPtr = numRecv;
7183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Update state. */
7203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (result == DE_SOCKETRESULT_CONNECTION_CLOSED)
7213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deSocket_setChannelsClosed(sock, DE_SOCKETCHANNEL_RECEIVE);
7223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (result == DE_SOCKETRESULT_CONNECTION_TERMINATED)
7233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deSocket_setChannelsClosed(sock, DE_SOCKETCHANNEL_BOTH);
7243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return result;
7263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif
729