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