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