1 /* 2 * PROJECT: ReactOS api tests 3 * LICENSE: GPL - See COPYING in the top level directory 4 * PURPOSE: Test for WSAAsync 5 * PROGRAMMERS: Miroslav Mastny 6 */ 7 8 #include "ws2_32.h" 9 10 #define SVR_PORT 5000 11 #define WAIT_TIMEOUT_ 10000 12 #define EXIT_FLAGS (FD_ACCEPT|FD_CONNECT) 13 14 START_TEST(WSAAsync) 15 { 16 WSADATA WsaData; 17 SOCKET ServerSocket = INVALID_SOCKET, 18 ClientSocket = INVALID_SOCKET; 19 WSAEVENT ServerEvent = WSA_INVALID_EVENT, 20 ClientEvent = WSA_INVALID_EVENT; 21 struct hostent *ent = NULL; 22 struct sockaddr_in server_addr_in; 23 struct sockaddr_in addr_remote; 24 struct sockaddr_in addr_con_loc; 25 int nConRes, nSockNameRes; 26 int addrsize, len; 27 WSAEVENT fEvents[2]; 28 SOCKET fSockets[2]; 29 SOCKET sockaccept; 30 WSANETWORKEVENTS WsaNetworkEvents; 31 ULONG ulValue = 1; 32 DWORD dwWait; 33 DWORD dwFlags = 0; 34 struct fd_set select_rfds; 35 struct fd_set select_wfds; 36 struct fd_set select_efds; 37 struct timeval timeval; 38 BOOL ConnectSent = FALSE; 39 40 if (WSAStartup(MAKEWORD(2, 2), &WsaData) != 0) 41 { 42 skip("WSAStartup failed\n"); 43 return; 44 } 45 46 ServerSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 47 ClientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 48 ServerEvent = WSACreateEvent(); 49 ClientEvent = WSACreateEvent(); 50 51 if (ServerSocket == INVALID_SOCKET) 52 { 53 skip("ERROR: Server socket creation failed\n"); 54 return; 55 } 56 if (ClientSocket == INVALID_SOCKET) 57 { 58 skip("ERROR: Client socket creation failed\n"); 59 closesocket(ServerSocket); 60 return; 61 } 62 if (ServerEvent == WSA_INVALID_EVENT) 63 { 64 skip("ERROR: Server WSAEvent creation failed\n"); 65 closesocket(ClientSocket); 66 closesocket(ServerSocket); 67 return; 68 } 69 if (ClientEvent == WSA_INVALID_EVENT) 70 { 71 skip("ERROR: Client WSAEvent creation failed\n"); 72 WSACloseEvent(ServerEvent); 73 closesocket(ClientSocket); 74 closesocket(ServerSocket); 75 return; 76 } 77 ent = gethostbyname("127.0.0.1"); 78 if (ent == NULL) 79 { 80 ok(ent != NULL, "ERROR: gethostbyname '127.0.0.1' failed, trying 'localhost'\n"); 81 ent = gethostbyname("localhost"); 82 83 if (ent == NULL) 84 { 85 skip("ERROR: gethostbyname 'localhost' failed\n"); 86 goto done; 87 } 88 } 89 90 server_addr_in.sin_family = AF_INET; 91 server_addr_in.sin_port = htons(SVR_PORT); 92 memcpy(&server_addr_in.sin_addr.S_un.S_addr, ent->h_addr_list[0], 4); 93 94 // Server initialization. 95 trace("Initializing server and client connections ...\n"); 96 ok(bind(ServerSocket, (struct sockaddr*)&server_addr_in, sizeof(server_addr_in)) == 0, "ERROR: server bind failed\n"); 97 ok(ioctlsocket(ServerSocket, FIONBIO, &ulValue) == 0, "ERROR: server ioctlsocket FIONBIO failed\n"); 98 ok(WSAEventSelect(ServerSocket, ServerEvent, FD_ACCEPT | FD_CLOSE) == 0, "ERROR: server accept EventSelect failed\n"); 99 100 // Client initialization. 101 ok(WSAEventSelect(ClientSocket, ClientEvent, FD_CONNECT | FD_CLOSE) == 0, "ERROR: client EventSelect failed\n"); 102 ok(ioctlsocket(ClientSocket, FIONBIO, &ulValue) == 0, "ERROR: client ioctlsocket FIONBIO failed\n"); 103 104 // listen 105 trace("Starting server listening mode ...\n"); 106 ok(listen(ServerSocket, SOMAXCONN) == 0, "ERROR: cannot initialize server listen\n"); 107 108 trace("Starting client to server connection ...\n"); 109 // connect 110 nConRes = connect(ClientSocket, (struct sockaddr*)&server_addr_in, sizeof(server_addr_in)); 111 ok(nConRes == SOCKET_ERROR, "ERROR: client connect() result is not SOCKET_ERROR\n"); 112 ok(WSAGetLastError() == WSAEWOULDBLOCK, "ERROR: client connect() last error is not WSAEWOULDBLOCK\n"); 113 114 fSockets[0] = ServerSocket; 115 fSockets[1] = ClientSocket; 116 117 fEvents[0] = ServerEvent; 118 fEvents[1] = ClientEvent; 119 120 while (dwFlags != EXIT_FLAGS) 121 { 122 dwWait = WaitForMultipleObjects(2, fEvents, FALSE, WAIT_TIMEOUT_); 123 124 ok(dwWait == WAIT_OBJECT_0 || // server socket event 125 dwWait == WAIT_OBJECT_0+1, // client socket event 126 "Unknown event received %ld\n", dwWait); 127 if (dwWait != WAIT_OBJECT_0 && dwWait != WAIT_OBJECT_0+1) 128 { 129 skip("ERROR: Connection timeout\n"); 130 break; 131 } 132 133 WSAEnumNetworkEvents(fSockets[dwWait-WAIT_OBJECT_0], fEvents[dwWait-WAIT_OBJECT_0], &WsaNetworkEvents); 134 135 if ((WsaNetworkEvents.lNetworkEvents & FD_ACCEPT) != 0) 136 {// connection accepted 137 trace("Event FD_ACCEPT...\n"); 138 ok(WsaNetworkEvents.iErrorCode[FD_ACCEPT_BIT] == 0, "Error on accept %d\n", WsaNetworkEvents.iErrorCode[FD_ACCEPT_BIT]); 139 if (WsaNetworkEvents.iErrorCode[FD_ACCEPT_BIT] == 0) 140 { 141 addrsize = sizeof(addr_remote); 142 sockaccept = accept(fSockets[dwWait - WAIT_OBJECT_0], (struct sockaddr*)&addr_remote, &addrsize); 143 ok(sockaccept != INVALID_SOCKET, "ERROR: Connection accept function failed, error %d\n", WSAGetLastError()); 144 dwFlags |= FD_ACCEPT; 145 } 146 } 147 148 if ((WsaNetworkEvents.lNetworkEvents & FD_CONNECT) != 0) 149 {// client connected 150 trace("Event FD_CONNECT...\n"); 151 ok(WsaNetworkEvents.iErrorCode[FD_CONNECT_BIT] == 0, "Error on connect %d\n", WsaNetworkEvents.iErrorCode[FD_CONNECT_BIT]); 152 if (WsaNetworkEvents.iErrorCode[FD_CONNECT_BIT] == 0) 153 { 154 len = sizeof(addr_con_loc); 155 ok(getsockname(fSockets[dwWait - WAIT_OBJECT_0], (struct sockaddr*)&addr_con_loc, &len) == 0, "\n"); 156 dwFlags |= FD_CONNECT; 157 } 158 } 159 } 160 closesocket(sockaccept); 161 closesocket(ServerSocket); 162 closesocket(ClientSocket); 163 164 /* same test but with waiting select and getsockname to return proper values */ 165 ServerSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 166 ClientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 167 168 if (ServerSocket == INVALID_SOCKET) 169 { 170 skip("ERROR: Server socket creation failed\n"); 171 return; 172 } 173 if (ClientSocket == INVALID_SOCKET) 174 { 175 skip("ERROR: Client socket creation failed\n"); 176 closesocket(ServerSocket); 177 return; 178 } 179 ent = gethostbyname("127.0.0.1"); 180 if (ent == NULL) 181 { 182 ok(ent != NULL, "ERROR: gethostbyname '127.0.0.1' failed, trying 'localhost'\n"); 183 ent = gethostbyname("localhost"); 184 185 if (ent == NULL) 186 { 187 skip("ERROR: gethostbyname 'localhost' failed\n"); 188 goto done; 189 } 190 } 191 192 server_addr_in.sin_family = AF_INET; 193 server_addr_in.sin_port = htons(SVR_PORT); 194 memcpy(&server_addr_in.sin_addr.S_un.S_addr, ent->h_addr_list[0], 4); 195 196 // Server initialization. 197 trace("Initializing server and client connections ...\n"); 198 ok(bind(ServerSocket, (struct sockaddr*)&server_addr_in, sizeof(server_addr_in)) == 0, "ERROR: server bind failed\n"); 199 ok(ioctlsocket(ServerSocket, FIONBIO, &ulValue) == 0, "ERROR: server ioctlsocket FIONBIO failed\n"); 200 201 // Client initialization. 202 ok(ioctlsocket(ClientSocket, FIONBIO, &ulValue) == 0, "ERROR: client ioctlsocket FIONBIO failed\n"); 203 204 // listen 205 trace("Starting server listening mode ...\n"); 206 ok(listen(ServerSocket, SOMAXCONN) == 0, "ERROR: cannot initialize server listen\n"); 207 208 memset(&timeval, 0, sizeof(timeval)); 209 timeval.tv_usec = WAIT_TIMEOUT_; 210 dwFlags = 0; 211 212 while (dwFlags != EXIT_FLAGS) 213 { 214 len = sizeof(addr_con_loc); 215 nSockNameRes = getsockname(ClientSocket, (struct sockaddr*)&addr_con_loc, &len); 216 if (dwFlags == 0 && !ConnectSent) 217 { 218 ok(nSockNameRes == SOCKET_ERROR, "ERROR: getsockname function failed, expected %d error %d\n", SOCKET_ERROR, nSockNameRes); 219 ok(WSAGetLastError() == WSAEINVAL, "ERROR: getsockname function failed, expected %ld error %d\n", WSAEINVAL, WSAGetLastError()); 220 trace("Starting client to server connection ...\n"); 221 // connect 222 nConRes = connect(ClientSocket, (struct sockaddr*)&server_addr_in, sizeof(server_addr_in)); 223 ok(nConRes == SOCKET_ERROR, "ERROR: client connect() result is not SOCKET_ERROR\n"); 224 ok(WSAGetLastError() == WSAEWOULDBLOCK, "ERROR: client connect() last error is not WSAEWOULDBLOCK\n"); 225 ConnectSent = TRUE; 226 continue; 227 } 228 else 229 { 230 ok(nSockNameRes == 0, "ERROR: getsockname function failed, expected %d error %d\n", 0, nSockNameRes); 231 ok(len == sizeof(addr_con_loc), "ERROR: getsockname function wrong size, expected %d returned %d\n", sizeof(addr_con_loc), len); 232 ok(addr_con_loc.sin_addr.s_addr == server_addr_in.sin_addr.s_addr, "ERROR: getsockname function wrong addr, expected %lx returned %lx\n", server_addr_in.sin_addr.s_addr, addr_con_loc.sin_addr.s_addr); 233 } 234 if ((dwFlags & FD_ACCEPT) != 0) 235 {// client connected 236 trace("Select CONNECT...\n"); 237 dwFlags |= FD_CONNECT; 238 } 239 240 FD_ZERO(&select_rfds); 241 FD_ZERO(&select_wfds); 242 FD_ZERO(&select_efds); 243 FD_SET(ServerSocket, &select_rfds); 244 FD_SET(ClientSocket, &select_rfds); 245 FD_SET(ServerSocket, &select_wfds); 246 FD_SET(ClientSocket, &select_wfds); 247 FD_SET(ServerSocket, &select_efds); 248 FD_SET(ClientSocket, &select_efds); 249 if ((dwFlags & FD_ACCEPT) != 0) 250 { 251 FD_SET(sockaccept, &select_rfds); 252 FD_SET(sockaccept, &select_wfds); 253 FD_SET(sockaccept, &select_efds); 254 } 255 if (select(0, &select_rfds, &select_wfds, &select_efds, &timeval) != 0) 256 {// connection accepted 257 if (dwFlags == (FD_ACCEPT | FD_CONNECT)) 258 { 259 trace("Select ACCEPT&CONNECT...\n"); 260 ok(FD_ISSET(ClientSocket, &select_wfds), "ClientSocket is not writable\n"); 261 ok(FD_ISSET(sockaccept, &select_wfds), "sockaccept is not writable\n"); 262 ok(!FD_ISSET(ServerSocket, &select_rfds), "ServerSocket is readable\n"); 263 } 264 if (dwFlags == FD_ACCEPT) 265 { 266 trace("Select ACCEPT...\n"); 267 ok(!FD_ISSET(ClientSocket, &select_wfds), "ClientSocket is writable\n"); 268 ok(FD_ISSET(sockaccept, &select_wfds), "sockaccept is not writable\n"); 269 ok(FD_ISSET(ServerSocket, &select_rfds), "ServerSocket is not readable\n"); 270 } 271 if (dwFlags == 0) 272 { 273 if (FD_ISSET(ServerSocket, &select_rfds)) 274 { 275 trace("Select ACCEPT...\n"); 276 addrsize = sizeof(addr_remote); 277 sockaccept = accept(ServerSocket, (struct sockaddr*)&addr_remote, &addrsize); 278 ok(sockaccept != INVALID_SOCKET, "ERROR: Connection accept function failed, error %d\n", WSAGetLastError()); 279 dwFlags |= FD_ACCEPT; 280 } 281 } 282 } 283 } 284 285 done: 286 WSACloseEvent(ServerEvent); 287 WSACloseEvent(ClientEvent); 288 closesocket(sockaccept); 289 closesocket(ServerSocket); 290 closesocket(ClientSocket); 291 292 WSACleanup(); 293 } 294