Changeset 27503 in vbox for trunk/src/VBox/Runtime/r3
- Timestamp:
- Mar 18, 2010 8:52:02 PM (15 years ago)
- 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 41 41 #include <iprt/mem.h> 42 42 #include <iprt/pipe.h> 43 #include <iprt/socket.h> 43 44 #include <iprt/string.h> 44 45 #include <iprt/thread.h> … … 300 301 case RTHANDLETYPE_PIPE: 301 302 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; 309 310 310 311 case RTHANDLETYPE_FILE: -
trunk/src/VBox/Runtime/r3/posix/process-posix.cpp
r27502 r27503 61 61 #include <iprt/file.h> 62 62 #include <iprt/pipe.h> 63 #include <iprt/socket.h> 63 64 #include <iprt/string.h> 64 65 #include "internal/process.h" … … 118 119 break; 119 120 120 //case RTHANDLETYPE_SOCKET:121 //aStdFds[i] = paHandles[i]->u.hSocket != NIL_RTSOCKET122 // ? (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; 125 126 126 127 default: -
trunk/src/VBox/Runtime/r3/socket.cpp
r27501 r27503 1 1 /* $Id$ */ 2 2 /** @file 3 * IPRT - TCP/IP.3 * IPRT - Network Sockets. 4 4 */ 5 5 … … 53 53 54 54 #include "internal/iprt.h" 55 #include <iprt/ tcp.h>55 #include <iprt/socket.h> 56 56 57 57 #include <iprt/asm.h> 58 58 #include <iprt/assert.h> 59 59 #include <iprt/err.h> 60 #include <iprt/mempool.h>61 60 #include <iprt/mem.h> 62 61 #include <iprt/string.h> … … 65 64 66 65 #include "internal/magics.h" 66 #include "internal/socket.h" 67 67 68 68 … … 144 144 145 145 146 147 /**148 * TCP Server state.149 */150 typedef enum RTTCPSERVERSTATE151 {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_DESTROYING168 } RTTCPSERVERSTATE;169 170 /*171 * Internal representation of the TCP Server handle.172 */173 typedef struct RTTCPSERVER174 {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 193 146 /******************************************************************************* 194 147 * Internal Functions * 195 148 *******************************************************************************/ 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 202 149 203 150 … … 235 182 * @returns iprt status code. 236 183 */ 237 DECLINLINE(int)rtSocketResolverError(void)184 int rtSocketResolverError(void) 238 185 { 239 186 #ifdef RT_OS_WINDOWS … … 292 239 int rtSocketCreateForNative(RTSOCKETINT **ppSocket, 293 240 #ifdef RT_OS_WINDOWS 294 HANDLEhNative241 SOCKET hNative 295 242 #else 296 243 int hNative … … 324 271 * @param iProtocol Socket parameter, usually 0. 325 272 */ 326 staticint rtSocketCreate(PRTSOCKET phSocket, int iDomain, int iType, int iProtocol)273 int rtSocketCreate(PRTSOCKET phSocket, int iDomain, int iType, int iProtocol) 327 274 { 328 275 /* … … 355 302 356 303 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) 304 RTDECL(int) RTSocketDestroy(RTSOCKET hSocket) 369 305 { 370 306 RTSOCKETINT *pThis = hSocket; … … 417 353 418 354 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) 355 RTDECL(RTHCUINTPTR) RTSocketToNative(RTSOCKET hSocket) 426 356 { 427 357 RTSOCKETINT *pThis = hSocket; … … 432 362 433 363 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) 364 RTDECL(int) RTSocketSetInheritance(RTSOCKET hSocket, bool fInheritable) 444 365 { 445 366 RTSOCKETINT *pThis = hSocket; … … 463 384 464 385 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) 386 RTDECL(int) RTSocketRead(RTSOCKET hSocket, void *pvBuffer, size_t cbBuffer, size_t *pcbRead) 477 387 { 478 388 /* … … 539 449 540 450 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) 451 RTDECL(int) RTSocketWrite(RTSOCKET hSocket, const void *pvBuffer, size_t cbBuffer) 552 452 { 553 453 /* … … 615 515 616 516 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) 517 RTDECL(int) RTSocketSelectOne(RTSOCKET hSocket, RTMSINTERVAL cMillies) 626 518 { 627 519 /* … … 664 556 665 557 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) 558 RTDECL(int) RTSocketShutdown(RTSOCKET hSocket, bool fRead, bool fWrite) 675 559 { 676 560 /* … … 743 627 744 628 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) 629 RTDECL(int) RTSocketGetLocalAddress(RTSOCKET hSocket, PRTNETADDR pAddr) 753 630 { 754 631 /* … … 781 658 782 659 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) 660 RTDECL(int) RTSocketGetPeerAddress(RTSOCKET hSocket, PRTNETADDR pAddr) 791 661 { 792 662 /* … … 818 688 } 819 689 820 821 /////////////////////////////////////////////////////////////////////////////////822 690 823 691 … … 992 860 } 993 861 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 for1061 * each of the incoming connections in turn. The pfnServe function can1062 * 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 else1107 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 else1137 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_WINDOWS1165 /*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 #endif1177 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 else1225 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 else1257 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 for1269 * each of the incoming connections in turn. The pfnServe function can1270 * return VERR_TCP_SERVER_STOP too terminate this loop. A stopped server1271 * 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 else1306 {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 by1317 * RTTcpServerCreate().1318 *1319 * The caller makes sure it has its own memory reference and releases it upon1320 * 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_ACCEPTING1335 && 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_HANDLE1352 || rc == VERR_INVALID_PARAMETER1353 || 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 change1380 * 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 else1387 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 not1434 * 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 client1442 * connection (on success only). Use1443 * RTTcpServerDisconnectClient() to clean it, this must1444 * be done before the next call to RTTcpServerListen2.1445 *1446 * @todo This can easily be extended to support multiple connections by1447 * adding a new state and a RTTcpServerDisconnectClient variant for1448 * 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_SERVING1469 && 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 else1510 {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_ACCEPTING1566 && 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_WINDOWS1674 /*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 #endif1686 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 61 61 #include <iprt/mem.h> 62 62 #include <iprt/string.h> 63 #include <iprt/socket.h> 63 64 #include <iprt/thread.h> 64 65 #include <iprt/time.h> 65 66 66 67 #include "internal/magics.h" 68 #include "internal/socket.h" 67 69 68 70 … … 201 203 202 204 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_WINDOWS212 return RTErrConvertFromWin32(WSAGetLastError());213 #else214 return RTErrConvertFromErrno(errno);215 #endif216 }217 218 219 /**220 * Resets the last error.221 */222 DECLINLINE(void) rtSocketErrorReset(void)223 {224 #ifdef RT_OS_WINDOWS225 WSASetLastError(0);226 #else227 errno = 0;228 #endif229 }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_WINDOWS240 return RTErrConvertFromWin32(WSAGetLastError());241 #else242 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 #endif257 }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_WINDOWS294 HANDLE hNative295 #else296 int hNative297 #endif298 )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_WINDOWS307 pThis->hEvent = INVALID_HANDLE_VALUE;308 pThis->hPollSet = 0;309 pThis->fPollEvts = 0;310 #endif311 *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 on321 * 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_WINDOWS332 SOCKET hNative = socket(iDomain, iType, iProtocol);333 if (hNative == INVALID_SOCKET)334 return rtSocketError();335 #else336 int hNative = socket(iDomain, iType, iProtocol);337 if (hNative == -1)338 return rtSocketError();339 #endif340 341 /*342 * Wrap it.343 */344 int rc = rtSocketCreateForNative(phSocket, hNative);345 if (RT_FAILURE(rc))346 {347 #ifdef RT_OS_WINDOWS348 closesocket(hNative);349 #else350 close(hNative);351 #endif352 }353 return rc;354 }355 356 357 /**358 * Destroys the specified handle, freeing associated resources and closing the359 * 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 will365 * just destroy it. Use the protocol specific close method if this is366 * 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_WINDOWS384 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 else396 {397 rc = rtSocketError();398 AssertMsgFailed(("\"%s\": closesocket(%p) -> %Rrc\n", pThis->hNative, rc));399 }400 pThis->hNative = INVALID_HANDLE_VALUE;401 }402 403 #else404 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 #endif414 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 code440 * @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_WINDOWS452 if (!SetHandleInformation(pThis->hNative, HANDLE_FLAG_INHERIT, fInheritable ? HANDLE_FLAG_INHERIT : 0))453 rc = RTErrConvertFromWin32(GetLastError());454 #else455 if (fcntl(pThis->hNative, F_SETFD, fInheritable ? 0 : FD_CLOEXEC) < 0)456 rc = RTErrConvertFromErrno(errno);457 #endif458 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 buffer473 * will be filled upon successful return. If not NULL a474 * 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_WINDOWS499 int cbNow = cbToRead >= INT_MAX/2 ? INT_MAX/2 : (int)cbToRead;500 #else501 size_t cbNow = cbToRead;502 #endif503 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 else513 {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_WINDOWS566 int cbNow = cbBuffer >= INT_MAX / 2 ? INT_MAX / 2 : (int)cbBuffer;567 #else568 size_t cbNow = cbBuffer >= SSIZE_MAX ? SSIZE_MAX : cbBuffer;569 #endif570 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 else576 {577 /*578 * Unfinished business, write the remainder of the request. Must ignore579 * 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_WINDOWS593 cbNow = cbBuffer >= INT_MAX / 2 ? INT_MAX / 2 : (int)cbBuffer;594 #else595 cbNow = cbBuffer >= SSIZE_MAX ? SSIZE_MAX : cbBuffer;596 #endif597 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 else602 {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. Use623 * 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 else648 {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 else659 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 else695 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 network711 * 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_V6727 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 #endif739 else740 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_WINDOWS768 int cbAddr = sizeof(u);769 #else770 socklen_t cbAddr = sizeof(u);771 #endif772 RT_ZERO(u);773 if (getsockname(pThis->hNative, &u.Addr, &cbAddr) == 0)774 rc = rtSocketConvertAddress(&u, cbAddr, pAddr);775 else776 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_WINDOWS806 int cbAddr = sizeof(u);807 #else808 socklen_t cbAddr = sizeof(u);809 #endif810 RT_ZERO(u);811 if (getpeername(pThis->hNative, &u.Addr, &cbAddr) == 0)812 rc = rtSocketConvertAddress(&u, cbAddr, pAddr);813 else814 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 pAddr831 * 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 on884 * success.885 * @param pAddr Where to return the client address.886 * @param pcbAddr On input this gives the size buffer size of what887 * @a pAddr point to. On return this contains the888 * 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_WINDOWS906 int cbAddr = (int)*pcbAddr;907 SOCKET hNative = accept(pThis->hNative, pAddr, &cbAddr);908 if (hNative != INVALID_SOCKET)909 #else910 socklen_t cbAddr = *pcbAddr;911 int hNative = accept(pThis->hNative, pAddr, &cbAddr);912 if (hNative != -1)913 #endif914 {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_WINDOWS924 closesocket(hNative);925 #else926 close(hNative);927 #endif928 }929 }930 else931 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 pAddr945 * 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 1004 205 /** 1005 206 * Atomicly updates a socket variable. … … 1048 249 { 1049 250 if (!fTryGracefulShutdown) 1050 rtSocketShutdown(hSocket, true /*fRead*/, true /*fWrite*/);251 RTSocketShutdown(hSocket, true /*fRead*/, true /*fWrite*/); 1051 252 return rtTcpClose(hSocket, pszMsg, fTryGracefulShutdown); 1052 253 } … … 1204 405 if (RT_SUCCESS(rc)) 1205 406 { 1206 rtSocketSetInheritance(WaitSock, false /*fInheritable*/);407 RTSocketSetInheritance(WaitSock, false /*fInheritable*/); 1207 408 1208 409 /* … … 1355 556 continue; 1356 557 } 1357 rtSocketSetInheritance(Socket, false /*fInheritable*/);558 RTSocketSetInheritance(Socket, false /*fInheritable*/); 1358 559 1359 560 /* … … 1495 696 continue; 1496 697 } 1497 rtSocketSetInheritance(Socket, false /*fInheritable*/);698 RTSocketSetInheritance(Socket, false /*fInheritable*/); 1498 699 1499 700 /* … … 1697 898 if (!pHostEnt) 1698 899 { 1699 rc = rtSocket Error();900 rc = rtSocketResolverError(); 1700 901 AssertMsgFailed(("Could not resolve '%s', rc=%Rrc\n", pszAddress, rc)); 1701 902 return rc; … … 1710 911 if (RT_SUCCESS(rc)) 1711 912 { 1712 rtSocketSetInheritance(Sock, false /*fInheritable*/);913 RTSocketSetInheritance(Sock, false /*fInheritable*/); 1713 914 1714 915 struct sockaddr_in InAddr; … … 1752 953 if (fTryGracefulShutdown) 1753 954 { 1754 rc = rtSocketShutdown(Sock, false /*fRead*/, true /*fWrite*/);955 rc = RTSocketShutdown(Sock, false /*fRead*/, true /*fWrite*/); 1755 956 if (RT_SUCCESS(rc)) 1756 957 { … … 1758 959 for (;;) 1759 960 { 1760 rc = rtSocketSelectOne(Sock, 1000);961 rc = RTSocketSelectOne(Sock, 1000); 1761 962 if (rc == VERR_TIMEOUT) 1762 963 { … … 1768 969 { 1769 970 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); 1771 972 if (cbBytesRead == 0) 1772 973 break; /* orderly shutdown in progress */ … … 1781 982 * Destroy the socket handle. 1782 983 */ 1783 return rtSocketDestroy(Sock);984 return RTSocketDestroy(Sock); 1784 985 } 1785 986 … … 1787 988 RTR3DECL(int) RTTcpRead(RTSOCKET Sock, void *pvBuffer, size_t cbBuffer, size_t *pcbRead) 1788 989 { 1789 return rtSocketRead(Sock, pvBuffer, cbBuffer, pcbRead);990 return RTSocketRead(Sock, pvBuffer, cbBuffer, pcbRead); 1790 991 } 1791 992 … … 1793 994 RTR3DECL(int) RTTcpWrite(RTSOCKET Sock, const void *pvBuffer, size_t cbBuffer) 1794 995 { 1795 return rtSocketWrite(Sock, pvBuffer, cbBuffer);996 return RTSocketWrite(Sock, pvBuffer, cbBuffer); 1796 997 } 1797 998 … … 1813 1014 RTR3DECL(int) RTTcpSelectOne(RTSOCKET Sock, RTMSINTERVAL cMillies) 1814 1015 { 1815 return rtSocketSelectOne(Sock, cMillies);1016 return RTSocketSelectOne(Sock, cMillies); 1816 1017 } 1817 1018 … … 1819 1020 RTR3DECL(int) RTTcpGetLocalAddress(RTSOCKET Sock, PRTNETADDR pAddr) 1820 1021 { 1821 return rtSocketGetLocalAddress(Sock, pAddr);1022 return RTSocketGetLocalAddress(Sock, pAddr); 1822 1023 } 1823 1024 … … 1825 1026 RTR3DECL(int) RTTcpGetPeerAddress(RTSOCKET Sock, PRTNETADDR pAddr) 1826 1027 { 1827 return rtSocketGetPeerAddress(Sock, pAddr);1828 } 1829 1028 return RTSocketGetPeerAddress(Sock, pAddr); 1029 } 1030
Note:
See TracChangeset
for help on using the changeset viewer.