1 /*
2 * PROJECT:         ReactOS api tests
3 * LICENSE:         GPL - See COPYING in the top level directory
4 * PURPOSE:         Test for nonblocking sockets
5 * PROGRAMMERS:     Peter Hater
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(nonblocking)
15 {
16     WSADATA    WsaData;
17     SOCKET     ServerSocket = INVALID_SOCKET,
18                ClientSocket = INVALID_SOCKET;
19     struct sockaddr_in server_addr_in;
20     struct sockaddr_in addr_remote;
21     struct sockaddr_in addr_con_loc;
22     int nConRes, err;
23     int addrsize;
24     SOCKET sockaccept;
25     ULONG ulValue = 1;
26     DWORD dwFlags = 0, dwLen, dwAddrLen;
27     fd_set readfds, writefds, exceptfds;
28     struct timeval tval = { 0 };
29     char address[100];
30 
31     if (!winetest_interactive)
32     {
33         skip("ROSTESTS-247: Skipping ws2_32_apitest:nonblocking because it times out on testbot\n");
34         return;
35     }
36 
37     if (WSAStartup(MAKEWORD(2, 2), &WsaData) != 0)
38     {
39         skip("WSAStartup failed\n");
40         return;
41     }
42 
43     ServerSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
44     ClientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
45 
46     if (ServerSocket == INVALID_SOCKET)
47     {
48         skip("ERROR: Server socket creation failed\n");
49         return;
50     }
51     if (ClientSocket == INVALID_SOCKET)
52     {
53         skip("ERROR: Client socket creation failed\n");
54         closesocket(ServerSocket);
55         return;
56     }
57     server_addr_in.sin_family = AF_INET;
58     server_addr_in.sin_addr.s_addr = INADDR_ANY;
59     server_addr_in.sin_port   = htons(SVR_PORT);
60 
61     // Server initialization.
62     trace("Initializing server and client connections ...\n");
63     err = bind(ServerSocket, (struct sockaddr*)&server_addr_in, sizeof(server_addr_in));
64     ok(err == 0, "ERROR: server bind failed\n");
65     err = ioctlsocket(ServerSocket, FIONBIO, &ulValue);
66     ok(err == 0, "ERROR: server ioctlsocket FIONBIO failed\n");
67 
68     // Client initialization.
69     err = ioctlsocket(ClientSocket, FIONBIO, &ulValue);
70     ok(err == 0, "ERROR: client ioctlsocket FIONBIO failed\n");
71 
72     // listen
73     trace("Starting server listening mode ...\n");
74     err = listen(ServerSocket, 2);
75     ok(err == 0, "ERROR: cannot initialize server listen\n");
76 
77     trace("Starting client to server connection ...\n");
78     // connect
79     server_addr_in.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
80     server_addr_in.sin_port = htons(SVR_PORT);
81     nConRes = connect(ClientSocket, (struct sockaddr*)&server_addr_in, sizeof(server_addr_in));
82     ok(nConRes == SOCKET_ERROR, "ERROR: client connect() result is not SOCKET_ERROR\n");
83     ok(WSAGetLastError() == WSAEWOULDBLOCK, "ERROR: client connect() last error is not WSAEWOULDBLOCK\n");
84     FD_ZERO(&readfds);
85     FD_ZERO(&writefds);
86     FD_ZERO(&exceptfds);
87     FD_SET(ServerSocket, &readfds);
88 
89     while (dwFlags != EXIT_FLAGS)
90     {
91         addrsize = sizeof(addr_con_loc);
92         err = getsockname(ClientSocket, (struct sockaddr*)&addr_con_loc, &addrsize);
93         if (err == 0)
94         {// client connected
95             dwLen = sizeof(addr_con_loc);
96             dwAddrLen = sizeof(address);
97             err = WSAAddressToStringA((PSOCKADDR)&addr_con_loc, dwLen, NULL, address, &dwAddrLen);
98             if (err == 0)
99             {
100                 trace("Event FD_CONNECT...\n");
101                 dwFlags |= FD_CONNECT;
102                 err = recv(ClientSocket, address, dwAddrLen, 0);
103                 ok(err == -1, "ERROR: error reading data from connected socket, error %d\n", WSAGetLastError());
104                 ok(WSAGetLastError() == WSAEWOULDBLOCK, "ERROR: client connect() last error is not WSAEWOULDBLOCK\n");
105                 err = send(ClientSocket, address, dwAddrLen, 0);
106                 ok(err == dwAddrLen, "ERROR: error writing data to connected socket, error %d %d\n", err, WSAGetLastError());
107             }
108             else
109             {
110                 trace("WSAAddressToStringA failed %d\n", WSAGetLastError());
111             }
112         }
113 
114         err = select(1, &readfds, &writefds, &exceptfds, &tval);
115         if (err == 1 && FD_ISSET(ServerSocket, &readfds))
116         {// connection ready to be accepted
117             trace("Event FD_ACCEPT...\n");
118             addrsize = sizeof(addr_remote);
119             sockaccept = accept(ServerSocket, (struct sockaddr*)&addr_remote, &addrsize);
120             ok(sockaccept != INVALID_SOCKET, "ERROR: Connection accept function failed, error %d\n", WSAGetLastError());
121             dwFlags |= FD_ACCEPT;
122             dwLen = sizeof(addr_remote);
123             dwAddrLen = sizeof(address);
124             err = WSAAddressToStringA((PSOCKADDR)&addr_remote, dwLen, NULL, address, &dwAddrLen);
125             ok(err == 0, "WSAAddressToStringA, error %d\n", WSAGetLastError());
126             ok(dwAddrLen > 7, "len <= 7\n");
127             err = send(sockaccept, address, dwAddrLen, 0);
128             ok(err == dwAddrLen, "ERROR: error sending data on accepted socket, error %d\n", WSAGetLastError());
129         }
130     }
131 
132     closesocket(sockaccept);
133     closesocket(ServerSocket);
134     closesocket(ClientSocket);
135 
136     WSACleanup();
137 }
138