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