VirtualBox

Changeset 27497 in vbox


Ignore:
Timestamp:
Mar 18, 2010 6:59:08 PM (15 years ago)
Author:
vboxsync
Message:

iprt,rdp,drvnamedpipe: Changed the RTSOCKET type from int to a struct pointer; need this for implementing polling of sockets on windows. Also split out the generic socket stuff from RTTcp.

Location:
trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/iprt/err.h

    r27431 r27497  
    611611/** Status code, typically given as a parameter, that isn't supposed to be used. */
    612612#define VERR_IGNORED                        (-91)
     613/** Concurrent access to the object is not allowed. */
     614#define VERR_CONCURRENT_ACCESS              (-92)
    613615/** @} */
    614616
  • trunk/include/iprt/tcp.h

    r26915 r27497  
    195195
    196196/**
    197  * Send data from a socket.
     197 * Send data to a socket.
    198198 *
    199199 * @returns iprt status code.
  • trunk/include/iprt/types.h

    r26734 r27497  
    12491249
    12501250/** Socket handle. */
    1251 typedef int RTSOCKET;
     1251typedef R3R0PTRTYPE(struct RTSOCKETINT *)          RTSOCKET;
    12521252/** Pointer to socket handle. */
    1253 typedef RTSOCKET *PRTSOCKET;
     1253typedef RTSOCKET                                   *PRTSOCKET;
    12541254/** Nil socket handle. */
    1255 #define NIL_RTSOCKET                                (~(RTSOCKET)0)
     1255#define NIL_RTSOCKET                                ((RTSOCKET)0)
    12561256
    12571257/** Thread handle.*/
  • trunk/src/VBox/Devices/Serial/DrvNamedPipe.cpp

    r26173 r27497  
    8686#else /* !RT_OS_WINDOWS */
    8787    /** Socket handle of the local socket for server. */
    88     RTSOCKET            LocalSocketServer;
     88    int                 LocalSocketServer;
    8989    /** Socket handle of the local socket. */
    90     RTSOCKET            LocalSocket;
     90    int                 LocalSocket;
    9191#endif /* !RT_OS_WINDOWS */
    9292    /** Thread for listening for new connections. */
     
    170170    }
    171171#else /* !RT_OS_WINDOWS */
    172     if (pThis->LocalSocket != NIL_RTSOCKET)
     172    if (pThis->LocalSocket != -1)
    173173    {
    174174        ssize_t cbReallyRead;
     
    176176        if (cbReallyRead == 0)
    177177        {
    178             RTSOCKET tmp = pThis->LocalSocket;
    179             pThis->LocalSocket = NIL_RTSOCKET;
     178            int tmp = pThis->LocalSocket;
     179            pThis->LocalSocket = -1;
    180180            close(tmp);
    181181        }
     
    256256    }
    257257#else /* !RT_OS_WINDOWS */
    258     if (pThis->LocalSocket != NIL_RTSOCKET)
     258    if (pThis->LocalSocket != -1)
    259259    {
    260260        ssize_t cbWritten;
     
    262262        if (cbWritten == 0)
    263263        {
    264             RTSOCKET tmp = pThis->LocalSocket;
    265             pThis->LocalSocket = NIL_RTSOCKET;
     264            int tmp = pThis->LocalSocket;
     265            pThis->LocalSocket = -1;
    266266            close(tmp);
    267267        }
     
    365365        else
    366366        {
    367             if (pThis->LocalSocket != NIL_RTSOCKET)
     367            if (pThis->LocalSocket != -1)
    368368            {
    369369                LogRel(("NamedPipe%d: only single connection supported\n", pThis->pDrvIns->iInstance));
     
    422422    if (pThis->fIsServer)
    423423    {
    424         if (pThis->LocalSocketServer != NIL_RTSOCKET)
     424        if (pThis->LocalSocketServer != -1)
     425        {
    425426            close(pThis->LocalSocketServer);
     427            pThis->LocalSocketServer = -1;
     428        }
    426429        if (pThis->pszLocation)
    427430            RTFileDelete(pThis->pszLocation);
     
    429432    else
    430433    {
    431         if (pThis->LocalSocket != NIL_RTSOCKET)
     434        if (pThis->LocalSocket != -1)
     435        {
    432436            close(pThis->LocalSocket);
     437            pThis->LocalSocket = -1;
     438        }
    433439    }
    434440#endif /* !RT_OS_WINDOWS */
     
    482488    pThis->NamedPipe                    = INVALID_HANDLE_VALUE;
    483489#else /* !RT_OS_WINDOWS */
    484     pThis->LocalSocketServer            = NIL_RTSOCKET;
    485     pThis->LocalSocket                  = NIL_RTSOCKET;
     490    pThis->LocalSocketServer            = -1;
     491    pThis->LocalSocket                  = -1;
    486492#endif /* !RT_OS_WINDOWS */
    487493    pThis->ListenThread                 = NIL_RTTHREAD;
  • trunk/src/VBox/Runtime/include/internal/magics.h

    r26801 r27497  
    127127/** RTSEMXROADSINTERNAL::u32Magic value after RTSemXRoadsDestroy. */
    128128#define RTSEMXROADS_MAGIC_DEAD          UINT32_C(0x20011110)
     129/** The magic value for RTSOCKETINT::u32Magic. (Stanislaw Lem) */
     130#define RTSOCKET_MAGIC                  UINT32_C(0x19210912)
     131/** The magic value for RTSOCKETINT::u32Magic after destruction. */
     132#define RTSOCKET_MAGIC_DEAD             UINT32_C(0x20060326)
    129133/** Magic value for RTSPINLOCKINTERNAL::u32Magic. (Terry Pratchett) */
    130134#define RTSPINLOCK_MAGIC                UINT32_C(0x19480428)
  • trunk/src/VBox/Runtime/r3/tcp.cpp

    r27288 r27497  
    5959#include <iprt/err.h>
    6060#include <iprt/mempool.h>
     61#include <iprt/mem.h>
    6162#include <iprt/string.h>
    6263#include <iprt/thread.h>
     
    100101*   Structures and Typedefs                                                    *
    101102*******************************************************************************/
     103/**
     104 * Socket handle data.
     105 *
     106 * This is mainly required for implementing RTPollSet on Windows.
     107 */
     108typedef struct RTSOCKETINT
     109{
     110    /** Magic number (RTTCPSOCKET_MAGIC). */
     111    uint32_t            u32Magic;
     112    /** Usage count.  This is used to prevent two threads from accessing the
     113     *  handle concurrently. */
     114    uint32_t volatile   cUsers;
     115#ifdef RT_OS_WINDOWS
     116    /** The native socket handle. */
     117    SOCKET              hNative;
     118    /** The event semaphore we've associated with the socket handle.
     119     * This is INVALID_HANDLE_VALUE if not done. */
     120    WSAEVENT            hEvent;
     121    /** The pollset currently polling this socket.  This is NIL if no one is
     122     * polling. */
     123    RTPOLLSET           hPollSet;
     124    /** The events we're polling for. */
     125    uint32_t            fPollEvts;
     126#else
     127    /** The native socket handle. */
     128    int                 hNative;
     129#endif
     130} RTSOCKETINT;
     131
     132
     133/**
     134 * Address union used internally for things like getpeername and getsockname.
     135 */
     136typedef union RTSOCKADDRUNION
     137{
     138    struct sockaddr     Addr;
     139    struct sockaddr_in  Ipv4;
     140#ifdef IPRT_WITH_TCPIP_V6
     141    struct sockaddr_in6 Ipv6;
     142#endif
     143} RTSOCKADDRUNION;
     144
     145
     146
    102147/**
    103148 * TCP Server state.
     
    145190} RTTCPSERVER;
    146191
    147 typedef union RTSOCKADDRUNION
    148 {
    149     struct sockaddr     Addr;
    150     struct sockaddr_in  Ipv4;
    151 #ifdef IPRT_WITH_TCPIP_V6
    152     struct sockaddr_in6 Ipv6;
    153 #endif
    154 } RTSOCKADDRUNION;
    155192
    156193/*******************************************************************************
     
    162199static int  rtTcpServerDestroySocket(RTSOCKET volatile *pSockClient, const char *pszMsg);
    163200static int  rtTcpClose(RTSOCKET Sock, const char *pszMsg, bool fTryGracefulShutdown);
    164 static int  rtTcpConvertAddress(RTSOCKADDRUNION *pSrc, size_t cbSrc, PRTNETADDR pAddr);
    165201
    166202
     
    169205 * Get the last error as an iprt status code.
    170206 *
    171  * @returns iprt status code.
    172  */
    173 DECLINLINE(int) rtTcpError(void)
     207 * @returns IPRT status code.
     208 */
     209DECLINLINE(int) rtSocketError(void)
    174210{
    175211#ifdef RT_OS_WINDOWS
     
    184220 * Resets the last error.
    185221 */
    186 DECLINLINE(void) rtTcpErrorReset(void)
     222DECLINLINE(void) rtSocketErrorReset(void)
    187223{
    188224#ifdef RT_OS_WINDOWS
     
    199235 * @returns iprt status code.
    200236 */
    201 DECLINLINE(int) rtTcpResolverError(void)
     237DECLINLINE(int) rtSocketResolverError(void)
    202238{
    203239#ifdef RT_OS_WINDOWS
     
    223259
    224260/**
     261 * Tries to lock the socket for exclusive usage by the calling thread.
     262 *
     263 * Call rtSocketUnlock() to unlock.
     264 *
     265 * @returns @c true if locked, @c false if not.
     266 * @param   pThis               The socket structure.
     267 */
     268DECLINLINE(bool) rtSocketTryLock(RTSOCKETINT *pThis)
     269{
     270    return ASMAtomicCmpXchgU32(&pThis->cUsers, 1, 0);
     271}
     272
     273
     274/**
     275 * Unlocks the socket.
     276 *
     277 * @param   pThis               The socket structure.
     278 */
     279DECLINLINE(void) rtSocketUnlock(RTSOCKETINT *pThis)
     280{
     281    ASMAtomicCmpXchgU32(&pThis->cUsers, 0, 1);
     282}
     283
     284
     285/**
     286 * Creates an IPRT socket handle for a native one.
     287 *
     288 * @returns IPRT status code.
     289 * @param   ppSocket        Where to return the IPRT socket handle.
     290 * @param   hNative         The native handle.
     291 */
     292int rtSocketCreateForNative(RTSOCKETINT **ppSocket,
     293#ifdef RT_OS_WINDOWS
     294                            HANDLE hNative
     295#else
     296                            int hNative
     297#endif
     298                            )
     299{
     300    RTSOCKETINT *pThis = (RTSOCKETINT *)RTMemAlloc(sizeof(*pThis));
     301    if (!pThis)
     302        return VERR_NO_MEMORY;
     303    pThis->u32Magic     = RTSOCKET_MAGIC;
     304    pThis->cUsers       = 0;
     305    pThis->hNative      = hNative;
     306#ifdef RT_OS_WINDOWS
     307    pThis->hEvent       = INVALID_HANDLE_VALUE;
     308    pThis->hPollSet     = 0;
     309    pThis->fPollEvts    = 0;
     310#endif
     311    *ppSocket = pThis;
     312    return VINF_SUCCESS;
     313}
     314
     315
     316/**
     317 * Wrapper around socket().
     318 *
     319 * @returns IPRT status code.
     320 * @param   phSocket            Where to store the handle to the socket on
     321 *                              success.
     322 * @param   iDomain             The protocol family (PF_XXX).
     323 * @param   iType               The socket type (SOCK_XXX).
     324 * @param   iProtocol           Socket parameter, usually 0.
     325 */
     326static int rtSocketCreate(PRTSOCKET phSocket, int iDomain, int iType, int iProtocol)
     327{
     328    /*
     329     * Create the socket.
     330     */
     331#ifdef RT_OS_WINDOWS
     332    SOCKET  hNative = socket(iDomain, iType, iProtocol);
     333    if (hNative == INVALID_SOCKET)
     334        return rtSocketError();
     335#else
     336    int     hNative = socket(iDomain, iType, iProtocol);
     337    if (hNative == -1)
     338        return rtSocketError();
     339#endif
     340
     341    /*
     342     * Wrap it.
     343     */
     344    int rc = rtSocketCreateForNative(phSocket, hNative);
     345    if (RT_FAILURE(rc))
     346    {
     347#ifdef RT_OS_WINDOWS
     348        closesocket(hNative);
     349#else
     350        close(hNative);
     351#endif
     352    }
     353    return rc;
     354}
     355
     356
     357/**
     358 * Destroys the specified handle, freeing associated resources and closing the
     359 * socket.
     360 *
     361 * @returns IPRT status code.
     362 * @param   hSocket         The socket handle.  NIL is ignored.
     363 *
     364 * @remarks This will not perform a graceful shutdown of the socket, it will
     365 *          just destroy it.  Use the protocol specific close method if this is
     366 *          desired.
     367 */
     368int rtSocketDestroy(RTSOCKET hSocket)
     369{
     370    RTSOCKETINT *pThis = hSocket;
     371    if (pThis == NIL_RTSOCKET)
     372        return VINF_SUCCESS;
     373    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
     374    AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
     375
     376    Assert(pThis->cUsers == 0);
     377    AssertReturn(ASMAtomicCmpXchgU32(&pThis->u32Magic, RTSOCKET_MAGIC_DEAD, RTSOCKET_MAGIC), VERR_INVALID_HANDLE);
     378
     379    /*
     380     * Do the cleanup.
     381     */
     382    int rc = VINF_SUCCESS;
     383#ifdef RT_OS_WINDOWS
     384    if (pThis->hEvent == INVALID_HANDLE_VALUE)
     385    {
     386        CloseHandle(pThis->hEvent);
     387        pThis->hEvent = INVALID_HANDLE_VALUE;
     388    }
     389
     390    if (pThis->hNative != INVALID_HANDLE_VALUE)
     391    {
     392        rc = closesocket(pThis->hNative);
     393        if (!rc)
     394            rc = VINF_SUCCESS;
     395        else
     396        {
     397            rc = rtSocketError();
     398            AssertMsgFailed(("\"%s\": closesocket(%p) -> %Rrc\n", pThis->hNative, rc));
     399        }
     400        pThis->hNative = INVALID_HANDLE_VALUE;
     401    }
     402
     403#else
     404    if (pThis->hNative != -1)
     405    {
     406        if (close(pThis->hNative))
     407        {
     408            rc = rtSocketError();
     409            AssertMsgFailed(("\"%s\": close(%d) -> %Rrc\n", pThis->hNative, rc));
     410        }
     411        pThis->hNative = -1;
     412    }
     413#endif
     414
     415    return rc;
     416}
     417
     418
     419/**
     420 * Gets the native socket handle.
     421 *
     422 * @returns The native socket handle or RTHCUINTPTR_MAX if not invalid.
     423 * @param   hSocket             The socket handle.
     424 */
     425RTHCUINTPTR rtSocketNative(RTSOCKET hSocket)
     426{
     427    RTSOCKETINT *pThis = hSocket;
     428    AssertPtrReturn(pThis, RTHCUINTPTR_MAX);
     429    AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, RTHCUINTPTR_MAX);
     430    return (RTHCUINTPTR)pThis->hNative;
     431}
     432
     433
     434/**
    225435 * Helper that ensures the correct inheritability of a socket.
    226436 *
    227437 * We're currently ignoring failures.
    228438 *
    229  * @param   Socket          The socket handle.
     439 * @returns IPRT status code
     440 * @param   hSocket         The socket handle.
    230441 * @param   fInheritable    The desired inheritability state.
    231442 */
    232 static void rtTcpSetInheritance(RTSOCKET Socket, bool fInheritable)
    233 {
    234 #ifdef RT_OS_WINDOWS
    235     /** @todo Find some magic way to change this...  Worst case we have to use
    236      *        DuplicateHandle w/bInheritable=FALSE and replace the original
    237      *        handles... */
     443int rtSocketSetInheritance(RTSOCKET hSocket, bool fInheritable)
     444{
     445    RTSOCKETINT *pThis = hSocket;
     446    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
     447    AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
     448    AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
     449
     450    int rc = VINF_SUCCESS;
     451#ifdef RT_OS_WINDOWS
     452    if (!SetHandleInformation(pThis->hNative, HANDLE_FLAG_INHERIT, fInheritable ? HANDLE_FLAG_INHERIT : 0))
     453        rc = RTErrConvertFromWin32(GetLastError());
    238454#else
    239     fcntl(Socket, F_SETFD, fInheritable ? 0 : FD_CLOEXEC);
    240 #endif
    241 }
     455    if (fcntl(pThis->hNative, F_SETFD, fInheritable ? 0 : FD_CLOEXEC) < 0)
     456        rc = RTErrConvertFromErrno(errno);
     457#endif
     458    AssertRC(rc); /// @todo remove later.
     459
     460    rtSocketUnlock(pThis);
     461    return rc;
     462}
     463
     464
     465/**
     466 * Receive data from a socket.
     467 *
     468 * @returns IPRT status code.
     469 * @param   hSocket         The socket handle.
     470 * @param   pvBuffer        Where to put the data we read.
     471 * @param   cbBuffer        Read buffer size.
     472 * @param   pcbRead         Number of bytes read. If NULL the entire buffer
     473 *                          will be filled upon successful return. If not NULL a
     474 *                          partial read can be done successfully.
     475 */
     476int rtSocketRead(RTSOCKET hSocket, void *pvBuffer, size_t cbBuffer, size_t *pcbRead)
     477{
     478    /*
     479     * Validate input.
     480     */
     481    RTSOCKETINT *pThis = hSocket;
     482    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
     483    AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
     484    AssertReturn(cbBuffer > 0, VERR_INVALID_PARAMETER);
     485    AssertPtr(pvBuffer);
     486    AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
     487
     488    /*
     489     * Read loop.
     490     * If pcbRead is NULL we have to fill the entire buffer!
     491     */
     492    int     rc       = VINF_SUCCESS;
     493    size_t  cbRead   = 0;
     494    size_t  cbToRead = cbBuffer;
     495    for (;;)
     496    {
     497        rtSocketErrorReset();
     498#ifdef RT_OS_WINDOWS
     499        int    cbNow = cbToRead >= INT_MAX/2 ? INT_MAX/2 : (int)cbToRead;
     500#else
     501        size_t cbNow = cbToRead;
     502#endif
     503        ssize_t cbBytesRead = recv(pThis->hNative, (char *)pvBuffer + cbRead, cbNow, MSG_NOSIGNAL);
     504        if (cbBytesRead <= 0)
     505        {
     506            rc = rtSocketError();
     507            Assert(RT_FAILURE_NP(rc) || cbBytesRead == 0);
     508            if (RT_SUCCESS_NP(rc))
     509            {
     510                if (!pcbRead)
     511                    rc = VERR_NET_SHUTDOWN;
     512                else
     513                {
     514                    *pcbRead = 0;
     515                    rc = VINF_SUCCESS;
     516                }
     517            }
     518            break;
     519        }
     520        if (pcbRead)
     521        {
     522            /* return partial data */
     523            *pcbRead = cbBytesRead;
     524            break;
     525        }
     526
     527        /* read more? */
     528        cbRead += cbBytesRead;
     529        if (cbRead == cbBuffer)
     530            break;
     531
     532        /* next */
     533        cbToRead = cbBuffer - cbRead;
     534    }
     535
     536    rtSocketUnlock(pThis);
     537    return rc;
     538}
     539
     540
     541/**
     542 * Send data to a socket.
     543 *
     544 * @returns IPRT status code.
     545 * @retval  VERR_INTERRUPTED if interrupted before anything was written.
     546 *
     547 * @param   hSocket         The socket handle.
     548 * @param   pvBuffer        Buffer to write data to socket.
     549 * @param   cbBuffer        How much to write.
     550 */
     551int rtSocketWrite(RTSOCKET hSocket, const void *pvBuffer, size_t cbBuffer)
     552{
     553    /*
     554     * Validate input.
     555     */
     556    RTSOCKETINT *pThis = hSocket;
     557    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
     558    AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
     559    AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
     560
     561    /*
     562     * Try write all at once.
     563     */
     564    int     rc        = VINF_SUCCESS;
     565#ifdef RT_OS_WINDOWS
     566    int     cbNow     = cbBuffer >= INT_MAX / 2 ? INT_MAX / 2 : (int)cbBuffer;
     567#else
     568    size_t  cbNow     = cbBuffer >= SSIZE_MAX   ? SSIZE_MAX   :      cbBuffer;
     569#endif
     570    ssize_t cbWritten = send(pThis->hNative, (const char *)pvBuffer, cbNow, MSG_NOSIGNAL);
     571    if (RT_LIKELY((size_t)cbWritten == cbBuffer && cbWritten >= 0))
     572        rc = VINF_SUCCESS;
     573    else if (cbWritten < 0)
     574        rc = rtSocketError();
     575    else
     576    {
     577        /*
     578         * Unfinished business, write the remainder of the request.  Must ignore
     579         * VERR_INTERRUPTED here if we've managed to send something.
     580         */
     581        size_t cbSentSoFar = 0;
     582        for (;;)
     583        {
     584            /* advance */
     585            cbBuffer    -= (size_t)cbWritten;
     586            if (!cbBuffer)
     587                break;
     588            cbSentSoFar += (size_t)cbWritten;
     589            pvBuffer     = (char const *)pvBuffer + cbWritten;
     590
     591            /* send */
     592#ifdef RT_OS_WINDOWS
     593            cbNow = cbBuffer >= INT_MAX / 2 ? INT_MAX / 2 : (int)cbBuffer;
     594#else
     595            cbNow = cbBuffer >= SSIZE_MAX   ? SSIZE_MAX   :      cbBuffer;
     596#endif
     597            cbWritten = send(pThis->hNative, (const char *)pvBuffer, cbNow, MSG_NOSIGNAL);
     598            if (cbWritten >= 0)
     599                AssertMsg(cbBuffer >= (size_t)cbWritten, ("Wrote more than we requested!!! cbWritten=%zu cbBuffer=%zu rtSocketError()=%d\n",
     600                                                          cbWritten, cbBuffer, rtSocketError()));
     601            else
     602            {
     603                rc = rtSocketError();
     604                if (rc != VERR_INTERNAL_ERROR || cbSentSoFar == 0)
     605                    break;
     606                cbWritten = 0;
     607                rc = VINF_SUCCESS;
     608            }
     609        }
     610    }
     611
     612    rtSocketUnlock(pThis);
     613    return rc;
     614}
     615
     616
     617/**
     618 * Checks if the socket is ready for reading (for I/O multiplexing).
     619 *
     620 * @returns IPRT status code.
     621 * @param   hSocket         The socket handle.
     622 * @param   cMillies        Number of milliseconds to wait for the socket.  Use
     623 *                          RT_INDEFINITE_WAIT to wait for ever.
     624 */
     625int rtSocketSelectOne(RTSOCKET hSocket, RTMSINTERVAL cMillies)
     626{
     627    /*
     628     * Validate input.
     629     */
     630    RTSOCKETINT *pThis = hSocket;
     631    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
     632    AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
     633    AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
     634
     635    /*
     636     * Set up the file descriptor sets and do the select.
     637     */
     638    fd_set fdsetR;
     639    FD_ZERO(&fdsetR);
     640    FD_SET(pThis->hNative, &fdsetR);
     641
     642    fd_set fdsetE = fdsetR;
     643
     644    int rc;
     645    if (cMillies == RT_INDEFINITE_WAIT)
     646        rc = select(pThis->hNative + 1, &fdsetR, NULL, &fdsetE, NULL);
     647    else
     648    {
     649        struct timeval timeout;
     650        timeout.tv_sec = cMillies / 1000;
     651        timeout.tv_usec = (cMillies % 1000) * 1000;
     652        rc = select(pThis->hNative + 1, &fdsetR, NULL, &fdsetE, &timeout);
     653    }
     654    if (rc > 0)
     655        rc = VINF_SUCCESS;
     656    else if (rc == 0)
     657        rc = VERR_TIMEOUT;
     658    else
     659        rc = rtSocketError();
     660
     661    rtSocketUnlock(pThis);
     662    return rc;
     663}
     664
     665
     666/**
     667 * Shuts down one or both directions of communciation.
     668 *
     669 * @returns IPRT status code.
     670 * @param   hSocket             The socket handle.
     671 * @param   fRead               Whether to shutdown our read direction.
     672 * @param   fWrite              Whether to shutdown our write direction.
     673 */
     674static int rtSocketShutdown(RTSOCKET hSocket, bool fRead, bool fWrite)
     675{
     676    /*
     677     * Validate input.
     678     */
     679    RTSOCKETINT *pThis = hSocket;
     680    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
     681    AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
     682    AssertReturn(fRead || fWrite, VERR_INVALID_PARAMETER);
     683    AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
     684
     685    /*
     686     * Do the job.
     687     */
     688    int rc = VINF_SUCCESS;
     689    int fHow;
     690    if (fRead && fWrite)
     691        fHow = SHUT_RDWR;
     692    else if (fRead)
     693        fHow = SHUT_RD;
     694    else
     695        fHow = SHUT_WR;
     696    if (shutdown(pThis->hNative, fHow) == -1)
     697        rc = rtSocketError();
     698
     699    rtSocketUnlock(pThis);
     700    return rc;
     701}
     702
     703
     704/**
     705 * Converts from a native socket address to a generic IPRT network address.
     706 *
     707 * @returns IPRT status code.
     708 * @param   pSrc                The source address.
     709 * @param   cbSrc               The size of the source address.
     710 * @param   pAddr               Where to return the generic IPRT network
     711 *                              address.
     712 */
     713static int rtSocketConvertAddress(RTSOCKADDRUNION const *pSrc, size_t cbSrc, PRTNETADDR pAddr)
     714{
     715    /*
     716     * Convert the address.
     717     */
     718    if (   cbSrc == sizeof(struct sockaddr_in)
     719        && pSrc->Addr.sa_family == AF_INET)
     720    {
     721        RT_ZERO(*pAddr);
     722        pAddr->enmType      = RTNETADDRTYPE_IPV4;
     723        pAddr->uPort        = RT_N2H_U16(pSrc->Ipv4.sin_port);
     724        pAddr->uAddr.IPv4.u = pSrc->Ipv4.sin_addr.s_addr;
     725    }
     726#ifdef IPRT_WITH_TCPIP_V6
     727    else if (   cbSrc == sizeof(struct sockaddr_in6)
     728             && pSrc->Addr.sa_family == AF_INET6)
     729    {
     730        RT_ZERO(*pAddr);
     731        pAddr->enmType            = RTNETADDRTYPE_IPV6;
     732        pAddr->uPort              = RT_N2H_U16(pSrc->Ipv6.sin6_port);
     733        pAddr->uAddr.IPv6.au32[0] = pSrc->Ipv6.sin6_addr.s6_addr32[0];
     734        pAddr->uAddr.IPv6.au32[1] = pSrc->Ipv6.sin6_addr.s6_addr32[1];
     735        pAddr->uAddr.IPv6.au32[2] = pSrc->Ipv6.sin6_addr.s6_addr32[2];
     736        pAddr->uAddr.IPv6.au32[3] = pSrc->Ipv6.sin6_addr.s6_addr32[3];
     737    }
     738#endif
     739    else
     740        return VERR_NET_ADDRESS_FAMILY_NOT_SUPPORTED;
     741    return VINF_SUCCESS;
     742}
     743
     744
     745/**
     746 * Gets the address of the local side.
     747 *
     748 * @returns IPRT status code.
     749 * @param   Sock            Socket descriptor.
     750 * @param   pAddr           Where to store the local address on success.
     751 */
     752int rtSocketGetLocalAddress(RTSOCKET hSocket, PRTNETADDR pAddr)
     753{
     754    /*
     755     * Validate input.
     756     */
     757    RTSOCKETINT *pThis = hSocket;
     758    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
     759    AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
     760    AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
     761
     762    /*
     763     * Get the address and convert it.
     764     */
     765    int             rc;
     766    RTSOCKADDRUNION u;
     767#ifdef RT_OS_WINDOWS
     768    int             cbAddr = sizeof(u);
     769#else
     770    socklen_t       cbAddr = sizeof(u);
     771#endif
     772    RT_ZERO(u);
     773    if (getsockname(pThis->hNative, &u.Addr, &cbAddr) == 0)
     774        rc = rtSocketConvertAddress(&u, cbAddr, pAddr);
     775    else
     776        rc = rtSocketError();
     777
     778    rtSocketUnlock(pThis);
     779    return rc;
     780}
     781
     782
     783/**
     784 * Gets the address of the other party.
     785 *
     786 * @returns IPRT status code.
     787 * @param   Sock            Socket descriptor.
     788 * @param   pAddr           Where to store the peer address on success.
     789 */
     790int rtSocketGetPeerAddress(RTSOCKET hSocket, PRTNETADDR pAddr)
     791{
     792    /*
     793     * Validate input.
     794     */
     795    RTSOCKETINT *pThis = hSocket;
     796    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
     797    AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
     798    AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
     799
     800    /*
     801     * Get the address and convert it.
     802     */
     803    int             rc;
     804    RTSOCKADDRUNION u;
     805#ifdef RT_OS_WINDOWS
     806    int             cbAddr = sizeof(u);
     807#else
     808    socklen_t       cbAddr = sizeof(u);
     809#endif
     810    RT_ZERO(u);
     811    if (getpeername(pThis->hNative, &u.Addr, &cbAddr) == 0)
     812        rc = rtSocketConvertAddress(&u, cbAddr, pAddr);
     813    else
     814        rc = rtSocketError();
     815
     816    rtSocketUnlock(pThis);
     817    return rc;
     818}
     819
     820
     821/////////////////////////////////////////////////////////////////////////////////
     822
     823
     824/**
     825 * Wrapper around bind.
     826 *
     827 * @returns IPRT status code.
     828 * @param   hSocket             The socket handle.
     829 * @param   pAddr               The socket address to bind to.
     830 * @param   cbAddr              The size of the address structure @a pAddr
     831 *                              points to.
     832 */
     833int rtSocketBind(RTSOCKET hSocket, const struct sockaddr *pAddr, int cbAddr)
     834{
     835    /*
     836     * Validate input.
     837     */
     838    RTSOCKETINT *pThis = hSocket;
     839    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
     840    AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
     841    AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
     842
     843    int rc = VINF_SUCCESS;
     844    if (bind(pThis->hNative, pAddr, cbAddr) != 0)
     845        rc = rtSocketError();
     846
     847    rtSocketUnlock(pThis);
     848    return rc;
     849}
     850
     851
     852/**
     853 * Wrapper around listen.
     854 *
     855 * @returns IPRT status code.
     856 * @param   hSocket             The socket handle.
     857 * @param   cMaxPending         The max number of pending connections.
     858 */
     859int rtSocketListen(RTSOCKET hSocket, int cMaxPending)
     860{
     861    /*
     862     * Validate input.
     863     */
     864    RTSOCKETINT *pThis = hSocket;
     865    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
     866    AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
     867    AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
     868
     869    int rc = VINF_SUCCESS;
     870    if (listen(pThis->hNative, cMaxPending) != 0)
     871        rc = rtSocketError();
     872
     873    rtSocketUnlock(pThis);
     874    return rc;
     875}
     876
     877
     878/**
     879 * Wrapper around accept.
     880 *
     881 * @returns IPRT status code.
     882 * @param   hSocket             The socket handle.
     883 * @param   phClient            Where to return the client socket handle on
     884 *                              success.
     885 * @param   pAddr               Where to return the client address.
     886 * @param   pcbAddr             On input this gives the size buffer size of what
     887 *                              @a pAddr point to.  On return this contains the
     888 *                              size of what's stored at @a pAddr.
     889 */
     890int rtSocketAccept(RTSOCKET hSocket, PRTSOCKET phClient, struct sockaddr *pAddr, size_t *pcbAddr)
     891{
     892    /*
     893     * Validate input.
     894     */
     895    RTSOCKETINT *pThis = hSocket;
     896    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
     897    AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
     898    AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
     899
     900    /*
     901     * Call accept().
     902     */
     903    rtSocketErrorReset();
     904    int         rc      = VINF_SUCCESS;
     905#ifdef RT_OS_WINDOWS
     906    int         cbAddr  = (int)*pcbAddr;
     907    SOCKET      hNative = accept(pThis->hNative, pAddr, &cbAddr);
     908    if (hNative != INVALID_SOCKET)
     909#else
     910    socklen_t   cbAddr  = *pcbAddr;
     911    int         hNative = accept(pThis->hNative, pAddr, &cbAddr);
     912    if (hNative != -1)
     913#endif
     914    {
     915        *pcbAddr = cbAddr;
     916
     917        /*
     918         * Wrap the client socket.
     919         */
     920        rc = rtSocketCreateForNative(phClient, hNative);
     921        if (RT_FAILURE(rc))
     922        {
     923#ifdef RT_OS_WINDOWS
     924            closesocket(hNative);
     925#else
     926            close(hNative);
     927#endif
     928        }
     929    }
     930    else
     931        rc = rtSocketError();
     932
     933    rtSocketUnlock(pThis);
     934    return rc;
     935}
     936
     937
     938/**
     939 * Wrapper around connect.
     940 *
     941 * @returns IPRT status code.
     942 * @param   hSocket             The socket handle.
     943 * @param   pAddr               The socket address to connect to.
     944 * @param   cbAddr              The size of the address structure @a pAddr
     945 *                              points to.
     946 */
     947int rtSocketConnect(RTSOCKET hSocket, const struct sockaddr *pAddr, int cbAddr)
     948{
     949    /*
     950     * Validate input.
     951     */
     952    RTSOCKETINT *pThis = hSocket;
     953    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
     954    AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
     955    AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
     956
     957    int rc = VINF_SUCCESS;
     958    if (connect(pThis->hNative, pAddr, cbAddr) != 0)
     959        rc = rtSocketError();
     960
     961    rtSocketUnlock(pThis);
     962    return rc;
     963}
     964
     965
     966/**
     967 * Wrapper around setsockopt.
     968 *
     969 * @returns IPRT status code.
     970 * @param   hSocket             The socket handle.
     971 * @param   iLevel              The protocol level, e.g. IPPORTO_TCP.
     972 * @param   iOption             The option, e.g. TCP_NODELAY.
     973 * @param   pvValue             The value buffer.
     974 * @param   cbValue             The size of the value pointed to by pvValue.
     975 */
     976int rtSocketSetOpt(RTSOCKET hSocket, int iLevel, int iOption, void const *pvValue, int cbValue)
     977{
     978    /*
     979     * Validate input.
     980     */
     981    RTSOCKETINT *pThis = hSocket;
     982    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
     983    AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
     984    AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
     985
     986    int rc = VINF_SUCCESS;
     987    if (setsockopt(pThis->hNative, iLevel, iOption, (const char *)pvValue, cbValue) != 0)
     988        rc = rtSocketError();
     989
     990    rtSocketUnlock(pThis);
     991    return rc;
     992}
     993
     994
     995
     996/////////////////////////////////////////////////////////////////////////////////
     997/////////////////////////////////////////////////////////////////////////////////
     998/////////////////////////////////////////////////////////////////////////////////
     999/////////////////////////////////////////////////////////////////////////////////
     1000/////////////////////////////////////////////////////////////////////////////////
     1001
    2421002
    2431003
     
    2801040}
    2811041
     1042
    2821043/**
    2831044 * Closes the a socket (client or server).
     
    2871048static int rtTcpServerDestroySocket(RTSOCKET volatile *pSock, const char *pszMsg, bool fTryGracefulShutdown)
    2881049{
    289     RTSOCKET Sock = rtTcpAtomicXchgSock(pSock, NIL_RTSOCKET);
    290     if (Sock != NIL_RTSOCKET)
     1050    RTSOCKET hSocket = rtTcpAtomicXchgSock(pSock, NIL_RTSOCKET);
     1051    if (hSocket != NIL_RTSOCKET)
    2911052    {
    2921053        if (!fTryGracefulShutdown)
    293             shutdown(Sock, SHUT_RDWR);
    294         return rtTcpClose(Sock, pszMsg, fTryGracefulShutdown);
     1054            rtSocketShutdown(hSocket, true /*fRead*/, true /*fWrite*/);
     1055        return rtTcpClose(hSocket, pszMsg, fTryGracefulShutdown);
    2951056    }
    2961057    return VINF_TCP_SERVER_NO_CLIENT;
     
    4331194            if (!pHostEnt)
    4341195            {
    435                 rc = rtTcpResolverError();
     1196                rc = rtSocketResolverError();
    4361197                AssertMsgFailed(("Could not get host address rc=%Rrc\n", rc));
    4371198                return rc;
     
    4431204     * Setting up socket.
    4441205     */
    445     RTSOCKET WaitSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    446     if (WaitSock != -1)
    447     {
    448         rtTcpSetInheritance(WaitSock, false /*fInheritable*/);
     1206    RTSOCKET WaitSock;
     1207    rc = rtSocketCreate(&WaitSock, AF_INET, SOCK_STREAM, IPPROTO_TCP);
     1208    if (RT_SUCCESS(rc))
     1209    {
     1210        rtSocketSetInheritance(WaitSock, false /*fInheritable*/);
    4491211
    4501212        /*
     
    4521214         */
    4531215        int fFlag = 1;
    454         if (!setsockopt(WaitSock, SOL_SOCKET, SO_REUSEADDR, (const char *)&fFlag, sizeof(fFlag)))
     1216        if (!rtSocketSetOpt(WaitSock, SOL_SOCKET, SO_REUSEADDR, &fFlag, sizeof(fFlag)))
    4551217        {
    4561218            /*
     
    4681230
    4691231            /*
    470              * Bind a name to a socket.
     1232             * Bind a name to a socket and set it listening for connections.
    4711233             */
    472             if (bind(WaitSock, (struct sockaddr *)&LocalAddr, sizeof(LocalAddr)) != -1)
     1234            rc = rtSocketBind(WaitSock, (struct sockaddr *)&LocalAddr, sizeof(LocalAddr));
     1235            if (RT_SUCCESS(rc))
     1236                rc = rtSocketListen(WaitSock, RTTCP_SERVER_BACKLOG);
     1237            if (RT_SUCCESS(rc))
    4731238            {
    4741239                /*
    475                  * Listen for connections on a socket.
     1240                 * Create the server handle.
    4761241                 */
    477                 if (listen(WaitSock, RTTCP_SERVER_BACKLOG) != -1)
     1242                PRTTCPSERVER pServer = (PRTTCPSERVER)RTMemPoolAlloc(RTMEMPOOL_DEFAULT, sizeof(*pServer));
     1243                if (pServer)
    4781244                {
    479                     /*
    480                      * Create the server handle.
    481                      */
    482                     PRTTCPSERVER pServer = (PRTTCPSERVER)RTMemPoolAlloc(RTMEMPOOL_DEFAULT, sizeof(*pServer));
    483                     if (pServer)
    484                     {
    485                         pServer->u32Magic   = RTTCPSERVER_MAGIC;
    486                         pServer->enmState   = RTTCPSERVERSTATE_CREATED;
    487                         pServer->Thread     = NIL_RTTHREAD;
    488                         pServer->SockServer = WaitSock;
    489                         pServer->SockClient = NIL_RTSOCKET;
    490                         pServer->pfnServe   = NULL;
    491                         pServer->pvUser     = NULL;
    492                         *ppServer = pServer;
    493                         return VINF_SUCCESS;
    494                     }
    495 
    496                     /* bail out */
    497                     rc = VERR_NO_MEMORY;
     1245                    pServer->u32Magic   = RTTCPSERVER_MAGIC;
     1246                    pServer->enmState   = RTTCPSERVERSTATE_CREATED;
     1247                    pServer->Thread     = NIL_RTTHREAD;
     1248                    pServer->SockServer = WaitSock;
     1249                    pServer->SockClient = NIL_RTSOCKET;
     1250                    pServer->pfnServe   = NULL;
     1251                    pServer->pvUser     = NULL;
     1252                    *ppServer = pServer;
     1253                    return VINF_SUCCESS;
    4981254                }
    499                 else
    500                 {
    501                     rc = rtTcpError();
    502                     AssertMsgFailed(("listen() %Rrc\n", rc));
    503                 }
     1255
     1256                /* bail out */
     1257                rc = VERR_NO_MEMORY;
    5041258            }
    505             else
    506             {
    507                 rc = rtTcpError();
    508             }
    5091259        }
    5101260        else
    511         {
    512             rc = rtTcpError();
    513             AssertMsgFailed(("setsockopt() %Rrc\n", rc));
    514         }
     1261            AssertMsgFailed(("rtSocketSetOpt: %Rrc\n", rc));
    5151262        rtTcpClose(WaitSock, "RTServerCreateEx", false /*fTryGracefulShutdown*/);
    516     }
    517     else
    518     {
    519         rc = rtTcpError();
    520         AssertMsgFailed(("socket() %Rrc\n", rc));
    5211263    }
    5221264
     
    6041346         */
    6051347        struct sockaddr_in  RemoteAddr;
     1348        size_t              cbRemoteAddr = sizeof(RemoteAddr);
     1349        RTSOCKET            Socket;
    6061350        RT_ZERO(RemoteAddr);
    607         socklen_t           cbRemoteAddr = sizeof(RemoteAddr);
    608         RTSOCKET Socket = accept(SockServer, (struct sockaddr *)&RemoteAddr, &cbRemoteAddr);
    609         if (Socket == -1)
    610         {
    611 #ifndef RT_OS_WINDOWS
     1351        int rc = rtSocketAccept(SockServer, &Socket, (struct sockaddr *)&RemoteAddr, &cbRemoteAddr);
     1352        if (RT_FAILURE(rc))
     1353        {
    6121354            /* These are typical for what can happen during destruction. */
    613             if (errno == EBADF || errno == EINVAL || errno == ENOTSOCK)
     1355            if (   rc == VERR_INVALID_HANDLE
     1356                || rc == VERR_INVALID_PARAMETER
     1357                || rc == VERR_NET_NOT_SOCKET)
    6141358                return rtTcpServerListenCleanup(pServer);
    615 #endif
    6161359            continue;
    6171360        }
    618         rtTcpSetInheritance(Socket, false /*fInheritable*/);
     1361        rtSocketSetInheritance(Socket, false /*fInheritable*/);
    6191362
    6201363        /*
     
    6271370        }
    6281371        rtTcpAtomicXchgSock(&pServer->SockClient, Socket);
    629         int rc = pServer->pfnServe(Socket, pServer->pvUser);
     1372        rc = pServer->pfnServe(Socket, pServer->pvUser);
    6301373        rtTcpServerDestroySocket(&pServer->SockClient, "Listener: client", true /*fTryGracefulShutdown*/);
    6311374
     
    7441487         */
    7451488        struct sockaddr_in  RemoteAddr;
    746         socklen_t           cbRemoteAddr = sizeof(RemoteAddr);
     1489        size_t              cbRemoteAddr = sizeof(RemoteAddr);
    7471490        RTSOCKET            Socket;
    7481491        RT_ZERO(RemoteAddr);
    749         rtTcpErrorReset();
    750         Socket = accept(SockServer, (struct sockaddr *)&RemoteAddr, &cbRemoteAddr);
    751         if (Socket == -1)
    752         {
    753             rc = rtTcpError();
     1492        rc = rtSocketAccept(SockServer, &Socket, (struct sockaddr *)&RemoteAddr, &cbRemoteAddr);
     1493        if (RT_FAILURE(rc))
     1494        {
    7541495            if (!rtTcpServerTrySetState(pServer, RTTCPSERVERSTATE_CREATED, RTTCPSERVERSTATE_ACCEPTING))
    7551496                rc = rtTcpServerListenCleanup(pServer);
     
    7581499            continue;
    7591500        }
    760         rtTcpSetInheritance(Socket, false /*fInheritable*/);
     1501        rtSocketSetInheritance(Socket, false /*fInheritable*/);
    7611502
    7621503        /*
     
    9241665
    9251666
    926 RTR3DECL(int) RTTcpRead(RTSOCKET Sock, void *pvBuffer, size_t cbBuffer, size_t *pcbRead)
    927 {
    928     /*
    929      * Validate input.
    930      */
    931     AssertReturn(cbBuffer > 0, VERR_INVALID_PARAMETER);
    932     AssertPtr(pvBuffer);
    933 
    934     /*
    935      * Read loop.
    936      * If pcbRead is NULL we have to fill the entire buffer!
    937      */
    938     size_t cbRead = 0;
    939     size_t cbToRead = cbBuffer;
    940     for (;;)
    941     {
    942         rtTcpErrorReset();
    943 #ifdef RT_OS_WINDOWS
    944         int    cbNow = cbToRead >= INT_MAX/2 ? INT_MAX/2 : (int)cbToRead;
    945 #else
    946         size_t cbNow = cbToRead;
    947 #endif
    948         ssize_t cbBytesRead = recv(Sock, (char *)pvBuffer + cbRead, cbNow, MSG_NOSIGNAL);
    949         if (cbBytesRead <= 0)
    950         {
    951             int rc = rtTcpError();
    952             Assert(RT_FAILURE_NP(rc) || cbBytesRead == 0);
    953             if (RT_FAILURE_NP(rc))
    954                 return rc;
    955             if (pcbRead)
    956             {
    957                 *pcbRead = 0;
    958                 return VINF_SUCCESS;
    959             }
    960             return VERR_NET_SHUTDOWN;
    961         }
    962         if (pcbRead)
    963         {
    964             /* return partial data */
    965             *pcbRead = cbBytesRead;
    966             break;
    967         }
    968 
    969         /* read more? */
    970         cbRead += cbBytesRead;
    971         if (cbRead == cbBuffer)
    972             break;
    973 
    974         /* next */
    975         cbToRead = cbBuffer - cbRead;
    976     }
    977 
    978     return VINF_SUCCESS;
    979 }
    980 
    981 
    982 RTR3DECL(int)  RTTcpWrite(RTSOCKET Sock, const void *pvBuffer, size_t cbBuffer)
    983 {
    984     /*
    985      * Try write all at once.
    986      */
    987 #ifdef RT_OS_WINDOWS
    988     int     cbNow     = cbBuffer >= INT_MAX / 2 ? INT_MAX / 2 : (int)cbBuffer;
    989 #else
    990     size_t  cbNow     = cbBuffer >= SSIZE_MAX   ? SSIZE_MAX   :      cbBuffer;
    991 #endif
    992     ssize_t cbWritten = send(Sock, (const char *)pvBuffer, cbNow, MSG_NOSIGNAL);
    993     if (RT_LIKELY((size_t)cbWritten == cbBuffer && cbWritten >= 0))
    994         return VINF_SUCCESS;
    995     if (cbWritten < 0)
    996         return rtTcpError();
    997 
    998     /*
    999      * Unfinished business, write the remainder of the request.  Must ignore
    1000      * VERR_INTERRUPTED here if we've managed to send something.
    1001      */
    1002     size_t cbSentSoFar = 0;
    1003     for (;;)
    1004     {
    1005         /* advance */
    1006         cbBuffer    -= (size_t)cbWritten;
    1007         if (!cbBuffer)
    1008             return VINF_SUCCESS;
    1009         cbSentSoFar += (size_t)cbWritten;
    1010         pvBuffer     = (char const *)pvBuffer + cbWritten;
    1011 
    1012         /* send */
    1013 #ifdef RT_OS_WINDOWS
    1014         cbNow = cbBuffer >= INT_MAX / 2 ? INT_MAX / 2 : (int)cbBuffer;
    1015 #else
    1016         cbNow = cbBuffer >= SSIZE_MAX   ? SSIZE_MAX   :      cbBuffer;
    1017 #endif
    1018         cbWritten = send(Sock, (const char *)pvBuffer, cbNow, MSG_NOSIGNAL);
    1019         if (cbWritten >= 0)
    1020             AssertMsg(cbBuffer >= (size_t)cbWritten, ("Wrote more than we requested!!! cbWritten=%zu cbBuffer=%zu rtTcpError()=%d\n",
    1021                                                       cbWritten, cbBuffer, rtTcpError()));
    1022         else
    1023         {
    1024             int rc = rtTcpError();
    1025             if (rc != VERR_INTERNAL_ERROR || cbSentSoFar == 0)
    1026                 return rc;
    1027             cbWritten = 0;
    1028         }
    1029     }
    1030 }
    1031 
    1032 
    1033 RTR3DECL(int)  RTTcpFlush(RTSOCKET Sock)
    1034 {
    1035     int fFlag = 1;
    1036     setsockopt(Sock, IPPROTO_TCP, TCP_NODELAY, (const char *)&fFlag, sizeof(fFlag));
    1037     fFlag = 0;
    1038     setsockopt(Sock, IPPROTO_TCP, TCP_NODELAY, (const char *)&fFlag, sizeof(fFlag));
    1039 
    1040     return VINF_SUCCESS;
    1041 }
    1042 
    1043 
    1044 RTR3DECL(int)  RTTcpSelectOne(RTSOCKET Sock, RTMSINTERVAL cMillies)
    1045 {
    1046     fd_set fdsetR;
    1047     FD_ZERO(&fdsetR);
    1048     FD_SET(Sock, &fdsetR);
    1049 
    1050     fd_set fdsetE = fdsetR;
    1051 
    1052     int rc;
    1053     if (cMillies == RT_INDEFINITE_WAIT)
    1054         rc = select(Sock + 1, &fdsetR, NULL, &fdsetE, NULL);
    1055     else
    1056     {
    1057         struct timeval timeout;
    1058         timeout.tv_sec = cMillies / 1000;
    1059         timeout.tv_usec = (cMillies % 1000) * 1000;
    1060         rc = select(Sock + 1, &fdsetR, NULL, &fdsetE, &timeout);
    1061     }
    1062     if (rc > 0)
    1063         return VINF_SUCCESS;
    1064     if (rc == 0)
    1065         return VERR_TIMEOUT;
    1066     return rtTcpError();
    1067 }
    1068 
    1069 
    1070 static int rtTcpConvertAddress(RTSOCKADDRUNION *pSrc, size_t cbSrc, PRTNETADDR pAddr)
    1071 {
    1072     /*
    1073      * Convert the address.
    1074      */
    1075     if (   cbSrc == sizeof(struct sockaddr_in)
    1076         && pSrc->Addr.sa_family == AF_INET)
    1077     {
    1078         RT_ZERO(*pAddr);
    1079         pAddr->enmType      = RTNETADDRTYPE_IPV4;
    1080         pAddr->uPort        = RT_N2H_U16(pSrc->Ipv4.sin_port);
    1081         pAddr->uAddr.IPv4.u = pSrc->Ipv4.sin_addr.s_addr;
    1082     }
    1083 #ifdef IPRT_WITH_TCPIP_V6
    1084     else if (   cbSrc == sizeof(struct sockaddr_in6)
    1085              && pSrc->Addr.sa_family == AF_INET6)
    1086     {
    1087         RT_ZERO(*pAddr);
    1088         pAddr->enmType            = RTNETADDRTYPE_IPV6;
    1089         pAddr->uPort              = RT_N2H_U16(pSrc->Ipv6.sin6_port);
    1090         pAddr->uAddr.IPv6.au32[0] = pSrc->Ipv6.sin6_addr.s6_addr32[0];
    1091         pAddr->uAddr.IPv6.au32[1] = pSrc->Ipv6.sin6_addr.s6_addr32[1];
    1092         pAddr->uAddr.IPv6.au32[2] = pSrc->Ipv6.sin6_addr.s6_addr32[2];
    1093         pAddr->uAddr.IPv6.au32[3] = pSrc->Ipv6.sin6_addr.s6_addr32[3];
    1094     }
    1095 #endif
    1096     else
    1097         return VERR_NET_ADDRESS_FAMILY_NOT_SUPPORTED;
    1098     return VINF_SUCCESS;
    1099 }
    1100 
    1101 
    1102 RTR3DECL(int) RTTcpGetLocalAddress(RTSOCKET Sock, PRTNETADDR pAddr)
    1103 {
    1104     RTSOCKADDRUNION u;
    1105 #ifdef RT_OS_WINDOWS
    1106     int             cbAddr = sizeof(u);
    1107 #else
    1108     socklen_t       cbAddr = sizeof(u);
    1109 #endif
    1110     RT_ZERO(u);
    1111     if (!getsockname(Sock, &u.Addr, &cbAddr))
    1112         return rtTcpConvertAddress(&u, cbAddr, pAddr);
    1113     return rtTcpError();
    1114 }
    1115 
    1116 
    1117 RTR3DECL(int) RTTcpGetPeerAddress(RTSOCKET Sock, PRTNETADDR pAddr)
    1118 {
    1119     RTSOCKADDRUNION u;
    1120 #ifdef RT_OS_WINDOWS
    1121     int             cbAddr = sizeof(u);
    1122 #else
    1123     socklen_t       cbAddr = sizeof(u);
    1124 #endif
    1125     RT_ZERO(u);
    1126     if (!getpeername(Sock, &u.Addr, &cbAddr))
    1127         return rtTcpConvertAddress(&u, cbAddr, pAddr);
    1128     return rtTcpError();
    1129 }
    1130 
    1131 
    11321667RTR3DECL(int) RTTcpClientConnect(const char *pszAddress, uint32_t uPort, PRTSOCKET pSock)
    11331668{
     
    11661701        if (!pHostEnt)
    11671702        {
    1168             rc = rtTcpError();
     1703            rc = rtSocketError();
    11691704            AssertMsgFailed(("Could not resolve '%s', rc=%Rrc\n", pszAddress, rc));
    11701705            return rc;
     
    11751710     * Create the socket and connect.
    11761711     */
    1177     RTSOCKET Sock = socket(PF_INET, SOCK_STREAM, 0);
    1178     if (Sock != -1)
    1179     {
    1180         rtTcpSetInheritance(Sock, false /*fInheritable*/);
     1712    RTSOCKET Sock;
     1713    rc = rtSocketCreate(&Sock, PF_INET, SOCK_STREAM, 0);
     1714    if (RT_SUCCESS(rc))
     1715    {
     1716        rtSocketSetInheritance(Sock, false /*fInheritable*/);
    11811717
    11821718        struct sockaddr_in InAddr;
     
    11851721        InAddr.sin_port = htons(uPort);
    11861722        InAddr.sin_addr = *((struct in_addr *)pHostEnt->h_addr);
    1187         if (!connect(Sock, (struct sockaddr *)&InAddr, sizeof(InAddr)))
     1723        rc = rtSocketConnect(Sock, (struct sockaddr *)&InAddr, sizeof(InAddr));
     1724        if (RT_SUCCESS(rc))
    11881725        {
    11891726            *pSock = Sock;
    11901727            return VINF_SUCCESS;
    11911728        }
    1192         rc = rtTcpError();
     1729
    11931730        rtTcpClose(Sock, "RTTcpClientConnect", false /*fTryGracefulShutdown*/);
    11941731    }
    1195     else
    1196         rc = rtTcpError();
    11971732    return rc;
    11981733}
     
    12211756    if (fTryGracefulShutdown)
    12221757    {
    1223         rc = shutdown(Sock, SHUT_WR);
    1224         if (!rc)
     1758        rc = rtSocketShutdown(Sock, false /*fRead*/, true /*fWrite*/);
     1759        if (RT_SUCCESS(rc))
    12251760        {
    12261761            uint64_t u64Start = RTTimeMilliTS();
    12271762            for (;;)
    12281763            {
    1229                 rc = RTTcpSelectOne(Sock, 1000);
     1764                rc = rtSocketSelectOne(Sock, 1000);
    12301765                if (rc == VERR_TIMEOUT)
    12311766                {
     
    12371772                {
    12381773                    char abBitBucket[16*_1K];
    1239                     ssize_t cbBytesRead = recv(Sock, &abBitBucket[0], sizeof(abBitBucket), MSG_NOSIGNAL);
     1774                    ssize_t cbBytesRead = recv(rtSocketNative(Sock), &abBitBucket[0], sizeof(abBitBucket), MSG_NOSIGNAL);
    12401775                    if (cbBytesRead == 0)
    12411776                        break; /* orderly shutdown in progress */
     
    12481783
    12491784    /*
    1250      * Attempt to close it.
    1251      */
    1252 #ifdef RT_OS_WINDOWS
    1253     rc = closesocket(Sock);
    1254 #else
    1255     rc = close(Sock);
    1256 #endif
    1257     if (!rc)
    1258         return VINF_SUCCESS;
    1259     rc = rtTcpError();
    1260     AssertMsgFailed(("\"%s\": close(%d) -> %Rrc\n", pszMsg, Sock, rc));
    1261     return rc;
    1262 }
    1263 
     1785     * Destroy the socket handle.
     1786     */
     1787    return rtSocketDestroy(Sock);
     1788}
     1789
     1790
     1791RTR3DECL(int) RTTcpRead(RTSOCKET Sock, void *pvBuffer, size_t cbBuffer, size_t *pcbRead)
     1792{
     1793    return rtSocketRead(Sock, pvBuffer, cbBuffer, pcbRead);
     1794}
     1795
     1796
     1797RTR3DECL(int)  RTTcpWrite(RTSOCKET Sock, const void *pvBuffer, size_t cbBuffer)
     1798{
     1799    return rtSocketWrite(Sock, pvBuffer, cbBuffer);
     1800}
     1801
     1802
     1803RTR3DECL(int)  RTTcpFlush(RTSOCKET Sock)
     1804{
     1805
     1806    int fFlag = 1;
     1807    int rc = rtSocketSetOpt(Sock, IPPROTO_TCP, TCP_NODELAY, &fFlag, sizeof(fFlag));
     1808    if (RT_SUCCESS(rc))
     1809    {
     1810        fFlag = 0;
     1811        rc = rtSocketSetOpt(Sock, IPPROTO_TCP, TCP_NODELAY, &fFlag, sizeof(fFlag));
     1812    }
     1813    return rc;
     1814}
     1815
     1816
     1817RTR3DECL(int)  RTTcpSelectOne(RTSOCKET Sock, RTMSINTERVAL cMillies)
     1818{
     1819    return rtSocketSelectOne(Sock, cMillies);
     1820}
     1821
     1822
     1823RTR3DECL(int) RTTcpGetLocalAddress(RTSOCKET Sock, PRTNETADDR pAddr)
     1824{
     1825    return rtSocketGetLocalAddress(Sock, pAddr);
     1826}
     1827
     1828
     1829RTR3DECL(int) RTTcpGetPeerAddress(RTSOCKET Sock, PRTNETADDR pAddr)
     1830{
     1831    return rtSocketGetPeerAddress(Sock, pAddr);
     1832}
     1833
Note: See TracChangeset for help on using the changeset viewer.

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