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