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         if (dwWait != WAIT_OBJECT_0 && // server socket event
125             dwWait != WAIT_OBJECT_0+1) // client socket event
126         {
127             ok(0, "Unknown event received %ld\n", dwWait);
128             skip("ERROR: Connection timeout\n");
129             break;
130         }
131 
132         WSAEnumNetworkEvents(fSockets[dwWait-WAIT_OBJECT_0], fEvents[dwWait-WAIT_OBJECT_0], &WsaNetworkEvents);
133 
134         if ((WsaNetworkEvents.lNetworkEvents & FD_ACCEPT) != 0)
135         {// connection accepted
136             trace("Event FD_ACCEPT...\n");
137             ok(WsaNetworkEvents.iErrorCode[FD_ACCEPT_BIT] == 0, "Error on accept %d\n", WsaNetworkEvents.iErrorCode[FD_ACCEPT_BIT]);
138             if (WsaNetworkEvents.iErrorCode[FD_ACCEPT_BIT] == 0)
139             {
140                 addrsize = sizeof(addr_remote);
141                 sockaccept = accept(fSockets[dwWait - WAIT_OBJECT_0], (struct sockaddr*)&addr_remote, &addrsize);
142                 ok(sockaccept != INVALID_SOCKET, "ERROR: Connection accept function failed, error %d\n", WSAGetLastError());
143                 dwFlags |= FD_ACCEPT;
144             }
145         }
146 
147         if ((WsaNetworkEvents.lNetworkEvents & FD_CONNECT) != 0)
148         {// client connected
149             trace("Event FD_CONNECT...\n");
150             ok(WsaNetworkEvents.iErrorCode[FD_CONNECT_BIT] == 0, "Error on connect %d\n", WsaNetworkEvents.iErrorCode[FD_CONNECT_BIT]);
151             if (WsaNetworkEvents.iErrorCode[FD_CONNECT_BIT] == 0)
152             {
153                 len = sizeof(addr_con_loc);
154                 ok(getsockname(fSockets[dwWait - WAIT_OBJECT_0], (struct sockaddr*)&addr_con_loc, &len) == 0, "\n");
155                 dwFlags |= FD_CONNECT;
156             }
157         }
158     }
159     closesocket(sockaccept);
160     closesocket(ServerSocket);
161     closesocket(ClientSocket);
162 
163     /* same test but with waiting select and getsockname to return proper values */
164     ServerSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
165     ClientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
166 
167     if (ServerSocket == INVALID_SOCKET)
168     {
169         skip("ERROR: Server socket creation failed\n");
170         return;
171     }
172     if (ClientSocket == INVALID_SOCKET)
173     {
174         skip("ERROR: Client socket creation failed\n");
175         closesocket(ServerSocket);
176         return;
177     }
178     ent = gethostbyname("127.0.0.1");
179     if (ent == NULL)
180     {
181         ok(ent != NULL, "ERROR: gethostbyname '127.0.0.1' failed, trying 'localhost'\n");
182         ent = gethostbyname("localhost");
183 
184         if (ent == NULL)
185         {
186             skip("ERROR: gethostbyname 'localhost' failed\n");
187             goto done;
188         }
189     }
190 
191     server_addr_in.sin_family = AF_INET;
192     server_addr_in.sin_port = htons(SVR_PORT);
193     memcpy(&server_addr_in.sin_addr.S_un.S_addr, ent->h_addr_list[0], 4);
194 
195     // Server initialization.
196     trace("Initializing server and client connections ...\n");
197     ok(bind(ServerSocket, (struct sockaddr*)&server_addr_in, sizeof(server_addr_in)) == 0, "ERROR: server bind failed\n");
198     ok(ioctlsocket(ServerSocket, FIONBIO, &ulValue) == 0, "ERROR: server ioctlsocket FIONBIO failed\n");
199 
200     // Client initialization.
201     ok(ioctlsocket(ClientSocket, FIONBIO, &ulValue) == 0, "ERROR: client ioctlsocket FIONBIO failed\n");
202 
203     // listen
204     trace("Starting server listening mode ...\n");
205     ok(listen(ServerSocket, SOMAXCONN) == 0, "ERROR: cannot initialize server listen\n");
206 
207     memset(&timeval, 0, sizeof(timeval));
208     timeval.tv_usec = WAIT_TIMEOUT_;
209     dwFlags = 0;
210 
211     while (dwFlags != EXIT_FLAGS)
212     {
213         len = sizeof(addr_con_loc);
214         nSockNameRes = getsockname(ClientSocket, (struct sockaddr*)&addr_con_loc, &len);
215         if (dwFlags == 0 && !ConnectSent)
216         {
217             ok(nSockNameRes == SOCKET_ERROR, "ERROR: getsockname function failed, expected %d error %d\n", SOCKET_ERROR, nSockNameRes);
218             ok(WSAGetLastError() == WSAEINVAL, "ERROR: getsockname function failed, expected %ld error %d\n", WSAEINVAL, WSAGetLastError());
219             trace("Starting client to server connection ...\n");
220             // connect
221             nConRes = connect(ClientSocket, (struct sockaddr*)&server_addr_in, sizeof(server_addr_in));
222             ok(nConRes == SOCKET_ERROR, "ERROR: client connect() result is not SOCKET_ERROR\n");
223             ok(WSAGetLastError() == WSAEWOULDBLOCK, "ERROR: client connect() last error is not WSAEWOULDBLOCK\n");
224             ConnectSent = TRUE;
225             continue;
226         }
227         else
228         {
229             if (nSockNameRes != 0)
230                 ok(0, "ERROR: getsockname function failed, expected %d error %d\n", 0, nSockNameRes);
231             if (len != sizeof(addr_con_loc))
232                 ok(0, "ERROR: getsockname function wrong size, expected %d returned %d\n", sizeof(addr_con_loc), len);
233             if (addr_con_loc.sin_addr.s_addr != server_addr_in.sin_addr.s_addr)
234                 ok(0, "ERROR: getsockname function wrong addr, expected %lx returned %lx\n", server_addr_in.sin_addr.s_addr, addr_con_loc.sin_addr.s_addr);
235         }
236         if ((dwFlags & FD_ACCEPT) != 0)
237         {// client connected
238             trace("Select CONNECT...\n");
239             dwFlags |= FD_CONNECT;
240         }
241 
242         FD_ZERO(&select_rfds);
243         FD_ZERO(&select_wfds);
244         FD_ZERO(&select_efds);
245         FD_SET(ServerSocket, &select_rfds);
246         FD_SET(ClientSocket, &select_rfds);
247         FD_SET(ServerSocket, &select_wfds);
248         FD_SET(ClientSocket, &select_wfds);
249         FD_SET(ServerSocket, &select_efds);
250         FD_SET(ClientSocket, &select_efds);
251         if ((dwFlags & FD_ACCEPT) != 0)
252         {
253             FD_SET(sockaccept, &select_rfds);
254             FD_SET(sockaccept, &select_wfds);
255             FD_SET(sockaccept, &select_efds);
256         }
257         if (select(0, &select_rfds, &select_wfds, &select_efds, &timeval) != 0)
258         {// connection accepted
259             if (dwFlags == (FD_ACCEPT | FD_CONNECT))
260             {
261                 trace("Select ACCEPT&CONNECT...\n");
262                 ok(FD_ISSET(ClientSocket, &select_wfds), "ClientSocket is not writable\n");
263                 ok(FD_ISSET(sockaccept, &select_wfds), "sockaccept is not writable\n");
264                 ok(!FD_ISSET(ServerSocket, &select_rfds), "ServerSocket is readable\n");
265             }
266             if (dwFlags == FD_ACCEPT)
267             {
268                 trace("Select ACCEPT...\n");
269                 ok(!FD_ISSET(ClientSocket, &select_wfds), "ClientSocket is writable\n");
270                 ok(FD_ISSET(sockaccept, &select_wfds), "sockaccept is not writable\n");
271                 ok(FD_ISSET(ServerSocket, &select_rfds), "ServerSocket is not readable\n");
272             }
273             if (dwFlags == 0)
274             {
275                 if (FD_ISSET(ServerSocket, &select_rfds))
276                 {
277                     trace("Select ACCEPT...\n");
278                     addrsize = sizeof(addr_remote);
279                     sockaccept = accept(ServerSocket, (struct sockaddr*)&addr_remote, &addrsize);
280                     ok(sockaccept != INVALID_SOCKET, "ERROR: Connection accept function failed, error %d\n", WSAGetLastError());
281                     dwFlags |= FD_ACCEPT;
282                 }
283             }
284         }
285     }
286 
287 done:
288     WSACloseEvent(ServerEvent);
289     WSACloseEvent(ClientEvent);
290     closesocket(sockaccept);
291     closesocket(ServerSocket);
292     closesocket(ClientSocket);
293 
294     WSACleanup();
295 }
296