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 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 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 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 89 deBool deSocketAddress_setFamily (deSocketAddress* address, deSocketFamily family) 90 { 91 address->family = family; 92 return DE_TRUE; 93 } 94 95 deSocketFamily deSocketAddress_getFamily (const deSocketAddress* address) 96 { 97 return address->family; 98 } 99 100 void deSocketAddress_destroy (deSocketAddress* address) 101 { 102 deFree(address->host); 103 deFree(address); 104 } 105 106 deBool deSocketAddress_setPort (deSocketAddress* address, int port) 107 { 108 address->port = port; 109 return DE_TRUE; 110 } 111 112 int deSocketAddress_getPort (const deSocketAddress* address) 113 { 114 return address->port; 115 } 116 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 129 const char* deSocketAddress_getHost (const deSocketAddress* address) 130 { 131 return address->host; 132 } 133 134 135 deBool deSocketAddress_setType (deSocketAddress* address, deSocketType type) 136 { 137 address->type = type; 138 return DE_TRUE; 139 } 140 141 deSocketType deSocketAddress_getType (const deSocketAddress* address) 142 { 143 return address->type; 144 } 145 146 deBool deSocketAddress_setProtocol (deSocketAddress* address, deSocketProtocol protocol) 147 { 148 address->protocol = protocol; 149 return DE_TRUE; 150 } 151 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 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 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 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 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 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 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 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 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 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 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 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 438 deSocketState deSocket_getState (const deSocket* sock) 439 { 440 return sock->state; 441 } 442 443 deUint32 deSocket_getOpenChannels (const deSocket* sock) 444 { 445 return sock->openChannels; 446 } 447 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 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 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 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 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 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 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 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 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 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