2 * PROJECT: ReactOS API Tests
3 * LICENSE: GPL - See COPYING in the top level directory
4 * PURPOSE: Test for recv
5 * COPYRIGHT: Copyright 2008 Colin Finck (colin@reactos.org)
6 * Copyright 2010 Timo Kreuzer (timo.kreuzer@reactos.org)
7 * Copyright 2012 Cameron Gutman (cameron.gutman@reactos.org)
8 * Copyright 2023 Thomas Faber (thomas.faber@reactos.org)
13 #include <ndk/exfuncs.h>
14 #include <ndk/iofuncs.h>
15 #include <ndk/obfuncs.h>
19 /* For valid test results, the ReactOS Website needs to return at least 8 bytes on a "GET / HTTP/1.0" request.
20 Also the first 4 bytes and the last 4 bytes need to be different.
21 Both factors usually apply on standard HTTP responses. */
25 const char szDummyBytes
[RECV_BUF
] = {0xFF, 0x00, 0xFF, 0x00};
27 char szBuf1
[RECV_BUF
];
28 char szBuf2
[RECV_BUF
];
33 IO_STATUS_BLOCK readIosb
;
35 LARGE_INTEGER readOffset
;
37 /* Start up Winsock */
38 iResult
= WSAStartup(MAKEWORD(2, 2), &wdata
);
39 ok(iResult
== 0, "WSAStartup failed, iResult == %d\n", iResult
);
41 /* If we call recv without a socket, it should return with an error and do nothing. */
42 memcpy(szBuf1
, szDummyBytes
, RECV_BUF
);
43 iResult
= recv(0, szBuf1
, RECV_BUF
, 0);
44 ok(iResult
== SOCKET_ERROR
, "iRseult = %d\n", iResult
);
45 ok(!memcmp(szBuf1
, szDummyBytes
, RECV_BUF
), "not equal\n");
47 /* Create the socket */
48 if (!CreateSocket(&sck
))
50 ok(0, "CreateSocket failed. Aborting test.\n");
54 /* Now we can pass at least a socket, but we have no connection yet. Should return with an error and do nothing. */
55 memcpy(szBuf1
, szDummyBytes
, RECV_BUF
);
56 iResult
= recv(sck
, szBuf1
, RECV_BUF
, 0);
57 ok(iResult
== SOCKET_ERROR
, "iResult = %d\n", iResult
);
58 ok(!memcmp(szBuf1
, szDummyBytes
, RECV_BUF
), "not equal\n");
60 /* Connect to "www.reactos.org" */
61 if (!ConnectToReactOSWebsite(sck
))
63 ok(0, "ConnectToReactOSWebsite failed. Aborting test.\n");
67 /* Send the GET request */
68 if (!GetRequestAndWait(sck
))
70 ok(0, "GetRequestAndWait failed. Aborting test.\n");
75 MSG_PEEK will not change the internal number of bytes read, so that a subsequent request should return the same bytes again. */
76 SCKTEST(recv(sck
, szBuf1
, RECV_BUF
, MSG_PEEK
));
77 SCKTEST(recv(sck
, szBuf2
, RECV_BUF
, 0));
78 ok(!memcmp(szBuf1
, szBuf2
, RECV_BUF
), "not equal\n");
80 /* The last recv() call moved the internal file pointer, so that the next request should return different data. */
81 SCKTEST(recv(sck
, szBuf1
, RECV_BUF
, 0));
82 ok(memcmp(szBuf1
, szBuf2
, RECV_BUF
), "equal\n");
84 /* Create an event for NtReadFile */
85 readOffset
.QuadPart
= 0LL;
86 memcpy(szBuf1
, szBuf2
, RECV_BUF
);
87 status
= NtCreateEvent(&readEvent
,
94 ok(0, "Failed to create event\n");
98 /* Try reading the socket using the NT file API */
99 status
= NtReadFile((HANDLE
)sck
,
108 if (status
== STATUS_PENDING
)
110 WaitForSingleObject(readEvent
, INFINITE
);
111 status
= readIosb
.Status
;
114 ok(status
== 0, "Read failed with status 0x%x\n", (unsigned int)status
);
115 ok(memcmp(szBuf2
, szBuf1
, RECV_BUF
), "equal\n");
116 ok(readIosb
.Information
== RECV_BUF
, "Short read\n");
124 static void Test_Overread(void)
127 SOCKET ListeningSocket
= INVALID_SOCKET
;
128 SOCKET ServerSocket
= INVALID_SOCKET
;
129 SOCKET ClientSocket
= INVALID_SOCKET
;
139 WSAOVERLAPPED overlapped
;
140 } receivers
[4] = { 0 };
141 DWORD bytesTransferred
;
146 ret
= WSAStartup(MAKEWORD(2, 2), &wsaData
);
149 skip("Failed to initialize WinSock, error %d\n", ret
);
153 ListeningSocket
= socket(AF_INET
, SOCK_STREAM
, IPPROTO_TCP
);
154 if (ListeningSocket
== INVALID_SOCKET
)
156 skip("Failed to create listening socket, error %d\n", WSAGetLastError());
160 /* Bind to random port */
161 address
.sin_family
= AF_INET
;
162 address
.sin_addr
.s_addr
= htonl(INADDR_LOOPBACK
);
163 address
.sin_port
= 0;
164 ret
= bind(ListeningSocket
, (SOCKADDR
*)&address
, sizeof(address
));
165 if (ret
== SOCKET_ERROR
)
167 skip("Failed to bind socket, error %d\n", WSAGetLastError());
171 ret
= listen(ListeningSocket
, 1);
172 if (ret
== SOCKET_ERROR
)
174 skip("Failed to listen on socket, error %d\n", WSAGetLastError());
178 len
= sizeof(address
);
179 ret
= getsockname(ListeningSocket
, (SOCKADDR
*)&address
, &len
);
180 if (ret
== SOCKET_ERROR
)
182 skip("Failed to get listening port on socket, error %d\n", WSAGetLastError());
185 ok(len
== sizeof(address
), "getsocketname length %d\n", len
);
187 /**************************************************************************
188 * Test 1: non-overlapped client socket
189 *************************************************************************/
190 ClientSocket
= socket(AF_INET
, SOCK_STREAM
, IPPROTO_TCP
);
191 if (ClientSocket
== INVALID_SOCKET
)
193 skip("Failed to create client socket, error %d\n", WSAGetLastError());
197 ret
= connect(ClientSocket
, (SOCKADDR
*)&address
, sizeof(address
));
198 if (ret
== SOCKET_ERROR
)
200 skip("Failed to connect to socket, error %d\n", WSAGetLastError());
204 ServerSocket
= accept(ListeningSocket
, NULL
, NULL
);
205 if (ServerSocket
== INVALID_SOCKET
)
207 skip("Failed to accept client socket, error %d\n", WSAGetLastError());
211 ret
= send(ServerSocket
, "blah", 4, 0);
212 if (ret
== SOCKET_ERROR
)
214 skip("Failed to send to socket, error %d\n", WSAGetLastError());
218 ret
= closesocket(ServerSocket
);
219 ServerSocket
= INVALID_SOCKET
;
220 ok(ret
== 0, "Failed to close socket with %d\n", WSAGetLastError());
222 memset(buffer
, 0, sizeof(buffer
));
223 ret
= recv(ClientSocket
, buffer
, sizeof(buffer
), 0);
224 error
= WSAGetLastError();
225 ok(ret
== 4, "recv (1) returned %d\n", ret
);
226 ok(error
== NO_ERROR
, "recv (1) returned error %d\n", error
);
228 ok(!strcmp(buffer
, "blah"), "recv (1) returned data: %s\n", buffer
);
230 ret
= recv(ClientSocket
, buffer
, sizeof(buffer
), 0);
231 error
= WSAGetLastError();
232 ok(ret
== 0, "recv (2) returned %d\n", ret
);
233 ok(error
== NO_ERROR
, "recv (2) returned error %d\n", error
);
235 ret
= recv(ClientSocket
, buffer
, sizeof(buffer
), 0);
236 error
= WSAGetLastError();
237 ok(ret
== 0, "recv (3) returned %d\n", ret
);
238 ok(error
== NO_ERROR
, "recv (3) returned error %d\n", error
);
240 closesocket(ClientSocket
);
242 /**************************************************************************
243 * Test 2: overlapped client socket with multiple pending receives
244 *************************************************************************/
245 ClientSocket
= WSASocketW(AF_INET
,
250 WSA_FLAG_OVERLAPPED
);
251 if (ClientSocket
== INVALID_SOCKET
)
253 skip("Failed to create overlapped client socket, error %d\n", WSAGetLastError());
257 ret
= connect(ClientSocket
, (SOCKADDR
*)&address
, sizeof(address
));
258 if (ret
== SOCKET_ERROR
)
260 skip("Failed to connect to socket, error %d\n", WSAGetLastError());
264 ServerSocket
= accept(ListeningSocket
, NULL
, NULL
);
265 if (ServerSocket
== INVALID_SOCKET
)
267 skip("Failed to accept client socket, error %d\n", WSAGetLastError());
271 /* Start overlapping receive calls */
272 for (i
= 0; i
< RTL_NUMBER_OF(receivers
); i
++)
274 wsaBuf
.len
= sizeof(receivers
[i
].buffer
);
275 wsaBuf
.buf
= receivers
[i
].buffer
;
276 receivers
[i
].flags
= 0;
277 receivers
[i
].overlapped
.hEvent
= WSACreateEvent();
278 ret
= WSARecv(ClientSocket
,
283 &receivers
[i
].overlapped
,
285 error
= WSAGetLastError();
286 ok(ret
== SOCKET_ERROR
, "[%Iu] WSARecv returned %d\n", i
, ret
);
287 ok(error
== WSA_IO_PENDING
, "[%Iu] WSARecv returned error %d\n", i
, error
);
290 /* They should all be pending */
291 for (i
= 0; i
< RTL_NUMBER_OF(receivers
); i
++)
293 ret
= WSAGetOverlappedResult(ClientSocket
,
294 &receivers
[i
].overlapped
,
298 error
= WSAGetLastError();
299 ok(ret
== FALSE
, "[%Iu] WSAGetOverlappedResult returned %d\n", i
, ret
);
300 ok(error
== WSA_IO_INCOMPLETE
, "[%Iu] WSAGetOverlappedResult returned error %d\n", i
, error
);
303 /* Sending some data should complete the first receive */
304 ret
= send(ServerSocket
, "blah", 4, 0);
305 if (ret
== SOCKET_ERROR
)
307 skip("Failed to send to socket, error %d\n", WSAGetLastError());
312 bytesTransferred
= 0x55555555;
313 ret
= WSAGetOverlappedResult(ClientSocket
,
314 &receivers
[0].overlapped
,
318 error
= WSAGetLastError();
319 ok(ret
== TRUE
, "WSAGetOverlappedResult returned %d\n", ret
);
320 ok(flags
== 0, "WSAGetOverlappedResult returned flags 0x%lx\n", flags
);
321 ok(bytesTransferred
== 4, "WSAGetOverlappedResult returned %lu bytes\n", bytesTransferred
);
322 receivers
[0].buffer
[4] = 0;
323 ok(!strcmp(receivers
[0].buffer
, "blah"), "WSARecv returned data: %s\n", receivers
[0].buffer
);
325 /* Others should still be in progress */
326 for (i
= 1; i
< RTL_NUMBER_OF(receivers
); i
++)
328 ret
= WSAGetOverlappedResult(ClientSocket
,
329 &receivers
[i
].overlapped
,
333 error
= WSAGetLastError();
334 ok(ret
== FALSE
, "[%Iu] WSAGetOverlappedResult returned %d\n", i
, ret
);
335 ok(error
== WSA_IO_INCOMPLETE
, "[%Iu] WSAGetOverlappedResult returned error %d\n", i
, error
);
338 /* Closing the server end should make all receives complete */
339 ret
= closesocket(ServerSocket
);
340 ServerSocket
= INVALID_SOCKET
;
341 ok(ret
== 0, "Failed to close socket with %d\n", WSAGetLastError());
343 for (i
= 1; i
< RTL_NUMBER_OF(receivers
); i
++)
346 bytesTransferred
= 0x55555555;
347 ret
= WSAGetOverlappedResult(ClientSocket
,
348 &receivers
[i
].overlapped
,
352 error
= WSAGetLastError();
353 ok(ret
== TRUE
, "[%Iu] WSAGetOverlappedResult returned %d\n", i
, ret
);
354 ok(flags
== 0, "[%Iu] WSAGetOverlappedResult returned flags 0x%lx\n", i
, flags
);
355 ok(bytesTransferred
== 0, "[%Iu] WSAGetOverlappedResult returned %lu bytes\n", i
, bytesTransferred
);
358 /* Start two more receives -- they should immediately return success */
359 ret
= recv(ClientSocket
, receivers
[0].buffer
, sizeof(receivers
[0].buffer
), 0);
360 error
= WSAGetLastError();
361 ok(ret
== 0, "recv (N+1) returned %d\n", ret
);
362 ok(error
== NO_ERROR
, "recv (N+1) returned error %d\n", error
);
364 ret
= recv(ClientSocket
, receivers
[0].buffer
, sizeof(receivers
[0].buffer
), 0);
365 error
= WSAGetLastError();
366 ok(ret
== 0, "recv (N+2) returned %d\n", ret
);
367 ok(error
== NO_ERROR
, "recv (N+2) returned error %d\n", error
);
370 for (i
= 0; i
< RTL_NUMBER_OF(receivers
); i
++)
372 if (receivers
[i
].overlapped
.hEvent
!= NULL
)
374 WSACloseEvent(receivers
[i
].overlapped
.hEvent
);
378 if (ListeningSocket
!= INVALID_SOCKET
)
380 ret
= closesocket(ListeningSocket
);
381 ok(ret
== 0, "closesocket (1) failed with %d\n", WSAGetLastError());
383 if (ClientSocket
!= INVALID_SOCKET
)
385 ret
= closesocket(ClientSocket
);
386 ok(ret
== 0, "closesocket (2) failed with %d\n", WSAGetLastError());
388 if (ServerSocket
!= INVALID_SOCKET
)
390 ret
= closesocket(ServerSocket
);
391 ok(ret
== 0, "closesocket (3) failed with %d\n", WSAGetLastError());
394 ok(ret
== 0, "WSACleanup failed with %d\n", WSAGetLastError());