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