From: Zebediah Figura zfigura@codeweavers.com
--- dlls/ws2_32/socket.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-)
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index d3c93e15a47..b0f90cccbe3 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -2709,6 +2709,10 @@ static int add_fd_to_set( SOCKET fd, struct fd_set *set ) int WINAPI select( int count, fd_set *read_ptr, fd_set *write_ptr, fd_set *except_ptr, const struct timeval *timeout) { + static const int read_flags = AFD_POLL_READ | AFD_POLL_ACCEPT | AFD_POLL_HUP | AFD_POLL_RESET; + static const int write_flags = AFD_POLL_WRITE; + static const int except_flags = AFD_POLL_OOB | AFD_POLL_CONNECT_ERR; + struct fd_set *read_input = NULL; struct afd_poll_params *params; unsigned int poll_count = 0; @@ -2760,7 +2764,7 @@ int WINAPI select( int count, fd_set *read_ptr, fd_set *write_ptr, for (i = 0; i < read_ptr->fd_count; ++i) { params->sockets[params->count].socket = read_ptr->fd_array[i]; - params->sockets[params->count].flags = AFD_POLL_READ | AFD_POLL_ACCEPT | AFD_POLL_HUP; + params->sockets[params->count].flags = read_flags; ++params->count; poll_socket = read_ptr->fd_array[i]; } @@ -2771,7 +2775,7 @@ int WINAPI select( int count, fd_set *read_ptr, fd_set *write_ptr, for (i = 0; i < write_ptr->fd_count; ++i) { params->sockets[params->count].socket = write_ptr->fd_array[i]; - params->sockets[params->count].flags = AFD_POLL_WRITE; + params->sockets[params->count].flags = write_flags; ++params->count; poll_socket = write_ptr->fd_array[i]; } @@ -2782,7 +2786,7 @@ int WINAPI select( int count, fd_set *read_ptr, fd_set *write_ptr, for (i = 0; i < except_ptr->fd_count; ++i) { params->sockets[params->count].socket = except_ptr->fd_array[i]; - params->sockets[params->count].flags = AFD_POLL_OOB | AFD_POLL_CONNECT_ERR; + params->sockets[params->count].flags = except_flags; ++params->count; poll_socket = except_ptr->fd_array[i]; } @@ -2819,8 +2823,7 @@ int WINAPI select( int count, fd_set *read_ptr, fd_set *write_ptr, { for (j = 0; j < read_input->fd_count; ++j) { - if (read_input->fd_array[j] == s - && (flags & (AFD_POLL_READ | AFD_POLL_ACCEPT | AFD_POLL_HUP | AFD_POLL_CLOSE))) + if (read_input->fd_array[j] == s && (flags & (read_flags | AFD_POLL_CLOSE))) { ret_count += add_fd_to_set( s, read_ptr ); flags &= ~AFD_POLL_CLOSE; @@ -2831,10 +2834,10 @@ int WINAPI select( int count, fd_set *read_ptr, fd_set *write_ptr, if (flags & AFD_POLL_CLOSE) status = STATUS_INVALID_HANDLE;
- if (flags & AFD_POLL_WRITE) + if (flags & write_flags) ret_count += add_fd_to_set( s, write_ptr );
- if (flags & (AFD_POLL_OOB | AFD_POLL_CONNECT_ERR)) + if (flags & except_flags) ret_count += add_fd_to_set( s, except_ptr ); } }
From: Zebediah Figura zfigura@codeweavers.com
--- dlls/ws2_32/socket.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index b0f90cccbe3..493ea3299a9 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -2839,6 +2839,9 @@ int WINAPI select( int count, fd_set *read_ptr, fd_set *write_ptr,
if (flags & except_flags) ret_count += add_fd_to_set( s, except_ptr ); + + if (flags & ~(read_flags | write_flags | except_flags | AFD_POLL_CLOSE)) + FIXME( "not reporting AFD flags %#x\n", flags ); } }
From: Zebediah Figura zfigura@codeweavers.com
--- dlls/ws2_32/socket.c | 2 +- dlls/ws2_32/tests/sock.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index 493ea3299a9..9d51fef1adb 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -2974,7 +2974,7 @@ int WINAPI WSAPoll( WSAPOLLFD *fds, ULONG count, int timeout ) revents |= POLLRDBAND; if (params->sockets[j].flags & AFD_POLL_WRITE) revents |= POLLWRNORM; - if (params->sockets[j].flags & AFD_POLL_HUP) + if (params->sockets[j].flags & (AFD_POLL_RESET | AFD_POLL_HUP)) revents |= POLLHUP; if (params->sockets[j].flags & (AFD_POLL_RESET | AFD_POLL_CONNECT_ERR)) revents |= POLLERR; diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index b0f07b9ab58..576fe1cee6a 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -12871,7 +12871,7 @@ static void test_tcp_reset(void) 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); + check_poll(client, POLLERR | POLLHUP | POLLWRNORM);
FD_ZERO(&readfds); FD_ZERO(&writefds);
From: Zebediah Figura zfigura@codeweavers.com
--- dlls/ws2_32/tests/afd.c | 17 ++++++++--------- dlls/ws2_32/tests/sock.c | 2 +- server/sock.c | 34 +++++++++++++++++++++++++++++++--- 3 files changed, 40 insertions(+), 13 deletions(-)
diff --git a/dlls/ws2_32/tests/afd.c b/dlls/ws2_32/tests/afd.c index eb525c78c54..21e7a50aef3 100644 --- a/dlls/ws2_32/tests/afd.c +++ b/dlls/ws2_32/tests/afd.c @@ -162,8 +162,7 @@ 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); - todo_wine_if (expect & AFD_POLL_RESET) - ok_(__FILE__, line)(!out_params.sockets[0].status, "got status %#x\n", out_params.sockets[0].status); + ok_(__FILE__, line)(!out_params.sockets[0].status, "got status %#x\n", out_params.sockets[0].status); }
static void test_poll(void) @@ -1407,10 +1406,10 @@ static void test_poll_reset(void) 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); - todo_wine ok(!out_params->sockets[0].status, "got status %#x\n", out_params->sockets[0].status); + 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); + check_poll(client, event, AFD_POLL_WRITE | AFD_POLL_CONNECT | AFD_POLL_RESET);
closesocket(client); CloseHandle(event); @@ -2042,9 +2041,9 @@ static void test_get_events_reset(void) 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); + 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) - todo_wine_if (i == AFD_POLL_BIT_HUP) ok(!params.status[i], "got status[%u] %#x\n", i, params.status[i]); + ok(!params.status[i], "got status[%u] %#x\n", i, params.status[i]);
closesocket(client);
@@ -2060,9 +2059,9 @@ static void test_get_events_reset(void) 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); + ok(params.flags == (AFD_POLL_RESET | AFD_POLL_WRITE), "got flags %#x\n", params.flags); for (i = 0; i < ARRAY_SIZE(params.status); ++i) - todo_wine_if (i == AFD_POLL_BIT_HUP) ok(!params.status[i], "got status[%u] %#x\n", i, params.status[i]); + ok(!params.status[i], "got status[%u] %#x\n", i, params.status[i]);
closesocket(server);
diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index 576fe1cee6a..3e6faaffa4c 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -12861,7 +12861,7 @@ static void test_tcp_reset(void) 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); + ok(!error, "got error %u\n", error);
wsabuf.buf = buffer; wsabuf.len = sizeof(buffer); diff --git a/server/sock.c b/server/sock.c index 53553ab8ee7..7d7e470be28 100644 --- a/server/sock.c +++ b/server/sock.c @@ -232,6 +232,7 @@ struct sock unsigned int aborted : 1; /* did we get a POLLERR or irregular POLLHUP? */ unsigned int nonblocking : 1; /* is the socket nonblocking? */ unsigned int bound : 1; /* is the socket bound? */ + unsigned int reset : 1; /* did we get a TCP reset? */ };
static void sock_dump( struct object *obj, int verbose ); @@ -667,7 +668,12 @@ static inline int sock_error( struct sock *sock )
case SOCK_CONNECTED: case SOCK_CONNECTIONLESS: - if (error) + if (error == ECONNRESET || error == EPIPE) + { + sock->reset = 1; + error = 0; + } + else if (error) sock->errors[AFD_POLL_BIT_HUP] = error; else error = sock->errors[AFD_POLL_BIT_HUP]; @@ -897,6 +903,8 @@ static int get_poll_flags( struct sock *sock, int event ) flags |= AFD_POLL_HUP; if (event & POLLERR) flags |= AFD_POLL_CONNECT_ERR; + if (sock->reset) + flags |= AFD_POLL_RESET;
return flags; } @@ -1081,6 +1089,15 @@ static int sock_dispatch_asyncs( struct sock *sock, int event, int error ) async_terminate( sock->connect_req->async, status ); }
+ if (sock->reset) + { + async_wake_up( &sock->read_q, STATUS_CONNECTION_RESET ); + async_wake_up( &sock->write_q, STATUS_CONNECTION_RESET ); + + if (sock->accept_recv_req && sock->accept_recv_req->iosb->status == STATUS_PENDING) + async_terminate( sock->accept_recv_req->async, STATUS_CONNECTION_RESET ); + } + return event; }
@@ -1116,6 +1133,9 @@ static void sock_dispatch_events( struct sock *sock, enum connection_state prevs
case SOCK_CONNECTED: case SOCK_CONNECTIONLESS: + if (sock->reset) + post_socket_event( sock, AFD_POLL_BIT_RESET ); + if (event & POLLIN) post_socket_event( sock, AFD_POLL_BIT_READ );
@@ -1171,6 +1191,9 @@ static void sock_poll_event( struct fd *fd, int event )
case SOCK_CONNECTED: case SOCK_CONNECTIONLESS: + if (sock->reset) + event &= ~(POLLIN | POLLERR | POLLHUP); + if (sock->type == WS_SOCK_STREAM && (event & POLLIN)) { char dummy; @@ -1189,7 +1212,11 @@ static void sock_poll_event( struct fd *fd, int event ) event &= ~POLLIN; /* EAGAIN can happen if an async recv() falls between the server's poll() call and the invocation of this routine */ - if ( errno != EAGAIN ) + if (errno == ECONNRESET || errno == EPIPE) + { + sock->reset = 1; + } + else if (errno != EAGAIN) { error = errno; event |= POLLERR; @@ -1312,7 +1339,7 @@ static int sock_get_poll_events( struct fd *fd ) return -1; }
- if (sock->aborted) + if (sock->aborted || sock->reset) return -1;
if (sock->accept_recv_req) @@ -1517,6 +1544,7 @@ static struct sock *create_socket(void) sock->aborted = 0; sock->nonblocking = 0; sock->bound = 0; + sock->reset = 0; sock->rcvbuf = 0; sock->sndbuf = 0; sock->rcvtimeo = 0;