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 23 int Test_recv() 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; 32 NTSTATUS status; 33 IO_STATUS_BLOCK readIosb; 34 HANDLE readEvent; 35 LARGE_INTEGER readOffset; 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" */ 61 if (!ConnectToReactOSWebsite(sck)) 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, 88 EVENT_ALL_ACCESS, 89 NULL, 90 NotificationEvent, 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 */ 99 status = NtReadFile((HANDLE)sck, 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 124 static void Test_Overread(void) 125 { 126 WSADATA wsaData; 127 SOCKET ListeningSocket = INVALID_SOCKET; 128 SOCKET ServerSocket = INVALID_SOCKET; 129 SOCKET ClientSocket = INVALID_SOCKET; 130 SOCKADDR_IN address; 131 char buffer[32]; 132 int ret; 133 int error; 134 int len; 135 struct 136 { 137 char buffer[32]; 138 DWORD flags; 139 WSAOVERLAPPED overlapped; 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); 205 if (ServerSocket == INVALID_SOCKET) 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 218 ret = closesocket(ServerSocket); 219 ServerSocket = INVALID_SOCKET; 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); 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); 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); 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); 234 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); 239 240 closesocket(ClientSocket); 241 242 /************************************************************************** 243 * Test 2: overlapped client socket with multiple pending receives 244 *************************************************************************/ 245 ClientSocket = WSASocketW(AF_INET, 246 SOCK_STREAM, 247 IPPROTO_TCP, 248 NULL, 249 0, 250 WSA_FLAG_OVERLAPPED); 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); 265 if (ServerSocket == INVALID_SOCKET) 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); 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); 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); 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); 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); 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); 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); 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); 336 } 337 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()); 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); 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); 356 } 357 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); 363 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); 368 369 Exit: 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 } 388 if (ServerSocket != INVALID_SOCKET) 389 { 390 ret = closesocket(ServerSocket); 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 397 START_TEST(recv) 398 { 399 Test_recv(); 400 Test_Overread(); 401 } 402 403