Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/ws2_32/tests/afd.c | 12 ++++++++++++ dlls/ws2_32/tests/sock.c | 3 +++ 2 files changed, 15 insertions(+)
diff --git a/dlls/ws2_32/tests/afd.c b/dlls/ws2_32/tests/afd.c index 43c401c940a..184c7e0725a 100644 --- a/dlls/ws2_32/tests/afd.c +++ b/dlls/ws2_32/tests/afd.c @@ -1819,6 +1819,18 @@ static void test_get_events(void) ok(!ret, "got error %lu\n", GetLastError()); ok(!events.lNetworkEvents, "got events %#lx\n", events.lNetworkEvents);
+ ret = WSAEventSelect(server, event, FD_ACCEPT | FD_CLOSE | FD_CONNECT | FD_OOB | FD_READ | FD_WRITE); + ok(!ret, "got error %lu\n", GetLastError()); + + memset(¶ms, 0xcc, sizeof(params)); + memset(&io, 0xcc, sizeof(io)); + ret = NtDeviceIoControlFile((HANDLE)server, NULL, NULL, NULL, &io, + IOCTL_AFD_GET_EVENTS, NULL, 0, ¶ms, sizeof(params)); + ok(!ret, "got %#x\n", ret); + ok(params.flags == AFD_POLL_WRITE, "got flags %#x\n", params.flags); + for (i = 0; i < ARRAY_SIZE(params.status); ++i) + ok(!params.status[i], "got status[%u] %#x\n", i, params.status[i]); + closesocket(client); closesocket(server);
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index 78c778586a8..ff3ff98e657 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -5599,6 +5599,9 @@ static void test_connect_events(struct event_test_ctx *ctx) server = accept(listener, NULL, NULL); ok(server != -1, "failed to accept, error %u\n", WSAGetLastError());
+ select_events(ctx, server, FD_ACCEPT | FD_CONNECT | FD_OOB | FD_READ | FD_WRITE); + check_events(ctx, FD_WRITE, 0, 200); + closesocket(client); closesocket(server);
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/ws2_32/tests/sock.c | 58 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+)
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index ff3ff98e657..33d7ed42262 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -219,6 +219,17 @@ static void check_poll_(int line, SOCKET s, short mask, short expect, BOOL todo) todo_wine_if (todo) ok_(__FILE__, line)(pollfd.revents == expect, "got wrong events %#x\n", pollfd.revents); }
+static DWORD WINAPI poll_async_thread(void *arg) +{ + WSAPOLLFD *pollfd = arg; + int ret; + + ret = pWSAPoll(pollfd, 1, 500); + ok(ret == (pollfd->revents ? 1 : 0), "WSAPoll() returned %d\n", ret); + + return 0; +} + static void set_so_opentype ( BOOL overlapped ) { int optval = !overlapped, newval, len = sizeof (int); @@ -5740,6 +5751,26 @@ static void test_write_events(struct event_test_ctx *ctx) closesocket(server); closesocket(client);
+ /* Select on a subset not containing FD_WRITE first. */ + + tcp_socketpair(&client, &server); + set_blocking(client, FALSE); + + ret = send(client, "data", 5, 0); + ok(ret == 5, "got %d\n", ret); + + select_events(ctx, client, FD_ACCEPT | FD_CONNECT | FD_OOB | FD_READ); + if (!ctx->is_message) + check_events(ctx, FD_CONNECT, 0, 200); + check_events(ctx, 0, 0, 0); + + select_events(ctx, client, FD_ACCEPT | FD_CONNECT | FD_OOB | FD_READ | FD_WRITE); + check_events(ctx, FD_WRITE, 0, 200); + check_events(ctx, 0, 0, 0); + + closesocket(client); + closesocket(server); + /* Despite the documentation, and unlike FD_ACCEPT and FD_RECV, calling * send() doesn't clear the FD_WRITE bit. */
@@ -5763,9 +5794,11 @@ static void test_read_events(struct event_test_ctx *ctx) OVERLAPPED overlapped = {0}; SOCKET server, client; DWORD size, flags = 0; + WSAPOLLFD pollfd; unsigned int i; char buffer[8]; WSABUF wsabuf; + HANDLE thread; int ret;
overlapped.hEvent = CreateEventA(NULL, TRUE, FALSE, NULL); @@ -5844,6 +5877,31 @@ static void test_read_events(struct event_test_ctx *ctx)
check_events(ctx, 0, 0, 200);
+ /* Send data while we're polling for data but not selecting for FD_READ. */ + + pollfd.fd = server; + pollfd.events = POLLIN; + thread = CreateThread(NULL, 0, poll_async_thread, &pollfd, 0, NULL); + + select_events(ctx, server, 0); + ret = send(client, "data", 5, 0); + ok(ret == 5, "got %d\n", ret); + + ret = WaitForSingleObject(thread, 1000); + ok(!ret, "wait timed out\n"); + CloseHandle(thread); + + /* And check events, to show that WSAEnumNetworkEvents() should not clear + * events we are not currently selecting for. */ + check_events(ctx, 0, 0, 0); + + select_events(ctx, server, FD_ACCEPT | FD_CONNECT | FD_OOB | FD_READ | FD_WRITE); + check_events_todo(ctx, FD_READ, FD_WRITE, 200); + check_events(ctx, 0, 0, 0); + + ret = sync_recv(server, buffer, 5, 0); + ok(ret == 5, "got %d\n", ret); + /* Send data while there is a pending WSARecv(). */
select_events(ctx, server, FD_ACCEPT | FD_CLOSE | FD_CONNECT | FD_OOB | FD_READ);
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/ws2_32/tests/sock.c | 2 +- server/sock.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index 33d7ed42262..10ac4ed2abe 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -5896,7 +5896,7 @@ static void test_read_events(struct event_test_ctx *ctx) check_events(ctx, 0, 0, 0);
select_events(ctx, server, FD_ACCEPT | FD_CONNECT | FD_OOB | FD_READ | FD_WRITE); - check_events_todo(ctx, FD_READ, FD_WRITE, 200); + check_events_todo_event(ctx, FD_READ, FD_WRITE, 200); check_events(ctx, 0, 0, 0);
ret = sync_recv(server, buffer, 5, 0); diff --git a/server/sock.c b/server/sock.c index a9d8d2ca2bd..9f9b9bdfcd9 100644 --- a/server/sock.c +++ b/server/sock.c @@ -505,8 +505,8 @@ static const enum afd_poll_bit event_bitorder[] = AFD_POLL_BIT_CONNECT_ERR, AFD_POLL_BIT_ACCEPT, AFD_POLL_BIT_OOB, - AFD_POLL_BIT_WRITE, AFD_POLL_BIT_READ, + AFD_POLL_BIT_WRITE, AFD_POLL_BIT_RESET, AFD_POLL_BIT_HUP, AFD_POLL_BIT_CLOSE,
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/ws2_32/tests/sock.c | 6 +++--- server/sock.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index 10ac4ed2abe..4eb2d16f871 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -5659,7 +5659,7 @@ static void test_connect_events(struct event_test_ctx *ctx) if (ctx->is_message) check_events(ctx, FD_WRITE, 0, 200); else - check_events_todo(ctx, FD_CONNECT, 0, 200); + check_events(ctx, FD_CONNECT, 0, 200);
closesocket(client); closesocket(server); @@ -5896,7 +5896,7 @@ static void test_read_events(struct event_test_ctx *ctx) check_events(ctx, 0, 0, 0);
select_events(ctx, server, FD_ACCEPT | FD_CONNECT | FD_OOB | FD_READ | FD_WRITE); - check_events_todo_event(ctx, FD_READ, FD_WRITE, 200); + check_events(ctx, FD_READ, FD_WRITE, 200); check_events(ctx, 0, 0, 0);
ret = sync_recv(server, buffer, 5, 0); @@ -6111,7 +6111,7 @@ static void test_close_events(struct event_test_ctx *ctx)
check_events(ctx, 0, 0, 200); select_events(ctx, server, FD_ACCEPT | FD_CLOSE | FD_CONNECT | FD_OOB | FD_READ); - check_events_todo_event(ctx, FD_CLOSE, 0, 200); + check_events(ctx, FD_CLOSE, 0, 200);
closesocket(server); } diff --git a/server/sock.c b/server/sock.c index 9f9b9bdfcd9..29dd1ca7fa8 100644 --- a/server/sock.c +++ b/server/sock.c @@ -2516,7 +2516,7 @@ static void sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ) for (i = 0; i < ARRAY_SIZE( params.status ); ++i) params.status[i] = sock_get_ntstatus( sock->errors[i] );
- sock->pending_events = 0; + sock->pending_events &= ~sock->mask; sock_reselect( sock );
set_reply_data( ¶ms, sizeof(params) );
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/ws2_32/tests/afd.c | 114 +++++++++++++++++++++++++++- dlls/ws2_32/tests/sock.c | 155 +++++++++++++++++++++++++++++++-------- 2 files changed, 237 insertions(+), 32 deletions(-)
diff --git a/dlls/ws2_32/tests/afd.c b/dlls/ws2_32/tests/afd.c index 184c7e0725a..cf27b4003c5 100644 --- a/dlls/ws2_32/tests/afd.c +++ b/dlls/ws2_32/tests/afd.c @@ -76,6 +76,21 @@ static void set_blocking(SOCKET s, ULONG blocking) ok(!ret, "got error %u\n", WSAGetLastError()); }
+/* Set the linger timeout to zero and close the socket. This will trigger an + * RST on the connection on Windows as well as on Unix systems. */ +static void close_with_rst(SOCKET s) +{ + static const struct linger linger = {.l_onoff = 1}; + int ret; + + SetLastError(0xdeadbeef); + ret = setsockopt(s, SOL_SOCKET, SO_LINGER, (const char *)&linger, sizeof(linger)); + ok(!ret, "got %d\n", ret); + ok(!GetLastError(), "got error %lu\n", GetLastError()); + + closesocket(s); +} + static void test_open_device(void) { OBJECT_BASIC_INFORMATION info; @@ -142,7 +157,8 @@ static void check_poll_(int line, SOCKET s, HANDLE event, int mask, int expect, ok_(__FILE__, line)(out_params.count == 1, "got count %u\n", out_params.count); ok_(__FILE__, line)(out_params.sockets[0].socket == s, "got socket %#Ix\n", out_params.sockets[0].socket); todo_wine_if (todo) ok_(__FILE__, line)(out_params.sockets[0].flags == expect, "got flags %#x\n", out_params.sockets[0].flags); - ok_(__FILE__, line)(!out_params.sockets[0].status, "got status %#x\n", out_params.sockets[0].status); + todo_wine_if (expect & AFD_POLL_RESET) + ok_(__FILE__, line)(!out_params.sockets[0].status, "got status %#x\n", out_params.sockets[0].status); }
static void test_poll(void) @@ -1311,6 +1327,50 @@ static void test_poll_completion_port(void) CloseHandle(event); }
+static void test_poll_reset(void) +{ + char in_buffer[offsetof(struct afd_poll_params, sockets[3])]; + char out_buffer[offsetof(struct afd_poll_params, sockets[3])]; + struct afd_poll_params *in_params = (struct afd_poll_params *)in_buffer; + struct afd_poll_params *out_params = (struct afd_poll_params *)out_buffer; + SOCKET client, server; + IO_STATUS_BLOCK io; + ULONG params_size; + HANDLE event; + int ret; + + memset(in_buffer, 0, sizeof(in_buffer)); + memset(out_buffer, 0, sizeof(out_buffer)); + event = CreateEventW(NULL, TRUE, FALSE, NULL); + tcp_socketpair(&client, &server); + + in_params->timeout = -1000 * 10000; + in_params->count = 1; + in_params->sockets[0].socket = client; + in_params->sockets[0].flags = ~(AFD_POLL_WRITE | AFD_POLL_CONNECT); + params_size = offsetof(struct afd_poll_params, sockets[1]); + + ret = NtDeviceIoControlFile((HANDLE)client, event, NULL, NULL, &io, + IOCTL_AFD_POLL, in_params, params_size, out_params, params_size); + ok(ret == STATUS_PENDING, "got %#x\n", ret); + + close_with_rst(server); + + ret = WaitForSingleObject(event, 100); + ok(!ret, "got %#x\n", ret); + ok(!io.Status, "got %#lx\n", io.Status); + ok(io.Information == offsetof(struct afd_poll_params, sockets[1]), "got %#Ix\n", io.Information); + ok(out_params->count == 1, "got count %u\n", out_params->count); + ok(out_params->sockets[0].socket == client, "got socket %#Ix\n", out_params->sockets[0].socket); + todo_wine ok(out_params->sockets[0].flags == AFD_POLL_RESET, "got flags %#x\n", out_params->sockets[0].flags); + ok(!out_params->sockets[0].status, "got status %#x\n", out_params->sockets[0].status); + + check_poll_todo(client, event, AFD_POLL_WRITE | AFD_POLL_CONNECT | AFD_POLL_RESET); + + closesocket(client); + CloseHandle(event); +} + static void test_recv(void) { const struct sockaddr_in bind_addr = {.sin_family = AF_INET, .sin_addr.s_addr = htonl(INADDR_LOOPBACK)}; @@ -1914,6 +1974,56 @@ static void test_get_events(void) CloseHandle(event); }
+static void test_get_events_reset(void) +{ + struct afd_get_events_params params; + SOCKET client, server; + IO_STATUS_BLOCK io; + unsigned int i; + HANDLE event; + int ret; + + event = CreateEventW(NULL, TRUE, FALSE, NULL); + + tcp_socketpair(&client, &server); + + ret = WSAEventSelect(client, event, FD_ACCEPT | FD_CONNECT | FD_CLOSE | FD_OOB | FD_READ | FD_WRITE); + ok(!ret, "got error %lu\n", GetLastError()); + + close_with_rst(server); + + memset(¶ms, 0xcc, sizeof(params)); + memset(&io, 0xcc, sizeof(io)); + ret = NtDeviceIoControlFile((HANDLE)client, NULL, NULL, NULL, &io, + IOCTL_AFD_GET_EVENTS, NULL, 0, ¶ms, sizeof(params)); + ok(!ret, "got %#x\n", ret); + todo_wine ok(params.flags == (AFD_POLL_RESET | AFD_POLL_CONNECT | AFD_POLL_WRITE), "got flags %#x\n", params.flags); + for (i = 0; i < ARRAY_SIZE(params.status); ++i) + ok(!params.status[i], "got status[%u] %#x\n", i, params.status[i]); + + closesocket(client); + + tcp_socketpair(&client, &server); + + ret = WSAEventSelect(server, event, FD_ACCEPT | FD_CONNECT | FD_CLOSE | FD_OOB | FD_READ | FD_WRITE); + ok(!ret, "got error %lu\n", GetLastError()); + + close_with_rst(client); + + memset(¶ms, 0xcc, sizeof(params)); + memset(&io, 0xcc, sizeof(io)); + ret = NtDeviceIoControlFile((HANDLE)server, NULL, NULL, NULL, &io, + IOCTL_AFD_GET_EVENTS, NULL, 0, ¶ms, sizeof(params)); + ok(!ret, "got %#x\n", ret); + todo_wine ok(params.flags == (AFD_POLL_RESET | AFD_POLL_WRITE), "got flags %#x\n", params.flags); + for (i = 0; i < ARRAY_SIZE(params.status); ++i) + ok(!params.status[i], "got status[%u] %#x\n", i, params.status[i]); + + closesocket(server); + + CloseHandle(event); +} + static void test_bind(void) { const struct sockaddr_in6 bind_addr6 = {.sin6_family = AF_INET6, .sin6_addr.s6_words = {0, 0, 0, 0, 0, 0, 0, htons(1)}}; @@ -2255,9 +2365,11 @@ START_TEST(afd) test_poll(); test_poll_exclusive(); test_poll_completion_port(); + test_poll_reset(); test_recv(); test_event_select(); test_get_events(); + test_get_events_reset(); test_bind(); test_getsockname();
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index 4eb2d16f871..99221ad52ca 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -202,6 +202,21 @@ static void tcp_socketpair(SOCKET *src, SOCKET *dst) tcp_socketpair_flags(src, dst, WSA_FLAG_OVERLAPPED); }
+/* Set the linger timeout to zero and close the socket. This will trigger an + * RST on the connection on Windows as well as on Unix systems. */ +static void close_with_rst(SOCKET s) +{ + static const struct linger linger = {.l_onoff = 1}; + int ret; + + SetLastError(0xdeadbeef); + ret = setsockopt(s, SOL_SOCKET, SO_LINGER, (const char *)&linger, sizeof(linger)); + ok(!ret, "got %d\n", ret); + ok(!GetLastError(), "got error %lu\n", GetLastError()); + + closesocket(s); +} + #define check_poll(a, b) check_poll_(__LINE__, a, POLLRDNORM | POLLRDBAND | POLLWRNORM, b, FALSE) #define check_poll_todo(a, b) check_poll_(__LINE__, a, POLLRDNORM | POLLRDBAND | POLLWRNORM, b, TRUE) #define check_poll_mask(a, b, c) check_poll_(__LINE__, a, b, c, FALSE) @@ -5302,7 +5317,9 @@ static void check_events_(int line, struct event_test_ctx *ctx, else { WSANETWORKEVENTS events; + unsigned int i;
+ memset(&events, 0xcc, sizeof(events)); ret = WaitForSingleObject(ctx->event, timeout); if (flag1 | flag2) todo_wine_if (todo_event && ret) ok_(__FILE__, line)(!ret, "event wait timed out\n"); @@ -5311,7 +5328,16 @@ static void check_events_(int line, struct event_test_ctx *ctx, ret = WSAEnumNetworkEvents(ctx->socket, ctx->event, &events); ok_(__FILE__, line)(!ret, "failed to get events, error %u\n", WSAGetLastError()); todo_wine_if (todo_event) - ok_(__FILE__, line)(events.lNetworkEvents == (flag1 | flag2), "got events %#lx\n", events.lNetworkEvents); + ok_(__FILE__, line)(events.lNetworkEvents == LOWORD(flag1 | flag2), "got events %#lx\n", events.lNetworkEvents); + for (i = 0; i < ARRAY_SIZE(events.iErrorCode); ++i) + { + if ((1u << i) == LOWORD(flag1) && (events.lNetworkEvents & LOWORD(flag1))) + todo_wine_if (HIWORD(flag1)) ok_(__FILE__, line)(events.iErrorCode[i] == HIWORD(flag1), + "got error code %d for event %#x\n", events.iErrorCode[i], 1u << i); + if ((1u << i) == LOWORD(flag2) && (events.lNetworkEvents & LOWORD(flag2))) + ok_(__FILE__, line)(events.iErrorCode[i] == HIWORD(flag2), + "got error code %d for event %#x\n", events.iErrorCode[i], 1u << i); + } } }
@@ -6114,6 +6140,28 @@ static void test_close_events(struct event_test_ctx *ctx) check_events(ctx, FD_CLOSE, 0, 200);
closesocket(server); + + /* Trigger RST. */ + + tcp_socketpair(&client, &server); + + select_events(ctx, server, FD_ACCEPT | FD_CLOSE | FD_CONNECT | FD_OOB | FD_READ); + + close_with_rst(client); + + check_events_todo_msg(ctx, MAKELONG(FD_CLOSE, WSAECONNABORTED), 0, 200); + check_events(ctx, 0, 0, 0); + select_events(ctx, server, FD_ACCEPT | FD_CLOSE | FD_CONNECT | FD_OOB | FD_READ); + if (ctx->is_message) + check_events_todo(ctx, MAKELONG(FD_CLOSE, WSAECONNABORTED), 0, 200); + check_events(ctx, 0, 0, 0); + select_events(ctx, server, 0); + select_events(ctx, server, FD_ACCEPT | FD_CLOSE | FD_CONNECT | FD_OOB | FD_READ); + if (ctx->is_message) + check_events_todo(ctx, MAKELONG(FD_CLOSE, WSAECONNABORTED), 0, 200); + check_events(ctx, 0, 0, 0); + + closesocket(server); }
static void test_events(void) @@ -6552,7 +6600,6 @@ static void test_WSARecv(void) WSABUF bufs[2]; WSAOVERLAPPED ov; DWORD bytesReturned, flags, id; - struct linger ling; struct sockaddr_in addr; int iret, len; DWORD dwret; @@ -6621,19 +6668,13 @@ static void test_WSARecv(void) if (!event) goto end;
- ling.l_onoff = 1; - ling.l_linger = 0; - iret = setsockopt (src, SOL_SOCKET, SO_LINGER, (char *) &ling, sizeof(ling)); - ok(!iret, "Failed to set linger %ld\n", GetLastError()); - iret = WSARecv(dest, bufs, 1, NULL, &flags, &ov, NULL); ok(iret == SOCKET_ERROR && GetLastError() == ERROR_IO_PENDING, "WSARecv failed - %d error %ld\n", iret, GetLastError());
iret = WSARecv(dest, bufs, 1, &bytesReturned, &flags, &ov, NULL); ok(iret == SOCKET_ERROR && GetLastError() == ERROR_IO_PENDING, "WSARecv failed - %d error %ld\n", iret, GetLastError());
- closesocket(src); - src = INVALID_SOCKET; + close_with_rst(src);
dwret = WaitForSingleObject(ov.hEvent, 1000); ok(dwret == WAIT_OBJECT_0, "Waiting for disconnect event failed with %ld + errno %ld\n", dwret, GetLastError()); @@ -9239,7 +9280,6 @@ static void test_completion_port(void) char buf[1024]; WSABUF bufs; DWORD num_bytes, flags; - struct linger ling; int iret; BOOL bret; ULONG_PTR key; @@ -9260,11 +9300,6 @@ static void test_completion_port(void) bufs.buf = buf; flags = 0;
- ling.l_onoff = 1; - ling.l_linger = 0; - iret = setsockopt (src, SOL_SOCKET, SO_LINGER, (char *) &ling, sizeof(ling)); - ok(!iret, "Failed to set linger %ld\n", GetLastError()); - io_port = CreateIoCompletionPort( (HANDLE)dest, io_port, 125, 0 ); ok(io_port != NULL, "Failed to create completion port %lu\n", GetLastError());
@@ -9276,8 +9311,7 @@ static void test_completion_port(void)
Sleep(100);
- closesocket(src); - src = INVALID_SOCKET; + close_with_rst(src);
SetLastError(0xdeadbeef); key = 0xdeadbeef; @@ -9314,18 +9348,12 @@ static void test_completion_port(void) bufs.buf = buf; flags = 0;
- ling.l_onoff = 1; - ling.l_linger = 0; - iret = setsockopt (src, SOL_SOCKET, SO_LINGER, (char *) &ling, sizeof(ling)); - ok(!iret, "Failed to set linger %ld\n", GetLastError()); - io_port = CreateIoCompletionPort((HANDLE)dest, io_port, 125, 0); ok(io_port != NULL, "failed to create completion port %lu\n", GetLastError());
set_blocking(dest, FALSE);
- closesocket(src); - src = INVALID_SOCKET; + close_with_rst(src);
Sleep(100);
@@ -9432,17 +9460,11 @@ static void test_completion_port(void) flags = 0; memset(&ov, 0, sizeof(ov));
- ling.l_onoff = 1; - ling.l_linger = 0; - iret = setsockopt (src, SOL_SOCKET, SO_LINGER, (char *) &ling, sizeof(ling)); - ok(!iret, "Failed to set linger %ld\n", GetLastError()); - io_port = CreateIoCompletionPort((HANDLE)dest, io_port, 125, 0); ok(io_port != NULL, "failed to create completion port %lu\n", GetLastError()); set_blocking(dest, FALSE);
- closesocket(src); - src = INVALID_SOCKET; + close_with_rst(src);
FD_ZERO(&fds_recv); FD_SET(dest, &fds_recv); @@ -12441,6 +12463,76 @@ static void test_sockopt_validity(void) CloseHandle(file); }
+static void test_tcp_reset(void) +{ + static const struct timeval select_timeout; + fd_set readfds, writefds, exceptfds; + OVERLAPPED overlapped = {0}; + SOCKET client, server; + DWORD size, flags = 0; + int ret, len, error; + char buffer[10]; + WSABUF wsabuf; + + overlapped.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL); + + tcp_socketpair(&client, &server); + + wsabuf.buf = buffer; + wsabuf.len = sizeof(buffer); + WSASetLastError(0xdeadbeef); + size = 0xdeadbeef; + ret = WSARecv(client, &wsabuf, 1, &size, &flags, &overlapped, NULL); + ok(ret == -1, "got %d\n", ret); + ok(WSAGetLastError() == ERROR_IO_PENDING, "got error %u\n", WSAGetLastError()); + + close_with_rst(server); + + ret = WaitForSingleObject(overlapped.hEvent, 1000); + ok(!ret, "wait failed\n"); + ret = GetOverlappedResult((HANDLE)client, &overlapped, &size, FALSE); + todo_wine ok(!ret, "expected failure\n"); + todo_wine ok(GetLastError() == ERROR_NETNAME_DELETED, "got error %lu\n", GetLastError()); + ok(!size, "got size %lu\n", size); + todo_wine ok((NTSTATUS)overlapped.Internal == STATUS_CONNECTION_RESET, "got status %#lx\n", (NTSTATUS)overlapped.Internal); + + len = sizeof(error); + ret = getsockopt(client, SOL_SOCKET, SO_ERROR, (char *)&error, &len); + ok(!ret, "got error %u\n", WSAGetLastError()); + todo_wine ok(!error, "got error %u\n", error); + + wsabuf.buf = buffer; + wsabuf.len = sizeof(buffer); + WSASetLastError(0xdeadbeef); + size = 0xdeadbeef; + ret = WSARecv(client, &wsabuf, 1, &size, &flags, &overlapped, NULL); + todo_wine ok(ret == -1, "got %d\n", ret); + todo_wine ok(WSAGetLastError() == WSAECONNRESET, "got error %u\n", WSAGetLastError()); + + check_poll_todo(client, POLLERR | POLLHUP | POLLWRNORM); + + FD_ZERO(&readfds); + FD_ZERO(&writefds); + FD_ZERO(&exceptfds); + FD_SET(client, &readfds); + FD_SET(client, &writefds); + FD_SET(client, &exceptfds); + ret = select(0, &readfds, &writefds, &exceptfds, &select_timeout); + ok(ret == 2, "got %d\n", ret); + ok(FD_ISSET(client, &readfds), "FD should be set\n"); + ok(FD_ISSET(client, &writefds), "FD should be set\n"); + ok(!FD_ISSET(client, &exceptfds), "FD should be set\n"); + + FD_ZERO(&exceptfds); + FD_SET(client, &exceptfds); + ret = select(0, NULL, NULL, &exceptfds, &select_timeout); + ok(!ret, "got %d\n", ret); + ok(!FD_ISSET(client, &exceptfds), "FD should be set\n"); + + closesocket(server); + CloseHandle(overlapped.hEvent); +} + START_TEST( sock ) { int i; @@ -12514,6 +12606,7 @@ START_TEST( sock ) test_simultaneous_async_recv(); test_empty_recv(); test_timeout(); + test_tcp_reset();
/* this is an io heavy test, do it at the end so the kernel doesn't start dropping packets */ test_send();
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=114067
Your paranoid android.
=== debian11 (32 bit Hebrew:Israel report) ===
ws2_32: sock.c:3629: Test failed: select returned 2 sock.c:3630: Test failed: fdWrite socket is in the set