VirtualBox

忽略:
時間撮記:
2009-10-8 下午04:56:22 (15 年 以前)
作者:
vboxsync
訊息:

IPRT: Added RTTcpServerShutdown and cleaned up the code.

檔案:
修改 1 筆資料

圖例:

未更動
新增
刪除
  • trunk/src/VBox/Runtime/r3/tcp.cpp

    r23613 r23625  
    3434*******************************************************************************/
    3535#ifdef RT_OS_WINDOWS
    36 #include <winsock.h>
     36# include <winsock.h>
    3737#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>
    4747#endif /* !RT_OS_WINDOWS */
    4848
     49#include "internal/iprt.h"
    4950#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>
    5057#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*******************************************************************************/
    5865/* non-standard linux stuff (it seems). */
    5966#ifndef MSG_NOSIGNAL
    60 # define MSG_NOSIGNAL 0
     67# define MSG_NOSIGNAL           0
    6168#endif
    6269#ifndef SHUT_RDWR
    6370# ifdef SD_BOTH
    64 #  define SHUT_RDWR SD_BOTH
     71#  define SHUT_RDWR             SD_BOTH
    6572# else
    66 #  define SHUT_RDWR 2
     73#  define SHUT_RDWR             2
    6774# endif
    6875#endif
     
    7077/* fixup backlevel OSes. */
    7178#if defined(RT_OS_OS2) || defined(RT_OS_WINDOWS)
    72 # define socklen_t  int
     79# define socklen_t              int
    7380#endif
    7481
    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
    8084
    8185
     
    102106    /** Listener terminated. */
    103107    RTTCPSERVERSTATE_STOPPED,
    104     /** Destroying signaling to the listener, listener will wait. */
    105     RTTCPSERVERSTATE_SIGNALING,
    106108    /** Listener cleans up. */
    107     RTTCPSERVERSTATE_DESTROYING,
    108     /** Freed. */
    109     RTTCPSERVERSTATE_FREED
     109    RTTCPSERVERSTATE_DESTROYING
    110110} RTTCPSERVERSTATE;
    111111
     
    115115typedef struct RTTCPSERVER
    116116{
     117    /** The magic value (RTTCPSERVER_MAGIC). */
     118    uint32_t volatile           u32Magic;
    117119    /** The server state. */
    118120    RTTCPSERVERSTATE volatile   enmState;
     
    135137*******************************************************************************/
    136138static DECLCALLBACK(int)  rtTcpServerThread(RTTHREAD ThreadSelf, void *pvServer);
    137 static int rtTcpServerListen(PRTTCPSERVER pServer);
    138 static void rcTcpServerListenCleanup(PRTTCPSERVER pServer);
    139 static void rtTcpServerDestroyServerSock(RTSOCKET SockServer, const char *pszMsg);
    140 static int rtTcpClose(RTSOCKET Sock, const char *pszMsg);
     139static int  rtTcpServerListen(PRTTCPSERVER pServer);
     140static int rcTcpServerListenCleanup(PRTTCPSERVER pServer);
     141static int  rtTcpServerDestroySocket(RTSOCKET volatile *pSockClient, const char *pszMsg);
     142static int  rtTcpClose(RTSOCKET Sock, const char *pszMsg);
    141143
    142144
     
    217219
    218220/**
    219  * Changes the TCP server state.
    220  */
    221 DECLINLINE(bool) rtTcpServerSetState(PRTTCPSERVER pServer, RTTCPSERVERSTATE enmStateNew, RTTCPSERVERSTATE enmStateOld)
     221 * Tries to change the TCP server state.
     222 */
     223DECLINLINE(bool) rtTcpServerTrySetState(PRTTCPSERVER pServer, RTTCPSERVERSTATE enmStateNew, RTTCPSERVERSTATE enmStateOld)
    222224{
    223225    bool fRc;
    224226    ASMAtomicCmpXchgSize(&pServer->enmState, enmStateNew, enmStateOld, fRc);
    225227    return fRc;
     228}
     229
     230/**
     231 * Changes the TCP server state.
     232 */
     233DECLINLINE(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 */
     245static 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;
    226254}
    227255
     
    249277{
    250278    /*
    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);
    258285
    259286    /*
    260287     * Create the server.
    261288     */
    262     PRTTCPSERVER    pServer;
     289    PRTTCPSERVER pServer;
    263290    int rc = RTTcpServerCreateEx(pszAddress, uPort, &pServer);
    264291    if (RT_SUCCESS(rc))
     
    267294         * Create the listener thread.
    268295         */
     296        RTMemPoolRetain(pServer);
    269297        pServer->enmState   = RTTCPSERVERSTATE_STARTING;
    270298        pServer->pvUser     = pvUser;
     
    276304            if (ppServer)
    277305                *ppServer = pServer;
     306            else
     307                RTMemPoolRelease(RTMEMPOOL_DEFAULT, pServer);
    278308            return rc;
    279309        }
     310        RTMemPoolRelease(RTMEMPOOL_DEFAULT, pServer);
    280311
    281312        /*
     
    300331{
    301332    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);
    305339    NOREF(ThreadSelf);
    306340    return VINF_SUCCESS;
     
    323357
    324358    /*
    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);
    332363
    333364#ifdef RT_OS_WINDOWS
     
    398429                 * Listen for connections on a socket.
    399430                 */
    400                 if (listen(WaitSock, BACKLOG) != -1)
     431                if (listen(WaitSock, RTTCP_SERVER_BACKLOG) != -1)
    401432                {
    402433                    /*
    403434                     * Create the server handle.
    404435                     */
    405                     PRTTCPSERVER pServer = (PRTTCPSERVER)RTMemAllocZ(sizeof(*pServer));
     436                    PRTTCPSERVER pServer = (PRTTCPSERVER)RTMemPoolAlloc(RTMEMPOOL_DEFAULT, sizeof(*pServer));
    406437                    if (pServer)
    407438                    {
     439                        pServer->u32Magic   = RTTCPSERVER_MAGIC;
    408440                        pServer->SockServer = WaitSock;
    409441                        pServer->SockClient = NIL_RTSOCKET;
     
    453485 * can only be destroyed.
    454486 *
    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 *
    456491 * @param   pServer         The server handle as returned from RTTcpServerCreateEx().
    457492 * @param   pfnServe        The function which will serve a new client connection.
     
    461496{
    462497    /*
    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))
    471507    {
    472508        Assert(!pServer->pfnServe);
     
    479515        pServer->Thread   = RTThreadSelf();
    480516        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.
    502535 */
    503536static int rtTcpServerListen(PRTTCPSERVER pServer)
     
    506539     * Accept connection loop.
    507540     */
    508     int rc = VINF_SUCCESS;
    509541    for (;;)
    510542    {
     
    512544         * Change state.
    513545         */
    514         RTTCPSERVERSTATE enmState = pServer->enmState;
     546        RTTCPSERVERSTATE    enmState   = pServer->enmState;
     547        RTSOCKET            SockServer = pServer->SockServer;
    515548        if (    enmState != RTTCPSERVERSTATE_ACCEPTING
    516549            &&  enmState != RTTCPSERVERSTATE_SERVING)
    517             break;
    518         if (!rtTcpServerSetState(pServer, RTTCPSERVERSTATE_ACCEPTING, enmState))
     550            return rcTcpServerListenCleanup(pServer);
     551        if (!rtTcpServerTrySetState(pServer, RTTCPSERVERSTATE_ACCEPTING, enmState))
    519552            continue;
    520553
     
    522555         * Accept connection.
    523556         */
    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);
    527560        if (Socket == -1)
    528561        {
     
    530563            /* These are typical for what can happen during destruction. */
    531564            if (errno == EBADF || errno == EINVAL || errno == ENOTSOCK)
    532                 break;
     565                return rcTcpServerListenCleanup(pServer);
    533566#endif
    534567            continue;
     
    538571         * Run a pfnServe callback.
    539572         */
    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        }
    542578        rtTcpAtomicXchgSock(&pServer->SockClient, Socket);
    543         rc = pServer->pfnServe(Socket, pServer->pvUser);
    544         rtTcpServerDestroyClientSock(&pServer->SockClient, "Listener: client");
     579        int rc = pServer->pfnServe(Socket, pServer->pvUser);
     580        rtTcpServerDestroySocket(&pServer->SockClient, "Listener: client");
    545581
    546582        /*
     
    549585        if (rc == VERR_TCP_SERVER_STOP)
    550586        {
    551             if (rtTcpServerSetState(pServer, RTTCPSERVERSTATE_STOPPING, RTTCPSERVERSTATE_SERVING))
     587            if (rtTcpServerTrySetState(pServer, RTTCPSERVERSTATE_STOPPING, RTTCPSERVERSTATE_SERVING))
    552588            {
    553589                /*
     
    558594                rtTcpServerSetState(pServer, RTTCPSERVERSTATE_STOPPED, RTTCPSERVERSTATE_STOPPING);
    559595                rtTcpClose(SockServer, "Listener: server stopped");
    560                 return rc;
    561596            }
    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 */
     608static 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 */
     647RTR3DECL(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);
    570659    return rc;
    571660}
     
    573662
    574663/**
    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 */
     669RTR3DECL(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 */
     723RTR3DECL(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;
    584738        RTTCPSERVERSTATE enmState = pServer->enmState;
    585739        switch (enmState)
    586740        {
     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
    587754            /*
    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.
    608756             */
    609757            default:
    610758                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
     782RTR3DECL(int) RTTcpRead(RTSOCKET Sock, void *pvBuffer, size_t cbBuffer, size_t *pcbRead)
    625783{
    626784    /*
    627785     * Validate input.
    628786     */
    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);
    756789
    757790    /*
     
    848881
    849882    /*
    850      * Do params checking
    851      */
    852     AssertReturn(uPort, VERR_INVALID_PARAMETER);
    853     AssertReturn(VALID_PTR(pszAddress), VERR_INVALID_PARAMETER);
     883     * Validate input.
     884     */
     885    AssertReturn(uPort > 0, VERR_INVALID_PARAMETER);
     886    AssertPtrReturn(pszAddress, VERR_INVALID_POINTER);
    854887
    855888#ifdef RT_OS_WINDOWS
注意: 瀏覽 TracChangeset 來幫助您使用更動檢視器

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette