vbox的更動 23625 路徑 trunk/src/VBox/Runtime/r3/tcp.cpp
- 時間撮記:
- 2009-10-8 下午04:56:22 (15 年 以前)
- 檔案:
-
- 修改 1 筆資料
圖例:
- 未更動
- 新增
- 刪除
-
trunk/src/VBox/Runtime/r3/tcp.cpp
r23613 r23625 34 34 *******************************************************************************/ 35 35 #ifdef RT_OS_WINDOWS 36 # include <winsock.h>36 # include <winsock.h> 37 37 #else /* !RT_OS_WINDOWS */ 38 # include <errno.h>39 # include <sys/stat.h>40 # include <sys/socket.h>41 # include <netinet/in.h>42 # include <netinet/tcp.h>43 # include <arpa/inet.h>44 # include <sys/un.h>45 # include <netdb.h>46 # include <unistd.h>38 # include <errno.h> 39 # include <sys/stat.h> 40 # include <sys/socket.h> 41 # include <netinet/in.h> 42 # include <netinet/tcp.h> 43 # include <arpa/inet.h> 44 # include <sys/un.h> 45 # include <netdb.h> 46 # include <unistd.h> 47 47 #endif /* !RT_OS_WINDOWS */ 48 48 49 #include "internal/iprt.h" 49 50 #include <iprt/tcp.h> 51 52 #include <iprt/asm.h> 53 #include <iprt/assert.h> 54 #include <iprt/err.h> 55 #include <iprt/mempool.h> 56 #include <iprt/string.h> 50 57 #include <iprt/thread.h> 51 #include <iprt/alloc.h> 52 #include <iprt/assert.h>53 #include <iprt/asm.h> 54 #include <iprt/err.h> 55 #include <iprt/string.h> 56 57 58 59 #include "internal/magics.h" 60 61 62 /******************************************************************************* 63 * Defined Constants And Macros * 64 *******************************************************************************/ 58 65 /* non-standard linux stuff (it seems). */ 59 66 #ifndef MSG_NOSIGNAL 60 # define MSG_NOSIGNAL 067 # define MSG_NOSIGNAL 0 61 68 #endif 62 69 #ifndef SHUT_RDWR 63 70 # ifdef SD_BOTH 64 # define SHUT_RDWR SD_BOTH71 # define SHUT_RDWR SD_BOTH 65 72 # else 66 # define SHUT_RDWR 273 # define SHUT_RDWR 2 67 74 # endif 68 75 #endif … … 70 77 /* fixup backlevel OSes. */ 71 78 #if defined(RT_OS_OS2) || defined(RT_OS_WINDOWS) 72 # define socklen_t int79 # define socklen_t int 73 80 #endif 74 81 75 76 /******************************************************************************* 77 * Defined Constants And Macros * 78 *******************************************************************************/ 79 #define BACKLOG 10 /* how many pending connections queue will hold */ 82 /** How many pending connection. */ 83 #define RTTCP_SERVER_BACKLOG 10 80 84 81 85 … … 102 106 /** Listener terminated. */ 103 107 RTTCPSERVERSTATE_STOPPED, 104 /** Destroying signaling to the listener, listener will wait. */105 RTTCPSERVERSTATE_SIGNALING,106 108 /** Listener cleans up. */ 107 RTTCPSERVERSTATE_DESTROYING, 108 /** Freed. */ 109 RTTCPSERVERSTATE_FREED 109 RTTCPSERVERSTATE_DESTROYING 110 110 } RTTCPSERVERSTATE; 111 111 … … 115 115 typedef struct RTTCPSERVER 116 116 { 117 /** The magic value (RTTCPSERVER_MAGIC). */ 118 uint32_t volatile u32Magic; 117 119 /** The server state. */ 118 120 RTTCPSERVERSTATE volatile enmState; … … 135 137 *******************************************************************************/ 136 138 static DECLCALLBACK(int) rtTcpServerThread(RTTHREAD ThreadSelf, void *pvServer); 137 static int rtTcpServerListen(PRTTCPSERVER pServer);138 static voidrcTcpServerListenCleanup(PRTTCPSERVER pServer);139 static void rtTcpServerDestroyServerSock(RTSOCKET SockServer, const char *pszMsg);140 static int rtTcpClose(RTSOCKET Sock, const char *pszMsg);139 static int rtTcpServerListen(PRTTCPSERVER pServer); 140 static int rcTcpServerListenCleanup(PRTTCPSERVER pServer); 141 static int rtTcpServerDestroySocket(RTSOCKET volatile *pSockClient, const char *pszMsg); 142 static int rtTcpClose(RTSOCKET Sock, const char *pszMsg); 141 143 142 144 … … 217 219 218 220 /** 219 * Changesthe TCP server state.220 */ 221 DECLINLINE(bool) rtTcpServer SetState(PRTTCPSERVER pServer, RTTCPSERVERSTATE enmStateNew, RTTCPSERVERSTATE enmStateOld)221 * Tries to change the TCP server state. 222 */ 223 DECLINLINE(bool) rtTcpServerTrySetState(PRTTCPSERVER pServer, RTTCPSERVERSTATE enmStateNew, RTTCPSERVERSTATE enmStateOld) 222 224 { 223 225 bool fRc; 224 226 ASMAtomicCmpXchgSize(&pServer->enmState, enmStateNew, enmStateOld, fRc); 225 227 return fRc; 228 } 229 230 /** 231 * Changes the TCP server state. 232 */ 233 DECLINLINE(void) rtTcpServerSetState(PRTTCPSERVER pServer, RTTCPSERVERSTATE enmStateNew, RTTCPSERVERSTATE enmStateOld) 234 { 235 bool fRc; 236 ASMAtomicCmpXchgSize(&pServer->enmState, enmStateNew, enmStateOld, fRc); 237 Assert(fRc); NOREF(fRc); 238 } 239 240 /** 241 * Closes the a socket (client or server). 242 * 243 * @returns IPRT status code. 244 */ 245 static int rtTcpServerDestroySocket(RTSOCKET volatile *pSock, const char *pszMsg) 246 { 247 RTSOCKET Sock = rtTcpAtomicXchgSock(pSock, NIL_RTSOCKET); 248 if (Sock != NIL_RTSOCKET) 249 { 250 shutdown(Sock, SHUT_RDWR); 251 return rtTcpClose(Sock, pszMsg); 252 } 253 return VINF_TCP_SERVER_NO_CLIENT; 226 254 } 227 255 … … 249 277 { 250 278 /* 251 * Do params checking 252 */ 253 if (!uPort || !pfnServe || !pszThrdName || !ppServer) 254 { 255 AssertMsgFailed(("Invalid params\n")); 256 return VERR_INVALID_PARAMETER; 257 } 279 * Validate input. 280 */ 281 AssertReturn(uPort > 0, VERR_INVALID_PARAMETER); 282 AssertPtrReturn(pfnServe, VERR_INVALID_POINTER); 283 AssertPtrReturn(pszThrdName, VERR_INVALID_POINTER); 284 AssertPtrReturn(ppServer, VERR_INVALID_POINTER); 258 285 259 286 /* 260 287 * Create the server. 261 288 */ 262 PRTTCPSERVER 289 PRTTCPSERVER pServer; 263 290 int rc = RTTcpServerCreateEx(pszAddress, uPort, &pServer); 264 291 if (RT_SUCCESS(rc)) … … 267 294 * Create the listener thread. 268 295 */ 296 RTMemPoolRetain(pServer); 269 297 pServer->enmState = RTTCPSERVERSTATE_STARTING; 270 298 pServer->pvUser = pvUser; … … 276 304 if (ppServer) 277 305 *ppServer = pServer; 306 else 307 RTMemPoolRelease(RTMEMPOOL_DEFAULT, pServer); 278 308 return rc; 279 309 } 310 RTMemPoolRelease(RTMEMPOOL_DEFAULT, pServer); 280 311 281 312 /* … … 300 331 { 301 332 PRTTCPSERVER pServer = (PRTTCPSERVER)pvServer; 302 if (rtTcpServerSetState(pServer, RTTCPSERVERSTATE_ACCEPTING, RTTCPSERVERSTATE_STARTING)) 303 return rtTcpServerListen(pServer); 304 rcTcpServerListenCleanup(pServer); 333 int rc; 334 if (rtTcpServerTrySetState(pServer, RTTCPSERVERSTATE_ACCEPTING, RTTCPSERVERSTATE_STARTING)) 335 rc = rtTcpServerListen(pServer); 336 else 337 rc = rcTcpServerListenCleanup(pServer); 338 RTMemPoolRelease(RTMEMPOOL_DEFAULT, pServer); 305 339 NOREF(ThreadSelf); 306 340 return VINF_SUCCESS; … … 323 357 324 358 /* 325 * Do params checking 326 */ 327 if (!uPort || !ppServer) 328 { 329 AssertMsgFailed(("Invalid params\n")); 330 return VERR_INVALID_PARAMETER; 331 } 359 * Validate input. 360 */ 361 AssertReturn(uPort > 0, VERR_INVALID_PARAMETER); 362 AssertPtrReturn(ppServer, VERR_INVALID_PARAMETER); 332 363 333 364 #ifdef RT_OS_WINDOWS … … 398 429 * Listen for connections on a socket. 399 430 */ 400 if (listen(WaitSock, BACKLOG) != -1)431 if (listen(WaitSock, RTTCP_SERVER_BACKLOG) != -1) 401 432 { 402 433 /* 403 434 * Create the server handle. 404 435 */ 405 PRTTCPSERVER pServer = (PRTTCPSERVER)RTMem AllocZ(sizeof(*pServer));436 PRTTCPSERVER pServer = (PRTTCPSERVER)RTMemPoolAlloc(RTMEMPOOL_DEFAULT, sizeof(*pServer)); 406 437 if (pServer) 407 438 { 439 pServer->u32Magic = RTTCPSERVER_MAGIC; 408 440 pServer->SockServer = WaitSock; 409 441 pServer->SockClient = NIL_RTSOCKET; … … 453 485 * can only be destroyed. 454 486 * 455 * @returns iprt status code. 487 * @returns IPRT status code. 488 * @retval VERR_TCP_SERVER_STOP if stopped by pfnServe. 489 * @retval VERR_TCP_SERVER_SHUTDOWN if shut down by RTTcpServerShutdown. 490 * 456 491 * @param pServer The server handle as returned from RTTcpServerCreateEx(). 457 492 * @param pfnServe The function which will serve a new client connection. … … 461 496 { 462 497 /* 463 * Validate input. 464 */ 465 if (!pfnServe || !pServer) 466 { 467 AssertMsgFailed(("pfnServer=%p pServer=%p\n", pfnServe, pServer)); 468 return VERR_INVALID_PARAMETER; 469 } 470 if (rtTcpServerSetState(pServer, RTTCPSERVERSTATE_ACCEPTING, RTTCPSERVERSTATE_CREATED)) 498 * Validate input and retain the instance. 499 */ 500 AssertPtrReturn(pfnServe, VERR_INVALID_POINTER); 501 AssertPtrReturn(pServer, VERR_INVALID_HANDLE); 502 AssertReturn(pServer->u32Magic == RTTCPSERVER_MAGIC, VERR_INVALID_HANDLE); 503 AssertReturn(RTMemPoolRetain(pServer) != UINT32_MAX, VERR_INVALID_HANDLE); 504 505 int rc = VERR_INVALID_STATE; 506 if (rtTcpServerTrySetState(pServer, RTTCPSERVERSTATE_ACCEPTING, RTTCPSERVERSTATE_CREATED)) 471 507 { 472 508 Assert(!pServer->pfnServe); … … 479 515 pServer->Thread = RTThreadSelf(); 480 516 Assert(pServer->Thread != NIL_RTTHREAD); 481 return rtTcpServerListen(pServer); 482 } 483 AssertMsgFailed(("pServer->enmState=%d\n", pServer->enmState)); 484 return VERR_INVALID_PARAMETER; 485 } 486 487 488 /** 489 * Closes the client socket. 490 */ 491 static int rtTcpServerDestroyClientSock(RTSOCKET volatile *pSock, const char *pszMsg) 492 { 493 RTSOCKET Sock = rtTcpAtomicXchgSock(pSock, NIL_RTSOCKET); 494 if (Sock != NIL_RTSOCKET) 495 shutdown(Sock, SHUT_RDWR); 496 return rtTcpClose(Sock, pszMsg); 497 } 498 499 500 /** 501 * Internal worker common for RTTcpServerListen and the thread created by RTTcpServerCreate(). 517 rc = rtTcpServerListen(pServer); 518 } 519 else 520 { 521 AssertMsgFailed(("enmState=%d\n", pServer->enmState)); 522 rc = VERR_INVALID_STATE; 523 } 524 RTMemPoolRelease(RTMEMPOOL_DEFAULT, pServer); 525 return rc; 526 } 527 528 529 /** 530 * Internal worker common for RTTcpServerListen and the thread created by 531 * RTTcpServerCreate(). 532 * 533 * The caller makes sure it has its own memory reference and releases it upon 534 * return. 502 535 */ 503 536 static int rtTcpServerListen(PRTTCPSERVER pServer) … … 506 539 * Accept connection loop. 507 540 */ 508 int rc = VINF_SUCCESS;509 541 for (;;) 510 542 { … … 512 544 * Change state. 513 545 */ 514 RTTCPSERVERSTATE enmState = pServer->enmState; 546 RTTCPSERVERSTATE enmState = pServer->enmState; 547 RTSOCKET SockServer = pServer->SockServer; 515 548 if ( enmState != RTTCPSERVERSTATE_ACCEPTING 516 549 && enmState != RTTCPSERVERSTATE_SERVING) 517 break;518 if (!rtTcpServer SetState(pServer, RTTCPSERVERSTATE_ACCEPTING, enmState))550 return rcTcpServerListenCleanup(pServer); 551 if (!rtTcpServerTrySetState(pServer, RTTCPSERVERSTATE_ACCEPTING, enmState)) 519 552 continue; 520 553 … … 522 555 * Accept connection. 523 556 */ 524 struct sockaddr_in RemoteAddr= {0};525 socklen_t Len= sizeof(RemoteAddr);526 RTSOCKET Socket = accept( pServer->SockServer, (struct sockaddr *)&RemoteAddr, &Len);557 struct sockaddr_in RemoteAddr = {0}; 558 socklen_t cbRemoteAddr = sizeof(RemoteAddr); 559 RTSOCKET Socket = accept(SockServer, (struct sockaddr *)&RemoteAddr, &cbRemoteAddr); 527 560 if (Socket == -1) 528 561 { … … 530 563 /* These are typical for what can happen during destruction. */ 531 564 if (errno == EBADF || errno == EINVAL || errno == ENOTSOCK) 532 break;565 return rcTcpServerListenCleanup(pServer); 533 566 #endif 534 567 continue; … … 538 571 * Run a pfnServe callback. 539 572 */ 540 if (!rtTcpServerSetState(pServer, RTTCPSERVERSTATE_SERVING, RTTCPSERVERSTATE_ACCEPTING)) 541 break; 573 if (!rtTcpServerTrySetState(pServer, RTTCPSERVERSTATE_SERVING, RTTCPSERVERSTATE_ACCEPTING)) 574 { 575 rtTcpClose(Socket, "rtTcpServerListen"); 576 return rcTcpServerListenCleanup(pServer); 577 } 542 578 rtTcpAtomicXchgSock(&pServer->SockClient, Socket); 543 rc = pServer->pfnServe(Socket, pServer->pvUser);544 rtTcpServerDestroy ClientSock(&pServer->SockClient, "Listener: client");579 int rc = pServer->pfnServe(Socket, pServer->pvUser); 580 rtTcpServerDestroySocket(&pServer->SockClient, "Listener: client"); 545 581 546 582 /* … … 549 585 if (rc == VERR_TCP_SERVER_STOP) 550 586 { 551 if (rtTcpServer SetState(pServer, RTTCPSERVERSTATE_STOPPING, RTTCPSERVERSTATE_SERVING))587 if (rtTcpServerTrySetState(pServer, RTTCPSERVERSTATE_STOPPING, RTTCPSERVERSTATE_SERVING)) 552 588 { 553 589 /* … … 558 594 rtTcpServerSetState(pServer, RTTCPSERVERSTATE_STOPPED, RTTCPSERVERSTATE_STOPPING); 559 595 rtTcpClose(SockServer, "Listener: server stopped"); 560 return rc;561 596 } 562 break; 563 } 564 } 565 566 /* 567 * Perform any pending clean and be gone. 568 */ 569 rcTcpServerListenCleanup(pServer); 597 else 598 rcTcpServerListenCleanup(pServer); /* ignore rc */ 599 return rc; 600 } 601 } 602 } 603 604 605 /** 606 * Clean up after listener. 607 */ 608 static int rcTcpServerListenCleanup(PRTTCPSERVER pServer) 609 { 610 /* 611 * Close the server socket, the client one shouldn't be set. 612 */ 613 rtTcpServerDestroySocket(&pServer->SockServer, "ListenCleanup"); 614 Assert(pServer->SockClient == NIL_RTSOCKET); 615 616 /* 617 * Figure the return code and make sure the state is OK. 618 */ 619 RTTCPSERVERSTATE enmState = pServer->enmState; 620 switch (enmState) 621 { 622 case RTTCPSERVERSTATE_STOPPING: 623 case RTTCPSERVERSTATE_STOPPED: 624 return VERR_TCP_SERVER_SHUTDOWN; 625 626 case RTTCPSERVERSTATE_ACCEPTING: 627 rtTcpServerTrySetState(pServer, RTTCPSERVERSTATE_STOPPED, enmState); 628 return VERR_TCP_SERVER_DESTROYED; 629 630 case RTTCPSERVERSTATE_DESTROYING: 631 return VERR_TCP_SERVER_DESTROYED; 632 633 case RTTCPSERVERSTATE_STARTING: 634 case RTTCPSERVERSTATE_SERVING: 635 default: 636 AssertMsgFailedReturn(("pServer=%p enmState=%d\n", pServer, enmState), VERR_INTERNAL_ERROR_4); 637 } 638 } 639 640 641 /** 642 * Terminate the open connection to the server. 643 * 644 * @returns iprt status code. 645 * @param pServer Handle to the server. 646 */ 647 RTR3DECL(int) RTTcpServerDisconnectClient(PRTTCPSERVER pServer) 648 { 649 /* 650 * Validate input and retain the instance. 651 */ 652 AssertPtrReturn(pServer, VERR_INVALID_HANDLE); 653 AssertReturn(pServer->u32Magic == RTTCPSERVER_MAGIC, VERR_INVALID_HANDLE); 654 AssertReturn(RTMemPoolRetain(pServer) != UINT32_MAX, VERR_INVALID_HANDLE); 655 656 int rc = rtTcpServerDestroySocket(&pServer->SockClient, "DisconnectClient: client"); 657 658 RTMemPoolRelease(RTMEMPOOL_DEFAULT, pServer); 570 659 return rc; 571 660 } … … 573 662 574 663 /** 575 * Clean up after listener. 576 */ 577 static void rcTcpServerListenCleanup(PRTTCPSERVER pServer) 578 { 579 /* 580 * Wait for any destroyers to finish signaling us. 581 */ 582 for (unsigned cTries = 99; cTries > 0; cTries--) 583 { 664 * Shuts down the server, leaving client connections open. 665 * 666 * @returns IPRT status code. 667 * @param pServer Handle to the server. 668 */ 669 RTR3DECL(int) RTTcpServerShutdown(PRTTCPSERVER pServer) 670 { 671 /* 672 * Validate input and retain the instance. 673 */ 674 AssertPtrReturn(pServer, VERR_INVALID_HANDLE); 675 AssertReturn(pServer->u32Magic == RTTCPSERVER_MAGIC, VERR_INVALID_HANDLE); 676 AssertReturn(RTMemPoolRetain(pServer) != UINT32_MAX, VERR_INVALID_HANDLE); 677 678 /* 679 * Try change the state to stopping, then replace and destroy the server socket. 680 */ 681 for (;;) 682 { 683 RTTCPSERVERSTATE enmState = pServer->enmState; 684 if ( enmState != RTTCPSERVERSTATE_ACCEPTING 685 && enmState != RTTCPSERVERSTATE_SERVING) 686 { 687 RTMemPoolRelease(RTMEMPOOL_DEFAULT, pServer); 688 switch (enmState) 689 { 690 case RTTCPSERVERSTATE_CREATED: 691 case RTTCPSERVERSTATE_STARTING: 692 default: 693 AssertMsgFailed(("%d\n", enmState)); 694 return VERR_INVALID_STATE; 695 696 case RTTCPSERVERSTATE_STOPPING: 697 case RTTCPSERVERSTATE_STOPPED: 698 return VINF_SUCCESS; 699 700 case RTTCPSERVERSTATE_DESTROYING: 701 return VERR_TCP_SERVER_DESTROYED; 702 } 703 } 704 if (rtTcpServerTrySetState(pServer, RTTCPSERVERSTATE_STOPPING, enmState)) 705 { 706 rtTcpServerDestroySocket(&pServer->SockServer, "RTTcpServerShutdown"); 707 rtTcpServerSetState(pServer, RTTCPSERVERSTATE_STOPPED, RTTCPSERVERSTATE_STOPPING); 708 709 RTMemPoolRelease(RTMEMPOOL_DEFAULT, pServer); 710 return VINF_SUCCESS; 711 } 712 } 713 } 714 715 716 /** 717 * Closes down and frees a TCP Server. 718 * This will also terminate any open connections to the server. 719 * 720 * @returns iprt status code. 721 * @param pServer Handle to the server. 722 */ 723 RTR3DECL(int) RTTcpServerDestroy(PRTTCPSERVER pServer) 724 { 725 /* 726 * Validate input and retain the instance. 727 */ 728 AssertPtrReturn(pServer, VERR_INVALID_HANDLE); 729 AssertReturn(pServer->u32Magic == RTTCPSERVER_MAGIC, VERR_INVALID_HANDLE); 730 AssertReturn(RTMemPoolRetain(pServer) != UINT32_MAX, VERR_INVALID_HANDLE); /* paranoia */ 731 732 /* 733 * Move the state along so the listener can figure out what's going on. 734 */ 735 for (;;) 736 { 737 bool fDestroyable; 584 738 RTTCPSERVERSTATE enmState = pServer->enmState; 585 739 switch (enmState) 586 740 { 741 case RTTCPSERVERSTATE_STARTING: 742 case RTTCPSERVERSTATE_ACCEPTING: 743 case RTTCPSERVERSTATE_SERVING: 744 case RTTCPSERVERSTATE_CREATED: 745 case RTTCPSERVERSTATE_STOPPED: 746 fDestroyable = rtTcpServerTrySetState(pServer, RTTCPSERVERSTATE_DESTROYING, enmState); 747 break; 748 749 /* destroyable states */ 750 case RTTCPSERVERSTATE_STOPPING: 751 fDestroyable = true; 752 break; 753 587 754 /* 588 * Intermediate state while the destroyer closes the client socket. 589 */ 590 case RTTCPSERVERSTATE_SIGNALING: 591 if (!RTThreadYield()) 592 RTThreadSleep(1); 593 break; 594 595 /* 596 * Free the handle. 597 */ 598 case RTTCPSERVERSTATE_DESTROYING: 599 { 600 rtTcpClose(rtTcpAtomicXchgSock(&pServer->SockServer, NIL_RTSOCKET), "Listener-cleanup: server"); 601 rtTcpServerSetState(pServer, RTTCPSERVERSTATE_FREED, RTTCPSERVERSTATE_DESTROYING); 602 RTMemFree(pServer); 603 return; 604 } 605 606 /* 607 * Everything else means failure. 755 * Everything else means user or internal misbehavior. 608 756 */ 609 757 default: 610 758 AssertMsgFailed(("pServer=%p enmState=%d\n", pServer, enmState)); 611 return; 612 } 613 } 614 AssertMsgFailed(("Timed out when trying to clean up after listener. pServer=%p enmState=%d\n", pServer, pServer->enmState)); 615 } 616 617 618 /** 619 * Terminate the open connection to the server. 620 * 621 * @returns iprt status code. 622 * @param pServer Handle to the server. 623 */ 624 RTR3DECL(int) RTTcpServerDisconnectClient(PRTTCPSERVER pServer) 759 RTMemPoolRelease(RTMEMPOOL_DEFAULT, pServer); 760 return VERR_INTERNAL_ERROR; 761 } 762 if (fDestroyable) 763 break; 764 } 765 766 /* 767 * Destroy it. 768 */ 769 ASMAtomicWriteU32(&pServer->u32Magic, ~RTTCPSERVER_MAGIC); 770 rtTcpServerDestroySocket(&pServer->SockServer, "Destroyer: server"); 771 rtTcpServerDestroySocket(&pServer->SockClient, "Destroyer: client"); 772 773 /* 774 * Release it. 775 */ 776 RTMemPoolRelease(RTMEMPOOL_DEFAULT, pServer); 777 RTMemPoolRelease(RTMEMPOOL_DEFAULT, pServer); 778 return VINF_SUCCESS; 779 } 780 781 782 RTR3DECL(int) RTTcpRead(RTSOCKET Sock, void *pvBuffer, size_t cbBuffer, size_t *pcbRead) 625 783 { 626 784 /* 627 785 * Validate input. 628 786 */ 629 if ( !pServer 630 || pServer->enmState <= RTTCPSERVERSTATE_INVALID 631 || pServer->enmState >= RTTCPSERVERSTATE_FREED) 632 { 633 AssertMsgFailed(("Invalid parameter!\n")); 634 return VERR_INVALID_PARAMETER; 635 } 636 637 return rtTcpServerDestroyClientSock(&pServer->SockClient, "DisconnectClient: client"); 638 } 639 640 641 /** 642 * Closes down and frees a TCP Server. 643 * This will also terminate any open connections to the server. 644 * 645 * @returns iprt status code. 646 * @param pServer Handle to the server. 647 */ 648 RTR3DECL(int) RTTcpServerDestroy(PRTTCPSERVER pServer) 649 { 650 /* 651 * Validate input. 652 */ 653 if ( !pServer 654 || pServer->enmState <= RTTCPSERVERSTATE_INVALID 655 || pServer->enmState >= RTTCPSERVERSTATE_FREED) 656 { 657 AssertMsgFailed(("Invalid parameter!\n")); 658 return VERR_INVALID_PARAMETER; 659 } 660 661 /** @todo r=bird: Some of this horrible code can probably be exchanged with a RTThreadWait(). (It didn't exist when this code was written.) */ 662 663 /* 664 * Move it to the destroying state. 665 */ 666 RTSOCKET SockServer = rtTcpAtomicXchgSock(&pServer->SockServer, NIL_RTSOCKET); 667 for (unsigned cTries = 99; cTries > 0; cTries--) 668 { 669 RTTCPSERVERSTATE enmState = pServer->enmState; 670 switch (enmState) 671 { 672 /* 673 * Try move it to the destroying state. 674 */ 675 case RTTCPSERVERSTATE_STARTING: 676 case RTTCPSERVERSTATE_ACCEPTING: 677 case RTTCPSERVERSTATE_SERVING: 678 { 679 if (rtTcpServerSetState(pServer, RTTCPSERVERSTATE_SIGNALING, enmState)) 680 { 681 /* client */ 682 rtTcpServerDestroyClientSock(&pServer->SockClient, "Destroyer: client"); 683 684 bool fRc = rtTcpServerSetState(pServer, RTTCPSERVERSTATE_DESTROYING, RTTCPSERVERSTATE_SIGNALING); 685 Assert(fRc); NOREF(fRc); 686 687 /* server */ 688 rtTcpServerDestroyServerSock(SockServer, "Destroyer: server destroying"); 689 RTThreadYield(); 690 691 return VINF_SUCCESS; 692 } 693 break; 694 } 695 696 697 /* 698 * Intermediate state. 699 */ 700 case RTTCPSERVERSTATE_STOPPING: 701 if (!RTThreadYield()) 702 RTThreadSleep(1); 703 break; 704 705 /* 706 * Just release the handle. 707 */ 708 case RTTCPSERVERSTATE_CREATED: 709 case RTTCPSERVERSTATE_STOPPED: 710 if (rtTcpServerSetState(pServer, RTTCPSERVERSTATE_FREED, enmState)) 711 { 712 rtTcpServerDestroyServerSock(SockServer, "Destroyer: server freeing"); 713 RTMemFree(pServer); 714 return VINF_TCP_SERVER_STOP; 715 } 716 break; 717 718 /* 719 * Everything else means failure. 720 */ 721 default: 722 AssertMsgFailed(("pServer=%p enmState=%d\n", pServer, enmState)); 723 return VERR_INTERNAL_ERROR; 724 } 725 } 726 727 AssertMsgFailed(("Giving up! pServer=%p enmState=%d\n", pServer, pServer->enmState)); 728 rtTcpServerDestroyServerSock(SockServer, "Destroyer: server timeout"); 729 return VERR_INTERNAL_ERROR; 730 } 731 732 733 /** 734 * Shutdowns the server socket. 735 */ 736 static void rtTcpServerDestroyServerSock(RTSOCKET SockServer, const char *pszMsg) 737 { 738 if (SockServer == NIL_RTSOCKET) 739 return; 740 shutdown(SockServer, SHUT_RDWR); 741 rtTcpClose(SockServer, "Destroyer: server destroying"); 742 } 743 744 745 746 RTR3DECL(int) RTTcpRead(RTSOCKET Sock, void *pvBuffer, size_t cbBuffer, size_t *pcbRead) 747 { 748 /* 749 * Do params checking 750 */ 751 if (!pvBuffer || !cbBuffer) 752 { 753 AssertMsgFailed(("Invalid params\n")); 754 return VERR_INVALID_PARAMETER; 755 } 787 AssertReturn(cbBuffer > 0, VERR_INVALID_PARAMETER); 788 AssertPtr(pvBuffer); 756 789 757 790 /* … … 848 881 849 882 /* 850 * Do params checking851 */ 852 AssertReturn(uPort , VERR_INVALID_PARAMETER);853 Assert Return(VALID_PTR(pszAddress), VERR_INVALID_PARAMETER);883 * Validate input. 884 */ 885 AssertReturn(uPort > 0, VERR_INVALID_PARAMETER); 886 AssertPtrReturn(pszAddress, VERR_INVALID_POINTER); 854 887 855 888 #ifdef RT_OS_WINDOWS
注意:
瀏覽 TracChangeset
來幫助您使用更動檢視器