1 /*-------------------------------------------------------------------------
2  * drawElements Utility Library
3  * ----------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Socket abstraction.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "deSocket.h"
25 #include "deMemory.h"
26 #include "deMutex.h"
27 #include "deInt32.h"
28 
29 #if (DE_OS == DE_OS_WIN32)
30 #	define DE_USE_WINSOCK
31 #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)
32 #	define DE_USE_BERKELEY_SOCKETS
33 #else
34 #	error Implement deSocket for your OS.
35 #endif
36 
37 /* Common utilities. */
38 
deGetSocketResultName(deSocketResult result)39 const char* deGetSocketResultName (deSocketResult result)
40 {
41 	switch (result)
42 	{
43 		case DE_SOCKETRESULT_SUCCESS:				return "DE_SOCKETRESULT_SUCCESS";
44 		case DE_SOCKETRESULT_WOULD_BLOCK:			return "DE_SOCKETRESULT_WOULD_BLOCK";
45 		case DE_SOCKETRESULT_CONNECTION_CLOSED:		return "DE_SOCKETRESULT_CONNECTION_CLOSED";
46 		case DE_SOCKETRESULT_CONNECTION_TERMINATED:	return "DE_SOCKETRESULT_CONNECTION_TERMINATED";
47 		case DE_SOCKETRESULT_ERROR:					return "DE_SOCKETRESULT_ERROR";
48 		default:									return DE_NULL;
49 	}
50 }
51 
deGetSocketFamilyName(deSocketFamily family)52 const char* deGetSocketFamilyName (deSocketFamily family)
53 {
54 	switch (family)
55 	{
56 		case DE_SOCKETFAMILY_INET4:		return "DE_SOCKETFAMILY_INET4";
57 		case DE_SOCKETFAMILY_INET6:		return "DE_SOCKETFAMILY_INET6";
58 		default:						return DE_NULL;
59 	}
60 }
61 
62 #if defined(DE_USE_WINSOCK) || defined(DE_USE_BERKELEY_SOCKETS)
63 
64 /* Common deSocketAddress implementation. */
65 
66 struct deSocketAddress_s
67 {
68 	char*				host;
69 	int					port;
70 	deSocketFamily		family;
71 	deSocketType		type;
72 	deSocketProtocol	protocol;
73 };
74 
deSocketAddress_create(void)75 deSocketAddress* deSocketAddress_create (void)
76 {
77 	deSocketAddress* addr = (deSocketAddress*)deCalloc(sizeof(deSocketAddress));
78 	if (!addr)
79 		return addr;
80 
81 	/* Sane defaults. */
82 	addr->family	= DE_SOCKETFAMILY_INET4;
83 	addr->type		= DE_SOCKETTYPE_STREAM;
84 	addr->protocol	= DE_SOCKETPROTOCOL_TCP;
85 
86 	return addr;
87 }
88 
deSocketAddress_setFamily(deSocketAddress * address,deSocketFamily family)89 deBool deSocketAddress_setFamily (deSocketAddress* address, deSocketFamily family)
90 {
91 	address->family = family;
92 	return DE_TRUE;
93 }
94 
deSocketAddress_getFamily(const deSocketAddress * address)95 deSocketFamily deSocketAddress_getFamily (const deSocketAddress* address)
96 {
97 	return address->family;
98 }
99 
deSocketAddress_destroy(deSocketAddress * address)100 void deSocketAddress_destroy (deSocketAddress* address)
101 {
102 	deFree(address->host);
103 	deFree(address);
104 }
105 
deSocketAddress_setPort(deSocketAddress * address,int port)106 deBool deSocketAddress_setPort (deSocketAddress* address, int port)
107 {
108 	address->port = port;
109 	return DE_TRUE;
110 }
111 
deSocketAddress_getPort(const deSocketAddress * address)112 int deSocketAddress_getPort (const deSocketAddress* address)
113 {
114 	return address->port;
115 }
116 
deSocketAddress_setHost(deSocketAddress * address,const char * host)117 deBool deSocketAddress_setHost (deSocketAddress* address, const char* host)
118 {
119 	if (address->host)
120 	{
121 		deFree(address->host);
122 		address->host = DE_NULL;
123 	}
124 
125 	address->host = deStrdup(host);
126 	return address->host != DE_NULL;
127 }
128 
deSocketAddress_getHost(const deSocketAddress * address)129 const char* deSocketAddress_getHost (const deSocketAddress* address)
130 {
131 	return address->host;
132 }
133 
134 
deSocketAddress_setType(deSocketAddress * address,deSocketType type)135 deBool deSocketAddress_setType (deSocketAddress* address, deSocketType type)
136 {
137 	address->type = type;
138 	return DE_TRUE;
139 }
140 
deSocketAddress_getType(const deSocketAddress * address)141 deSocketType deSocketAddress_getType (const deSocketAddress* address)
142 {
143 	return address->type;
144 }
145 
deSocketAddress_setProtocol(deSocketAddress * address,deSocketProtocol protocol)146 deBool deSocketAddress_setProtocol (deSocketAddress* address, deSocketProtocol protocol)
147 {
148 	address->protocol = protocol;
149 	return DE_TRUE;
150 }
151 
deSocketAddress_getProtocol(const deSocketAddress * address)152 deSocketProtocol deSocketAddress_getProtocol (const deSocketAddress* address)
153 {
154 	return address->protocol;
155 }
156 
157 #endif
158 
159 #if defined(DE_USE_WINSOCK)
160 
161 	/* WinSock spesific. */
162 #	include <WinSock2.h>
163 #	include <WS2tcpip.h>
164 #	include <WinDef.h>
165 
initWinsock(void)166 static deBool initWinsock (void)
167 {
168 	WSADATA wsaData;
169 	if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
170 		return DE_FALSE;
171 
172 	return DE_TRUE;
173 }
174 
175 #elif defined(DE_USE_BERKELEY_SOCKETS)
176 
177 	/* Berkeley Socket includes. */
178 #	include <sys/socket.h>
179 #	include <netinet/in.h>
180 #	include <netinet/tcp.h>
181 #	include <arpa/inet.h>
182 #	include <netdb.h>
183 #	include <unistd.h>
184 #	include <fcntl.h>
185 #	include <errno.h>
186 
187 #endif
188 
189 /* Socket type. */
190 #if defined(DE_USE_WINSOCK)
191 	/* \note SOCKET is unsigned type! */
192 	typedef SOCKET					deSocketHandle;
193 	typedef int						NativeSocklen;
194 	typedef int						NativeSize;
195 #	define DE_INVALID_SOCKET_HANDLE	INVALID_SOCKET
196 #else
197 	typedef int						deSocketHandle;
198 	typedef socklen_t				NativeSocklen;
199 	typedef size_t					NativeSize;
200 #	define DE_INVALID_SOCKET_HANDLE	-1
201 #endif
202 
deSocketHandleIsValid(deSocketHandle handle)203 DE_INLINE deBool deSocketHandleIsValid (deSocketHandle handle)
204 {
205 	return handle != DE_INVALID_SOCKET_HANDLE;
206 }
207 
208 #if defined(DE_USE_WINSOCK) || defined(DE_USE_BERKELEY_SOCKETS)
209 
210 /* Shared berkeley and winsock implementation. */
211 
212 struct deSocket_s
213 {
214 	deSocketHandle			handle;
215 
216 	deMutex					stateLock;
217 	volatile deSocketState	state;
218 	volatile deUint32		openChannels;
219 };
220 
221 /* Common socket functions. */
222 
deHostToNetworkOrder16(deUint16 v)223 static deUint16 deHostToNetworkOrder16 (deUint16 v)
224 {
225 #if (DE_ENDIANNESS == DE_LITTLE_ENDIAN)
226 	return deReverseBytes16(v);
227 #else
228 	return v;
229 #endif
230 }
231 
deNetworkToHostOrder16(deUint16 v)232 static deUint16 deNetworkToHostOrder16 (deUint16 v)
233 {
234 #if (DE_ENDIANNESS == DE_LITTLE_ENDIAN)
235 	return deReverseBytes16(v);
236 #else
237 	return v;
238 #endif
239 }
240 
241 DE_STATIC_ASSERT(sizeof(((struct sockaddr_in*)DE_NULL)->sin_port) == sizeof(deUint16));
242 DE_STATIC_ASSERT(sizeof(((struct sockaddr_in6*)DE_NULL)->sin6_port) == sizeof(deUint16));
243 
deSocketFamilyToBsdFamily(deSocketFamily family)244 static int deSocketFamilyToBsdFamily (deSocketFamily family)
245 {
246 	switch (family)
247 	{
248 		case DE_SOCKETFAMILY_INET4:	return AF_INET;
249 		case DE_SOCKETFAMILY_INET6:	return AF_INET6;
250 		default:
251 			DE_ASSERT(DE_FALSE);
252 			return 0;
253 	}
254 }
255 
deSocketTypeToBsdType(deSocketType type)256 static int deSocketTypeToBsdType (deSocketType type)
257 {
258 	switch (type)
259 	{
260 		case DE_SOCKETTYPE_STREAM:		return SOCK_STREAM;
261 		case DE_SOCKETTYPE_DATAGRAM:	return SOCK_DGRAM;
262 		default:
263 			DE_ASSERT(DE_FALSE);
264 			return 0;
265 	}
266 }
267 
deSocketProtocolToBsdProtocol(deSocketProtocol protocol)268 static int deSocketProtocolToBsdProtocol (deSocketProtocol protocol)
269 {
270 	switch (protocol)
271 	{
272 		case DE_SOCKETPROTOCOL_TCP:	return IPPROTO_TCP;
273 		case DE_SOCKETPROTOCOL_UDP:	return IPPROTO_UDP;
274 		default:
275 			DE_ASSERT(DE_FALSE);
276 			return 0;
277 	}
278 }
279 
deSocketAddressToBsdAddress(const deSocketAddress * address,size_t bsdAddrBufSize,struct sockaddr * bsdAddr,NativeSocklen * bsdAddrLen)280 static deBool deSocketAddressToBsdAddress (const deSocketAddress* address, size_t bsdAddrBufSize, struct sockaddr* bsdAddr, NativeSocklen* bsdAddrLen)
281 {
282 	deMemset(bsdAddr, 0, bsdAddrBufSize);
283 
284 	/* Resolve host. */
285 	if (address->host != DE_NULL)
286 	{
287 		struct addrinfo*	result	= DE_NULL;
288 		struct addrinfo		hints;
289 
290 		deMemset(&hints, 0, sizeof(hints));
291 		hints.ai_family		= deSocketFamilyToBsdFamily(address->family);
292 		hints.ai_socktype	= deSocketTypeToBsdType(address->type);
293 		hints.ai_protocol	= deSocketProtocolToBsdProtocol(address->protocol);
294 
295 		if (getaddrinfo(address->host, DE_NULL, &hints, &result) != 0 || !result)
296 		{
297 			if (result)
298 				freeaddrinfo(result);
299 			return DE_FALSE;
300 		}
301 
302 		/* \note Always uses first address. */
303 
304 		if (bsdAddrBufSize < (size_t)result->ai_addrlen)
305 		{
306 			DE_FATAL("Too small bsdAddr buffer");
307 			freeaddrinfo(result);
308 			return DE_FALSE;
309 		}
310 
311 		*bsdAddrLen	= (NativeSocklen)result->ai_addrlen;
312 
313 		deMemcpy(bsdAddr, result->ai_addr, (size_t)result->ai_addrlen);
314 		freeaddrinfo(result);
315 
316 		/* Add port. */
317 		if (bsdAddr->sa_family == AF_INET)
318 		{
319 			if (*bsdAddrLen < (NativeSocklen)sizeof(struct sockaddr_in))
320 				return DE_FALSE;
321 			((struct sockaddr_in*)bsdAddr)->sin_port = deHostToNetworkOrder16((deUint16)address->port);
322 		}
323 		else if (bsdAddr->sa_family == AF_INET6)
324 		{
325 			if (*bsdAddrLen < (NativeSocklen)sizeof(struct sockaddr_in6))
326 				return DE_FALSE;
327 			((struct sockaddr_in6*)bsdAddr)->sin6_port = deHostToNetworkOrder16((deUint16)address->port);
328 		}
329 		else
330 			return DE_FALSE;
331 
332 		return DE_TRUE;
333 	}
334 	else if (address->family == DE_SOCKETFAMILY_INET4)
335 	{
336 		struct sockaddr_in* addr4 = (struct sockaddr_in*)bsdAddr;
337 
338 		if (bsdAddrBufSize < sizeof(struct sockaddr_in))
339 		{
340 			DE_FATAL("Too small bsdAddr buffer");
341 			return DE_FALSE;
342 		}
343 
344 		addr4->sin_port			= deHostToNetworkOrder16((deUint16)address->port);
345 		addr4->sin_family		= AF_INET;
346 		addr4->sin_addr.s_addr	= INADDR_ANY;
347 
348 		*bsdAddrLen	= (NativeSocklen)sizeof(struct sockaddr_in);
349 
350 		return DE_TRUE;
351 	}
352 	else if (address->family == DE_SOCKETFAMILY_INET6)
353 	{
354 		struct sockaddr_in6* addr6 = (struct sockaddr_in6*)bsdAddr;
355 
356 		if (bsdAddrBufSize < sizeof(struct sockaddr_in6))
357 		{
358 			DE_FATAL("Too small bsdAddr buffer");
359 			return DE_FALSE;
360 		}
361 
362 		addr6->sin6_port	= deHostToNetworkOrder16((deUint16)address->port);
363 		addr6->sin6_family	= AF_INET6;
364 
365 		*bsdAddrLen	= (NativeSocklen)sizeof(struct sockaddr_in6);
366 
367 		return DE_TRUE;
368 	}
369 	else
370 		return DE_FALSE;
371 }
372 
deBsdAddressToSocketAddress(deSocketAddress * address,const struct sockaddr * bsdAddr,int addrLen)373 void deBsdAddressToSocketAddress (deSocketAddress* address, const struct sockaddr* bsdAddr, int addrLen)
374 {
375 	/* Decode client address info. */
376 	if (bsdAddr->sa_family == AF_INET)
377 	{
378 		const struct sockaddr_in* addr4 = (const struct sockaddr_in*)bsdAddr;
379 		DE_ASSERT(addrLen >= (int)sizeof(struct sockaddr_in));
380 		DE_UNREF(addrLen);
381 
382 		deSocketAddress_setFamily(address, DE_SOCKETFAMILY_INET4);
383 		deSocketAddress_setPort(address, (int)deNetworkToHostOrder16((deUint16)addr4->sin_port));
384 
385 		{
386 			char buf[16]; /* Max valid address takes 3*4 + 3 = 15 chars */
387 			inet_ntop(AF_INET, (void*)&addr4->sin_addr, buf, sizeof(buf));
388 			deSocketAddress_setHost(address, buf);
389 		}
390 	}
391 	else if (bsdAddr->sa_family == AF_INET6)
392 	{
393 		const struct sockaddr_in6* addr6 = (const struct sockaddr_in6*)bsdAddr;
394 		DE_ASSERT(addrLen >= (int)sizeof(struct sockaddr_in6));
395 		DE_UNREF(addrLen);
396 
397 		deSocketAddress_setFamily(address, DE_SOCKETFAMILY_INET6);
398 		deSocketAddress_setPort(address, (int)deNetworkToHostOrder16((deUint16)addr6->sin6_port));
399 
400 		{
401 			char buf[40]; /* Max valid address takes 8*4 + 7 = 39 chars */
402 			inet_ntop(AF_INET6, (void*)&addr6->sin6_addr, buf, sizeof(buf));
403 			deSocketAddress_setHost(address, buf);
404 		}
405 	}
406 	else
407 		DE_ASSERT(DE_FALSE);
408 }
409 
deSocket_create(void)410 deSocket* deSocket_create (void)
411 {
412 	deSocket* sock = (deSocket*)deCalloc(sizeof(deSocket));
413 	if (!sock)
414 		return sock;
415 
416 #if defined(DE_USE_WINSOCK)
417 	/* Make sure WSA is up. */
418 	if (!initWinsock())
419 		return DE_NULL;
420 #endif
421 
422 	sock->stateLock	= deMutex_create(0);
423 	sock->handle	= DE_INVALID_SOCKET_HANDLE;
424 	sock->state		= DE_SOCKETSTATE_CLOSED;
425 
426 	return sock;
427 }
428 
deSocket_destroy(deSocket * sock)429 void deSocket_destroy (deSocket* sock)
430 {
431 	if (sock->state != DE_SOCKETSTATE_CLOSED)
432 		deSocket_close(sock);
433 
434 	deMutex_destroy(sock->stateLock);
435 	deFree(sock);
436 }
437 
deSocket_getState(const deSocket * sock)438 deSocketState deSocket_getState (const deSocket* sock)
439 {
440 	return sock->state;
441 }
442 
deSocket_getOpenChannels(const deSocket * sock)443 deUint32 deSocket_getOpenChannels (const deSocket* sock)
444 {
445 	return sock->openChannels;
446 }
447 
deSocket_setFlags(deSocket * sock,deUint32 flags)448 deBool deSocket_setFlags (deSocket* sock, deUint32 flags)
449 {
450 	deSocketHandle fd = sock->handle;
451 
452 	if (sock->state == DE_SOCKETSTATE_CLOSED)
453 		return DE_FALSE;
454 
455 	/* Keepalive. */
456 	{
457 		int mode = (flags & DE_SOCKET_KEEPALIVE) ? 1 : 0;
458 		if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (const char*)&mode, sizeof(mode)) != 0)
459 			return DE_FALSE;
460 	}
461 
462 	/* Nodelay. */
463 	{
464 		int mode = (flags & DE_SOCKET_NODELAY) ? 1 : 0;
465 		if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (const char*)&mode, sizeof(mode)) != 0)
466 			return DE_FALSE;
467 	}
468 
469 	/* Non-blocking. */
470 	{
471 #if defined(DE_USE_WINSOCK)
472 		u_long mode = (flags & DE_SOCKET_NONBLOCKING) ? 1 : 0;
473 		if (ioctlsocket(fd, FIONBIO, &mode) != 0)
474 			return DE_FALSE;
475 #else
476 		int oldFlags	= fcntl(fd, F_GETFL, 0);
477 		int newFlags	= (flags & DE_SOCKET_NONBLOCKING) ? (oldFlags | O_NONBLOCK) : (oldFlags & ~O_NONBLOCK);
478 		if (fcntl(fd, F_SETFL, newFlags) != 0)
479 			return DE_FALSE;
480 #endif
481 	}
482 
483 	/* Close on exec. */
484 	{
485 #if defined(DE_USE_BERKELEY_SOCKETS)
486 		int oldFlags = fcntl(fd, F_GETFD, 0);
487 		int newFlags = (flags & DE_SOCKET_CLOSE_ON_EXEC) ? (oldFlags | FD_CLOEXEC) : (oldFlags & ~FD_CLOEXEC);
488 		if (fcntl(fd, F_SETFD, newFlags) != 0)
489 			return DE_FALSE;
490 #endif
491 	}
492 
493 	return DE_TRUE;
494 }
495 
deSocket_listen(deSocket * sock,const deSocketAddress * address)496 deBool deSocket_listen (deSocket* sock, const deSocketAddress* address)
497 {
498 	const int			backlogSize	= 4;
499 	deUint8				bsdAddrBuf[sizeof(struct sockaddr_in6)];
500 	struct sockaddr*	bsdAddr		= (struct sockaddr*)&bsdAddrBuf[0];
501 	NativeSocklen		bsdAddrLen;
502 
503 	if (sock->state != DE_SOCKETSTATE_CLOSED)
504 		return DE_FALSE;
505 
506 	/* Resolve address. */
507 	if (!deSocketAddressToBsdAddress(address, sizeof(bsdAddrBuf), bsdAddr, &bsdAddrLen))
508 		return DE_FALSE;
509 
510 	/* Create socket. */
511 	sock->handle = socket(bsdAddr->sa_family, deSocketTypeToBsdType(address->type), deSocketProtocolToBsdProtocol(address->protocol));
512 	if (!deSocketHandleIsValid(sock->handle))
513 		return DE_FALSE;
514 
515 	sock->state = DE_SOCKETSTATE_DISCONNECTED;
516 
517 	/* Allow re-using address. */
518 	{
519 		int reuseVal = 1;
520 		setsockopt(sock->handle, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuseVal, (int)sizeof(reuseVal));
521 	}
522 
523 	/* Bind to address. */
524 	if (bind(sock->handle, bsdAddr, (NativeSocklen)bsdAddrLen) != 0)
525 	{
526 		deSocket_close(sock);
527 		return DE_FALSE;
528 	}
529 
530 	/* Start listening. */
531 	if (listen(sock->handle, backlogSize) != 0)
532 	{
533 		deSocket_close(sock);
534 		return DE_FALSE;
535 	}
536 
537 	sock->state = DE_SOCKETSTATE_LISTENING;
538 
539 	return DE_TRUE;
540 }
541 
deSocket_accept(deSocket * sock,deSocketAddress * clientAddress)542 deSocket* deSocket_accept (deSocket* sock, deSocketAddress* clientAddress)
543 {
544 	deSocketHandle		newFd		= DE_INVALID_SOCKET_HANDLE;
545 	deSocket*			newSock		= DE_NULL;
546 	deUint8				bsdAddrBuf[sizeof(struct sockaddr_in6)];
547 	struct sockaddr*	bsdAddr		= (struct sockaddr*)&bsdAddrBuf[0];
548 	NativeSocklen		bsdAddrLen	= (NativeSocklen)sizeof(bsdAddrBuf);
549 
550 	deMemset(bsdAddr, 0, (size_t)bsdAddrLen);
551 
552 	newFd = accept(sock->handle, bsdAddr, &bsdAddrLen);
553 	if (!deSocketHandleIsValid(newFd))
554 		return DE_NULL;
555 
556 	newSock = (deSocket*)deCalloc(sizeof(deSocket));
557 	if (!newSock)
558 	{
559 #if defined(DE_USE_WINSOCK)
560 		closesocket(newFd);
561 #else
562 		close(newFd);
563 #endif
564 		return DE_NULL;
565 	}
566 
567 	newSock->stateLock		= deMutex_create(0);
568 	newSock->handle			= newFd;
569 	newSock->state			= DE_SOCKETSTATE_CONNECTED;
570 	newSock->openChannels	= DE_SOCKETCHANNEL_BOTH;
571 
572 	if (clientAddress)
573 		deBsdAddressToSocketAddress(clientAddress, bsdAddr, (int)bsdAddrLen);
574 
575 	return newSock;
576 }
577 
deSocket_connect(deSocket * sock,const deSocketAddress * address)578 deBool deSocket_connect (deSocket* sock, const deSocketAddress* address)
579 {
580 	deUint8				bsdAddrBuf[sizeof(struct sockaddr_in6)];
581 	struct sockaddr*	bsdAddr		= (struct sockaddr*)&bsdAddrBuf[0];
582 	NativeSocklen		bsdAddrLen;
583 
584 	/* Resolve address. */
585 	if (!deSocketAddressToBsdAddress(address, sizeof(bsdAddrBuf), bsdAddr, &bsdAddrLen))
586 		return DE_FALSE;
587 
588 	/* Create socket. */
589 	sock->handle = socket(bsdAddr->sa_family, deSocketTypeToBsdType(address->type), deSocketProtocolToBsdProtocol(address->protocol));
590 	if (!deSocketHandleIsValid(sock->handle))
591 		return DE_FALSE;
592 
593 	/* Connect. */
594 	if (connect(sock->handle, bsdAddr, bsdAddrLen) != 0)
595 	{
596 #if defined(DE_USE_WINSOCK)
597 		closesocket(sock->handle);
598 #else
599 		close(sock->handle);
600 #endif
601 		sock->handle = DE_INVALID_SOCKET_HANDLE;
602 		return DE_FALSE;
603 	}
604 
605 	sock->state			= DE_SOCKETSTATE_CONNECTED;
606 	sock->openChannels	= DE_SOCKETCHANNEL_BOTH;
607 
608 	return DE_TRUE;
609 }
610 
deSocket_shutdown(deSocket * sock,deUint32 channels)611 deBool deSocket_shutdown (deSocket* sock, deUint32 channels)
612 {
613 	deUint32 closedChannels = 0;
614 
615 	deMutex_lock(sock->stateLock);
616 
617 	if (sock->state == DE_SOCKETSTATE_DISCONNECTED ||
618 		sock->state == DE_SOCKETSTATE_CLOSED)
619 	{
620 		deMutex_unlock(sock->stateLock);
621 		return DE_FALSE;
622 	}
623 
624 	DE_ASSERT(channels != 0 && (channels & ~(deUint32)DE_SOCKETCHANNEL_BOTH) == 0);
625 
626 	/* Don't attempt to close already closed channels on partially open socket. */
627 	channels &= sock->openChannels;
628 
629 	if (channels == 0)
630 	{
631 		deMutex_unlock(sock->stateLock);
632 		return DE_FALSE;
633 	}
634 
635 #if defined(DE_USE_WINSOCK)
636 	{
637 		int how = 0;
638 
639 		if ((channels & DE_SOCKETCHANNEL_BOTH) == DE_SOCKETCHANNEL_BOTH)
640 			how = SD_BOTH;
641 		else if (channels & DE_SOCKETCHANNEL_SEND)
642 			how = SD_SEND;
643 		else if (channels & DE_SOCKETCHANNEL_RECEIVE)
644 			how = SD_RECEIVE;
645 
646 		if (shutdown(sock->handle, how) == 0)
647 			closedChannels = channels;
648 		else
649 		{
650 			int err = WSAGetLastError();
651 
652 			/* \note Due to asynchronous behavior certain errors are perfectly ok. */
653 			if (err == WSAECONNABORTED || err == WSAECONNRESET || err == WSAENOTCONN)
654 				closedChannels = DE_SOCKETCHANNEL_BOTH;
655 			else
656 			{
657 				deMutex_unlock(sock->stateLock);
658 				return DE_FALSE;
659 			}
660 		}
661 	}
662 #else
663 	{
664 		int how = 0;
665 
666 		if ((channels & DE_SOCKETCHANNEL_BOTH) == DE_SOCKETCHANNEL_BOTH)
667 			how = SHUT_RDWR;
668 		else if (channels & DE_SOCKETCHANNEL_SEND)
669 			how = SHUT_WR;
670 		else if (channels & DE_SOCKETCHANNEL_RECEIVE)
671 			how = SHUT_RD;
672 
673 		if (shutdown(sock->handle, how) == 0)
674 			closedChannels = channels;
675 		else
676 		{
677 			if (errno == ENOTCONN)
678 				closedChannels = DE_SOCKETCHANNEL_BOTH;
679 			else
680 			{
681 				deMutex_unlock(sock->stateLock);
682 				return DE_FALSE;
683 			}
684 		}
685 	}
686 #endif
687 
688 	sock->openChannels &= ~closedChannels;
689 	if (sock->openChannels == 0)
690 		sock->state = DE_SOCKETSTATE_DISCONNECTED;
691 
692 	deMutex_unlock(sock->stateLock);
693 	return DE_TRUE;
694 }
695 
deSocket_close(deSocket * sock)696 deBool deSocket_close (deSocket* sock)
697 {
698 	deMutex_lock(sock->stateLock);
699 
700 	if (sock->state == DE_SOCKETSTATE_CLOSED)
701 	{
702 		deMutex_unlock(sock->stateLock);
703 		return DE_FALSE;
704 	}
705 
706 #if !defined(DE_USE_WINSOCK)
707 	if (sock->state == DE_SOCKETSTATE_LISTENING)
708 	{
709 		/* There can be a thread blockin in accept(). Release it by calling shutdown. */
710 		shutdown(sock->handle, SHUT_RDWR);
711 	}
712 #endif
713 
714 #if defined(DE_USE_WINSOCK)
715 	if (closesocket(sock->handle) != 0)
716 		return DE_FALSE;
717 #else
718 	if (close(sock->handle) != 0)
719 		return DE_FALSE;
720 #endif
721 	sock->state			= DE_SOCKETSTATE_CLOSED;
722 	sock->handle		= DE_INVALID_SOCKET_HANDLE;
723 	sock->openChannels	= 0;
724 
725 	deMutex_unlock(sock->stateLock);
726 	return DE_TRUE;
727 }
728 
mapSendRecvResult(int numBytes)729 static deSocketResult mapSendRecvResult (int numBytes)
730 {
731 	if (numBytes > 0)
732 		return DE_SOCKETRESULT_SUCCESS;
733 	else if (numBytes == 0)
734 		return DE_SOCKETRESULT_CONNECTION_CLOSED;
735 	else
736 	{
737 		/* Other errors. */
738 #if defined(DE_USE_WINSOCK)
739 		int	error = WSAGetLastError();
740 		switch (error)
741 		{
742 			case WSAEWOULDBLOCK:	return DE_SOCKETRESULT_WOULD_BLOCK;
743 			case WSAENETDOWN:
744 			case WSAENETRESET:
745 			case WSAECONNABORTED:
746 			case WSAECONNRESET:		return DE_SOCKETRESULT_CONNECTION_TERMINATED;
747 			default:				return DE_SOCKETRESULT_ERROR;
748 		}
749 #else
750 		switch (errno)
751 		{
752 			case EAGAIN:		return DE_SOCKETRESULT_WOULD_BLOCK;
753 			case ECONNABORTED:
754 			case ECONNRESET:	return DE_SOCKETRESULT_CONNECTION_TERMINATED;
755 			default:			return DE_SOCKETRESULT_ERROR;
756 		}
757 #endif
758 	}
759 }
760 
deSocket_setChannelsClosed(deSocket * sock,deUint32 channels)761 DE_INLINE void deSocket_setChannelsClosed (deSocket* sock, deUint32 channels)
762 {
763 	deMutex_lock(sock->stateLock);
764 
765 	sock->openChannels &= ~channels;
766 	if (sock->openChannels == 0)
767 		sock->state = DE_SOCKETSTATE_DISCONNECTED;
768 
769 	deMutex_unlock(sock->stateLock);
770 }
771 
deSocket_send(deSocket * sock,const void * buf,size_t bufSize,size_t * numSentPtr)772 deSocketResult deSocket_send (deSocket* sock, const void* buf, size_t bufSize, size_t* numSentPtr)
773 {
774 	int				numSent	= (int)send(sock->handle, (const char*)buf, (NativeSize)bufSize, 0);
775 	deSocketResult	result	= mapSendRecvResult(numSent);
776 
777 	if (numSentPtr)
778 		*numSentPtr = (numSent > 0) ? ((size_t)numSent) : (0);
779 
780 	/* Update state. */
781 	if (result == DE_SOCKETRESULT_CONNECTION_CLOSED)
782 		deSocket_setChannelsClosed(sock, DE_SOCKETCHANNEL_SEND);
783 	else if (result == DE_SOCKETRESULT_CONNECTION_TERMINATED)
784 		deSocket_setChannelsClosed(sock, DE_SOCKETCHANNEL_BOTH);
785 
786 	return result;
787 }
788 
deSocket_receive(deSocket * sock,void * buf,size_t bufSize,size_t * numReceivedPtr)789 deSocketResult deSocket_receive (deSocket* sock, void* buf, size_t bufSize, size_t* numReceivedPtr)
790 {
791 	int				numRecv	= (int)recv(sock->handle, (char*)buf, (NativeSize)bufSize, 0);
792 	deSocketResult	result	= mapSendRecvResult(numRecv);
793 
794 	if (numReceivedPtr)
795 		*numReceivedPtr = (numRecv > 0) ? ((size_t)numRecv) : (0);
796 
797 	/* Update state. */
798 	if (result == DE_SOCKETRESULT_CONNECTION_CLOSED)
799 		deSocket_setChannelsClosed(sock, DE_SOCKETCHANNEL_RECEIVE);
800 	else if (result == DE_SOCKETRESULT_CONNECTION_TERMINATED)
801 		deSocket_setChannelsClosed(sock, DE_SOCKETCHANNEL_BOTH);
802 
803 	return result;
804 }
805 
806 #endif
807