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