VirtualBox

Changeset 27503 in vbox for trunk/src/VBox/Runtime/r3


Ignore:
Timestamp:
Mar 18, 2010 8:52:02 PM (15 years ago)
Author:
vboxsync
Message:

iprt/socket.h: RTSocket API.

Location:
trunk/src/VBox/Runtime/r3
Files:
3 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/r3/posix/poll-posix.cpp

    r27501 r27503  
    4141#include <iprt/mem.h>
    4242#include <iprt/pipe.h>
     43#include <iprt/socket.h>
    4344#include <iprt/string.h>
    4445#include <iprt/thread.h>
     
    300301        case RTHANDLETYPE_PIPE:
    301302            if (pHandle->u.hPipe != NIL_RTPIPE)
    302                 fd = RTPipeToNative(pHandle->u.hPipe);
    303             break;
    304 
    305         //case RTHANDLETYPE_SOCKET:
    306         //    if (pHandle->u.hSocket != NIL_RTSOCKET)
    307        //         fd = (int)pHandle->u.hSocket; //fd = RTTcpToNative(pHandle->u.hSocket);
    308        //     break;
     303                fd = (int)RTPipeToNative(pHandle->u.hPipe);
     304            break;
     305
     306        case RTHANDLETYPE_SOCKET:
     307            if (pHandle->u.hSocket != NIL_RTSOCKET)
     308                fd = (int)RTSocketToNative(pHandle->u.hSocket);
     309            break;
    309310
    310311        case RTHANDLETYPE_FILE:
  • trunk/src/VBox/Runtime/r3/posix/process-posix.cpp

    r27502 r27503  
    6161#include <iprt/file.h>
    6262#include <iprt/pipe.h>
     63#include <iprt/socket.h>
    6364#include <iprt/string.h>
    6465#include "internal/process.h"
     
    118119                    break;
    119120
    120                 //case RTHANDLETYPE_SOCKET:
    121                 //    aStdFds[i] = paHandles[i]->u.hSocket != NIL_RTSOCKET
    122                 //               ? (int)paHandles[i]->u.hSocket //RTTcpToNative(paHandles[i]->u.hSocket)
    123                 //               : -2 /* close it */;
    124                 //    break;
     121                case RTHANDLETYPE_SOCKET:
     122                    aStdFds[i] = paHandles[i]->u.hSocket != NIL_RTSOCKET
     123                               ? (int)RTSocketToNative(paHandles[i]->u.hSocket)
     124                               : -2 /* close it */;
     125                    break;
    125126
    126127                default:
  • trunk/src/VBox/Runtime/r3/socket.cpp

    r27501 r27503  
    11/* $Id$ */
    22/** @file
    3  * IPRT - TCP/IP.
     3 * IPRT - Network Sockets.
    44 */
    55
     
    5353
    5454#include "internal/iprt.h"
    55 #include <iprt/tcp.h>
     55#include <iprt/socket.h>
    5656
    5757#include <iprt/asm.h>
    5858#include <iprt/assert.h>
    5959#include <iprt/err.h>
    60 #include <iprt/mempool.h>
    6160#include <iprt/mem.h>
    6261#include <iprt/string.h>
     
    6564
    6665#include "internal/magics.h"
     66#include "internal/socket.h"
    6767
    6868
     
    144144
    145145
    146 
    147 /**
    148  * TCP Server state.
    149  */
    150 typedef enum RTTCPSERVERSTATE
    151 {
    152     /** Invalid. */
    153     RTTCPSERVERSTATE_INVALID = 0,
    154     /** Created. */
    155     RTTCPSERVERSTATE_CREATED,
    156     /** Listener thread is starting up. */
    157     RTTCPSERVERSTATE_STARTING,
    158     /** Accepting client connections. */
    159     RTTCPSERVERSTATE_ACCEPTING,
    160     /** Serving a client. */
    161     RTTCPSERVERSTATE_SERVING,
    162     /** Listener terminating. */
    163     RTTCPSERVERSTATE_STOPPING,
    164     /** Listener terminated. */
    165     RTTCPSERVERSTATE_STOPPED,
    166     /** Listener cleans up. */
    167     RTTCPSERVERSTATE_DESTROYING
    168 } RTTCPSERVERSTATE;
    169 
    170 /*
    171  * Internal representation of the TCP Server handle.
    172  */
    173 typedef struct RTTCPSERVER
    174 {
    175     /** The magic value (RTTCPSERVER_MAGIC). */
    176     uint32_t volatile           u32Magic;
    177     /** The server state. */
    178     RTTCPSERVERSTATE volatile   enmState;
    179     /** The server thread. */
    180     RTTHREAD                    Thread;
    181     /** The server socket. */
    182     RTSOCKET volatile           SockServer;
    183     /** The socket to the client currently being serviced.
    184      * This is NIL_RTSOCKET when no client is serviced. */
    185     RTSOCKET volatile           SockClient;
    186     /** The connection function. */
    187     PFNRTTCPSERVE               pfnServe;
    188     /** Argument to pfnServer. */
    189     void                       *pvUser;
    190 } RTTCPSERVER;
    191 
    192 
    193146/*******************************************************************************
    194147*   Internal Functions                                                         *
    195148*******************************************************************************/
    196 static DECLCALLBACK(int)  rtTcpServerThread(RTTHREAD ThreadSelf, void *pvServer);
    197 static int  rtTcpServerListen(PRTTCPSERVER pServer);
    198 static int  rtTcpServerListenCleanup(PRTTCPSERVER pServer);
    199 static int  rtTcpServerDestroySocket(RTSOCKET volatile *pSockClient, const char *pszMsg);
    200 static int  rtTcpClose(RTSOCKET Sock, const char *pszMsg, bool fTryGracefulShutdown);
    201 
    202149
    203150
     
    235182 * @returns iprt status code.
    236183 */
    237 DECLINLINE(int) rtSocketResolverError(void)
     184int rtSocketResolverError(void)
    238185{
    239186#ifdef RT_OS_WINDOWS
     
    292239int rtSocketCreateForNative(RTSOCKETINT **ppSocket,
    293240#ifdef RT_OS_WINDOWS
    294                             HANDLE hNative
     241                            SOCKET hNative
    295242#else
    296243                            int hNative
     
    324271 * @param   iProtocol           Socket parameter, usually 0.
    325272 */
    326 static int rtSocketCreate(PRTSOCKET phSocket, int iDomain, int iType, int iProtocol)
     273int rtSocketCreate(PRTSOCKET phSocket, int iDomain, int iType, int iProtocol)
    327274{
    328275    /*
     
    355302
    356303
    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  */
    368 int rtSocketDestroy(RTSOCKET hSocket)
     304RTDECL(int) RTSocketDestroy(RTSOCKET hSocket)
    369305{
    370306    RTSOCKETINT *pThis = hSocket;
     
    417353
    418354
    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  */
    425 RTHCUINTPTR rtSocketNative(RTSOCKET hSocket)
     355RTDECL(RTHCUINTPTR) RTSocketToNative(RTSOCKET hSocket)
    426356{
    427357    RTSOCKETINT *pThis = hSocket;
     
    432362
    433363
    434 /**
    435  * Helper that ensures the correct inheritability of a socket.
    436  *
    437  * We're currently ignoring failures.
    438  *
    439  * @returns IPRT status code
    440  * @param   hSocket         The socket handle.
    441  * @param   fInheritable    The desired inheritability state.
    442  */
    443 int rtSocketSetInheritance(RTSOCKET hSocket, bool fInheritable)
     364RTDECL(int) RTSocketSetInheritance(RTSOCKET hSocket, bool fInheritable)
    444365{
    445366    RTSOCKETINT *pThis = hSocket;
     
    463384
    464385
    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  */
    476 int rtSocketRead(RTSOCKET hSocket, void *pvBuffer, size_t cbBuffer, size_t *pcbRead)
     386RTDECL(int) RTSocketRead(RTSOCKET hSocket, void *pvBuffer, size_t cbBuffer, size_t *pcbRead)
    477387{
    478388    /*
     
    539449
    540450
    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  */
    551 int rtSocketWrite(RTSOCKET hSocket, const void *pvBuffer, size_t cbBuffer)
     451RTDECL(int) RTSocketWrite(RTSOCKET hSocket, const void *pvBuffer, size_t cbBuffer)
    552452{
    553453    /*
     
    615515
    616516
    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  */
    625 int rtSocketSelectOne(RTSOCKET hSocket, RTMSINTERVAL cMillies)
     517RTDECL(int) RTSocketSelectOne(RTSOCKET hSocket, RTMSINTERVAL cMillies)
    626518{
    627519    /*
     
    664556
    665557
    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  */
    674 static int rtSocketShutdown(RTSOCKET hSocket, bool fRead, bool fWrite)
     558RTDECL(int) RTSocketShutdown(RTSOCKET hSocket, bool fRead, bool fWrite)
    675559{
    676560    /*
     
    743627
    744628
    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  */
    752 int rtSocketGetLocalAddress(RTSOCKET hSocket, PRTNETADDR pAddr)
     629RTDECL(int) RTSocketGetLocalAddress(RTSOCKET hSocket, PRTNETADDR pAddr)
    753630{
    754631    /*
     
    781658
    782659
    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  */
    790 int rtSocketGetPeerAddress(RTSOCKET hSocket, PRTNETADDR pAddr)
     660RTDECL(int) RTSocketGetPeerAddress(RTSOCKET hSocket, PRTNETADDR pAddr)
    791661{
    792662    /*
     
    818688}
    819689
    820 
    821 /////////////////////////////////////////////////////////////////////////////////
    822690
    823691
     
    992860}
    993861
    994 
    995 
    996 /////////////////////////////////////////////////////////////////////////////////
    997 /////////////////////////////////////////////////////////////////////////////////
    998 /////////////////////////////////////////////////////////////////////////////////
    999 /////////////////////////////////////////////////////////////////////////////////
    1000 /////////////////////////////////////////////////////////////////////////////////
    1001 
    1002 
    1003 
    1004 /**
    1005  * Atomicly updates a socket variable.
    1006  * @returns The old handle value.
    1007  * @param   phSock          The socket handle variable to update.
    1008  * @param   hSock           The new socket handle value.
    1009  */
    1010 DECLINLINE(RTSOCKET) rtTcpAtomicXchgSock(RTSOCKET volatile *phSock, const RTSOCKET hNew)
    1011 {
    1012     RTSOCKET hRet;
    1013     ASMAtomicXchgHandle(phSock, hNew, &hRet);
    1014     return hRet;
    1015 }
    1016 
    1017 
    1018 /**
    1019  * Tries to change the TCP server state.
    1020  */
    1021 DECLINLINE(bool) rtTcpServerTrySetState(PRTTCPSERVER pServer, RTTCPSERVERSTATE enmStateNew, RTTCPSERVERSTATE enmStateOld)
    1022 {
    1023     bool fRc;
    1024     ASMAtomicCmpXchgSize(&pServer->enmState, enmStateNew, enmStateOld, fRc);
    1025     return fRc;
    1026 }
    1027 
    1028 /**
    1029  * Changes the TCP server state.
    1030  */
    1031 DECLINLINE(void) rtTcpServerSetState(PRTTCPSERVER pServer, RTTCPSERVERSTATE enmStateNew, RTTCPSERVERSTATE enmStateOld)
    1032 {
    1033     bool fRc;
    1034     ASMAtomicCmpXchgSize(&pServer->enmState, enmStateNew, enmStateOld, fRc);
    1035     Assert(fRc); NOREF(fRc);
    1036 }
    1037 
    1038 
    1039 /**
    1040  * Closes the a socket (client or server).
    1041  *
    1042  * @returns IPRT status code.
    1043  */
    1044 static int rtTcpServerDestroySocket(RTSOCKET volatile *pSock, const char *pszMsg, bool fTryGracefulShutdown)
    1045 {
    1046     RTSOCKET hSocket = rtTcpAtomicXchgSock(pSock, NIL_RTSOCKET);
    1047     if (hSocket != NIL_RTSOCKET)
    1048     {
    1049         if (!fTryGracefulShutdown)
    1050             rtSocketShutdown(hSocket, true /*fRead*/, true /*fWrite*/);
    1051         return rtTcpClose(hSocket, pszMsg, fTryGracefulShutdown);
    1052     }
    1053     return VINF_TCP_SERVER_NO_CLIENT;
    1054 }
    1055 
    1056 
    1057 /**
    1058  * Create single connection at a time TCP Server in a separate thread.
    1059  *
    1060  * The thread will loop accepting connections and call pfnServe for
    1061  * each of the incoming connections in turn. The pfnServe function can
    1062  * return VERR_TCP_SERVER_STOP too terminate this loop. RTTcpServerDestroy()
    1063  * should be used to terminate the server.
    1064  *
    1065  * @returns iprt status code.
    1066  * @param   pszAddress      The address for creating a listening socket.
    1067  *                          If NULL or empty string the server is bound to all interfaces.
    1068  * @param   uPort           The port for creating a listening socket.
    1069  * @param   enmType         The thread type.
    1070  * @param   pszThrdName     The name of the worker thread.
    1071  * @param   pfnServe        The function which will serve a new client connection.
    1072  * @param   pvUser          User argument passed to pfnServe.
    1073  * @param   ppServer        Where to store the serverhandle.
    1074  */
    1075 RTR3DECL(int)  RTTcpServerCreate(const char *pszAddress, unsigned uPort, RTTHREADTYPE enmType, const char *pszThrdName,
    1076                                  PFNRTTCPSERVE pfnServe, void *pvUser, PPRTTCPSERVER ppServer)
    1077 {
    1078     /*
    1079      * Validate input.
    1080      */
    1081     AssertReturn(uPort > 0, VERR_INVALID_PARAMETER);
    1082     AssertPtrReturn(pfnServe, VERR_INVALID_POINTER);
    1083     AssertPtrReturn(pszThrdName, VERR_INVALID_POINTER);
    1084     AssertPtrReturn(ppServer, VERR_INVALID_POINTER);
    1085 
    1086     /*
    1087      * Create the server.
    1088      */
    1089     PRTTCPSERVER pServer;
    1090     int rc = RTTcpServerCreateEx(pszAddress, uPort, &pServer);
    1091     if (RT_SUCCESS(rc))
    1092     {
    1093         /*
    1094          * Create the listener thread.
    1095          */
    1096         RTMemPoolRetain(pServer);
    1097         pServer->enmState   = RTTCPSERVERSTATE_STARTING;
    1098         pServer->pvUser     = pvUser;
    1099         pServer->pfnServe   = pfnServe;
    1100         rc = RTThreadCreate(&pServer->Thread, rtTcpServerThread, pServer, 0, enmType, /*RTTHREADFLAGS_WAITABLE*/0, pszThrdName);
    1101         if (RT_SUCCESS(rc))
    1102         {
    1103             /* done */
    1104             if (ppServer)
    1105                 *ppServer = pServer;
    1106             else
    1107                 RTMemPoolRelease(RTMEMPOOL_DEFAULT, pServer);
    1108             return rc;
    1109         }
    1110         RTMemPoolRelease(RTMEMPOOL_DEFAULT, pServer);
    1111 
    1112         /*
    1113          * Destroy the server.
    1114          */
    1115         rtTcpServerSetState(pServer, RTTCPSERVERSTATE_CREATED, RTTCPSERVERSTATE_STARTING);
    1116         RTTcpServerDestroy(pServer);
    1117     }
    1118 
    1119     return rc;
    1120 }
    1121 
    1122 
    1123 /**
    1124  * Server thread, loops accepting connections until it's terminated.
    1125  *
    1126  * @returns iprt status code. (ignored).
    1127  * @param   ThreadSelf      Thread handle.
    1128  * @param   pvServer        Server handle.
    1129  */
    1130 static DECLCALLBACK(int)  rtTcpServerThread(RTTHREAD ThreadSelf, void *pvServer)
    1131 {
    1132     PRTTCPSERVER    pServer = (PRTTCPSERVER)pvServer;
    1133     int             rc;
    1134     if (rtTcpServerTrySetState(pServer, RTTCPSERVERSTATE_ACCEPTING, RTTCPSERVERSTATE_STARTING))
    1135         rc = rtTcpServerListen(pServer);
    1136     else
    1137         rc = rtTcpServerListenCleanup(pServer);
    1138     RTMemPoolRelease(RTMEMPOOL_DEFAULT, pServer);
    1139     NOREF(ThreadSelf);
    1140     return VINF_SUCCESS;
    1141 }
    1142 
    1143 
    1144 /**
    1145  * Create single connection at a time TCP Server.
    1146  * The caller must call RTTcpServerListen() to actually start the server.
    1147  *
    1148  * @returns iprt status code.
    1149  * @param   pszAddress      The address for creating a listening socket.
    1150  *                          If NULL the server is bound to all interfaces.
    1151  * @param   uPort           The port for creating a listening socket.
    1152  * @param   ppServer        Where to store the serverhandle.
    1153  */
    1154 RTR3DECL(int) RTTcpServerCreateEx(const char *pszAddress, uint32_t uPort, PPRTTCPSERVER ppServer)
    1155 {
    1156     int rc;
    1157 
    1158     /*
    1159      * Validate input.
    1160      */
    1161     AssertReturn(uPort > 0, VERR_INVALID_PARAMETER);
    1162     AssertPtrReturn(ppServer, VERR_INVALID_PARAMETER);
    1163 
    1164 #ifdef RT_OS_WINDOWS
    1165     /*
    1166      * Initialize WinSock and check version.
    1167      */
    1168     WORD    wVersionRequested = MAKEWORD(1, 1);
    1169     WSADATA wsaData;
    1170     rc = WSAStartup(wVersionRequested, &wsaData);
    1171     if (wsaData.wVersion != wVersionRequested)
    1172     {
    1173         AssertMsgFailed(("Wrong winsock version\n"));
    1174         return VERR_NOT_SUPPORTED;
    1175     }
    1176 #endif
    1177 
    1178     /*
    1179      * Get host listening address.
    1180      */
    1181     struct hostent *pHostEnt = NULL;
    1182     if (pszAddress != NULL && *pszAddress)
    1183     {
    1184         pHostEnt = gethostbyname(pszAddress);
    1185         if (!pHostEnt)
    1186         {
    1187             struct in_addr InAddr;
    1188             InAddr.s_addr = inet_addr(pszAddress);
    1189             pHostEnt = gethostbyaddr((char *)&InAddr, 4, AF_INET);
    1190             if (!pHostEnt)
    1191             {
    1192                 rc = rtSocketResolverError();
    1193                 AssertMsgFailed(("Could not get host address rc=%Rrc\n", rc));
    1194                 return rc;
    1195             }
    1196         }
    1197     }
    1198 
    1199     /*
    1200      * Setting up socket.
    1201      */
    1202     RTSOCKET WaitSock;
    1203     rc = rtSocketCreate(&WaitSock, AF_INET, SOCK_STREAM, IPPROTO_TCP);
    1204     if (RT_SUCCESS(rc))
    1205     {
    1206         rtSocketSetInheritance(WaitSock, false /*fInheritable*/);
    1207 
    1208         /*
    1209          * Set socket options.
    1210          */
    1211         int fFlag = 1;
    1212         if (!rtSocketSetOpt(WaitSock, SOL_SOCKET, SO_REUSEADDR, &fFlag, sizeof(fFlag)))
    1213         {
    1214             /*
    1215              * Set socket family, address and port.
    1216              */
    1217             struct sockaddr_in LocalAddr;
    1218             RT_ZERO(LocalAddr);
    1219             LocalAddr.sin_family = AF_INET;
    1220             LocalAddr.sin_port = htons(uPort);
    1221             /* if address not specified, use INADDR_ANY. */
    1222             if (!pHostEnt)
    1223                 LocalAddr.sin_addr.s_addr = INADDR_ANY;
    1224             else
    1225                 LocalAddr.sin_addr = *((struct in_addr *)pHostEnt->h_addr);
    1226 
    1227             /*
    1228              * Bind a name to a socket and set it listening for connections.
    1229              */
    1230             rc = rtSocketBind(WaitSock, (struct sockaddr *)&LocalAddr, sizeof(LocalAddr));
    1231             if (RT_SUCCESS(rc))
    1232                 rc = rtSocketListen(WaitSock, RTTCP_SERVER_BACKLOG);
    1233             if (RT_SUCCESS(rc))
    1234             {
    1235                 /*
    1236                  * Create the server handle.
    1237                  */
    1238                 PRTTCPSERVER pServer = (PRTTCPSERVER)RTMemPoolAlloc(RTMEMPOOL_DEFAULT, sizeof(*pServer));
    1239                 if (pServer)
    1240                 {
    1241                     pServer->u32Magic   = RTTCPSERVER_MAGIC;
    1242                     pServer->enmState   = RTTCPSERVERSTATE_CREATED;
    1243                     pServer->Thread     = NIL_RTTHREAD;
    1244                     pServer->SockServer = WaitSock;
    1245                     pServer->SockClient = NIL_RTSOCKET;
    1246                     pServer->pfnServe   = NULL;
    1247                     pServer->pvUser     = NULL;
    1248                     *ppServer = pServer;
    1249                     return VINF_SUCCESS;
    1250                 }
    1251 
    1252                 /* bail out */
    1253                 rc = VERR_NO_MEMORY;
    1254             }
    1255         }
    1256         else
    1257             AssertMsgFailed(("rtSocketSetOpt: %Rrc\n", rc));
    1258         rtTcpClose(WaitSock, "RTServerCreateEx", false /*fTryGracefulShutdown*/);
    1259     }
    1260 
    1261     return rc;
    1262 }
    1263 
    1264 
    1265 /**
    1266  * Listen for incoming connections.
    1267  *
    1268  * The function will loop accepting connections and call pfnServe for
    1269  * each of the incoming connections in turn. The pfnServe function can
    1270  * return VERR_TCP_SERVER_STOP too terminate this loop. A stopped server
    1271  * can only be destroyed.
    1272  *
    1273  * @returns IPRT status code.
    1274  * @retval  VERR_TCP_SERVER_STOP if stopped by pfnServe.
    1275  * @retval  VERR_TCP_SERVER_SHUTDOWN if shut down by RTTcpServerShutdown.
    1276  *
    1277  * @param   pServer         The server handle as returned from RTTcpServerCreateEx().
    1278  * @param   pfnServe        The function which will serve a new client connection.
    1279  * @param   pvUser          User argument passed to pfnServe.
    1280  */
    1281 RTR3DECL(int) RTTcpServerListen(PRTTCPSERVER pServer, PFNRTTCPSERVE pfnServe, void *pvUser)
    1282 {
    1283     /*
    1284      * Validate input and retain the instance.
    1285      */
    1286     AssertPtrReturn(pfnServe, VERR_INVALID_POINTER);
    1287     AssertPtrReturn(pServer, VERR_INVALID_HANDLE);
    1288     AssertReturn(pServer->u32Magic == RTTCPSERVER_MAGIC, VERR_INVALID_HANDLE);
    1289     AssertReturn(RTMemPoolRetain(pServer) != UINT32_MAX, VERR_INVALID_HANDLE);
    1290 
    1291     int rc = VERR_INVALID_STATE;
    1292     if (rtTcpServerTrySetState(pServer, RTTCPSERVERSTATE_ACCEPTING, RTTCPSERVERSTATE_CREATED))
    1293     {
    1294         Assert(!pServer->pfnServe);
    1295         Assert(!pServer->pvUser);
    1296         Assert(pServer->Thread == NIL_RTTHREAD);
    1297         Assert(pServer->SockClient == NIL_RTSOCKET);
    1298 
    1299         pServer->pfnServe = pfnServe;
    1300         pServer->pvUser   = pvUser;
    1301         pServer->Thread   = RTThreadSelf();
    1302         Assert(pServer->Thread != NIL_RTTHREAD);
    1303         rc = rtTcpServerListen(pServer);
    1304     }
    1305     else
    1306     {
    1307         AssertMsgFailed(("enmState=%d\n", pServer->enmState));
    1308         rc = VERR_INVALID_STATE;
    1309     }
    1310     RTMemPoolRelease(RTMEMPOOL_DEFAULT, pServer);
    1311     return rc;
    1312 }
    1313 
    1314 
    1315 /**
    1316  * Internal worker common for RTTcpServerListen and the thread created by
    1317  * RTTcpServerCreate().
    1318  *
    1319  * The caller makes sure it has its own memory reference and releases it upon
    1320  * return.
    1321  */
    1322 static int rtTcpServerListen(PRTTCPSERVER pServer)
    1323 {
    1324     /*
    1325      * Accept connection loop.
    1326      */
    1327     for (;;)
    1328     {
    1329         /*
    1330          * Change state.
    1331          */
    1332         RTTCPSERVERSTATE    enmState   = pServer->enmState;
    1333         RTSOCKET            SockServer = pServer->SockServer;
    1334         if (    enmState != RTTCPSERVERSTATE_ACCEPTING
    1335             &&  enmState != RTTCPSERVERSTATE_SERVING)
    1336             return rtTcpServerListenCleanup(pServer);
    1337         if (!rtTcpServerTrySetState(pServer, RTTCPSERVERSTATE_ACCEPTING, enmState))
    1338             continue;
    1339 
    1340         /*
    1341          * Accept connection.
    1342          */
    1343         struct sockaddr_in  RemoteAddr;
    1344         size_t              cbRemoteAddr = sizeof(RemoteAddr);
    1345         RTSOCKET            Socket;
    1346         RT_ZERO(RemoteAddr);
    1347         int rc = rtSocketAccept(SockServer, &Socket, (struct sockaddr *)&RemoteAddr, &cbRemoteAddr);
    1348         if (RT_FAILURE(rc))
    1349         {
    1350             /* These are typical for what can happen during destruction. */
    1351             if (   rc == VERR_INVALID_HANDLE
    1352                 || rc == VERR_INVALID_PARAMETER
    1353                 || rc == VERR_NET_NOT_SOCKET)
    1354                 return rtTcpServerListenCleanup(pServer);
    1355             continue;
    1356         }
    1357         rtSocketSetInheritance(Socket, false /*fInheritable*/);
    1358 
    1359         /*
    1360          * Run a pfnServe callback.
    1361          */
    1362         if (!rtTcpServerTrySetState(pServer, RTTCPSERVERSTATE_SERVING, RTTCPSERVERSTATE_ACCEPTING))
    1363         {
    1364             rtTcpClose(Socket, "rtTcpServerListen", true /*fTryGracefulShutdown*/);
    1365             return rtTcpServerListenCleanup(pServer);
    1366         }
    1367         rtTcpAtomicXchgSock(&pServer->SockClient, Socket);
    1368         rc = pServer->pfnServe(Socket, pServer->pvUser);
    1369         rtTcpServerDestroySocket(&pServer->SockClient, "Listener: client", true /*fTryGracefulShutdown*/);
    1370 
    1371         /*
    1372          * Stop the server?
    1373          */
    1374         if (rc == VERR_TCP_SERVER_STOP)
    1375         {
    1376             if (rtTcpServerTrySetState(pServer, RTTCPSERVERSTATE_STOPPING, RTTCPSERVERSTATE_SERVING))
    1377             {
    1378                 /*
    1379                  * Reset the server socket and change the state to stopped. After that state change
    1380                  * we cannot safely access the handle so we'll have to return here.
    1381                  */
    1382                 SockServer = rtTcpAtomicXchgSock(&pServer->SockServer, NIL_RTSOCKET);
    1383                 rtTcpServerSetState(pServer, RTTCPSERVERSTATE_STOPPED, RTTCPSERVERSTATE_STOPPING);
    1384                 rtTcpClose(SockServer, "Listener: server stopped", false /*fTryGracefulShutdown*/);
    1385             }
    1386             else
    1387                 rtTcpServerListenCleanup(pServer); /* ignore rc */
    1388             return rc;
    1389         }
    1390     }
    1391 }
    1392 
    1393 
    1394 /**
    1395  * Clean up after listener.
    1396  */
    1397 static int rtTcpServerListenCleanup(PRTTCPSERVER pServer)
    1398 {
    1399     /*
    1400      * Close the server socket, the client one shouldn't be set.
    1401      */
    1402     rtTcpServerDestroySocket(&pServer->SockServer, "ListenCleanup", false /*fTryGracefulShutdown*/);
    1403     Assert(pServer->SockClient == NIL_RTSOCKET);
    1404 
    1405     /*
    1406      * Figure the return code and make sure the state is OK.
    1407      */
    1408     RTTCPSERVERSTATE enmState = pServer->enmState;
    1409     switch (enmState)
    1410     {
    1411         case RTTCPSERVERSTATE_STOPPING:
    1412         case RTTCPSERVERSTATE_STOPPED:
    1413             return VERR_TCP_SERVER_SHUTDOWN;
    1414 
    1415         case RTTCPSERVERSTATE_ACCEPTING:
    1416             rtTcpServerTrySetState(pServer, RTTCPSERVERSTATE_STOPPED, enmState);
    1417             return VERR_TCP_SERVER_DESTROYED;
    1418 
    1419         case RTTCPSERVERSTATE_DESTROYING:
    1420             return VERR_TCP_SERVER_DESTROYED;
    1421 
    1422         case RTTCPSERVERSTATE_STARTING:
    1423         case RTTCPSERVERSTATE_SERVING:
    1424         default:
    1425             AssertMsgFailedReturn(("pServer=%p enmState=%d\n", pServer, enmState), VERR_INTERNAL_ERROR_4);
    1426     }
    1427 }
    1428 
    1429 
    1430 /**
    1431  * Listen and accept one incomming connection.
    1432  *
    1433  * This is an alternative to RTTcpServerListen for the use the callbacks are not
    1434  * possible.
    1435  *
    1436  * @returns IPRT status code.
    1437  * @retval  VERR_TCP_SERVER_SHUTDOWN if shut down by RTTcpServerShutdown.
    1438  * @retval  VERR_INTERRUPTED if the listening was interrupted.
    1439  *
    1440  * @param   pServer         The server handle as returned from RTTcpServerCreateEx().
    1441  * @param   pSockClient     Where to return the socket handle to the client
    1442  *                          connection (on success only).  Use
    1443  *                          RTTcpServerDisconnectClient() to clean it, this must
    1444  *                          be done before the next call to RTTcpServerListen2.
    1445  *
    1446  * @todo    This can easily be extended to support multiple connections by
    1447  *          adding a new state and a RTTcpServerDisconnectClient variant for
    1448  *          closing client sockets.
    1449  */
    1450 RTR3DECL(int) RTTcpServerListen2(PRTTCPSERVER pServer, PRTSOCKET pSockClient)
    1451 {
    1452     /*
    1453      * Validate input and retain the instance.
    1454      */
    1455     AssertPtrReturn(pSockClient, VERR_INVALID_HANDLE);
    1456     *pSockClient = NIL_RTSOCKET;
    1457     AssertReturn(pServer->u32Magic == RTTCPSERVER_MAGIC, VERR_INVALID_HANDLE);
    1458     AssertReturn(RTMemPoolRetain(pServer) != UINT32_MAX, VERR_INVALID_HANDLE);
    1459 
    1460     int rc = VERR_INVALID_STATE;
    1461     for (;;)
    1462     {
    1463         /*
    1464          * Change state to accepting.
    1465          */
    1466         RTTCPSERVERSTATE    enmState   = pServer->enmState;
    1467         RTSOCKET            SockServer = pServer->SockServer;
    1468         if (    enmState != RTTCPSERVERSTATE_SERVING
    1469             &&  enmState != RTTCPSERVERSTATE_CREATED)
    1470         {
    1471             rc = rtTcpServerListenCleanup(pServer);
    1472             break;
    1473         }
    1474         if (!rtTcpServerTrySetState(pServer, RTTCPSERVERSTATE_ACCEPTING, enmState))
    1475             continue;
    1476         Assert(!pServer->pfnServe);
    1477         Assert(!pServer->pvUser);
    1478         Assert(pServer->Thread == NIL_RTTHREAD);
    1479         Assert(pServer->SockClient == NIL_RTSOCKET);
    1480 
    1481         /*
    1482          * Accept connection.
    1483          */
    1484         struct sockaddr_in  RemoteAddr;
    1485         size_t              cbRemoteAddr = sizeof(RemoteAddr);
    1486         RTSOCKET            Socket;
    1487         RT_ZERO(RemoteAddr);
    1488         rc = rtSocketAccept(SockServer, &Socket, (struct sockaddr *)&RemoteAddr, &cbRemoteAddr);
    1489         if (RT_FAILURE(rc))
    1490         {
    1491             if (!rtTcpServerTrySetState(pServer, RTTCPSERVERSTATE_CREATED, RTTCPSERVERSTATE_ACCEPTING))
    1492                 rc = rtTcpServerListenCleanup(pServer);
    1493             if (RT_FAILURE(rc))
    1494                 break;
    1495             continue;
    1496         }
    1497         rtSocketSetInheritance(Socket, false /*fInheritable*/);
    1498 
    1499         /*
    1500          * Chance to the 'serving' state and return the socket.
    1501          */
    1502         if (rtTcpServerTrySetState(pServer, RTTCPSERVERSTATE_SERVING, RTTCPSERVERSTATE_ACCEPTING))
    1503         {
    1504             RTSOCKET OldSocket = rtTcpAtomicXchgSock(&pServer->SockClient, Socket);
    1505             Assert(OldSocket == NIL_RTSOCKET); NOREF(OldSocket);
    1506             *pSockClient = Socket;
    1507             rc = VINF_SUCCESS;
    1508         }
    1509         else
    1510         {
    1511             rtTcpClose(Socket, "RTTcpServerListen2", true /*fTryGracefulShutdown*/);
    1512             rc = rtTcpServerListenCleanup(pServer);
    1513         }
    1514         break;
    1515     }
    1516 
    1517     RTMemPoolRelease(RTMEMPOOL_DEFAULT, pServer);
    1518     return rc;
    1519 }
    1520 
    1521 
    1522 /**
    1523  * Terminate the open connection to the server.
    1524  *
    1525  * @returns iprt status code.
    1526  * @param   pServer         Handle to the server.
    1527  */
    1528 RTR3DECL(int) RTTcpServerDisconnectClient(PRTTCPSERVER pServer)
    1529 {
    1530     /*
    1531      * Validate input and retain the instance.
    1532      */
    1533     AssertPtrReturn(pServer, VERR_INVALID_HANDLE);
    1534     AssertReturn(pServer->u32Magic == RTTCPSERVER_MAGIC, VERR_INVALID_HANDLE);
    1535     AssertReturn(RTMemPoolRetain(pServer) != UINT32_MAX, VERR_INVALID_HANDLE);
    1536 
    1537     int rc = rtTcpServerDestroySocket(&pServer->SockClient, "DisconnectClient: client", true /*fTryGracefulShutdown*/);
    1538 
    1539     RTMemPoolRelease(RTMEMPOOL_DEFAULT, pServer);
    1540     return rc;
    1541 }
    1542 
    1543 
    1544 /**
    1545  * Shuts down the server, leaving client connections open.
    1546  *
    1547  * @returns IPRT status code.
    1548  * @param   pServer         Handle to the server.
    1549  */
    1550 RTR3DECL(int) RTTcpServerShutdown(PRTTCPSERVER pServer)
    1551 {
    1552     /*
    1553      * Validate input and retain the instance.
    1554      */
    1555     AssertPtrReturn(pServer, VERR_INVALID_HANDLE);
    1556     AssertReturn(pServer->u32Magic == RTTCPSERVER_MAGIC, VERR_INVALID_HANDLE);
    1557     AssertReturn(RTMemPoolRetain(pServer) != UINT32_MAX, VERR_INVALID_HANDLE);
    1558 
    1559     /*
    1560      * Try change the state to stopping, then replace and destroy the server socket.
    1561      */
    1562     for (;;)
    1563     {
    1564         RTTCPSERVERSTATE enmState = pServer->enmState;
    1565         if (    enmState != RTTCPSERVERSTATE_ACCEPTING
    1566             &&  enmState != RTTCPSERVERSTATE_SERVING)
    1567         {
    1568             RTMemPoolRelease(RTMEMPOOL_DEFAULT, pServer);
    1569             switch (enmState)
    1570             {
    1571                 case RTTCPSERVERSTATE_CREATED:
    1572                 case RTTCPSERVERSTATE_STARTING:
    1573                 default:
    1574                     AssertMsgFailed(("%d\n", enmState));
    1575                     return VERR_INVALID_STATE;
    1576 
    1577                 case RTTCPSERVERSTATE_STOPPING:
    1578                 case RTTCPSERVERSTATE_STOPPED:
    1579                     return VINF_SUCCESS;
    1580 
    1581                 case RTTCPSERVERSTATE_DESTROYING:
    1582                     return VERR_TCP_SERVER_DESTROYED;
    1583             }
    1584         }
    1585         if (rtTcpServerTrySetState(pServer, RTTCPSERVERSTATE_STOPPING, enmState))
    1586         {
    1587             rtTcpServerDestroySocket(&pServer->SockServer, "RTTcpServerShutdown", false /*fTryGracefulShutdown*/);
    1588             rtTcpServerSetState(pServer, RTTCPSERVERSTATE_STOPPED, RTTCPSERVERSTATE_STOPPING);
    1589 
    1590             RTMemPoolRelease(RTMEMPOOL_DEFAULT, pServer);
    1591             return VINF_SUCCESS;
    1592         }
    1593     }
    1594 }
    1595 
    1596 
    1597 /**
    1598  * Closes down and frees a TCP Server.
    1599  * This will also terminate any open connections to the server.
    1600  *
    1601  * @returns iprt status code.
    1602  * @param   pServer         Handle to the server.
    1603  */
    1604 RTR3DECL(int) RTTcpServerDestroy(PRTTCPSERVER pServer)
    1605 {
    1606     /*
    1607      * Validate input and retain the instance.
    1608      */
    1609     AssertPtrReturn(pServer, VERR_INVALID_HANDLE);
    1610     AssertReturn(pServer->u32Magic == RTTCPSERVER_MAGIC, VERR_INVALID_HANDLE);
    1611     AssertReturn(RTMemPoolRetain(pServer) != UINT32_MAX, VERR_INVALID_HANDLE); /* paranoia */
    1612 
    1613     /*
    1614      * Move the state along so the listener can figure out what's going on.
    1615      */
    1616     for (;;)
    1617     {
    1618         bool             fDestroyable;
    1619         RTTCPSERVERSTATE enmState = pServer->enmState;
    1620         switch (enmState)
    1621         {
    1622             case RTTCPSERVERSTATE_STARTING:
    1623             case RTTCPSERVERSTATE_ACCEPTING:
    1624             case RTTCPSERVERSTATE_SERVING:
    1625             case RTTCPSERVERSTATE_CREATED:
    1626             case RTTCPSERVERSTATE_STOPPED:
    1627                 fDestroyable = rtTcpServerTrySetState(pServer, RTTCPSERVERSTATE_DESTROYING, enmState);
    1628                 break;
    1629 
    1630             /* destroyable states */
    1631             case RTTCPSERVERSTATE_STOPPING:
    1632                 fDestroyable = true;
    1633                 break;
    1634 
    1635             /*
    1636              * Everything else means user or internal misbehavior.
    1637              */
    1638             default:
    1639                 AssertMsgFailed(("pServer=%p enmState=%d\n", pServer, enmState));
    1640                 RTMemPoolRelease(RTMEMPOOL_DEFAULT, pServer);
    1641                 return VERR_INTERNAL_ERROR;
    1642         }
    1643         if (fDestroyable)
    1644             break;
    1645     }
    1646 
    1647     /*
    1648      * Destroy it.
    1649      */
    1650     ASMAtomicWriteU32(&pServer->u32Magic, ~RTTCPSERVER_MAGIC);
    1651     rtTcpServerDestroySocket(&pServer->SockServer, "Destroyer: server", false /*fTryGracefulShutdown*/);
    1652     rtTcpServerDestroySocket(&pServer->SockClient, "Destroyer: client", true  /*fTryGracefulShutdown*/);
    1653 
    1654     /*
    1655      * Release it.
    1656      */
    1657     RTMemPoolRelease(RTMEMPOOL_DEFAULT, pServer);
    1658     RTMemPoolRelease(RTMEMPOOL_DEFAULT, pServer);
    1659     return VINF_SUCCESS;
    1660 }
    1661 
    1662 
    1663 RTR3DECL(int) RTTcpClientConnect(const char *pszAddress, uint32_t uPort, PRTSOCKET pSock)
    1664 {
    1665     int rc;
    1666 
    1667     /*
    1668      * Validate input.
    1669      */
    1670     AssertReturn(uPort > 0, VERR_INVALID_PARAMETER);
    1671     AssertPtrReturn(pszAddress, VERR_INVALID_POINTER);
    1672 
    1673 #ifdef RT_OS_WINDOWS
    1674     /*
    1675      * Initialize WinSock and check version.
    1676      */
    1677     WORD    wVersionRequested = MAKEWORD(1, 1);
    1678     WSADATA wsaData;
    1679     rc = WSAStartup(wVersionRequested, &wsaData);
    1680     if (wsaData.wVersion != wVersionRequested)
    1681     {
    1682         AssertMsgFailed(("Wrong winsock version\n"));
    1683         return VERR_NOT_SUPPORTED;
    1684     }
    1685 #endif
    1686 
    1687     /*
    1688      * Resolve the address.
    1689      */
    1690     struct hostent *pHostEnt = NULL;
    1691     pHostEnt = gethostbyname(pszAddress);
    1692     if (!pHostEnt)
    1693     {
    1694         struct in_addr InAddr;
    1695         InAddr.s_addr = inet_addr(pszAddress);
    1696         pHostEnt = gethostbyaddr((char *)&InAddr, 4, AF_INET);
    1697         if (!pHostEnt)
    1698         {
    1699             rc = rtSocketError();
    1700             AssertMsgFailed(("Could not resolve '%s', rc=%Rrc\n", pszAddress, rc));
    1701             return rc;
    1702         }
    1703     }
    1704 
    1705     /*
    1706      * Create the socket and connect.
    1707      */
    1708     RTSOCKET Sock;
    1709     rc = rtSocketCreate(&Sock, PF_INET, SOCK_STREAM, 0);
    1710     if (RT_SUCCESS(rc))
    1711     {
    1712         rtSocketSetInheritance(Sock, false /*fInheritable*/);
    1713 
    1714         struct sockaddr_in InAddr;
    1715         RT_ZERO(InAddr);
    1716         InAddr.sin_family = AF_INET;
    1717         InAddr.sin_port = htons(uPort);
    1718         InAddr.sin_addr = *((struct in_addr *)pHostEnt->h_addr);
    1719         rc = rtSocketConnect(Sock, (struct sockaddr *)&InAddr, sizeof(InAddr));
    1720         if (RT_SUCCESS(rc))
    1721         {
    1722             *pSock = Sock;
    1723             return VINF_SUCCESS;
    1724         }
    1725 
    1726         rtTcpClose(Sock, "RTTcpClientConnect", false /*fTryGracefulShutdown*/);
    1727     }
    1728     return rc;
    1729 }
    1730 
    1731 
    1732 RTR3DECL(int) RTTcpClientClose(RTSOCKET Sock)
    1733 {
    1734     return rtTcpClose(Sock, "RTTcpClientClose", true /*fTryGracefulShutdown*/);
    1735 }
    1736 
    1737 
    1738 /**
    1739  * Internal close function which does all the proper bitching.
    1740  */
    1741 static int rtTcpClose(RTSOCKET Sock, const char *pszMsg, bool fTryGracefulShutdown)
    1742 {
    1743     int rc;
    1744 
    1745     /* ignore nil handles. */
    1746     if (Sock == NIL_RTSOCKET)
    1747         return VINF_SUCCESS;
    1748 
    1749     /*
    1750      * Try to gracefully shut it down.
    1751      */
    1752     if (fTryGracefulShutdown)
    1753     {
    1754         rc = rtSocketShutdown(Sock, false /*fRead*/, true /*fWrite*/);
    1755         if (RT_SUCCESS(rc))
    1756         {
    1757             uint64_t u64Start = RTTimeMilliTS();
    1758             for (;;)
    1759             {
    1760                 rc = rtSocketSelectOne(Sock, 1000);
    1761                 if (rc == VERR_TIMEOUT)
    1762                 {
    1763                     if (RTTimeMilliTS() - u64Start > 30000)
    1764                         break;
    1765                 }
    1766                 else if (rc != VINF_SUCCESS)
    1767                     break;
    1768                 {
    1769                     char abBitBucket[16*_1K];
    1770                     ssize_t cbBytesRead = recv(rtSocketNative(Sock), &abBitBucket[0], sizeof(abBitBucket), MSG_NOSIGNAL);
    1771                     if (cbBytesRead == 0)
    1772                         break; /* orderly shutdown in progress */
    1773                     if (cbBytesRead < 0)
    1774                         break; /* some kind of error, never mind which... */
    1775                 }
    1776             }  /* forever */
    1777         }
    1778     }
    1779 
    1780     /*
    1781      * Destroy the socket handle.
    1782      */
    1783     return rtSocketDestroy(Sock);
    1784 }
    1785 
    1786 
    1787 RTR3DECL(int) RTTcpRead(RTSOCKET Sock, void *pvBuffer, size_t cbBuffer, size_t *pcbRead)
    1788 {
    1789     return rtSocketRead(Sock, pvBuffer, cbBuffer, pcbRead);
    1790 }
    1791 
    1792 
    1793 RTR3DECL(int)  RTTcpWrite(RTSOCKET Sock, const void *pvBuffer, size_t cbBuffer)
    1794 {
    1795     return rtSocketWrite(Sock, pvBuffer, cbBuffer);
    1796 }
    1797 
    1798 
    1799 RTR3DECL(int)  RTTcpFlush(RTSOCKET Sock)
    1800 {
    1801 
    1802     int fFlag = 1;
    1803     int rc = rtSocketSetOpt(Sock, IPPROTO_TCP, TCP_NODELAY, &fFlag, sizeof(fFlag));
    1804     if (RT_SUCCESS(rc))
    1805     {
    1806         fFlag = 0;
    1807         rc = rtSocketSetOpt(Sock, IPPROTO_TCP, TCP_NODELAY, &fFlag, sizeof(fFlag));
    1808     }
    1809     return rc;
    1810 }
    1811 
    1812 
    1813 RTR3DECL(int)  RTTcpSelectOne(RTSOCKET Sock, RTMSINTERVAL cMillies)
    1814 {
    1815     return rtSocketSelectOne(Sock, cMillies);
    1816 }
    1817 
    1818 
    1819 RTR3DECL(int) RTTcpGetLocalAddress(RTSOCKET Sock, PRTNETADDR pAddr)
    1820 {
    1821     return rtSocketGetLocalAddress(Sock, pAddr);
    1822 }
    1823 
    1824 
    1825 RTR3DECL(int) RTTcpGetPeerAddress(RTSOCKET Sock, PRTNETADDR pAddr)
    1826 {
    1827     return rtSocketGetPeerAddress(Sock, pAddr);
    1828 }
    1829 
  • trunk/src/VBox/Runtime/r3/tcp.cpp

    r27500 r27503  
    6161#include <iprt/mem.h>
    6262#include <iprt/string.h>
     63#include <iprt/socket.h>
    6364#include <iprt/thread.h>
    6465#include <iprt/time.h>
    6566
    6667#include "internal/magics.h"
     68#include "internal/socket.h"
    6769
    6870
     
    201203
    202204
    203 
    204 /**
    205  * Get the last error as an iprt status code.
    206  *
    207  * @returns IPRT status code.
    208  */
    209 DECLINLINE(int) rtSocketError(void)
    210 {
    211 #ifdef RT_OS_WINDOWS
    212     return RTErrConvertFromWin32(WSAGetLastError());
    213 #else
    214     return RTErrConvertFromErrno(errno);
    215 #endif
    216 }
    217 
    218 
    219 /**
    220  * Resets the last error.
    221  */
    222 DECLINLINE(void) rtSocketErrorReset(void)
    223 {
    224 #ifdef RT_OS_WINDOWS
    225     WSASetLastError(0);
    226 #else
    227     errno = 0;
    228 #endif
    229 }
    230 
    231 
    232 /**
    233  * Get the last resolver error as an iprt status code.
    234  *
    235  * @returns iprt status code.
    236  */
    237 DECLINLINE(int) rtSocketResolverError(void)
    238 {
    239 #ifdef RT_OS_WINDOWS
    240     return RTErrConvertFromWin32(WSAGetLastError());
    241 #else
    242     switch (h_errno)
    243     {
    244         case HOST_NOT_FOUND:
    245             return VERR_NET_HOST_NOT_FOUND;
    246         case NO_DATA:
    247             return VERR_NET_ADDRESS_NOT_AVAILABLE;
    248         case NO_RECOVERY:
    249             return VERR_IO_GEN_FAILURE;
    250         case TRY_AGAIN:
    251             return VERR_TRY_AGAIN;
    252 
    253         default:
    254             return VERR_UNRESOLVED_ERROR;
    255     }
    256 #endif
    257 }
    258 
    259 
    260 /**
    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  */
    268 DECLINLINE(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  */
    279 DECLINLINE(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  */
    292 int 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  */
    326 static 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  */
    368 int 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  */
    425 RTHCUINTPTR 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 /**
    435  * Helper that ensures the correct inheritability of a socket.
    436  *
    437  * We're currently ignoring failures.
    438  *
    439  * @returns IPRT status code
    440  * @param   hSocket         The socket handle.
    441  * @param   fInheritable    The desired inheritability state.
    442  */
    443 int 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());
    454 #else
    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  */
    476 int 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  */
    551 int 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  */
    625 int 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  */
    674 static 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  */
    713 static 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  */
    752 int 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  */
    790 int 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  */
    833 int 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  */
    859 int 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  */
    890 int 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  */
    947 int 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  */
    976 int 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 
    1002 
    1003 
    1004205/**
    1005206 * Atomicly updates a socket variable.
     
    1048249    {
    1049250        if (!fTryGracefulShutdown)
    1050             rtSocketShutdown(hSocket, true /*fRead*/, true /*fWrite*/);
     251            RTSocketShutdown(hSocket, true /*fRead*/, true /*fWrite*/);
    1051252        return rtTcpClose(hSocket, pszMsg, fTryGracefulShutdown);
    1052253    }
     
    1204405    if (RT_SUCCESS(rc))
    1205406    {
    1206         rtSocketSetInheritance(WaitSock, false /*fInheritable*/);
     407        RTSocketSetInheritance(WaitSock, false /*fInheritable*/);
    1207408
    1208409        /*
     
    1355556            continue;
    1356557        }
    1357         rtSocketSetInheritance(Socket, false /*fInheritable*/);
     558        RTSocketSetInheritance(Socket, false /*fInheritable*/);
    1358559
    1359560        /*
     
    1495696            continue;
    1496697        }
    1497         rtSocketSetInheritance(Socket, false /*fInheritable*/);
     698        RTSocketSetInheritance(Socket, false /*fInheritable*/);
    1498699
    1499700        /*
     
    1697898        if (!pHostEnt)
    1698899        {
    1699             rc = rtSocketError();
     900            rc = rtSocketResolverError();
    1700901            AssertMsgFailed(("Could not resolve '%s', rc=%Rrc\n", pszAddress, rc));
    1701902            return rc;
     
    1710911    if (RT_SUCCESS(rc))
    1711912    {
    1712         rtSocketSetInheritance(Sock, false /*fInheritable*/);
     913        RTSocketSetInheritance(Sock, false /*fInheritable*/);
    1713914
    1714915        struct sockaddr_in InAddr;
     
    1752953    if (fTryGracefulShutdown)
    1753954    {
    1754         rc = rtSocketShutdown(Sock, false /*fRead*/, true /*fWrite*/);
     955        rc = RTSocketShutdown(Sock, false /*fRead*/, true /*fWrite*/);
    1755956        if (RT_SUCCESS(rc))
    1756957        {
     
    1758959            for (;;)
    1759960            {
    1760                 rc = rtSocketSelectOne(Sock, 1000);
     961                rc = RTSocketSelectOne(Sock, 1000);
    1761962                if (rc == VERR_TIMEOUT)
    1762963                {
     
    1768969                {
    1769970                    char abBitBucket[16*_1K];
    1770                     ssize_t cbBytesRead = recv(rtSocketNative(Sock), &abBitBucket[0], sizeof(abBitBucket), MSG_NOSIGNAL);
     971                    ssize_t cbBytesRead = recv(RTSocketToNative(Sock), &abBitBucket[0], sizeof(abBitBucket), MSG_NOSIGNAL);
    1771972                    if (cbBytesRead == 0)
    1772973                        break; /* orderly shutdown in progress */
     
    1781982     * Destroy the socket handle.
    1782983     */
    1783     return rtSocketDestroy(Sock);
     984    return RTSocketDestroy(Sock);
    1784985}
    1785986
     
    1787988RTR3DECL(int) RTTcpRead(RTSOCKET Sock, void *pvBuffer, size_t cbBuffer, size_t *pcbRead)
    1788989{
    1789     return rtSocketRead(Sock, pvBuffer, cbBuffer, pcbRead);
     990    return RTSocketRead(Sock, pvBuffer, cbBuffer, pcbRead);
    1790991}
    1791992
     
    1793994RTR3DECL(int)  RTTcpWrite(RTSOCKET Sock, const void *pvBuffer, size_t cbBuffer)
    1794995{
    1795     return rtSocketWrite(Sock, pvBuffer, cbBuffer);
     996    return RTSocketWrite(Sock, pvBuffer, cbBuffer);
    1796997}
    1797998
     
    18131014RTR3DECL(int)  RTTcpSelectOne(RTSOCKET Sock, RTMSINTERVAL cMillies)
    18141015{
    1815     return rtSocketSelectOne(Sock, cMillies);
     1016    return RTSocketSelectOne(Sock, cMillies);
    18161017}
    18171018
     
    18191020RTR3DECL(int) RTTcpGetLocalAddress(RTSOCKET Sock, PRTNETADDR pAddr)
    18201021{
    1821     return rtSocketGetLocalAddress(Sock, pAddr);
     1022    return RTSocketGetLocalAddress(Sock, pAddr);
    18221023}
    18231024
     
    18251026RTR3DECL(int) RTTcpGetPeerAddress(RTSOCKET Sock, PRTNETADDR pAddr)
    18261027{
    1827     return rtSocketGetPeerAddress(Sock, pAddr);
    1828 }
    1829 
     1028    return RTSocketGetPeerAddress(Sock, pAddr);
     1029}
     1030
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