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) || (DE_OS == DE_OS_QNX)
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