VirtualBox

Ignore:
Timestamp:
Sep 7, 2017 3:12:54 PM (8 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
117930
Message:

pdmifs.h,Serial: Reworked stream interface. The old design with the two read/write threads had a race where the read thread could access already destroyed VMM structures during destruction if data was read. This was solved by adding a poll callback which waits for data to arrive and which can be interrupt to make the thread respond to VM state changes and suspend before destruction starts. This required reworking all the drivers using it. DrvTCP was reworked to make use of the RTTcp*, RTSocket* and RTPoll* API in that process to get rid of platform dependent code there (which wasn't all available when the driver was createt).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Serial/DrvTCP.cpp

    r62956 r68699  
    55
    66/*
    7  * Copyright (C) 2006-2016 Oracle Corporation.
     7 * Copyright (C) 2006-2017 Oracle Corporation.
    88 *
    99 * This file was contributed by Alexey Eromenko (derived from DrvNamedPipe)
     
    2828#include <iprt/stream.h>
    2929#include <iprt/alloc.h>
     30#include <iprt/pipe.h>
     31#include <iprt/poll.h>
    3032#include <iprt/string.h>
    3133#include <iprt/semaphore.h>
     34#include <iprt/socket.h>
     35#include <iprt/tcp.h>
    3236#include <iprt/uuid.h>
    3337#include <stdlib.h>
    3438
    3539#include "VBoxDD.h"
    36 
    37 #ifdef RT_OS_WINDOWS
    38 # include <iprt/win/ws2tcpip.h>
    39 #else /* !RT_OS_WINDOWS */
    40 # include <errno.h>
    41 # include <unistd.h>
    42 # include <sys/types.h>
    43 # include <sys/socket.h>
    44 # include <netinet/in.h>
    45 # include <netdb.h>
    46 # ifndef SHUT_RDWR /* OS/2 */
    47 #  define SHUT_RDWR 3
    48 # endif
    49 #endif /* !RT_OS_WINDOWS */
    50 
    51 #ifndef SHUT_RDWR
    52 # ifdef SD_BOTH
    53 #  define SHUT_RDWR SD_BOTH
    54 # else
    55 #  define SHUT_RDWR 2
    56 # endif
    57 #endif
    58 
    5940
    6041/*********************************************************************************************************************************
    6142*   Defined Constants And Macros                                                                                                 *
    6243*********************************************************************************************************************************/
    63 /** Converts a pointer to DRVTCP::IMedia to a PDRVTCP. */
    64 #define PDMISTREAM_2_DRVTCP(pInterface) ( (PDRVTCP)((uintptr_t)pInterface - RT_OFFSETOF(DRVTCP, IStream)) )
    65 
     44
     45#define DRVTCP_POLLSET_ID_SOCKET 0
     46#define DRVTCP_POLLSET_ID_WAKEUP 1
     47
     48#define DRVTCP_WAKEUP_REASON_EXTERNAL       0
     49#define DRVTCP_WAKEUP_REASON_NEW_CONNECTION 1
    6650
    6751/*********************************************************************************************************************************
     
    8468    bool                fIsServer;
    8569
    86     /** Socket handle of the TCP socket for server. */
    87     int                 TCPServer;
     70    /** Handle of the TCP server for incoming connections. */
     71    PRTTCPSERVER        hTcpServ;
    8872    /** Socket handle of the TCP socket connection. */
    89     int                 TCPConnection;
     73    RTSOCKET            hTcpSock;
     74
     75    /** Poll set used to wait for I/O events. */
     76    RTPOLLSET           hPollSet;
     77    /** Reading end of the wakeup pipe. */
     78    RTPIPE              hPipeWakeR;
     79    /** Writing end of the wakeup pipe. */
     80    RTPIPE              hPipeWakeW;
     81    /** Flag whether the socket is in the pollset. */
     82    bool                fTcpSockInPollSet;
    9083
    9184    /** Thread for listening for new connections. */
     
    10194
    10295
     96/**
     97 * Kicks any possibly polling thread to get informed about changes.
     98 *
     99 * @returns VBOx status code.
     100 * @param   pThis                  The TCP driver instance.
     101 * @param   bReason                The reason code to handle.
     102 */
     103static int drvTcpPollerKick(PDRVTCP pThis, uint8_t bReason)
     104{
     105    size_t cbWritten = 0;
     106    return RTPipeWrite(pThis->hPipeWakeW, &bReason, 1, &cbWritten);
     107}
     108
     109
     110/** @interface_method_impl{PDMISTREAM,pfnPoll} */
     111static DECLCALLBACK(int) drvTcpPoll(PPDMISTREAM pInterface, uint32_t fEvts, uint32_t *pfEvts, RTMSINTERVAL cMillies)
     112{
     113    int rc = VINF_SUCCESS;
     114    PDRVTCP pThis = RT_FROM_MEMBER(pInterface, DRVTCP, IStream);
     115
     116    if (pThis->hTcpSock != NIL_RTSOCKET)
     117    {
     118        if (!pThis->fTcpSockInPollSet)
     119        {
     120            rc = RTPollSetAddSocket(pThis->hPollSet, pThis->hTcpSock,
     121                                    fEvts, DRVTCP_POLLSET_ID_SOCKET);
     122            if (RT_SUCCESS(rc))
     123                pThis->fTcpSockInPollSet = true;
     124        }
     125        else
     126        {
     127            /* Always include error event. */
     128            fEvts |= RTPOLL_EVT_ERROR;
     129            rc = RTPollSetEventsChange(pThis->hPollSet, DRVTCP_POLLSET_ID_SOCKET, fEvts);
     130            AssertRC(rc);
     131        }
     132    }
     133
     134    if (RT_SUCCESS(rc))
     135    {
     136        while (RT_SUCCESS(rc))
     137        {
     138            uint32_t fEvtsRecv = 0;
     139            uint32_t idHnd = 0;
     140
     141            rc = RTPoll(pThis->hPollSet, cMillies, &fEvtsRecv, &idHnd);
     142            if (RT_SUCCESS(rc))
     143            {
     144                if (idHnd == DRVTCP_POLLSET_ID_WAKEUP)
     145                {
     146                    /* We got woken up, drain the pipe and return. */
     147                    uint8_t bReason;
     148                    size_t cbRead = 0;
     149                    rc = RTPipeRead(pThis->hPipeWakeR, &bReason, 1, &cbRead);
     150                    AssertRC(rc);
     151
     152                    if (bReason == DRVTCP_WAKEUP_REASON_EXTERNAL)
     153                        rc = VERR_INTERRUPTED;
     154                    else if (bReason == DRVTCP_WAKEUP_REASON_NEW_CONNECTION)
     155                    {
     156                        Assert(!pThis->fTcpSockInPollSet);
     157                        rc = RTPollSetAddSocket(pThis->hPollSet, pThis->hTcpSock,
     158                                                fEvts, DRVTCP_POLLSET_ID_SOCKET);
     159                        if (RT_SUCCESS(rc))
     160                            pThis->fTcpSockInPollSet = true;
     161                    }
     162                    else
     163                        AssertMsgFailed(("Unknown wakeup reason in pipe %u\n", bReason));
     164                }
     165                else
     166                {
     167                    Assert(idHnd == DRVTCP_POLLSET_ID_SOCKET);
     168
     169                    /* On error we close the socket here. */
     170                    if (fEvtsRecv & RTPOLL_EVT_ERROR)
     171                    {
     172                        rc = RTPollSetRemove(pThis->hPollSet, DRVTCP_POLLSET_ID_SOCKET);
     173                        AssertRC(rc);
     174
     175                        if (pThis->fIsServer)
     176                            RTTcpServerDisconnectClient2(pThis->hTcpSock);
     177                        else
     178                            RTSocketClose(pThis->hTcpSock);
     179                        pThis->hTcpSock = NIL_RTSOCKET;
     180                        pThis->fTcpSockInPollSet = false;
     181                        /* Continue with polling. */
     182                    }
     183                    else
     184                    {
     185                        *pfEvts = fEvtsRecv;
     186                        break;
     187                    }
     188                }
     189            }
     190        }
     191    }
     192
     193    return rc;
     194}
     195
     196
     197/** @interface_method_impl{PDMISTREAM,pfnPollInterrupt} */
     198static DECLCALLBACK(int) drvTcpPollInterrupt(PPDMISTREAM pInterface)
     199{
     200    PDRVTCP pThis = RT_FROM_MEMBER(pInterface, DRVTCP, IStream);
     201    return drvTcpPollerKick(pThis, DRVTCP_WAKEUP_REASON_EXTERNAL);
     202}
     203
     204
    103205/** @interface_method_impl{PDMISTREAM,pfnRead} */
    104 static DECLCALLBACK(int) drvTCPRead(PPDMISTREAM pInterface, void *pvBuf, size_t *pcbRead)
     206static DECLCALLBACK(int) drvTcpRead(PPDMISTREAM pInterface, void *pvBuf, size_t *pcbRead)
    105207{
    106208    int rc = VINF_SUCCESS;
    107     PDRVTCP pThis = PDMISTREAM_2_DRVTCP(pInterface);
     209    PDRVTCP pThis = RT_FROM_MEMBER(pInterface, DRVTCP, IStream);
    108210    LogFlow(("%s: pvBuf=%p *pcbRead=%#x (%s)\n", __FUNCTION__, pvBuf, *pcbRead, pThis->pszLocation));
    109211
    110212    Assert(pvBuf);
    111213
    112     if (pThis->TCPConnection != -1)
    113     {
    114         ssize_t cbReallyRead;
    115         unsigned cbBuf = (unsigned)*pcbRead;
    116         cbReallyRead = recv(pThis->TCPConnection, (char *)pvBuf, cbBuf, 0);
    117         if (cbReallyRead == 0)
     214    if (pThis->hTcpSock != NIL_RTSOCKET)
     215    {
     216        size_t cbRead;
     217        size_t cbBuf = *pcbRead;
     218        rc = RTSocketReadNB(pThis->hTcpSock, pvBuf, cbBuf, &cbRead);
     219        if (RT_SUCCESS(rc))
    118220        {
    119             int tmp = pThis->TCPConnection;
    120             pThis->TCPConnection = -1;
    121 #ifdef RT_OS_WINDOWS
    122             closesocket(tmp);
    123 #else
    124             close(tmp);
    125 #endif
     221            if (!cbRead && rc != VINF_TRY_AGAIN)
     222            {
     223                rc = RTPollSetRemove(pThis->hPollSet, DRVTCP_POLLSET_ID_SOCKET);
     224                AssertRC(rc);
     225
     226                if (pThis->fIsServer)
     227                    RTTcpServerDisconnectClient2(pThis->hTcpSock);
     228                else
     229                    RTSocketClose(pThis->hTcpSock);
     230                pThis->hTcpSock = NIL_RTSOCKET;
     231                pThis->fTcpSockInPollSet = false;
     232                rc = VINF_SUCCESS;
     233            }
     234            *pcbRead = cbRead;
    126235        }
    127         else if (cbReallyRead == -1)
    128         {
    129             cbReallyRead = 0;
    130             rc = RTErrConvertFromErrno(errno);
    131         }
    132         *pcbRead = cbReallyRead;
    133236    }
    134237    else
     
    144247
    145248/** @interface_method_impl{PDMISTREAM,pfnWrite} */
    146 static DECLCALLBACK(int) drvTCPWrite(PPDMISTREAM pInterface, const void *pvBuf, size_t *pcbWrite)
     249static DECLCALLBACK(int) drvTcpWrite(PPDMISTREAM pInterface, const void *pvBuf, size_t *pcbWrite)
    147250{
    148251    int rc = VINF_SUCCESS;
    149     PDRVTCP pThis = PDMISTREAM_2_DRVTCP(pInterface);
     252    PDRVTCP pThis = RT_FROM_MEMBER(pInterface, DRVTCP, IStream);
    150253    LogFlow(("%s: pvBuf=%p *pcbWrite=%#x (%s)\n", __FUNCTION__, pvBuf, *pcbWrite, pThis->pszLocation));
    151254
    152255    Assert(pvBuf);
    153     if (pThis->TCPConnection != -1)
    154     {
    155         ssize_t cbWritten;
    156         unsigned cbBuf = (unsigned)*pcbWrite;
    157         cbWritten = send(pThis->TCPConnection, (const char *)pvBuf, cbBuf, 0);
    158         if (cbWritten == 0)
    159         {
    160             int tmp = pThis->TCPConnection;
    161             pThis->TCPConnection = -1;
    162 #ifdef RT_OS_WINDOWS
    163             closesocket(tmp);
    164 #else
    165             close(tmp);
    166 #endif
    167         }
    168         else if (cbWritten == -1)
    169         {
    170             cbWritten = 0;
    171             rc = RTErrConvertFromErrno(errno);
    172         }
    173         *pcbWrite = cbWritten;
    174     }
     256    if (pThis->hTcpSock != NIL_RTSOCKET)
     257    {
     258        size_t cbBuf = *pcbWrite;
     259        rc = RTSocketWriteNB(pThis->hTcpSock, pvBuf, cbBuf, pcbWrite);
     260    }
     261    else
     262        *pcbWrite = 0;
    175263
    176264    LogFlow(("%s: returns %Rrc\n", __FUNCTION__, rc));
     
    205293    RT_NOREF(hThreadSelf);
    206294    PDRVTCP pThis = (PDRVTCP)pvUser;
    207     int     rc;
    208295
    209296    while (RT_LIKELY(!pThis->fShutdown))
    210297    {
    211         if (listen(pThis->TCPServer, 0) == -1)
     298        RTSOCKET hTcpSockNew = NIL_RTSOCKET;
     299        int rc = RTTcpServerListen2(pThis->hTcpServ, &hTcpSockNew);
     300        if (RT_SUCCESS(rc))
    212301        {
    213             rc = RTErrConvertFromErrno(errno);
    214             LogRel(("DrvTCP%d: listen failed, rc=%Rrc\n", pThis->pDrvIns->iInstance, rc));
    215             break;
     302            if (pThis->hTcpSock != NIL_RTSOCKET)
     303            {
     304                LogRel(("DrvTCP%d: only single connection supported\n", pThis->pDrvIns->iInstance));
     305                RTTcpServerDisconnectClient2(hTcpSockNew);
     306            }
     307            else
     308            {
     309                pThis->hTcpSock = hTcpSockNew;
     310                /* Inform the poller about the new socket. */
     311                drvTcpPollerKick(pThis, DRVTCP_WAKEUP_REASON_NEW_CONNECTION);
     312            }
    216313        }
    217         int s = accept(pThis->TCPServer, NULL, NULL);
    218         if (s == -1)
    219         {
    220             rc = RTErrConvertFromErrno(errno);
    221             LogRel(("DrvTCP%d: accept failed, rc=%Rrc\n", pThis->pDrvIns->iInstance, rc));
    222             break;
    223         }
    224         if (pThis->TCPConnection != -1)
    225         {
    226             LogRel(("DrvTCP%d: only single connection supported\n", pThis->pDrvIns->iInstance));
    227 #ifdef RT_OS_WINDOWS
    228             closesocket(s);
    229 #else
    230             close(s);
    231 #endif
    232         }
    233         else
    234             pThis->TCPConnection = s;
    235314    }
    236315
     
    252331    pThis->fShutdown = true;
    253332    if (    pThis->fIsServer
    254         &&  pThis->TCPServer != -1)
    255     {
    256         int rc = shutdown(pThis->TCPServer, SHUT_RDWR);
    257         AssertRC(rc == 0); NOREF(rc);
    258 
    259 #ifdef RT_OS_WINDOWS
    260         rc = closesocket(pThis->TCPServer);
    261 #else
    262         rc = close(pThis->TCPServer);
    263 #endif
    264         AssertRC(rc == 0);
    265         pThis->TCPServer = -1;
     333        &&  pThis->hTcpServ != NULL)
     334    {
     335        int rc = RTTcpServerShutdown(pThis->hTcpServ);
     336        AssertRC(rc);
     337        pThis->hTcpServ = NULL;
    266338    }
    267339}
     
    303375     * While the thread exits, clean up as much as we can.
    304376     */
    305 
    306     Assert(pThis->TCPServer == -1);
    307     if (pThis->TCPConnection != -1)
    308     {
    309         int rc = shutdown(pThis->TCPConnection, SHUT_RDWR);
    310         AssertRC(rc == 0); NOREF(rc);
    311 
    312 #ifdef RT_OS_WINDOWS
    313         rc = closesocket(pThis->TCPConnection);
    314 #else
    315         rc = close(pThis->TCPConnection);
    316 #endif
    317         Assert(rc == 0);
    318         pThis->TCPConnection = -1;
    319     }
    320     if (   pThis->fIsServer
    321         && pThis->pszLocation)
    322         RTFileDelete(pThis->pszLocation);
    323 
     377    if (pThis->hTcpSock != NIL_RTSOCKET)
     378    {
     379        int rc = RTPollSetRemove(pThis->hPollSet, DRVTCP_POLLSET_ID_SOCKET);
     380        AssertRC(rc);
     381
     382        rc = RTSocketShutdown(pThis->hTcpSock, true /* fRead */, true /* fWrite */);
     383        AssertRC(rc);
     384
     385        rc = RTSocketClose(pThis->hTcpSock);
     386        AssertRC(rc); RT_NOREF(rc);
     387
     388        pThis->hTcpSock = NIL_RTSOCKET;
     389    }
     390
     391    if (pThis->hPipeWakeR != NIL_RTPIPE)
     392    {
     393        int rc = RTPipeClose(pThis->hPipeWakeR);
     394        AssertRC(rc);
     395
     396        pThis->hPipeWakeR = NIL_RTPIPE;
     397    }
     398
     399    if (pThis->hPipeWakeW != NIL_RTPIPE)
     400    {
     401        int rc = RTPipeClose(pThis->hPipeWakeW);
     402        AssertRC(rc);
     403
     404        pThis->hPipeWakeW = NIL_RTPIPE;
     405    }
     406
     407    if (pThis->hPollSet != NIL_RTPOLLSET)
     408    {
     409        int rc = RTPollSetDestroy(pThis->hPollSet);
     410        AssertRC(rc);
     411
     412        pThis->hPollSet = NIL_RTPOLLSET;
     413    }
    324414
    325415    MMR3HeapFree(pThis->pszLocation);
     
    337427            LogRel(("DrvTCP%d: listen thread did not terminate (%Rrc)\n", pDrvIns->iInstance, rc));
    338428    }
    339 
    340429}
    341430
     
    351440    PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);
    352441    PDRVTCP pThis = PDMINS_2_DATA(pDrvIns, PDRVTCP);
    353 
    354 #ifdef RT_OS_WINDOWS
    355     {
    356         WSADATA wsaData;
    357         int err;
    358 
    359         err = WSAStartup(MAKEWORD(2,2), &wsaData);
    360         if (err != 0)
    361         {
    362             LogRel(("DrvTCP: Failed to initialize Winsock, error %d\n", err));
    363             /* XXX: let socket creation fail below */
    364         }
    365     }
    366 #endif
    367442
    368443    /*
     
    373448    pThis->fIsServer                    = false;
    374449
    375     pThis->TCPServer                    = -1;
    376     pThis->TCPConnection                = -1;
     450    pThis->hTcpServ                     = NULL;
     451    pThis->hTcpSock                     = NIL_RTSOCKET;
     452
     453    pThis->hPollSet                     = NIL_RTPOLLSET;
     454    pThis->hPipeWakeR                   = NIL_RTPIPE;
     455    pThis->hPipeWakeW                   = NIL_RTPIPE;
     456    pThis->fTcpSockInPollSet            = false;
    377457
    378458    pThis->ListenThread                 = NIL_RTTHREAD;
     
    381461    pDrvIns->IBase.pfnQueryInterface    = drvTCPQueryInterface;
    382462    /* IStream */
    383     pThis->IStream.pfnRead              = drvTCPRead;
    384     pThis->IStream.pfnWrite             = drvTCPWrite;
     463    pThis->IStream.pfnPoll              = drvTcpPoll;
     464    pThis->IStream.pfnPollInterrupt     = drvTcpPollInterrupt;
     465    pThis->IStream.pfnRead              = drvTcpRead;
     466    pThis->IStream.pfnWrite             = drvTcpWrite;
    385467
    386468    /*
     
    398480                                   N_("Configuration error: querying \"IsServer\" resulted in %Rrc"), rc);
    399481
     482    rc = RTPipeCreate(&pThis->hPipeWakeR, &pThis->hPipeWakeW, 0 /* fFlags */);
     483    if (RT_FAILURE(rc))
     484        return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS,
     485                                   N_("DrvTCP#%d: Failed to create wake pipe"), pDrvIns->iInstance);
     486
     487    rc = RTPollSetCreate(&pThis->hPollSet);
     488    if (RT_FAILURE(rc))
     489        return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS,
     490                                   N_("DrvTCP#%d: Failed to create poll set"), pDrvIns->iInstance);
     491
     492    rc = RTPollSetAddPipe(pThis->hPollSet, pThis->hPipeWakeR,
     493                            RTPOLL_EVT_READ | RTPOLL_EVT_ERROR,
     494                            DRVTCP_POLLSET_ID_WAKEUP);
     495    if (RT_FAILURE(rc))
     496        return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS,
     497                                   N_("DrvTCP#%d failed to add wakeup pipe for %s to poll set"),
     498                                   pDrvIns->iInstance, pThis->pszLocation);
     499
    400500    /*
    401501     * Create/Open the socket.
    402502     */
    403     int s = socket(PF_INET, SOCK_STREAM, 0);
    404     if (s == -1)
    405         return PDMDrvHlpVMSetError(pDrvIns, RTErrConvertFromErrno(errno), RT_SRC_POS,
    406                                    N_("DrvTCP#%d failed to create socket"), pDrvIns->iInstance);
    407 
    408     struct sockaddr_in addr;
    409     memset(&addr, 0, sizeof(addr));
    410     addr.sin_family = AF_INET;
    411 
    412503    if (pThis->fIsServer)
    413504    {
    414         addr.sin_addr.s_addr = INADDR_ANY;
    415         addr.sin_port = htons(/*PORT*/ atoi(pThis->pszLocation));
    416 
    417         /* Bind address to the telnet socket. */
    418         pThis->TCPServer = s;
    419         RTFileDelete(pThis->pszLocation);
    420         if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) == -1)
    421             return PDMDrvHlpVMSetError(pDrvIns, RTErrConvertFromErrno(errno), RT_SRC_POS,
    422                                        N_("DrvTCP#%d failed to bind to socket %s"),
    423                                        pDrvIns->iInstance, pThis->pszLocation);
     505        uint32_t uPort = 0;
     506        rc = RTStrToUInt32Ex(pThis->pszLocation, NULL, 10, &uPort);
     507        if (RT_FAILURE(rc))
     508            return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS,
     509                                       N_("DrvTCP#%d: The port part of the location is not a numerical value"),
     510                                       pDrvIns->iInstance);
     511
     512        /** @todo: Allow binding to distinct interfaces. */
     513        rc = RTTcpServerCreateEx(NULL, uPort, &pThis->hTcpServ);
     514        if (RT_FAILURE(rc))
     515            return PDMDrvHlpVMSetError(pDrvIns, rc,  RT_SRC_POS,
     516                                       N_("DrvTCP#%d failed to create server socket"), pDrvIns->iInstance);
     517
    424518        rc = RTThreadCreate(&pThis->ListenThread, drvTCPListenLoop, (void *)pThis, 0,
    425519                            RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "DrvTCPStream");
     
    430524    else
    431525    {
    432         char *token;
    433         const char *delim = ":";
    434         struct hostent *server;
    435         token = strtok(pThis->pszLocation, delim);
    436         if(token) {
    437             server = gethostbyname(token);
    438             memmove((char *)&addr.sin_addr.s_addr,
    439                     (char *)server->h_addr,
    440                      server->h_length);
    441         }
    442         token = strtok(NULL, delim);
    443         if(token) {
    444             addr.sin_port = htons(/*PORT*/ atoi(token));
    445         }
    446 
    447         /* Connect to the telnet socket. */
    448         pThis->TCPConnection = s;
    449         if (connect(s, (struct sockaddr *)&addr, sizeof(addr)) == -1)
    450             return PDMDrvHlpVMSetError(pDrvIns, RTErrConvertFromErrno(errno), RT_SRC_POS,
     526        char *pszPort = strchr(pThis->pszLocation, ':');
     527        if (!pszPort)
     528            return PDMDrvHlpVMSetError(pDrvIns, VERR_NOT_FOUND, RT_SRC_POS,
     529                                       N_("DrvTCP#%d: The location misses the port to connect to"),
     530                                       pDrvIns->iInstance);
     531
     532        *pszPort = '\0'; /* Overwrite temporarily to avoid copying the hostname into a temporary buffer. */
     533        uint32_t uPort = 0;
     534        rc = RTStrToUInt32Ex(pszPort + 1, NULL, 10, &uPort);
     535        if (RT_FAILURE(rc))
     536            return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS,
     537                                       N_("DrvTCP#%d: The port part of the location is not a numerical value"),
     538                                       pDrvIns->iInstance);
     539
     540        rc = RTTcpClientConnect(pThis->pszLocation, uPort, &pThis->hTcpSock);
     541        *pszPort = ':'; /* Restore delimiter before checking the status. */
     542        if (RT_FAILURE(rc))
     543            return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS,
    451544                                       N_("DrvTCP#%d failed to connect to socket %s"),
    452545                                       pDrvIns->iInstance, pThis->pszLocation);
     546
     547        rc = RTPollSetAddSocket(pThis->hPollSet, pThis->hTcpSock,
     548                                RTPOLL_EVT_READ | RTPOLL_EVT_WRITE | RTPOLL_EVT_ERROR,
     549                                DRVTCP_POLLSET_ID_SOCKET);
     550        if (RT_FAILURE(rc))
     551            return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS,
     552                                       N_("DrvTCP#%d failed to add socket for %s to poll set"),
     553                                       pDrvIns->iInstance, pThis->pszLocation);
     554
     555        pThis->fTcpSockInPollSet = true;
    453556    }
    454557
Note: See TracChangeset for help on using the changeset viewer.

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