ReactOS 0.4.15-dev-8219-ge8b88cf
recv.c
Go to the documentation of this file.
1/*
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)
9 */
10
11#include "ws2_32.h"
12
13#include <ndk/exfuncs.h>
14#include <ndk/iofuncs.h>
15#include <ndk/obfuncs.h>
16
17#define RECV_BUF 4
18
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. */
22
24{
25 const char szDummyBytes[RECV_BUF] = {0xFF, 0x00, 0xFF, 0x00};
26
27 char szBuf1[RECV_BUF];
28 char szBuf2[RECV_BUF];
29 int iResult;
30 SOCKET sck;
31 WSADATA wdata;
33 IO_STATUS_BLOCK readIosb;
34 HANDLE readEvent;
36
37 /* Start up Winsock */
38 iResult = WSAStartup(MAKEWORD(2, 2), &wdata);
39 ok(iResult == 0, "WSAStartup failed, iResult == %d\n", iResult);
40
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");
46
47 /* Create the socket */
48 if (!CreateSocket(&sck))
49 {
50 ok(0, "CreateSocket failed. Aborting test.\n");
51 return 0;
52 }
53
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");
59
60 /* Connect to "www.reactos.org" */
62 {
63 ok(0, "ConnectToReactOSWebsite failed. Aborting test.\n");
64 return 0;
65 }
66
67 /* Send the GET request */
68 if (!GetRequestAndWait(sck))
69 {
70 ok(0, "GetRequestAndWait failed. Aborting test.\n");
71 return 0;
72 }
73
74 /* Receive the data.
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");
79
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");
83
84 /* Create an event for NtReadFile */
85 readOffset.QuadPart = 0LL;
86 memcpy(szBuf1, szBuf2, RECV_BUF);
87 status = NtCreateEvent(&readEvent,
89 NULL,
91 FALSE);
92 if (status != 0)
93 {
94 ok(0, "Failed to create event\n");
95 return 0;
96 }
97
98 /* Try reading the socket using the NT file API */
100 readEvent,
101 NULL,
102 NULL,
103 &readIosb,
104 szBuf1,
105 RECV_BUF,
106 &readOffset,
107 NULL);
108 if (status == STATUS_PENDING)
109 {
110 WaitForSingleObject(readEvent, INFINITE);
111 status = readIosb.Status;
112 }
113
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");
117
118 NtClose(readEvent);
119 closesocket(sck);
120 WSACleanup();
121 return 1;
122}
123
124static void Test_Overread(void)
125{
126 WSADATA wsaData;
127 SOCKET ListeningSocket = INVALID_SOCKET;
129 SOCKET ClientSocket = INVALID_SOCKET;
131 char buffer[32];
132 int ret;
133 int error;
134 int len;
135 struct
136 {
137 char buffer[32];
138 DWORD flags;
140 } receivers[4] = { 0 };
141 DWORD bytesTransferred;
142 DWORD flags;
143 WSABUF wsaBuf;
144 size_t i;
145
146 ret = WSAStartup(MAKEWORD(2, 2), &wsaData);
147 if (ret != 0)
148 {
149 skip("Failed to initialize WinSock, error %d\n", ret);
150 goto Exit;
151 }
152
153 ListeningSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
154 if (ListeningSocket == INVALID_SOCKET)
155 {
156 skip("Failed to create listening socket, error %d\n", WSAGetLastError());
157 goto Exit;
158 }
159
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)
166 {
167 skip("Failed to bind socket, error %d\n", WSAGetLastError());
168 goto Exit;
169 }
170
171 ret = listen(ListeningSocket, 1);
172 if (ret == SOCKET_ERROR)
173 {
174 skip("Failed to listen on socket, error %d\n", WSAGetLastError());
175 goto Exit;
176 }
177
178 len = sizeof(address);
179 ret = getsockname(ListeningSocket, (SOCKADDR *)&address, &len);
180 if (ret == SOCKET_ERROR)
181 {
182 skip("Failed to get listening port on socket, error %d\n", WSAGetLastError());
183 goto Exit;
184 }
185 ok(len == sizeof(address), "getsocketname length %d\n", len);
186
187 /**************************************************************************
188 * Test 1: non-overlapped client socket
189 *************************************************************************/
190 ClientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
191 if (ClientSocket == INVALID_SOCKET)
192 {
193 skip("Failed to create client socket, error %d\n", WSAGetLastError());
194 goto Exit;
195 }
196
197 ret = connect(ClientSocket, (SOCKADDR *)&address, sizeof(address));
198 if (ret == SOCKET_ERROR)
199 {
200 skip("Failed to connect to socket, error %d\n", WSAGetLastError());
201 goto Exit;
202 }
203
204 ServerSocket = accept(ListeningSocket, NULL, NULL);
206 {
207 skip("Failed to accept client socket, error %d\n", WSAGetLastError());
208 goto Exit;
209 }
210
211 ret = send(ServerSocket, "blah", 4, 0);
212 if (ret == SOCKET_ERROR)
213 {
214 skip("Failed to send to socket, error %d\n", WSAGetLastError());
215 goto Exit;
216 }
217
220 ok(ret == 0, "Failed to close socket with %d\n", WSAGetLastError());
221
222 memset(buffer, 0, sizeof(buffer));
223 ret = recv(ClientSocket, buffer, sizeof(buffer), 0);
225 ok(ret == 4, "recv (1) returned %d\n", ret);
226 ok(error == NO_ERROR, "recv (1) returned error %d\n", error);
227 buffer[4] = 0;
228 ok(!strcmp(buffer, "blah"), "recv (1) returned data: %s\n", buffer);
229
230 ret = recv(ClientSocket, buffer, sizeof(buffer), 0);
232 ok(ret == 0, "recv (2) returned %d\n", ret);
233 ok(error == NO_ERROR, "recv (2) returned error %d\n", error);
234
235 ret = recv(ClientSocket, buffer, sizeof(buffer), 0);
237 ok(ret == 0, "recv (3) returned %d\n", ret);
238 ok(error == NO_ERROR, "recv (3) returned error %d\n", error);
239
240 closesocket(ClientSocket);
241
242 /**************************************************************************
243 * Test 2: overlapped client socket with multiple pending receives
244 *************************************************************************/
245 ClientSocket = WSASocketW(AF_INET,
248 NULL,
249 0,
251 if (ClientSocket == INVALID_SOCKET)
252 {
253 skip("Failed to create overlapped client socket, error %d\n", WSAGetLastError());
254 goto Exit;
255 }
256
257 ret = connect(ClientSocket, (SOCKADDR *)&address, sizeof(address));
258 if (ret == SOCKET_ERROR)
259 {
260 skip("Failed to connect to socket, error %d\n", WSAGetLastError());
261 goto Exit;
262 }
263
264 ServerSocket = accept(ListeningSocket, NULL, NULL);
266 {
267 skip("Failed to accept client socket, error %d\n", WSAGetLastError());
268 goto Exit;
269 }
270
271 /* Start overlapping receive calls */
272 for (i = 0; i < RTL_NUMBER_OF(receivers); i++)
273 {
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,
279 &wsaBuf,
280 1,
281 NULL,
282 &receivers[i].flags,
283 &receivers[i].overlapped,
284 NULL);
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);
288 }
289
290 /* They should all be pending */
291 for (i = 0; i < RTL_NUMBER_OF(receivers); i++)
292 {
293 ret = WSAGetOverlappedResult(ClientSocket,
294 &receivers[i].overlapped,
295 &bytesTransferred,
296 FALSE,
297 &flags);
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);
301 }
302
303 /* Sending some data should complete the first receive */
304 ret = send(ServerSocket, "blah", 4, 0);
305 if (ret == SOCKET_ERROR)
306 {
307 skip("Failed to send to socket, error %d\n", WSAGetLastError());
308 goto Exit;
309 }
310
311 flags = 0x55555555;
312 bytesTransferred = 0x55555555;
313 ret = WSAGetOverlappedResult(ClientSocket,
314 &receivers[0].overlapped,
315 &bytesTransferred,
316 FALSE,
317 &flags);
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);
324
325 /* Others should still be in progress */
326 for (i = 1; i < RTL_NUMBER_OF(receivers); i++)
327 {
328 ret = WSAGetOverlappedResult(ClientSocket,
329 &receivers[i].overlapped,
330 &bytesTransferred,
331 FALSE,
332 &flags);
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);
336 }
337
338 /* Closing the server end should make all receives complete */
341 ok(ret == 0, "Failed to close socket with %d\n", WSAGetLastError());
342
343 for (i = 1; i < RTL_NUMBER_OF(receivers); i++)
344 {
345 flags = 0x55555555;
346 bytesTransferred = 0x55555555;
347 ret = WSAGetOverlappedResult(ClientSocket,
348 &receivers[i].overlapped,
349 &bytesTransferred,
350 FALSE,
351 &flags);
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);
356 }
357
358 /* Start two more receives -- they should immediately return success */
359 ret = recv(ClientSocket, receivers[0].buffer, sizeof(receivers[0].buffer), 0);
361 ok(ret == 0, "recv (N+1) returned %d\n", ret);
362 ok(error == NO_ERROR, "recv (N+1) returned error %d\n", error);
363
364 ret = recv(ClientSocket, receivers[0].buffer, sizeof(receivers[0].buffer), 0);
366 ok(ret == 0, "recv (N+2) returned %d\n", ret);
367 ok(error == NO_ERROR, "recv (N+2) returned error %d\n", error);
368
369Exit:
370 for (i = 0; i < RTL_NUMBER_OF(receivers); i++)
371 {
372 if (receivers[i].overlapped.hEvent != NULL)
373 {
374 WSACloseEvent(receivers[i].overlapped.hEvent);
375 }
376 }
377
378 if (ListeningSocket != INVALID_SOCKET)
379 {
380 ret = closesocket(ListeningSocket);
381 ok(ret == 0, "closesocket (1) failed with %d\n", WSAGetLastError());
382 }
383 if (ClientSocket != INVALID_SOCKET)
384 {
385 ret = closesocket(ClientSocket);
386 ok(ret == 0, "closesocket (2) failed with %d\n", WSAGetLastError());
387 }
389 {
391 ok(ret == 0, "closesocket (3) failed with %d\n", WSAGetLastError());
392 }
393 ret = WSACleanup();
394 ok(ret == 0, "WSACleanup failed with %d\n", WSAGetLastError());
395}
396
398{
399 Test_recv();
401}
402
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
#define ok(value,...)
Definition: atltest.h:57
#define skip(...)
Definition: atltest.h:64
#define START_TEST(x)
Definition: atltest.h:75
LONG NTSTATUS
Definition: precomp.h:26
#define NO_ERROR
Definition: dderror.h:5
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
BOOL WSAAPI WSACloseEvent(IN WSAEVENT hEvent)
Definition: event.c:23
INT WSAAPI WSARecv(IN SOCKET s, IN OUT LPWSABUF lpBuffers, IN DWORD dwBufferCount, OUT LPDWORD lpNumberOfBytesRecvd, IN OUT LPDWORD lpFlags, IN LPWSAOVERLAPPED lpOverlapped, IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
Definition: recv.c:155
INT WSAAPI recv(IN SOCKET s, OUT CHAR FAR *buf, IN INT len, IN INT flags)
Definition: recv.c:23
INT WSAAPI send(IN SOCKET s, IN CONST CHAR FAR *buf, IN INT len, IN INT flags)
Definition: send.c:23
INT WINAPI WSAStartup(IN WORD wVersionRequested, OUT LPWSADATA lpWSAData)
Definition: startup.c:113
#define IPPROTO_TCP
Definition: ip.h:196
#define SOCK_STREAM
Definition: tcpip.h:118
#define AF_INET
Definition: tcpip.h:117
#define INFINITE
Definition: serial.h:102
unsigned long DWORD
Definition: ntddk_ex.h:95
GLuint address
Definition: glext.h:9393
GLenum GLintptr readOffset
Definition: glext.h:7109
GLuint buffer
Definition: glext.h:5915
GLbitfield flags
Definition: glext.h:7161
GLenum GLsizei len
Definition: glext.h:6722
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define INADDR_LOOPBACK
Definition: inet.h:51
#define EVENT_ALL_ACCESS
Definition: isotest.c:82
#define error(str)
Definition: mkdosfs.c:1605
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define htonl(x)
Definition: module.h:214
int GetRequestAndWait(SOCKET sck)
Definition: helpers.c:45
int ConnectToReactOSWebsite(SOCKET sck)
Definition: helpers.c:27
int Test_recv()
Definition: recv.c:23
#define RECV_BUF
Definition: recv.c:17
static void Test_Overread(void)
Definition: recv.c:124
#define SCKTEST(_cmd_)
Definition: ws2_32.h:25
#define closesocket
Definition: ncftp.h:477
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3402
@ NotificationEvent
NTSTATUS NTAPI NtCreateEvent(OUT PHANDLE EventHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN EVENT_TYPE EventType, IN BOOLEAN InitialState)
Definition: event.c:96
#define STATUS_PENDING
Definition: ntstatus.h:82
#define memset(x, y, z)
Definition: compat.h:39
NTSTATUS NTAPI NtReadFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, PVOID Buffer, ULONG Length, PLARGE_INTEGER ByteOffset, PULONG Key)
static void Exit(void)
Definition: sock.c:1330
namespace GUID const ADDRINFOEXW ADDRINFOEXW struct timeval OVERLAPPED * overlapped
Definition: sock.c:81
INT WSAAPI getsockname(IN SOCKET s, OUT LPSOCKADDR name, IN OUT INT FAR *namelen)
Definition: sockctrl.c:213
INT WSAAPI listen(IN SOCKET s, IN INT backlog)
Definition: sockctrl.c:123
BOOL WSAAPI WSAGetOverlappedResult(IN SOCKET s, IN LPWSAOVERLAPPED lpOverlapped, OUT LPDWORD lpcbTransfer, IN BOOL fWait, OUT LPDWORD lpdwFlags)
Definition: sockctrl.c:603
SOCKET ServerSocket
Definition: socket.c:3
SOCKET WSAAPI WSASocketW(IN INT af, IN INT type, IN INT protocol, IN LPWSAPROTOCOL_INFOW lpProtocolInfo, IN GROUP g, IN DWORD dwFlags)
Definition: socklife.c:490
INT WSAAPI bind(IN SOCKET s, IN CONST struct sockaddr *name, IN INT namelen)
Definition: socklife.c:36
SOCKET WSAAPI accept(IN SOCKET s, OUT LPSOCKADDR addr, OUT INT FAR *addrlen)
Definition: socklife.c:23
SOCKET WSAAPI socket(IN INT af, IN INT type, IN INT protocol)
Definition: socklife.c:143
ULONG len
Definition: ws2def.h:519
CHAR FAR * buf
Definition: ws2def.h:520
Definition: ps.c:97
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
static void CreateSocket(void)
Definition: telnetd.c:102
#define LL
Definition: tui.h:167
#define MAKEWORD(a, b)
Definition: typedefs.h:248
int ret
#define WSA_FLAG_OVERLAPPED
Definition: winsock2.h:466
WINSOCK_API_LINKAGE WSAEVENT WSAAPI WSACreateEvent(void)
Definition: event.c:42
#define WSA_IO_PENDING
Definition: winsock2.h:616
#define WSA_IO_INCOMPLETE
Definition: winsock2.h:617
int PASCAL FAR WSAGetLastError(void)
Definition: dllmain.c:112
int PASCAL FAR WSACleanup(void)
Definition: startup.c:60
#define INVALID_SOCKET
Definition: winsock.h:332
UINT_PTR SOCKET
Definition: winsock.h:47
#define MSG_PEEK
Definition: winsock.h:222
#define SOCKET_ERROR
Definition: winsock.h:333