1 /*
2  * PROJECT:         ReactOS api tests
3  * LICENSE:         GPL - See COPYING in the top level directory
4  * PURPOSE:         Test for WSARecv
5  * PROGRAMMERS:     Peter Hater
6  */
7 
8 #include "ws2_32.h"
9 
10 #define RECV_BUF   4
11 #define WSARecv_TIMEOUT 2000
12 
13 static int count = 0;
14 
15 void
16 CALLBACK completion(
17     DWORD dwError,
18     DWORD cbTransferred,
19     LPWSAOVERLAPPED lpOverlapped,
20     DWORD dwFlags)
21 {
22     //trace("completion called dwFlags %ld cbTransferred %ld lpOverlapped %p dwFlags %ld\n", dwError, cbTransferred, lpOverlapped, dwFlags);
23     count++;
24     ok(count == 1, "completion sould be called only once count = %d\n", count);
25     ok(dwError == 0, "dwError = %ld\n", dwError);
26     ok(cbTransferred == RECV_BUF, "cbTransferred %ld != %d\n", cbTransferred, RECV_BUF);
27     ok(lpOverlapped != NULL, "lpOverlapped %p\n", lpOverlapped);
28     if (lpOverlapped)
29     {
30         ok(lpOverlapped->hEvent != INVALID_HANDLE_VALUE, "lpOverlapped->hEvent %p\n", lpOverlapped->hEvent);
31         if (lpOverlapped->hEvent != INVALID_HANDLE_VALUE)
32             WSASetEvent(lpOverlapped->hEvent);
33     }
34 }
35 
36 void Test_WSARecv()
37 {
38     const char szDummyBytes[RECV_BUF] = { 0xFF, 0x00, 0xFF, 0x00 };
39 
40     char szBuf[RECV_BUF];
41     char szRecvBuf[RECV_BUF];
42     int iResult, err;
43     SOCKET sck;
44     WSADATA wdata;
45     WSABUF buffers;
46     DWORD dwRecv, dwSent, dwFlags;
47     WSAOVERLAPPED overlapped;
48     char szGetRequest[] = "GET / HTTP/1.0\r\n\r\n";
49     struct fd_set readable;
50     BOOL ret;
51 
52     /* Start up Winsock */
53     iResult = WSAStartup(MAKEWORD(2, 2), &wdata);
54     ok(iResult == 0, "WSAStartup failed, iResult == %d\n", iResult);
55 
56     /* If we call recv without a socket, it should return with an error and do nothing. */
57     memcpy(szBuf, szDummyBytes, RECV_BUF);
58     buffers.buf = szBuf;
59     buffers.len = sizeof(szBuf);
60     dwFlags = 0;
61     dwRecv = 0;
62     iResult = WSARecv(0, &buffers, 1, &dwRecv, &dwFlags, NULL, NULL);
63     ok(iResult == SOCKET_ERROR, "iRseult = %d\n", iResult);
64     ok(!memcmp(szBuf, szDummyBytes, RECV_BUF), "not equal\n");
65 
66     /* Create the socket */
67     sck = WSASocketW(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
68     if(sck == INVALID_SOCKET)
69     {
70         WSACleanup();
71         skip("CreateSocket failed. Aborting test.\n");
72         return;
73     }
74 
75     /* Now we can pass at least a socket, but we have no connection yet. Should return with an error and do nothing. */
76     memcpy(szBuf, szDummyBytes, RECV_BUF);
77     buffers.buf = szBuf;
78     buffers.len = sizeof(szBuf);
79     dwFlags = 0;
80     dwRecv = 0;
81     iResult = WSARecv(sck, &buffers, 1, &dwRecv, &dwFlags, NULL, NULL);
82     ok(iResult == SOCKET_ERROR, "iResult = %d\n", iResult);
83     ok(!memcmp(szBuf, szDummyBytes, RECV_BUF), "not equal\n");
84 
85     /* Connect to "www.reactos.org" */
86     if (!ConnectToReactOSWebsite(sck))
87     {
88         WSACleanup();
89         skip("ConnectToReactOSWebsite failed. Aborting test.\n");
90         return;
91     }
92 
93     /* prepare overlapped */
94     memset(&overlapped, 0, sizeof(overlapped));
95     overlapped.hEvent = WSACreateEvent();
96 
97     /* Send the GET request */
98     buffers.buf = szGetRequest;
99     buffers.len = lstrlenA(szGetRequest);
100     dwSent = 0;
101     WSASetLastError(0xdeadbeef);
102     iResult = WSASend(sck, &buffers, 1, &dwSent, 0, &overlapped, NULL);
103     err = WSAGetLastError();
104     ok(iResult == 0 || (iResult == SOCKET_ERROR && err == WSA_IO_PENDING), "iResult = %d, %d\n", iResult, err);
105     if (err == WSA_IO_PENDING)
106     {
107         iResult = WSAWaitForMultipleEvents(1, &overlapped.hEvent, TRUE, WSARecv_TIMEOUT, TRUE);
108         ok(iResult == WSA_WAIT_EVENT_0, "WSAWaitForMultipleEvents failed %d\n", iResult);
109         ret = WSAGetOverlappedResult(sck, &overlapped, &dwSent, TRUE, &dwFlags);
110         ok(ret, "WSAGetOverlappedResult failed %d\n", WSAGetLastError());
111     }
112     ok(dwSent == strlen(szGetRequest), "dwSent %ld != %d\n", dwSent, strlen(szGetRequest));
113 #if 0 /* break windows too */
114     /* Shutdown the SEND connection */
115     iResult = shutdown(sck, SD_SEND);
116     ok(iResult != SOCKET_ERROR, "iResult = %d\n", iResult);
117 #endif
118     /* Wait until we're ready to read */
119     FD_ZERO(&readable);
120     FD_SET(sck, &readable);
121 
122     iResult = select(0, &readable, NULL, NULL, NULL);
123     ok(iResult != SOCKET_ERROR, "iResult = %d\n", iResult);
124 
125     /* Receive the data. */
126     buffers.buf = szBuf;
127     buffers.len = sizeof(szBuf);
128     dwRecv = sizeof(szBuf);
129     iResult = WSARecv(sck, &buffers, 1, &dwRecv, &dwFlags, NULL, NULL);
130     ok(iResult != SOCKET_ERROR, "iResult = %d\n", iResult);
131     ok(dwRecv == sizeof(szBuf), "dwRecv %ld != %d\n", dwRecv, sizeof(szBuf));
132     /* MSG_PEEK is invalid for overlapped (MSDN), but passes??? */
133     buffers.buf = szRecvBuf;
134     buffers.len = sizeof(szRecvBuf);
135     dwFlags = MSG_PEEK;
136     dwRecv = sizeof(szRecvBuf);
137     ok(overlapped.hEvent != NULL, "WSACreateEvent failed %d\n", WSAGetLastError());
138     WSASetLastError(0xdeadbeef);
139     iResult = WSARecv(sck, &buffers, 1, &dwRecv, &dwFlags, &overlapped, NULL);
140     err = WSAGetLastError();
141     ok(iResult == 0 || (iResult == SOCKET_ERROR && err == WSA_IO_PENDING), "iResult = %d, %d\n", iResult, err);
142     if (err == WSA_IO_PENDING)
143     {
144         iResult = WSAWaitForMultipleEvents(1, &overlapped.hEvent, TRUE, WSARecv_TIMEOUT, TRUE);
145         ok(iResult == WSA_WAIT_EVENT_0, "WSAWaitForMultipleEvents failed %d\n", iResult);
146         ret = WSAGetOverlappedResult(sck, &overlapped, &dwRecv, TRUE, &dwFlags);
147         ok(ret, "WSAGetOverlappedResult failed %d\n", WSAGetLastError());
148     }
149     ok(dwRecv == sizeof(szRecvBuf), "dwRecv %ld != %d\n", dwRecv, sizeof(szRecvBuf));
150     /* normal overlapped, no completion */
151     buffers.buf = szBuf;
152     buffers.len = sizeof(szBuf);
153     dwFlags = 0;
154     dwRecv = sizeof(szBuf);
155     WSAResetEvent(overlapped.hEvent);
156     WSASetLastError(0xdeadbeef);
157     iResult = WSARecv(sck, &buffers, 1, &dwRecv, &dwFlags, &overlapped, NULL);
158     err = WSAGetLastError();
159     ok(iResult == 0 || (iResult == SOCKET_ERROR && err == WSA_IO_PENDING), "iResult = %d, %d\n", iResult, err);
160     if (err == WSA_IO_PENDING)
161     {
162         iResult = WSAWaitForMultipleEvents(1, &overlapped.hEvent, TRUE, WSARecv_TIMEOUT, TRUE);
163         ok(iResult == WSA_WAIT_EVENT_0, "WSAWaitForMultipleEvents failed %d\n", iResult);
164         ret = WSAGetOverlappedResult(sck, &overlapped, &dwRecv, TRUE, &dwFlags);
165         ok(ret, "WSAGetOverlappedResult failed %d\n", WSAGetLastError());
166     }
167     ok(dwRecv == sizeof(szBuf), "dwRecv %ld != %d\n", dwRecv, sizeof(szBuf));
168     ok(memcmp(szRecvBuf, szBuf, sizeof(szBuf)) == 0, "MSG_PEEK shouldn't have moved the pointer\n");
169     /* overlapped with completion */
170     dwFlags = 0;
171     dwRecv = sizeof(szBuf);
172     WSAResetEvent(overlapped.hEvent);
173     WSASetLastError(0xdeadbeef);
174     iResult = WSARecv(sck, &buffers, 1, &dwRecv, &dwFlags, &overlapped, &completion);
175     err = WSAGetLastError();
176     ok(iResult == 0 || (iResult == SOCKET_ERROR && err == WSA_IO_PENDING), "iResult = %d, %d\n", iResult, err);
177     if (err == WSA_IO_PENDING)
178     {
179         iResult = WSAWaitForMultipleEvents(1, &overlapped.hEvent, TRUE, WSARecv_TIMEOUT, TRUE);
180         ok(iResult == WSA_WAIT_EVENT_0, "WSAWaitForMultipleEvents failed %d\n", iResult);
181         ret = WSAGetOverlappedResult(sck, &overlapped, &dwRecv, TRUE, &dwFlags);
182         ok(ret, "WSAGetOverlappedResult failed %d\n", WSAGetLastError());
183     }
184     ret = WSACloseEvent(overlapped.hEvent);
185     ok(ret, "WSACloseEvent failed %d\n", WSAGetLastError());
186     ok(dwRecv == sizeof(szBuf), "dwRecv %ld != %d\n", dwRecv, sizeof(szBuf));
187     /* no overlapped with completion */
188     dwFlags = 0;
189     dwRecv = sizeof(szBuf);
190     WSASetLastError(0xdeadbeef);
191     /* call doesn't fail, but completion is not called */
192     iResult = WSARecv(sck, &buffers, 1, &dwRecv, &dwFlags, NULL, &completion);
193     err = WSAGetLastError();
194     ok(iResult == 0 || (iResult == SOCKET_ERROR && err == WSA_IO_PENDING), "iResult = %d, %d\n", iResult, err);
195     ok(err == 0, "WSARecv failed %d\n", err);
196     ok(dwRecv == sizeof(szBuf), "dwRecv %ld != %d and 0\n", dwRecv, sizeof(szBuf));
197 
198     closesocket(sck);
199     WSACleanup();
200     return;
201 }
202 
203 START_TEST(WSARecv)
204 {
205     Test_WSARecv();
206 }
207 
208