Commit 7961e00e authored by Zebediah Figura's avatar Zebediah Figura Committed by Alexandre Julliard

server: Properly implement AFD_POLL_RESET.

parent 21dfab61
......@@ -162,7 +162,6 @@ 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);
}
......@@ -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, &params, 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, &params, 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);
......
......@@ -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);
......
......@@ -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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment