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