Thanks, sorry about that; forgot to pull. Here's an updated version.
And the compile warning is harmless.
Also - small question: there is a for loop so that the test doesn't
run forever should it fail. What would be a good replacement for that?
(the way its set up is: select is 10ms*4000=40secs max)
Mike.
On Sat, Jul 11, 2009 at 5:47 PM, Paul Vriens<[email protected]> wrote:
> Mike Kaplinskiy wrote:
>>
>> Can someone try this test on win2000+? This tests the
>> WSAAccept->Defer->AcceptEx scenario, and I've only verified the
>> behavior on xp.
>>
>> Thanks,
>> Mike
>>
>>
>> ------------------------------------------------------------------------
>>
>>
> Hi Mike,
>
> No failures on W2K3 SP2.
>
> Patch doesn't apply cleanly and there is compile warning:
>
> sock.c:2781: warning: passing argument 5 of 'WSAAccept' makes integer from
> pointer without a cast
>
> --
> Cheers,
>
> Paul.
>
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c
index acb2638..4e9627a 100644
--- a/dlls/ws2_32/tests/sock.c
+++ b/dlls/ws2_32/tests/sock.c
@@ -2539,17 +2539,26 @@ static void test_GetAddrInfoW(void)
pFreeAddrInfoW(result);
}
+static int CALLBACK AlwaysDeferConditionFunc(LPWSABUF lpCallerId, LPWSABUF lpCallerData, LPQOS pQos,
+ LPQOS lpGQOS, LPWSABUF lpCalleeId, LPWSABUF lpCalleeData,
+ GROUP FAR * g, DWORD_PTR dwCallbackData)
+{
+ return CF_DEFER;
+}
+
static void test_AcceptEx(void)
{
SOCKET listener = INVALID_SOCKET;
SOCKET acceptor = INVALID_SOCKET;
SOCKET connector = INVALID_SOCKET;
+ SOCKET connector2 = INVALID_SOCKET;
struct sockaddr_in bindAddress;
int socklen;
GUID acceptExGuid = WSAID_ACCEPTEX;
- BOOL WINAPI (*pAcceptEx)(SOCKET listener, SOCKET acceptor, PVOID dest, DWORD dest_len,
- DWORD local_addr_len, DWORD rem_addr_len, LPDWORD received,
- LPOVERLAPPED overlapped);
+ LPFN_ACCEPTEX pAcceptEx = NULL;
+ fd_set fds_accept, fds_send;
+ struct timeval timeout = {0,10}; /* wait for 10 milliseconds */
+ int got, conn1, i;
DWORD bytesReturned;
char buffer[1024];
OVERLAPPED overlapped;
@@ -2711,6 +2720,116 @@ static void test_AcceptEx(void)
bret = GetOverlappedResult((HANDLE)listener, &overlapped, &bytesReturned, FALSE);
ok(bret, "GetOverlappedResult failed, error %d\n", GetLastError());
ok(bytesReturned == 1, "bytesReturned isn't supposed to be %d\n", bytesReturned);
+
+ closesocket(connector);
+ connector = INVALID_SOCKET;
+ closesocket(acceptor);
+ acceptor = INVALID_SOCKET;
+
+ /* Test CF_DEFER & AcceptEx interaction */
+
+ acceptor = socket(AF_INET, SOCK_STREAM, 0);
+ if (acceptor == INVALID_SOCKET) {
+ skip("could not create acceptor socket, error %d\n", WSAGetLastError());
+ goto end;
+ }
+ connector = socket(AF_INET, SOCK_STREAM, 0);
+ if (connector == INVALID_SOCKET) {
+ skip("could not create connector socket, error %d\n", WSAGetLastError());
+ goto end;
+ }
+ connector2 = socket(AF_INET, SOCK_STREAM, 0);
+ if (connector == INVALID_SOCKET) {
+ skip("could not create connector socket, error %d\n", WSAGetLastError());
+ goto end;
+ }
+
+ if (set_blocking(connector, FALSE)) {
+ skip("couldn't make socket non-blocking, error %d\n", WSAGetLastError());
+ goto end;
+ }
+
+ if (set_blocking(connector2, FALSE)) {
+ skip("couldn't make socket non-blocking, error %d\n", WSAGetLastError());
+ goto end;
+ }
+
+ /* Connect socket #1 */
+ iret = connect(connector, (struct sockaddr*)&bindAddress, sizeof(bindAddress));
+ ok(iret == 0 ||
+ (iret == SOCKET_ERROR && WSAGetLastError() == WSAEWOULDBLOCK), "connecting to accepting socket failed, error %d\n", WSAGetLastError());
+
+ FD_ZERO ( &fds_accept );
+ FD_ZERO ( &fds_send );
+
+ FD_SET ( listener, &fds_accept );
+ FD_SET ( connector, &fds_send );
+
+ buffer[0] = '0';
+ got = 0;
+ conn1 = 0;
+
+ for (i = 0; i < 4000; ++i)
+ {
+ wsa_ok ( ( select ( 0, &fds_accept, &fds_send, NULL, &timeout ) ), SOCKET_ERROR !=,
+ "select_server (%x): select() failed: %d\n" );
+
+ /* check for incoming requests */
+ if ( FD_ISSET ( listener, &fds_accept ) ) {
+ got++;
+ if (got == 1) {
+ SOCKET tmp = WSAAccept(listener, NULL, NULL, (LPCONDITIONPROC) AlwaysDeferConditionFunc, NULL);
+ ok(tmp == INVALID_SOCKET && WSAGetLastError() == WSATRY_AGAIN, "Failed to defer connection\n");
+ bret = pAcceptEx(listener, acceptor, buffer, 0,
+ sizeof(struct sockaddr_in) + 16, sizeof(struct sockaddr_in) + 16,
+ &bytesReturned, &overlapped);
+ ok(bret == FALSE && WSAGetLastError() == ERROR_IO_PENDING, "AcceptEx returned %d + errno %d\n", bret, WSAGetLastError());
+ }
+ else if (got == 2) {
+ /* this should be socket #2 */
+ SOCKET tmp = accept(listener, NULL, NULL);
+ ok(tmp != INVALID_SOCKET, "accept failed %d\n", WSAGetLastError());
+ closesocket(tmp);
+ }
+ else {
+ ok(FALSE, "Got more than 2 connections?\n");
+ }
+ }
+ if ( conn1 && FD_ISSET ( connector2, &fds_send ) ) {
+ /* Send data on second socket, and stop */
+ send(connector2, "2", 1, 0);
+ FD_CLR ( connector2, &fds_send );
+
+ break;
+ }
+ if ( FD_ISSET ( connector, &fds_send ) ) {
+ /* Once #1 is connected, allow #2 to connect */
+ conn1 = 1;
+
+ send(connector, "1", 1, 0);
+ FD_CLR ( connector, &fds_send );
+
+ iret = connect(connector2, (struct sockaddr*)&bindAddress, sizeof(bindAddress));
+ ok(iret == 0 ||
+ (iret == SOCKET_ERROR && WSAGetLastError() == WSAEWOULDBLOCK), "connecting to accepting socket failed, error %d\n", WSAGetLastError());
+ FD_SET ( connector2, &fds_send );
+ }
+ }
+
+ ok (got == 2, "Did not get both connections\n");
+
+ dwret = WaitForSingleObject(overlapped.hEvent, 0);
+ ok(dwret == WAIT_OBJECT_0, "Waiting for accept event failed with %d + errno %d\n", dwret, GetLastError());
+
+ bret = GetOverlappedResult((HANDLE)listener, &overlapped, &bytesReturned, FALSE);
+ ok(bret, "GetOverlappedResult failed, error %d\n", GetLastError());
+ ok(bytesReturned == 0, "bytesReturned isn't supposed to be %d\n", bytesReturned);
+
+ set_blocking(acceptor, TRUE);
+ iret = recv( acceptor, buffer, 2, 0);
+ ok(iret == 1, "Failed to get data, %d\n", iret);
+
+ ok(buffer[0] == '1', "The wrong first client was accepted by acceptex: %c != 1\n", buffer[0]);
closesocket(connector);
connector = INVALID_SOCKET;
@@ -2756,6 +2875,8 @@ end:
closesocket(acceptor);
if (connector != INVALID_SOCKET)
closesocket(connector);
+ if (connector2 != INVALID_SOCKET)
+ closesocket(connector2);
}
/**************** Main program ***************/