Changeset 37196 in vbox for trunk/src/VBox/Runtime/r3
- Timestamp:
- May 24, 2011 2:50:05 PM (14 years ago)
- svn:sync-xref-src-repo-rev:
- 71892
- Location:
- trunk/src/VBox/Runtime/r3
- Files:
-
- 1 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/r3/socket.cpp
r34507 r37196 5 5 6 6 /* 7 * Copyright (C) 2006-201 0Oracle Corporation7 * Copyright (C) 2006-2011 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 221 221 222 222 /** 223 * Converts from a native socket address to a generic IPRT network address. 224 * 225 * @returns IPRT status code. 226 * @param pSrc The source address. 227 * @param cbSrc The size of the source address. 228 * @param pAddr Where to return the generic IPRT network 229 * address. 230 */ 231 static int rtSocketNetAddrFromAddr(RTSOCKADDRUNION const *pSrc, size_t cbSrc, PRTNETADDR pAddr) 232 { 233 /* 234 * Convert the address. 235 */ 236 if ( cbSrc == sizeof(struct sockaddr_in) 237 && pSrc->Addr.sa_family == AF_INET) 238 { 239 RT_ZERO(*pAddr); 240 pAddr->enmType = RTNETADDRTYPE_IPV4; 241 pAddr->uPort = RT_N2H_U16(pSrc->Ipv4.sin_port); 242 pAddr->uAddr.IPv4.u = pSrc->Ipv4.sin_addr.s_addr; 243 } 244 #ifdef IPRT_WITH_TCPIP_V6 245 else if ( cbSrc == sizeof(struct sockaddr_in6) 246 && pSrc->Addr.sa_family == AF_INET6) 247 { 248 RT_ZERO(*pAddr); 249 pAddr->enmType = RTNETADDRTYPE_IPV6; 250 pAddr->uPort = RT_N2H_U16(pSrc->Ipv6.sin6_port); 251 pAddr->uAddr.IPv6.au32[0] = pSrc->Ipv6.sin6_addr.s6_addr32[0]; 252 pAddr->uAddr.IPv6.au32[1] = pSrc->Ipv6.sin6_addr.s6_addr32[1]; 253 pAddr->uAddr.IPv6.au32[2] = pSrc->Ipv6.sin6_addr.s6_addr32[2]; 254 pAddr->uAddr.IPv6.au32[3] = pSrc->Ipv6.sin6_addr.s6_addr32[3]; 255 } 256 #endif 257 else 258 return VERR_NET_ADDRESS_FAMILY_NOT_SUPPORTED; 259 return VINF_SUCCESS; 260 } 261 262 263 /** 264 * Converts from a generic IPRT network address to a native socket address. 265 * 266 * @returns IPRT status code. 267 * @param pAddr Pointer to the generic IPRT network address. 268 * @param pDst The source address. 269 * @param cbSrc The size of the source address. 270 */ 271 static int rtSocketAddrFromNetAddr(PCRTNETADDR pAddr, RTSOCKADDRUNION *pDst, size_t cbDst) 272 { 273 RT_BZERO(pDst, cbDst); 274 if ( pAddr->enmType == RTNETADDRTYPE_IPV4 275 && cbDst >= sizeof(struct sockaddr_in)) 276 { 277 pDst->Addr.sa_family = AF_INET; 278 pDst->Ipv4.sin_port = RT_H2N_U16(pAddr->uPort); 279 pDst->Ipv4.sin_addr.s_addr = pAddr->uAddr.IPv4.u; 280 } 281 #ifdef IPRT_WITH_TCPIP_V6 282 else if ( pAddr->enmType == RTNETADDRTYPE_IPV6 283 && cbDst >= sizeof(struct sockaddr_in6)) 284 { 285 pDst->Addr.sa_family = AF_INET6; 286 pDst->Ipv6.sin6_port = RT_H2N_U16(pAddr->uPort); 287 pSrc->Ipv6.sin6_addr.s6_addr32[0] = pAddr->uAddr.IPv6.au32[0]; 288 pSrc->Ipv6.sin6_addr.s6_addr32[1] = pAddr->uAddr.IPv6.au32[1]; 289 pSrc->Ipv6.sin6_addr.s6_addr32[2] = pAddr->uAddr.IPv6.au32[2]; 290 pSrc->Ipv6.sin6_addr.s6_addr32[3] = pAddr->uAddr.IPv6.au32[3]; 291 } 292 #endif 293 else 294 return VERR_NET_ADDRESS_FAMILY_NOT_SUPPORTED; 295 return VINF_SUCCESS; 296 } 297 298 299 /** 223 300 * Tries to lock the socket for exclusive usage by the calling thread. 224 301 * … … 502 579 503 580 return rc; 581 } 582 583 584 RTDECL(int) RTSocketParseInetAddress(const char *pszAddress, unsigned uPort, PRTNETADDR pAddr) 585 { 586 int rc; 587 588 /* 589 * Validate input. 590 */ 591 AssertReturn(uPort > 0, VERR_INVALID_PARAMETER); 592 AssertPtrReturn(pszAddress, VERR_INVALID_POINTER); 593 594 #ifdef RT_OS_WINDOWS 595 /* 596 * Initialize WinSock and check version. 597 */ 598 WORD wVersionRequested = MAKEWORD(1, 1); 599 WSADATA wsaData; 600 rc = WSAStartup(wVersionRequested, &wsaData); 601 if (wsaData.wVersion != wVersionRequested) 602 { 603 AssertMsgFailed(("Wrong winsock version\n")); 604 return VERR_NOT_SUPPORTED; 605 } 606 #endif 607 608 /* 609 * Resolve the address. 610 */ 611 /** @todo this only supports IPv4, and IPv6 support needs to be added. 612 * It probably needs to be converted to getnameinfo(). */ 613 struct hostent *pHostEnt = NULL; 614 pHostEnt = gethostbyname(pszAddress); 615 if (!pHostEnt) 616 { 617 struct in_addr InAddr; 618 InAddr.s_addr = inet_addr(pszAddress); 619 pHostEnt = gethostbyaddr((char *)&InAddr, 4, AF_INET); 620 if (!pHostEnt) 621 { 622 rc = rtSocketResolverError(); 623 AssertMsgFailed(("Could not resolve '%s', rc=%Rrc\n", pszAddress, rc)); 624 return rc; 625 } 626 } 627 628 if (pHostEnt->h_addrtype == AF_INET) 629 { 630 RT_ZERO(*pAddr); 631 pAddr->enmType = RTNETADDRTYPE_IPV4; 632 pAddr->uPort = uPort; 633 pAddr->uAddr.IPv4.u = ((struct in_addr *)pHostEnt->h_addr)->s_addr; 634 } 635 else 636 return VERR_NET_ADDRESS_FAMILY_NOT_SUPPORTED; 637 638 return VINF_SUCCESS; 504 639 } 505 640 … … 574 709 575 710 711 RTDECL(int) RTSocketReadFrom(RTSOCKET hSocket, void *pvBuffer, size_t cbBuffer, size_t *pcbRead, PRTNETADDR pSrcAddr) 712 { 713 /* 714 * Validate input. 715 */ 716 RTSOCKETINT *pThis = hSocket; 717 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 718 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE); 719 AssertReturn(cbBuffer > 0, VERR_INVALID_PARAMETER); 720 AssertPtr(pvBuffer); 721 AssertPtr(pcbRead); 722 AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS); 723 724 int rc = rtSocketSwitchBlockingMode(pThis, true /* fBlocking */); 725 if (RT_FAILURE(rc)) 726 return rc; 727 728 /* 729 * Read data. 730 */ 731 size_t cbRead = 0; 732 size_t cbToRead = cbBuffer; 733 rtSocketErrorReset(); 734 RTSOCKADDRUNION u; 735 #ifdef RT_OS_WINDOWS 736 int cbNow = cbToRead >= INT_MAX/2 ? INT_MAX/2 : (int)cbToRead; 737 int cbAddr = sizeof(u); 738 #else 739 size_t cbNow = cbToRead; 740 socklen_t cbAddr = sizeof(u); 741 #endif 742 ssize_t cbBytesRead = recvfrom(pThis->hNative, (char *)pvBuffer + cbRead, cbNow, MSG_NOSIGNAL, &u.Addr, &cbAddr); 743 if (cbBytesRead <= 0) 744 { 745 rc = rtSocketError(); 746 Assert(RT_FAILURE_NP(rc) || cbBytesRead == 0); 747 if (RT_SUCCESS_NP(rc)) 748 { 749 *pcbRead = 0; 750 rc = VINF_SUCCESS; 751 } 752 } 753 else 754 { 755 if (pSrcAddr) 756 rc = rtSocketNetAddrFromAddr(&u, cbAddr, pSrcAddr); 757 *pcbRead = cbBytesRead; 758 } 759 760 rtSocketUnlock(pThis); 761 return rc; 762 } 763 764 576 765 RTDECL(int) RTSocketWrite(RTSOCKET hSocket, const void *pvBuffer, size_t cbBuffer) 577 766 { … … 643 832 644 833 834 RTDECL(int) RTSocketWriteTo(RTSOCKET hSocket, const void *pvBuffer, size_t cbBuffer, PCRTNETADDR pAddr) 835 { 836 /* 837 * Validate input. 838 */ 839 RTSOCKETINT *pThis = hSocket; 840 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 841 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE); 842 843 /* no locking since UDP reads may be done concurrently to writes, and 844 * this is the normal use case of this code. */ 845 846 int rc = rtSocketSwitchBlockingMode(pThis, true /* fBlocking */); 847 if (RT_FAILURE(rc)) 848 return rc; 849 850 /* Figure out destination address. */ 851 struct sockaddr *pSA = NULL; 852 #ifdef RT_OS_WINDOWS 853 int cbSA = 0; 854 #else 855 socklen_t cbSA = 0; 856 #endif 857 RTSOCKADDRUNION u; 858 if (pAddr) 859 { 860 rc = rtSocketAddrFromNetAddr(pAddr, &u, sizeof(u)); 861 if (RT_FAILURE(rc)) 862 return rc; 863 pSA = &u.Addr; 864 cbSA = sizeof(u); 865 } 866 867 /* 868 * Must write all at once, otherwise it is a failure. 869 */ 870 #ifdef RT_OS_WINDOWS 871 int cbNow = cbBuffer >= INT_MAX / 2 ? INT_MAX / 2 : (int)cbBuffer; 872 #else 873 size_t cbNow = cbBuffer >= SSIZE_MAX ? SSIZE_MAX : cbBuffer; 874 #endif 875 ssize_t cbWritten = sendto(pThis->hNative, (const char *)pvBuffer, cbNow, MSG_NOSIGNAL, pSA, cbSA); 876 if (RT_LIKELY((size_t)cbWritten == cbBuffer && cbWritten >= 0)) 877 rc = VINF_SUCCESS; 878 else if (cbWritten < 0) 879 rc = rtSocketError(); 880 else 881 rc = VERR_TOO_MUCH_DATA; 882 883 rtSocketUnlock(pThis); 884 return rc; 885 } 886 887 645 888 RTDECL(int) RTSocketSgWrite(RTSOCKET hSocket, PCRTSGBUF pSgBuf) 646 889 { … … 1085 1328 1086 1329 1087 /**1088 * Converts from a native socket address to a generic IPRT network address.1089 *1090 * @returns IPRT status code.1091 * @param pSrc The source address.1092 * @param cbSrc The size of the source address.1093 * @param pAddr Where to return the generic IPRT network1094 * address.1095 */1096 static int rtSocketConvertAddress(RTSOCKADDRUNION const *pSrc, size_t cbSrc, PRTNETADDR pAddr)1097 {1098 /*1099 * Convert the address.1100 */1101 if ( cbSrc == sizeof(struct sockaddr_in)1102 && pSrc->Addr.sa_family == AF_INET)1103 {1104 RT_ZERO(*pAddr);1105 pAddr->enmType = RTNETADDRTYPE_IPV4;1106 pAddr->uPort = RT_N2H_U16(pSrc->Ipv4.sin_port);1107 pAddr->uAddr.IPv4.u = pSrc->Ipv4.sin_addr.s_addr;1108 }1109 #ifdef IPRT_WITH_TCPIP_V61110 else if ( cbSrc == sizeof(struct sockaddr_in6)1111 && pSrc->Addr.sa_family == AF_INET6)1112 {1113 RT_ZERO(*pAddr);1114 pAddr->enmType = RTNETADDRTYPE_IPV6;1115 pAddr->uPort = RT_N2H_U16(pSrc->Ipv6.sin6_port);1116 pAddr->uAddr.IPv6.au32[0] = pSrc->Ipv6.sin6_addr.s6_addr32[0];1117 pAddr->uAddr.IPv6.au32[1] = pSrc->Ipv6.sin6_addr.s6_addr32[1];1118 pAddr->uAddr.IPv6.au32[2] = pSrc->Ipv6.sin6_addr.s6_addr32[2];1119 pAddr->uAddr.IPv6.au32[3] = pSrc->Ipv6.sin6_addr.s6_addr32[3];1120 }1121 #endif1122 else1123 return VERR_NET_ADDRESS_FAMILY_NOT_SUPPORTED;1124 return VINF_SUCCESS;1125 }1126 1127 1128 1330 RTDECL(int) RTSocketGetLocalAddress(RTSOCKET hSocket, PRTNETADDR pAddr) 1129 1331 { … … 1148 1350 RT_ZERO(u); 1149 1351 if (getsockname(pThis->hNative, &u.Addr, &cbAddr) == 0) 1150 rc = rtSocket ConvertAddress(&u, cbAddr, pAddr);1352 rc = rtSocketNetAddrFromAddr(&u, cbAddr, pAddr); 1151 1353 else 1152 1354 rc = rtSocketError(); … … 1178 1380 RT_ZERO(u); 1179 1381 if (getpeername(pThis->hNative, &u.Addr, &cbAddr) == 0) 1180 rc = rtSocket ConvertAddress(&u, cbAddr, pAddr);1382 rc = rtSocketNetAddrFromAddr(&u, cbAddr, pAddr); 1181 1383 else 1182 1384 rc = rtSocketError(); -
trunk/src/VBox/Runtime/r3/udp.cpp
r37166 r37196 1 1 /* $Id$ */ 2 2 /** @file 3 * IPRT - TCP/IP.3 * IPRT - UDP/IP. 4 4 */ 5 5 6 6 /* 7 * Copyright (C) 2006-201 0Oracle Corporation7 * Copyright (C) 2006-2011 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 36 36 # include <errno.h> 37 37 # include <netinet/in.h> 38 # include <netinet/ tcp.h>38 # include <netinet/udp.h> 39 39 # include <arpa/inet.h> 40 40 # include <netdb.h> 41 # ifdef FIX_FOR_3_242 # include <fcntl.h>43 # endif44 41 #endif 45 42 #include <limits.h> 46 43 47 44 #include "internal/iprt.h" 48 #include <iprt/ tcp.h>45 #include <iprt/udp.h> 49 46 50 47 #include <iprt/asm.h> … … 65 62 * Defined Constants And Macros * 66 63 *******************************************************************************/ 67 /* non-standard linux stuff (it seems). */68 #ifndef MSG_NOSIGNAL69 # define MSG_NOSIGNAL 070 #endif71 #ifndef SHUT_RDWR72 # ifdef SD_BOTH73 # define SHUT_RDWR SD_BOTH74 # else75 # define SHUT_RDWR 276 # endif77 #endif78 #ifndef SHUT_WR79 # ifdef SD_SEND80 # define SHUT_WR SD_SEND81 # else82 # define SHUT_WR 183 # endif84 #endif85 86 64 /* fixup backlevel OSes. */ 87 65 #if defined(RT_OS_OS2) || defined(RT_OS_WINDOWS) … … 89 67 #endif 90 68 91 /** How many pending connection. */92 #define RTTCP_SERVER_BACKLOG 1093 94 69 95 70 /******************************************************************************* … … 97 72 *******************************************************************************/ 98 73 /** 99 * TCP Server state.100 */ 101 typedef enum RT TCPSERVERSTATE74 * UDP Server state. 75 */ 76 typedef enum RTUDPSERVERSTATE 102 77 { 103 78 /** Invalid. */ 104 RT TCPSERVERSTATE_INVALID = 0,79 RTUDPSERVERSTATE_INVALID = 0, 105 80 /** Created. */ 106 RT TCPSERVERSTATE_CREATED,107 /** Listener threadis starting up. */108 RT TCPSERVERSTATE_STARTING,109 /** Accepting client connections. */110 RT TCPSERVERSTATE_ACCEPTING,111 /** Serving a client. */112 RT TCPSERVERSTATE_SERVING,113 /** Listenerterminating. */114 RT TCPSERVERSTATE_STOPPING,115 /** Listenerterminated. */116 RT TCPSERVERSTATE_STOPPED,117 /** Listener cleans up. */118 RT TCPSERVERSTATE_DESTROYING119 } RT TCPSERVERSTATE;81 RTUDPSERVERSTATE_CREATED, 82 /** Thread for incoming datagrams is starting up. */ 83 RTUDPSERVERSTATE_STARTING, 84 /** Waiting for incoming datagrams. */ 85 RTUDPSERVERSTATE_WAITING, 86 /** Handling an incoming datagram. */ 87 RTUDPSERVERSTATE_RECEIVING, 88 /** Thread terminating. */ 89 RTUDPSERVERSTATE_STOPPING, 90 /** Thread terminated. */ 91 RTUDPSERVERSTATE_STOPPED, 92 /** Final cleanup before being unusable. */ 93 RTUDPSERVERSTATE_DESTROYING 94 } RTUDPSERVERSTATE; 120 95 121 96 /* 122 * Internal representation of the TCP Server handle.123 */ 124 typedef struct RT TCPSERVER125 { 126 /** The magic value (RT TCPSERVER_MAGIC). */97 * Internal representation of the UDP Server handle. 98 */ 99 typedef struct RTUDPSERVER 100 { 101 /** The magic value (RTUDPSERVER_MAGIC). */ 127 102 uint32_t volatile u32Magic; 128 103 /** The server state. */ 129 RT TCPSERVERSTATE volatile enmState;104 RTUDPSERVERSTATE volatile enmState; 130 105 /** The server thread. */ 131 106 RTTHREAD Thread; 132 107 /** The server socket. */ 133 RTSOCKET volatile hServerSocket; 134 /** The socket to the client currently being serviced. 135 * This is NIL_RTSOCKET when no client is serviced. */ 136 RTSOCKET volatile hClientSocket; 137 /** The connection function. */ 138 PFNRTTCPSERVE pfnServe; 108 RTSOCKET volatile hSocket; 109 /** The datagram receiver function. */ 110 PFNRTUDPSERVE pfnServe; 139 111 /** Argument to pfnServer. */ 140 112 void *pvUser; 141 } RT TCPSERVER;113 } RTUDPSERVER; 142 114 143 115 … … 145 117 * Internal Functions * 146 118 *******************************************************************************/ 147 static DECLCALLBACK(int) rt TcpServerThread(RTTHREAD ThreadSelf, void *pvServer);148 static int rt TcpServerListen(PRTTCPSERVER pServer);149 static int rt TcpServerListenCleanup(PRTTCPSERVER pServer);150 static int rt TcpServerDestroySocket(RTSOCKET volatile *pSockClient, const char *pszMsg);151 static int rt TcpClose(RTSOCKET Sock, const char *pszMsg, bool fTryGracefulShutdown);119 static DECLCALLBACK(int) rtUdpServerThread(RTTHREAD ThreadSelf, void *pvServer); 120 static int rtUdpServerListen(PRTUDPSERVER pServer); 121 static int rtUdpServerListenCleanup(PRTUDPSERVER pServer); 122 static int rtUdpServerDestroySocket(RTSOCKET volatile *pSock, const char *pszMsg); 123 static int rtUdpClose(RTSOCKET Sock, const char *pszMsg); 152 124 153 125 … … 158 130 * @param hSock The new socket handle value. 159 131 */ 160 DECLINLINE(RTSOCKET) rt TcpAtomicXchgSock(RTSOCKET volatile *phSock, const RTSOCKET hNew)132 DECLINLINE(RTSOCKET) rtUdpAtomicXchgSock(RTSOCKET volatile *phSock, const RTSOCKET hNew) 161 133 { 162 134 RTSOCKET hRet; … … 167 139 168 140 /** 169 * Tries to change the TCP server state.170 */ 171 DECLINLINE(bool) rt TcpServerTrySetState(PRTTCPSERVER pServer, RTTCPSERVERSTATE enmStateNew, RTTCPSERVERSTATE enmStateOld)141 * Tries to change the UDP server state. 142 */ 143 DECLINLINE(bool) rtUdpServerTrySetState(PRTUDPSERVER pServer, RTUDPSERVERSTATE enmStateNew, RTUDPSERVERSTATE enmStateOld) 172 144 { 173 145 bool fRc; … … 177 149 178 150 /** 179 * Changes the TCP server state.180 */ 181 DECLINLINE(void) rt TcpServerSetState(PRTTCPSERVER pServer, RTTCPSERVERSTATE enmStateNew, RTTCPSERVERSTATE enmStateOld)151 * Changes the UDP server state. 152 */ 153 DECLINLINE(void) rtUdpServerSetState(PRTUDPSERVER pServer, RTUDPSERVERSTATE enmStateNew, RTUDPSERVERSTATE enmStateOld) 182 154 { 183 155 bool fRc; … … 188 160 189 161 /** 190 * Closes the a socket (client or server).162 * Closes a socket. 191 163 * 192 164 * @returns IPRT status code. 193 165 */ 194 static int rt TcpServerDestroySocket(RTSOCKET volatile *pSock, const char *pszMsg, bool fTryGracefulShutdown)195 { 196 RTSOCKET hSocket = rt TcpAtomicXchgSock(pSock, NIL_RTSOCKET);166 static int rtUdpServerDestroySocket(RTSOCKET volatile *pSock, const char *pszMsg) 167 { 168 RTSOCKET hSocket = rtUdpAtomicXchgSock(pSock, NIL_RTSOCKET); 197 169 if (hSocket != NIL_RTSOCKET) 198 170 { 199 if (!fTryGracefulShutdown) 200 RTSocketShutdown(hSocket, true /*fRead*/, true /*fWrite*/); 201 return rtTcpClose(hSocket, pszMsg, fTryGracefulShutdown); 202 } 203 return VINF_TCP_SERVER_NO_CLIENT; 204 } 205 206 207 /** 208 * Create single connection at a time TCP Server in a separate thread. 209 * 210 * The thread will loop accepting connections and call pfnServe for 211 * each of the incoming connections in turn. The pfnServe function can 212 * return VERR_TCP_SERVER_STOP too terminate this loop. RTTcpServerDestroy() 171 return rtUdpClose(hSocket, pszMsg); 172 } 173 return VINF_UDP_SERVER_NO_CLIENT; 174 } 175 176 177 /** 178 * Create single datagram at a time UDP Server in a separate thread. 179 * 180 * The thread will loop waiting for datagrams and call pfnServe for 181 * each of the incoming datagrams in turn. The pfnServe function can 182 * return VERR_UDP_SERVER_STOP too terminate this loop. RTUdpServerDestroy() 213 183 * should be used to terminate the server. 214 184 * 215 185 * @returns iprt status code. 216 * @param pszAddress The address for creating a listeningsocket.186 * @param pszAddress The address for creating a datagram socket. 217 187 * If NULL or empty string the server is bound to all interfaces. 218 * @param uPort The port for creating a listeningsocket.188 * @param uPort The port for creating a datagram socket. 219 189 * @param enmType The thread type. 220 190 * @param pszThrdName The name of the worker thread. 221 * @param pfnServe The function which will serve a new client connection.191 * @param pfnServe The function which will handle incoming datagrams. 222 192 * @param pvUser User argument passed to pfnServe. 223 193 * @param ppServer Where to store the serverhandle. 224 194 */ 225 RTR3DECL(int) RT TcpServerCreate(const char *pszAddress, unsigned uPort, RTTHREADTYPE enmType, const char *pszThrdName,226 PFNRT TCPSERVE pfnServe, void *pvUser, PPRTTCPSERVER ppServer)195 RTR3DECL(int) RTUdpServerCreate(const char *pszAddress, unsigned uPort, RTTHREADTYPE enmType, const char *pszThrdName, 196 PFNRTUDPSERVE pfnServe, void *pvUser, PPRTUDPSERVER ppServer) 227 197 { 228 198 /* … … 237 207 * Create the server. 238 208 */ 239 PRT TCPSERVER pServer;240 int rc = RT TcpServerCreateEx(pszAddress, uPort, &pServer);209 PRTUDPSERVER pServer; 210 int rc = RTUdpServerCreateEx(pszAddress, uPort, &pServer); 241 211 if (RT_SUCCESS(rc)) 242 212 { … … 245 215 */ 246 216 RTMemPoolRetain(pServer); 247 pServer->enmState = RT TCPSERVERSTATE_STARTING;217 pServer->enmState = RTUDPSERVERSTATE_STARTING; 248 218 pServer->pvUser = pvUser; 249 219 pServer->pfnServe = pfnServe; 250 rc = RTThreadCreate(&pServer->Thread, rt TcpServerThread, pServer, 0, enmType, /*RTTHREADFLAGS_WAITABLE*/0, pszThrdName);220 rc = RTThreadCreate(&pServer->Thread, rtUdpServerThread, pServer, 0, enmType, /*RTTHREADFLAGS_WAITABLE*/0, pszThrdName); 251 221 if (RT_SUCCESS(rc)) 252 222 { … … 263 233 * Destroy the server. 264 234 */ 265 rt TcpServerSetState(pServer, RTTCPSERVERSTATE_CREATED, RTTCPSERVERSTATE_STARTING);266 RT TcpServerDestroy(pServer);235 rtUdpServerSetState(pServer, RTUDPSERVERSTATE_CREATED, RTUDPSERVERSTATE_STARTING); 236 RTUdpServerDestroy(pServer); 267 237 } 268 238 … … 272 242 273 243 /** 274 * Server thread, loops accepting connections until it's terminated.244 * Server thread, loops waiting for datagrams until it's terminated. 275 245 * 276 246 * @returns iprt status code. (ignored). … … 278 248 * @param pvServer Server handle. 279 249 */ 280 static DECLCALLBACK(int) rt TcpServerThread(RTTHREAD ThreadSelf, void *pvServer)281 { 282 PRT TCPSERVER pServer = (PRTTCPSERVER)pvServer;250 static DECLCALLBACK(int) rtUdpServerThread(RTTHREAD ThreadSelf, void *pvServer) 251 { 252 PRTUDPSERVER pServer = (PRTUDPSERVER)pvServer; 283 253 int rc; 284 if (rt TcpServerTrySetState(pServer, RTTCPSERVERSTATE_ACCEPTING, RTTCPSERVERSTATE_STARTING))285 rc = rt TcpServerListen(pServer);254 if (rtUdpServerTrySetState(pServer, RTUDPSERVERSTATE_WAITING, RTUDPSERVERSTATE_STARTING)) 255 rc = rtUdpServerListen(pServer); 286 256 else 287 rc = rt TcpServerListenCleanup(pServer);257 rc = rtUdpServerListenCleanup(pServer); 288 258 RTMemPoolRelease(RTMEMPOOL_DEFAULT, pServer); 289 259 NOREF(ThreadSelf); … … 293 263 294 264 /** 295 * Create single connection at a time TCP Server.296 * The caller must call RT TcpServerListen() to actually start the server.265 * Create single datagram at a time UDP Server. 266 * The caller must call RTUdpServerReceive() to actually start the server. 297 267 * 298 268 * @returns iprt status code. 299 * @param pszAddress The address for creating a listeningsocket.269 * @param pszAddress The address for creating a datagram socket. 300 270 * If NULL the server is bound to all interfaces. 301 * @param uPort The port for creating a listeningsocket.271 * @param uPort The port for creating a datagram socket. 302 272 * @param ppServer Where to store the serverhandle. 303 273 */ 304 RTR3DECL(int) RT TcpServerCreateEx(const char *pszAddress, uint32_t uPort, PPRTTCPSERVER ppServer)274 RTR3DECL(int) RTUdpServerCreateEx(const char *pszAddress, uint32_t uPort, PPRTUDPSERVER ppServer) 305 275 { 306 276 int rc; … … 349 319 * Setting up socket. 350 320 */ 351 RTSOCKET WaitSock;352 rc = rtSocketCreate(& WaitSock, AF_INET, SOCK_STREAM, IPPROTO_TCP);321 RTSOCKET Sock; 322 rc = rtSocketCreate(&Sock, AF_INET, SOCK_DGRAM, IPPROTO_UDP); 353 323 if (RT_SUCCESS(rc)) 354 324 { 355 RTSocketSetInheritance( WaitSock, false /*fInheritable*/);325 RTSocketSetInheritance(Sock, false /*fInheritable*/); 356 326 357 327 /* … … 359 329 */ 360 330 int fFlag = 1; 361 if (!rtSocketSetOpt( WaitSock, SOL_SOCKET, SO_REUSEADDR, &fFlag, sizeof(fFlag)))331 if (!rtSocketSetOpt(Sock, SOL_SOCKET, SO_REUSEADDR, &fFlag, sizeof(fFlag))) 362 332 { 363 333 /* … … 375 345 376 346 /* 377 * Bind a name to a socket and set it listening for connections.347 * Bind a name to the socket. 378 348 */ 379 rc = rtSocketBind(WaitSock, (struct sockaddr *)&LocalAddr, sizeof(LocalAddr)); 380 if (RT_SUCCESS(rc)) 381 rc = rtSocketListen(WaitSock, RTTCP_SERVER_BACKLOG); 349 rc = rtSocketBind(Sock, (struct sockaddr *)&LocalAddr, sizeof(LocalAddr)); 382 350 if (RT_SUCCESS(rc)) 383 351 { … … 385 353 * Create the server handle. 386 354 */ 387 PRT TCPSERVER pServer = (PRTTCPSERVER)RTMemPoolAlloc(RTMEMPOOL_DEFAULT, sizeof(*pServer));355 PRTUDPSERVER pServer = (PRTUDPSERVER)RTMemPoolAlloc(RTMEMPOOL_DEFAULT, sizeof(*pServer)); 388 356 if (pServer) 389 357 { 390 pServer->u32Magic = RTTCPSERVER_MAGIC; 391 pServer->enmState = RTTCPSERVERSTATE_CREATED; 392 pServer->Thread = NIL_RTTHREAD; 393 pServer->hServerSocket = WaitSock; 394 pServer->hClientSocket = NIL_RTSOCKET; 395 pServer->pfnServe = NULL; 396 pServer->pvUser = NULL; 358 pServer->u32Magic = RTUDPSERVER_MAGIC; 359 pServer->enmState = RTUDPSERVERSTATE_CREATED; 360 pServer->Thread = NIL_RTTHREAD; 361 pServer->hSocket = Sock; 362 pServer->pfnServe = NULL; 363 pServer->pvUser = NULL; 397 364 *ppServer = pServer; 398 365 return VINF_SUCCESS; … … 405 372 else 406 373 AssertMsgFailed(("rtSocketSetOpt: %Rrc\n", rc)); 407 rt TcpClose(WaitSock, "RTServerCreateEx", false /*fTryGracefulShutdown*/);374 rtUdpClose(Sock, "RTServerCreateEx"); 408 375 } 409 376 … … 413 380 414 381 /** 415 * Listen for incoming connections.416 * 417 * The function will loop accepting connections and call pfnServe for418 * each of the incoming connections in turn. The pfnServe function can419 * return VERR_ TCP_SERVER_STOP too terminate this loop. A stopped server382 * Listen for incoming datagrams. 383 * 384 * The function will loop waiting for datagrams and call pfnServe for 385 * each of the incoming datagrams in turn. The pfnServe function can 386 * return VERR_UDP_SERVER_STOP too terminate this loop. A stopped server 420 387 * can only be destroyed. 421 388 * 422 389 * @returns IPRT status code. 423 * @retval VERR_ TCP_SERVER_STOP if stopped by pfnServe.424 * @retval VERR_ TCP_SERVER_SHUTDOWN if shut down by RTTcpServerShutdown.425 * 426 * @param pServer The server handle as returned from RT TcpServerCreateEx().427 * @param pfnServe The function which will serve a new client connection.390 * @retval VERR_UDP_SERVER_STOP if stopped by pfnServe. 391 * @retval VERR_UDP_SERVER_SHUTDOWN if shut down by RTUdpServerShutdown. 392 * 393 * @param pServer The server handle as returned from RTUdpServerCreateEx(). 394 * @param pfnServe The function which will handle incoming datagrams. 428 395 * @param pvUser User argument passed to pfnServe. 429 396 */ 430 RTR3DECL(int) RT TcpServerListen(PRTTCPSERVER pServer, PFNRTTCPSERVE pfnServe, void *pvUser)397 RTR3DECL(int) RTUdpServerListen(PRTUDPSERVER pServer, PFNRTUDPSERVE pfnServe, void *pvUser) 431 398 { 432 399 /* … … 435 402 AssertPtrReturn(pfnServe, VERR_INVALID_POINTER); 436 403 AssertPtrReturn(pServer, VERR_INVALID_HANDLE); 437 AssertReturn(pServer->u32Magic == RT TCPSERVER_MAGIC, VERR_INVALID_HANDLE);404 AssertReturn(pServer->u32Magic == RTUDPSERVER_MAGIC, VERR_INVALID_HANDLE); 438 405 AssertReturn(RTMemPoolRetain(pServer) != UINT32_MAX, VERR_INVALID_HANDLE); 439 406 440 407 int rc = VERR_INVALID_STATE; 441 if (rt TcpServerTrySetState(pServer, RTTCPSERVERSTATE_ACCEPTING, RTTCPSERVERSTATE_CREATED))408 if (rtUdpServerTrySetState(pServer, RTUDPSERVERSTATE_WAITING, RTUDPSERVERSTATE_CREATED)) 442 409 { 443 410 Assert(!pServer->pfnServe); 444 411 Assert(!pServer->pvUser); 445 412 Assert(pServer->Thread == NIL_RTTHREAD); 446 Assert(pServer->hClientSocket == NIL_RTSOCKET);447 413 448 414 pServer->pfnServe = pfnServe; … … 450 416 pServer->Thread = RTThreadSelf(); 451 417 Assert(pServer->Thread != NIL_RTTHREAD); 452 rc = rt TcpServerListen(pServer);418 rc = rtUdpServerListen(pServer); 453 419 } 454 420 else … … 463 429 464 430 /** 465 * Internal worker common for RT TcpServerListen and the thread created by466 * RT TcpServerCreate().431 * Internal worker common for RTUdpServerListen and the thread created by 432 * RTUdpServerCreate(). 467 433 * 468 434 * The caller makes sure it has its own memory reference and releases it upon 469 435 * return. 470 436 */ 471 static int rt TcpServerListen(PRTTCPSERVER pServer)472 { 473 /* 474 * Accept connectionloop.437 static int rtUdpServerListen(PRTUDPSERVER pServer) 438 { 439 /* 440 * Wait for incoming datagrams loop. 475 441 */ 476 442 for (;;) … … 480 446 * allow others to close it while we're stuck in rtSocketAccept. 481 447 */ 482 RTTCPSERVERSTATE enmState = pServer->enmState; 483 RTSOCKET hServerSocket; 484 ASMAtomicXchgHandle(&pServer->hServerSocket, NIL_RTSOCKET, &hServerSocket); 485 if (hServerSocket != NIL_RTSOCKET) 486 { 487 RTSocketRetain(hServerSocket); 488 ASMAtomicWriteHandle(&pServer->hServerSocket, hServerSocket); 489 } 490 if ( enmState != RTTCPSERVERSTATE_ACCEPTING 491 && enmState != RTTCPSERVERSTATE_SERVING) 492 { 493 RTSocketRelease(hServerSocket); 494 return rtTcpServerListenCleanup(pServer); 495 } 496 if (!rtTcpServerTrySetState(pServer, RTTCPSERVERSTATE_ACCEPTING, enmState)) 497 { 498 RTSocketRelease(hServerSocket); 448 RTUDPSERVERSTATE enmState = pServer->enmState; 449 RTSOCKET hSocket; 450 ASMAtomicReadHandle(&pServer->hSocket, &hSocket); 451 if (hSocket != NIL_RTSOCKET) 452 RTSocketRetain(hSocket); 453 if ( enmState != RTUDPSERVERSTATE_WAITING 454 && enmState != RTUDPSERVERSTATE_RECEIVING) 455 { 456 RTSocketRelease(hSocket); 457 return rtUdpServerListenCleanup(pServer); 458 } 459 if (!rtUdpServerTrySetState(pServer, RTUDPSERVERSTATE_WAITING, enmState)) 460 { 461 RTSocketRelease(hSocket); 499 462 continue; 500 463 } 501 464 502 465 /* 503 * Accept connection.466 * Wait for incoming datagrams or errors. 504 467 */ 505 struct sockaddr_in RemoteAddr; 506 size_t cbRemoteAddr = sizeof(RemoteAddr); 507 RTSOCKET hClientSocket; 508 RT_ZERO(RemoteAddr); 509 int rc = rtSocketAccept(hServerSocket, &hClientSocket, (struct sockaddr *)&RemoteAddr, &cbRemoteAddr); 510 RTSocketRelease(hServerSocket); 468 uint32_t fEvents; 469 int rc = RTSocketSelectOneEx(hSocket, RTSOCKET_EVT_READ | RTSOCKET_EVT_ERROR, &fEvents, 1000); 470 RTSocketRelease(hSocket); 471 if (rc == VERR_TIMEOUT) 472 continue; 511 473 if (RT_FAILURE(rc)) 512 474 { … … 515 477 || rc == VERR_INVALID_PARAMETER 516 478 || rc == VERR_NET_NOT_SOCKET) 517 return rt TcpServerListenCleanup(pServer);479 return rtUdpServerListenCleanup(pServer); 518 480 continue; 519 481 } 520 RTSocketSetInheritance(hClientSocket, false /*fInheritable*/); 482 if (fEvents & RTSOCKET_EVT_ERROR) 483 return rtUdpServerListenCleanup(pServer); 521 484 522 485 /* 523 486 * Run a pfnServe callback. 524 487 */ 525 if (!rtTcpServerTrySetState(pServer, RTTCPSERVERSTATE_SERVING, RTTCPSERVERSTATE_ACCEPTING)) 526 { 527 rtTcpClose(hClientSocket, "rtTcpServerListen", true /*fTryGracefulShutdown*/); 528 return rtTcpServerListenCleanup(pServer); 529 } 530 RTSocketRetain(hClientSocket); 531 rtTcpAtomicXchgSock(&pServer->hClientSocket, hClientSocket); 532 rc = pServer->pfnServe(hClientSocket, pServer->pvUser); 533 rtTcpServerDestroySocket(&pServer->hClientSocket, "Listener: client (secondary)", true /*fTryGracefulShutdown*/); 534 RTSocketRelease(hClientSocket); 488 if (!rtUdpServerTrySetState(pServer, RTUDPSERVERSTATE_RECEIVING, RTUDPSERVERSTATE_WAITING)) 489 return rtUdpServerListenCleanup(pServer); 490 rc = pServer->pfnServe(hSocket, pServer->pvUser); 535 491 536 492 /* 537 493 * Stop the server? 538 494 */ 539 if (rc == VERR_ TCP_SERVER_STOP)540 { 541 if (rt TcpServerTrySetState(pServer, RTTCPSERVERSTATE_STOPPING, RTTCPSERVERSTATE_SERVING))495 if (rc == VERR_UDP_SERVER_STOP) 496 { 497 if (rtUdpServerTrySetState(pServer, RTUDPSERVERSTATE_STOPPING, RTUDPSERVERSTATE_RECEIVING)) 542 498 { 543 499 /* … … 545 501 * we cannot safely access the handle so we'll have to return here. 546 502 */ 547 hS erverSocket = rtTcpAtomicXchgSock(&pServer->hServerSocket, NIL_RTSOCKET);548 rt TcpServerSetState(pServer, RTTCPSERVERSTATE_STOPPED, RTTCPSERVERSTATE_STOPPING);549 rt TcpClose(hServerSocket, "Listener: server stopped", false /*fTryGracefulShutdown*/);503 hSocket = rtUdpAtomicXchgSock(&pServer->hSocket, NIL_RTSOCKET); 504 rtUdpServerSetState(pServer, RTUDPSERVERSTATE_STOPPED, RTUDPSERVERSTATE_STOPPING); 505 rtUdpClose(hSocket, "Listener: server stopped"); 550 506 } 551 507 else 552 rt TcpServerListenCleanup(pServer); /* ignore rc */508 rtUdpServerListenCleanup(pServer); /* ignore rc */ 553 509 return rc; 554 510 } … … 560 516 * Clean up after listener. 561 517 */ 562 static int rtTcpServerListenCleanup(PRTTCPSERVER pServer) 563 { 564 /* 565 * Close the server socket, the client one shouldn't be set. 566 */ 567 rtTcpServerDestroySocket(&pServer->hServerSocket, "ListenCleanup", false /*fTryGracefulShutdown*/); 568 Assert(pServer->hClientSocket == NIL_RTSOCKET); 518 static int rtUdpServerListenCleanup(PRTUDPSERVER pServer) 519 { 520 /* 521 * Close the server socket. 522 */ 523 rtUdpServerDestroySocket(&pServer->hSocket, "ListenCleanup"); 569 524 570 525 /* 571 526 * Figure the return code and make sure the state is OK. 572 527 */ 573 RT TCPSERVERSTATE enmState = pServer->enmState;528 RTUDPSERVERSTATE enmState = pServer->enmState; 574 529 switch (enmState) 575 530 { 576 case RT TCPSERVERSTATE_STOPPING:577 case RT TCPSERVERSTATE_STOPPED:578 return VERR_ TCP_SERVER_SHUTDOWN;579 580 case RT TCPSERVERSTATE_ACCEPTING:581 rt TcpServerTrySetState(pServer, RTTCPSERVERSTATE_STOPPED, enmState);582 return VERR_ TCP_SERVER_DESTROYED;583 584 case RT TCPSERVERSTATE_DESTROYING:585 return VERR_ TCP_SERVER_DESTROYED;586 587 case RT TCPSERVERSTATE_STARTING:588 case RT TCPSERVERSTATE_SERVING:531 case RTUDPSERVERSTATE_STOPPING: 532 case RTUDPSERVERSTATE_STOPPED: 533 return VERR_UDP_SERVER_SHUTDOWN; 534 535 case RTUDPSERVERSTATE_WAITING: 536 rtUdpServerTrySetState(pServer, RTUDPSERVERSTATE_STOPPED, enmState); 537 return VERR_UDP_SERVER_DESTROYED; 538 539 case RTUDPSERVERSTATE_DESTROYING: 540 return VERR_UDP_SERVER_DESTROYED; 541 542 case RTUDPSERVERSTATE_STARTING: 543 case RTUDPSERVERSTATE_RECEIVING: 589 544 default: 590 545 AssertMsgFailedReturn(("pServer=%p enmState=%d\n", pServer, enmState), VERR_INTERNAL_ERROR_4); … … 594 549 595 550 /** 596 * Listen and accept one incoming connection. 597 * 598 * This is an alternative to RTTcpServerListen for the use the callbacks are not 599 * possible. 600 * 601 * @returns IPRT status code. 602 * @retval VERR_TCP_SERVER_SHUTDOWN if shut down by RTTcpServerShutdown. 603 * @retval VERR_INTERRUPTED if the listening was interrupted. 604 * 605 * @param pServer The server handle as returned from RTTcpServerCreateEx(). 606 * @param phClientSocket Where to return the socket handle to the client 607 * connection (on success only). This must be closed 608 * by calling RTTcpServerDisconnectClient2(). 609 */ 610 RTR3DECL(int) RTTcpServerListen2(PRTTCPSERVER pServer, PRTSOCKET phClientSocket) 611 { 612 /* 613 * Validate input and retain the instance. 614 */ 615 AssertPtrReturn(phClientSocket, VERR_INVALID_HANDLE); 616 *phClientSocket = NIL_RTSOCKET; 617 AssertReturn(pServer->u32Magic == RTTCPSERVER_MAGIC, VERR_INVALID_HANDLE); 618 AssertReturn(RTMemPoolRetain(pServer) != UINT32_MAX, VERR_INVALID_HANDLE); 619 620 int rc = VERR_INVALID_STATE; 621 for (;;) 622 { 623 /* 624 * Change state, getting an extra reference to the socket so we can 625 * allow others to close it while we're stuck in rtSocketAccept. 626 */ 627 RTTCPSERVERSTATE enmState = pServer->enmState; 628 RTSOCKET hServerSocket; 629 ASMAtomicXchgHandle(&pServer->hServerSocket, NIL_RTSOCKET, &hServerSocket); 630 if (hServerSocket != NIL_RTSOCKET) 631 { 632 RTSocketRetain(hServerSocket); 633 ASMAtomicWriteHandle(&pServer->hServerSocket, hServerSocket); 634 } 635 if ( enmState != RTTCPSERVERSTATE_SERVING 636 && enmState != RTTCPSERVERSTATE_CREATED) 637 { 638 RTSocketRelease(hServerSocket); 639 return rtTcpServerListenCleanup(pServer); 640 } 641 if (!rtTcpServerTrySetState(pServer, RTTCPSERVERSTATE_ACCEPTING, enmState)) 642 { 643 RTSocketRelease(hServerSocket); 644 continue; 645 } 646 Assert(!pServer->pfnServe); 647 Assert(!pServer->pvUser); 648 Assert(pServer->Thread == NIL_RTTHREAD); 649 Assert(pServer->hClientSocket == NIL_RTSOCKET); 650 651 /* 652 * Accept connection. 653 */ 654 struct sockaddr_in RemoteAddr; 655 size_t cbRemoteAddr = sizeof(RemoteAddr); 656 RTSOCKET hClientSocket; 657 RT_ZERO(RemoteAddr); 658 rc = rtSocketAccept(hServerSocket, &hClientSocket, (struct sockaddr *)&RemoteAddr, &cbRemoteAddr); 659 RTSocketRelease(hServerSocket); 660 if (RT_FAILURE(rc)) 661 { 662 if (!rtTcpServerTrySetState(pServer, RTTCPSERVERSTATE_CREATED, RTTCPSERVERSTATE_ACCEPTING)) 663 rc = rtTcpServerListenCleanup(pServer); 664 if (RT_FAILURE(rc)) 665 break; 666 continue; 667 } 668 RTSocketSetInheritance(hClientSocket, false /*fInheritable*/); 669 670 /* 671 * Chance to the 'serving' state and return the socket. 672 */ 673 if (rtTcpServerTrySetState(pServer, RTTCPSERVERSTATE_SERVING, RTTCPSERVERSTATE_ACCEPTING)) 674 { 675 *phClientSocket = hClientSocket; 676 rc = VINF_SUCCESS; 677 } 678 else 679 { 680 rtTcpClose(hClientSocket, "RTTcpServerListen2", true /*fTryGracefulShutdown*/); 681 rc = rtTcpServerListenCleanup(pServer); 682 } 683 break; 684 } 685 686 RTMemPoolRelease(RTMEMPOOL_DEFAULT, pServer); 687 return rc; 688 } 689 690 691 /** 692 * Terminate the open connection to the server. 693 * 694 * @returns iprt status code. 695 * @param pServer Handle to the server. 696 */ 697 RTR3DECL(int) RTTcpServerDisconnectClient(PRTTCPSERVER pServer) 698 { 699 /* 700 * Validate input and retain the instance. 701 */ 702 AssertPtrReturn(pServer, VERR_INVALID_HANDLE); 703 AssertReturn(pServer->u32Magic == RTTCPSERVER_MAGIC, VERR_INVALID_HANDLE); 704 AssertReturn(RTMemPoolRetain(pServer) != UINT32_MAX, VERR_INVALID_HANDLE); 705 706 int rc = rtTcpServerDestroySocket(&pServer->hClientSocket, "DisconnectClient: client", true /*fTryGracefulShutdown*/); 707 708 RTMemPoolRelease(RTMEMPOOL_DEFAULT, pServer); 709 return rc; 710 } 711 712 713 /** 714 * Terminates an open client connect when using RTTcpListen2 715 * 716 * @returns IPRT status code. 717 * @param hClientSocket The client socket handle. This will be invalid upon 718 * return, whether successful or not. NIL is quietly 719 * ignored (VINF_SUCCESS). 720 */ 721 RTR3DECL(int) RTTcpServerDisconnectClient2(RTSOCKET hClientSocket) 722 { 723 return rtTcpClose(hClientSocket, "RTTcpServerDisconnectClient2", true /*fTryGracefulShutdown*/); 724 } 725 726 727 /** 728 * Shuts down the server, leaving client connections open. 551 * Shuts down the server. 729 552 * 730 553 * @returns IPRT status code. 731 554 * @param pServer Handle to the server. 732 555 */ 733 RTR3DECL(int) RT TcpServerShutdown(PRTTCPSERVER pServer)556 RTR3DECL(int) RTUdpServerShutdown(PRTUDPSERVER pServer) 734 557 { 735 558 /* … … 737 560 */ 738 561 AssertPtrReturn(pServer, VERR_INVALID_HANDLE); 739 AssertReturn(pServer->u32Magic == RT TCPSERVER_MAGIC, VERR_INVALID_HANDLE);562 AssertReturn(pServer->u32Magic == RTUDPSERVER_MAGIC, VERR_INVALID_HANDLE); 740 563 AssertReturn(RTMemPoolRetain(pServer) != UINT32_MAX, VERR_INVALID_HANDLE); 741 564 … … 745 568 for (;;) 746 569 { 747 RT TCPSERVERSTATE enmState = pServer->enmState;748 if ( enmState != RT TCPSERVERSTATE_ACCEPTING749 && enmState != RT TCPSERVERSTATE_SERVING)570 RTUDPSERVERSTATE enmState = pServer->enmState; 571 if ( enmState != RTUDPSERVERSTATE_WAITING 572 && enmState != RTUDPSERVERSTATE_RECEIVING) 750 573 { 751 574 RTMemPoolRelease(RTMEMPOOL_DEFAULT, pServer); 752 575 switch (enmState) 753 576 { 754 case RT TCPSERVERSTATE_CREATED:755 case RT TCPSERVERSTATE_STARTING:577 case RTUDPSERVERSTATE_CREATED: 578 case RTUDPSERVERSTATE_STARTING: 756 579 default: 757 580 AssertMsgFailed(("%d\n", enmState)); 758 581 return VERR_INVALID_STATE; 759 582 760 case RT TCPSERVERSTATE_STOPPING:761 case RT TCPSERVERSTATE_STOPPED:583 case RTUDPSERVERSTATE_STOPPING: 584 case RTUDPSERVERSTATE_STOPPED: 762 585 return VINF_SUCCESS; 763 586 764 case RT TCPSERVERSTATE_DESTROYING:765 return VERR_ TCP_SERVER_DESTROYED;587 case RTUDPSERVERSTATE_DESTROYING: 588 return VERR_UDP_SERVER_DESTROYED; 766 589 } 767 590 } 768 if (rt TcpServerTrySetState(pServer, RTTCPSERVERSTATE_STOPPING, enmState))769 { 770 rt TcpServerDestroySocket(&pServer->hServerSocket, "RTTcpServerShutdown", false /*fTryGracefulShutdown*/);771 rt TcpServerSetState(pServer, RTTCPSERVERSTATE_STOPPED, RTTCPSERVERSTATE_STOPPING);591 if (rtUdpServerTrySetState(pServer, RTUDPSERVERSTATE_STOPPING, enmState)) 592 { 593 rtUdpServerDestroySocket(&pServer->hSocket, "RTUdpServerShutdown"); 594 rtUdpServerSetState(pServer, RTUDPSERVERSTATE_STOPPED, RTUDPSERVERSTATE_STOPPING); 772 595 773 596 RTMemPoolRelease(RTMEMPOOL_DEFAULT, pServer); … … 779 602 780 603 /** 781 * Closes down and frees a TCP Server. 782 * This will also terminate any open connections to the server. 604 * Closes down and frees a UDP Server. 783 605 * 784 606 * @returns iprt status code. 785 607 * @param pServer Handle to the server. 786 608 */ 787 RTR3DECL(int) RT TcpServerDestroy(PRTTCPSERVER pServer)609 RTR3DECL(int) RTUdpServerDestroy(PRTUDPSERVER pServer) 788 610 { 789 611 /* … … 791 613 */ 792 614 AssertPtrReturn(pServer, VERR_INVALID_HANDLE); 793 AssertReturn(pServer->u32Magic == RT TCPSERVER_MAGIC, VERR_INVALID_HANDLE);615 AssertReturn(pServer->u32Magic == RTUDPSERVER_MAGIC, VERR_INVALID_HANDLE); 794 616 AssertReturn(RTMemPoolRetain(pServer) != UINT32_MAX, VERR_INVALID_HANDLE); /* paranoia */ 795 617 … … 800 622 { 801 623 bool fDestroyable; 802 RT TCPSERVERSTATE enmState = pServer->enmState;624 RTUDPSERVERSTATE enmState = pServer->enmState; 803 625 switch (enmState) 804 626 { 805 case RT TCPSERVERSTATE_STARTING:806 case RT TCPSERVERSTATE_ACCEPTING:807 case RT TCPSERVERSTATE_SERVING:808 case RT TCPSERVERSTATE_CREATED:809 case RT TCPSERVERSTATE_STOPPED:810 fDestroyable = rt TcpServerTrySetState(pServer, RTTCPSERVERSTATE_DESTROYING, enmState);627 case RTUDPSERVERSTATE_STARTING: 628 case RTUDPSERVERSTATE_WAITING: 629 case RTUDPSERVERSTATE_RECEIVING: 630 case RTUDPSERVERSTATE_CREATED: 631 case RTUDPSERVERSTATE_STOPPED: 632 fDestroyable = rtUdpServerTrySetState(pServer, RTUDPSERVERSTATE_DESTROYING, enmState); 811 633 break; 812 634 813 635 /* destroyable states */ 814 case RT TCPSERVERSTATE_STOPPING:636 case RTUDPSERVERSTATE_STOPPING: 815 637 fDestroyable = true; 816 638 break; … … 831 653 * Destroy it. 832 654 */ 833 ASMAtomicWriteU32(&pServer->u32Magic, ~RTTCPSERVER_MAGIC); 834 rtTcpServerDestroySocket(&pServer->hServerSocket, "Destroyer: server", false /*fTryGracefulShutdown*/); 835 rtTcpServerDestroySocket(&pServer->hClientSocket, "Destroyer: client", true /*fTryGracefulShutdown*/); 655 ASMAtomicWriteU32(&pServer->u32Magic, ~RTUDPSERVER_MAGIC); 656 rtUdpServerDestroySocket(&pServer->hSocket, "Destroyer: server"); 836 657 837 658 /* … … 844 665 845 666 846 RTR3DECL(int) RTTcpClientConnect(const char *pszAddress, uint32_t uPort, PRTSOCKET pSock)847 {848 int rc;849 850 /*851 * Validate input.852 */853 AssertReturn(uPort > 0, VERR_INVALID_PARAMETER);854 AssertPtrReturn(pszAddress, VERR_INVALID_POINTER);855 856 #ifdef RT_OS_WINDOWS857 /*858 * Initialize WinSock and check version.859 */860 WORD wVersionRequested = MAKEWORD(1, 1);861 WSADATA wsaData;862 rc = WSAStartup(wVersionRequested, &wsaData);863 if (wsaData.wVersion != wVersionRequested)864 {865 AssertMsgFailed(("Wrong winsock version\n"));866 return VERR_NOT_SUPPORTED;867 }868 #endif869 870 /*871 * Resolve the address.872 */873 struct hostent *pHostEnt = NULL;874 pHostEnt = gethostbyname(pszAddress);875 if (!pHostEnt)876 {877 struct in_addr InAddr;878 InAddr.s_addr = inet_addr(pszAddress);879 pHostEnt = gethostbyaddr((char *)&InAddr, 4, AF_INET);880 if (!pHostEnt)881 {882 rc = rtSocketResolverError();883 AssertMsgFailed(("Could not resolve '%s', rc=%Rrc\n", pszAddress, rc));884 return rc;885 }886 }887 888 /*889 * Create the socket and connect.890 */891 RTSOCKET Sock;892 rc = rtSocketCreate(&Sock, PF_INET, SOCK_STREAM, 0);893 if (RT_SUCCESS(rc))894 {895 RTSocketSetInheritance(Sock, false /*fInheritable*/);896 897 struct sockaddr_in InAddr;898 RT_ZERO(InAddr);899 InAddr.sin_family = AF_INET;900 InAddr.sin_port = htons(uPort);901 InAddr.sin_addr = *((struct in_addr *)pHostEnt->h_addr);902 rc = rtSocketConnect(Sock, (struct sockaddr *)&InAddr, sizeof(InAddr));903 if (RT_SUCCESS(rc))904 {905 *pSock = Sock;906 return VINF_SUCCESS;907 }908 909 rtTcpClose(Sock, "RTTcpClientConnect", false /*fTryGracefulShutdown*/);910 }911 return rc;912 }913 914 915 RTR3DECL(int) RTTcpClientClose(RTSOCKET Sock)916 {917 return rtTcpClose(Sock, "RTTcpClientClose", true /*fTryGracefulShutdown*/);918 }919 920 921 RTR3DECL(int) RTTcpClientCloseEx(RTSOCKET Sock, bool fGracefulShutdown)922 {923 return rtTcpClose(Sock, "RTTcpClientCloseEx", fGracefulShutdown);924 }925 926 927 #ifdef FIX_FOR_3_2928 /**929 * Changes the blocking mode of the socket.930 *931 * @returns 0 on success, -1 on failure.932 * @param hSocket The socket to work on.933 * @param fBlocking The desired mode of operation.934 */935 static int rtTcpSetBlockingMode(RTHCUINTPTR hSocket, bool fBlocking)936 {937 int rc = VINF_SUCCESS;938 #ifdef RT_OS_WINDOWS939 u_long uBlocking = fBlocking ? 0 : 1;940 if (ioctlsocket(hSocket, FIONBIO, &uBlocking))941 return -1;942 943 #else944 int fFlags = fcntl(hSocket, F_GETFL, 0);945 if (fFlags == -1)946 return -1;947 948 if (fBlocking)949 fFlags &= ~O_NONBLOCK;950 else951 fFlags |= O_NONBLOCK;952 if (fcntl(hSocket, F_SETFL, fFlags) == -1)953 return -1;954 #endif955 956 return 0;957 }958 #endif959 960 961 667 /** 962 668 * Internal close function which does all the proper bitching. 963 669 */ 964 static int rt TcpClose(RTSOCKET Sock, const char *pszMsg, bool fTryGracefulShutdown)670 static int rtUdpClose(RTSOCKET Sock, const char *pszMsg) 965 671 { 966 672 int rc; … … 971 677 972 678 /* 973 * Try to gracefully shut it down.974 */975 if (fTryGracefulShutdown)976 {977 rc = RTSocketShutdown(Sock, false /*fRead*/, true /*fWrite*/);978 #ifdef FIX_FOR_3_2979 RTHCUINTPTR hNative = RTSocketToNative(Sock);980 if (RT_SUCCESS(rc) && rtTcpSetBlockingMode(hNative, false /*fBlocking*/) == 0)981 #else982 if (RT_SUCCESS(rc))983 #endif984 {985 986 size_t cbReceived = 0;987 uint64_t u64Start = RTTimeMilliTS();988 while ( cbReceived < _1G989 && RTTimeMilliTS() - u64Start < 30000)990 {991 #ifdef FIX_FOR_3_2992 fd_set FdSetR;993 FD_ZERO(&FdSetR);994 FD_SET(hNative, &FdSetR);995 996 fd_set FdSetE;997 FD_ZERO(&FdSetE);998 FD_SET(hNative, &FdSetE);999 1000 struct timeval TvTimeout;1001 TvTimeout.tv_sec = 1;1002 TvTimeout.tv_usec = 0;1003 rc = select(hNative + 1, &FdSetR, NULL, &FdSetE, &TvTimeout);1004 if (rc == 0)1005 continue;1006 if (rc < 0)1007 break;1008 if (FD_ISSET(hNative, &FdSetE))1009 break;1010 #else1011 uint32_t fEvents;1012 rc = RTSocketSelectOneEx(Sock, RTSOCKET_EVT_READ | RTSOCKET_EVT_ERROR, &fEvents, 1000);1013 if (rc == VERR_TIMEOUT)1014 continue;1015 if (RT_FAILURE(rc))1016 break;1017 if (fEvents & RTSOCKET_EVT_ERROR)1018 break;1019 #endif1020 1021 char abBitBucket[16*_1K];1022 #ifdef FIX_FOR_3_21023 ssize_t cbRead = recv(hNative, &abBitBucket[0], sizeof(abBitBucket), MSG_NOSIGNAL);1024 if (cbRead == 0)1025 break; /* orderly shutdown in progress */1026 if (cbRead < 0 && errno != EAGAIN)1027 break; /* some kind of error, never mind which... */1028 #else1029 size_t cbRead;1030 rc = RTSocketReadNB(Sock, &abBitBucket[0], sizeof(abBitBucket), &cbRead);1031 if (RT_FAILURE(rc))1032 break; /* some kind of error, never mind which... */1033 if (rc != VINF_TRY_AGAIN && !cbRead)1034 break; /* orderly shutdown in progress */1035 #endif1036 1037 cbReceived += cbRead;1038 }1039 }1040 }1041 1042 /*1043 679 * Close the socket handle (drops our reference to it). 1044 680 */ … … 1047 683 1048 684 1049 RTR3DECL(int) RTTcpRead(RTSOCKET Sock, void *pvBuffer, size_t cbBuffer, size_t *pcbRead) 1050 { 1051 return RTSocketRead(Sock, pvBuffer, cbBuffer, pcbRead); 1052 } 1053 1054 1055 RTR3DECL(int) RTTcpWrite(RTSOCKET Sock, const void *pvBuffer, size_t cbBuffer) 1056 { 1057 return RTSocketWrite(Sock, pvBuffer, cbBuffer); 1058 } 1059 1060 1061 RTR3DECL(int) RTTcpFlush(RTSOCKET Sock) 1062 { 1063 int fFlag = 1; 1064 int rc = rtSocketSetOpt(Sock, IPPROTO_TCP, TCP_NODELAY, &fFlag, sizeof(fFlag)); 685 RTR3DECL(int) RTUdpRead(RTSOCKET Sock, void *pvBuffer, size_t cbBuffer, size_t *pcbRead, PRTNETADDR pSrcAddr) 686 { 687 if (!RT_VALID_PTR(pcbRead)) 688 return VERR_INVALID_POINTER; 689 return RTSocketReadFrom(Sock, pvBuffer, cbBuffer, pcbRead, pSrcAddr); 690 } 691 692 693 RTR3DECL(int) RTUdpWrite(PRTUDPSERVER pServer, const void *pvBuffer, size_t cbBuffer, PCRTNETADDR pDstAddr) 694 { 695 /* 696 * Validate input and retain the instance. 697 */ 698 AssertPtrReturn(pServer, VERR_INVALID_HANDLE); 699 AssertReturn(pServer->u32Magic == RTUDPSERVER_MAGIC, VERR_INVALID_HANDLE); 700 AssertReturn(RTMemPoolRetain(pServer) != UINT32_MAX, VERR_INVALID_HANDLE); 701 702 RTSOCKET hSocket; 703 ASMAtomicReadHandle(&pServer->hSocket, &hSocket); 704 if (hSocket == NIL_RTSOCKET) 705 { 706 RTMemPoolRelease(RTMEMPOOL_DEFAULT, pServer); 707 return VERR_INVALID_HANDLE; 708 } 709 RTSocketRetain(hSocket); 710 711 int rc = VINF_SUCCESS; 712 RTUDPSERVERSTATE enmState = pServer->enmState; 713 if ( enmState != RTUDPSERVERSTATE_CREATED 714 && enmState != RTUDPSERVERSTATE_STARTING 715 && enmState != RTUDPSERVERSTATE_WAITING 716 && enmState != RTUDPSERVERSTATE_RECEIVING 717 && enmState != RTUDPSERVERSTATE_STOPPING) 718 rc = VERR_INVALID_STATE; 719 1065 720 if (RT_SUCCESS(rc)) 1066 { 1067 fFlag = 0; 1068 rc = rtSocketSetOpt(Sock, IPPROTO_TCP, TCP_NODELAY, &fFlag, sizeof(fFlag)); 1069 } 721 rc = RTSocketWriteTo(hSocket, pvBuffer, cbBuffer, pDstAddr); 722 723 RTSocketRelease(hSocket); 724 RTMemPoolRelease(RTMEMPOOL_DEFAULT, pServer); 725 1070 726 return rc; 1071 727 } 1072 728 1073 1074 RTR3DECL(int) RTTcpSetSendCoalescing(RTSOCKET Sock, bool fEnable)1075 {1076 int fFlag = fEnable ? 0 : 1;1077 return rtSocketSetOpt(Sock, IPPROTO_TCP, TCP_NODELAY, &fFlag, sizeof(fFlag));1078 }1079 1080 1081 RTR3DECL(int) RTTcpSelectOne(RTSOCKET Sock, RTMSINTERVAL cMillies)1082 {1083 return RTSocketSelectOne(Sock, cMillies);1084 }1085 1086 1087 RTR3DECL(int) RTTcpSelectOneEx(RTSOCKET Sock, uint32_t fEvents, uint32_t *pfEvents,1088 RTMSINTERVAL cMillies)1089 {1090 return RTSocketSelectOneEx(Sock, fEvents, pfEvents, cMillies);1091 }1092 1093 1094 RTR3DECL(int) RTTcpGetLocalAddress(RTSOCKET Sock, PRTNETADDR pAddr)1095 {1096 return RTSocketGetLocalAddress(Sock, pAddr);1097 }1098 1099 1100 RTR3DECL(int) RTTcpGetPeerAddress(RTSOCKET Sock, PRTNETADDR pAddr)1101 {1102 return RTSocketGetPeerAddress(Sock, pAddr);1103 }1104 1105 1106 RTR3DECL(int) RTTcpSgWrite(RTSOCKET Sock, PCRTSGBUF pSgBuf)1107 {1108 return RTSocketSgWrite(Sock, pSgBuf);1109 }1110 1111 1112 RTR3DECL(int) RTTcpSgWriteL(RTSOCKET hSocket, size_t cSegs, ...)1113 {1114 va_list va;1115 va_start(va, cSegs);1116 int rc = RTSocketSgWriteLV(hSocket, cSegs, va);1117 va_end(va);1118 return rc;1119 }1120 1121 1122 RTR3DECL(int) RTTcpSgWriteLV(RTSOCKET hSocket, size_t cSegs, va_list va)1123 {1124 return RTSocketSgWriteLV(hSocket, cSegs, va);1125 }1126 1127 1128 RTR3DECL(int) RTTcpReadNB(RTSOCKET Sock, void *pvBuffer, size_t cbBuffer, size_t *pcbRead)1129 {1130 return RTSocketReadNB(Sock, pvBuffer, cbBuffer, pcbRead);1131 }1132 1133 1134 RTR3DECL(int) RTTcpWriteNB(RTSOCKET Sock, const void *pvBuffer, size_t cbBuffer, size_t *pcbWritten)1135 {1136 return RTSocketWriteNB(Sock, pvBuffer, cbBuffer, pcbWritten);1137 }1138 1139 1140 RTR3DECL(int) RTTcpSgWriteNB(RTSOCKET Sock, PCRTSGBUF pSgBuf, size_t *pcbWritten)1141 {1142 return RTSocketSgWriteNB(Sock, pSgBuf, pcbWritten);1143 }1144 1145 1146 RTR3DECL(int) RTTcpSgWriteLNB(RTSOCKET hSocket, size_t cSegs, size_t *pcbWritten, ...)1147 {1148 va_list va;1149 va_start(va, pcbWritten);1150 int rc = RTSocketSgWriteLVNB(hSocket, cSegs, pcbWritten, va);1151 va_end(va);1152 return rc;1153 }1154 1155 1156 RTR3DECL(int) RTTcpSgWriteLVNB(RTSOCKET hSocket, size_t cSegs, size_t *pcbWritten, va_list va)1157 {1158 return RTSocketSgWriteLVNB(hSocket, cSegs, pcbWritten, va);1159 }1160
Note:
See TracChangeset
for help on using the changeset viewer.