Commit 2bad8d9f authored by Zebediah Figura's avatar Zebediah Figura Committed by Alexandre Julliard

http.sys: Keep connection sockets open after sending a 400 response.

Tests show that the socket is shut down, but sending further data doesn't result in a TCP reset, so we need to keep the socket itself open until the TCP connection is closed.
parent 25bcb9d3
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
*/ */
#include <assert.h> #include <assert.h>
#include <stdbool.h>
#include "ntstatus.h" #include "ntstatus.h"
#define WIN32_NO_STATUS #define WIN32_NO_STATUS
#include "wine/http.h" #include "wine/http.h"
...@@ -54,6 +55,7 @@ struct connection ...@@ -54,6 +55,7 @@ struct connection
char *buffer; char *buffer;
unsigned int len, size; unsigned int len, size;
bool shutdown;
/* If there is a request fully received and waiting to be read, the /* If there is a request fully received and waiting to be read, the
* "available" parameter will be TRUE. Either there is no queue matching * "available" parameter will be TRUE. Either there is no queue matching
...@@ -111,7 +113,7 @@ static struct list request_queues = LIST_INIT(request_queues); ...@@ -111,7 +113,7 @@ static struct list request_queues = LIST_INIT(request_queues);
static void accept_connection(SOCKET socket) static void accept_connection(SOCKET socket)
{ {
struct connection *conn; struct connection *conn;
ULONG true = 1; ULONG one = 1;
SOCKET peer; SOCKET peer;
if ((peer = accept(socket, NULL, NULL)) == INVALID_SOCKET) if ((peer = accept(socket, NULL, NULL)) == INVALID_SOCKET)
...@@ -134,15 +136,22 @@ static void accept_connection(SOCKET socket) ...@@ -134,15 +136,22 @@ static void accept_connection(SOCKET socket)
} }
conn->size = 8192; conn->size = 8192;
WSAEventSelect(peer, request_event, FD_READ | FD_CLOSE); WSAEventSelect(peer, request_event, FD_READ | FD_CLOSE);
ioctlsocket(peer, FIONBIO, &true); ioctlsocket(peer, FIONBIO, &one);
conn->socket = peer; conn->socket = peer;
list_add_head(&connections, &conn->entry); list_add_head(&connections, &conn->entry);
} }
static void close_connection(struct connection *conn) static void shutdown_connection(struct connection *conn)
{ {
free(conn->buffer); free(conn->buffer);
shutdown(conn->socket, SD_BOTH); shutdown(conn->socket, SD_BOTH);
conn->shutdown = true;
}
static void close_connection(struct connection *conn)
{
if (!conn->shutdown)
shutdown_connection(conn);
closesocket(conn->socket); closesocket(conn->socket);
list_remove(&conn->entry); list_remove(&conn->entry);
free(conn); free(conn);
...@@ -593,12 +602,24 @@ static void send_400(struct connection *conn) ...@@ -593,12 +602,24 @@ static void send_400(struct connection *conn)
strcat(buffer, response_body); strcat(buffer, response_body);
if (send(conn->socket, buffer, strlen(buffer), 0) < 0) if (send(conn->socket, buffer, strlen(buffer), 0) < 0)
ERR("Failed to send 400 response, error %u.\n", WSAGetLastError()); ERR("Failed to send 400 response, error %u.\n", WSAGetLastError());
shutdown_connection(conn);
} }
static void receive_data(struct connection *conn) static void receive_data(struct connection *conn)
{ {
int len, ret; int len, ret;
if (conn->shutdown)
{
WSANETWORKEVENTS events;
if ((ret = WSAEnumNetworkEvents(conn->socket, NULL, &events)) < 0)
ERR("Failed to enumerate network events, error %u.\n", WSAGetLastError());
if (events.lNetworkEvents & FD_CLOSE)
close_connection(conn);
return;
}
/* We might be waiting for an IRP, but always call recv() anyway, since we /* We might be waiting for an IRP, but always call recv() anyway, since we
* might have been woken up by the socket closing. */ * might have been woken up by the socket closing. */
if ((len = recv(conn->socket, conn->buffer + conn->len, conn->size - conn->len, 0)) <= 0) if ((len = recv(conn->socket, conn->buffer + conn->len, conn->size - conn->len, 0)) <= 0)
...@@ -653,7 +674,6 @@ static void receive_data(struct connection *conn) ...@@ -653,7 +674,6 @@ static void receive_data(struct connection *conn)
{ {
WARN("Failed to parse request; shutting down connection.\n"); WARN("Failed to parse request; shutting down connection.\n");
send_400(conn); send_400(conn);
close_connection(conn);
} }
} }
...@@ -714,7 +734,7 @@ static NTSTATUS http_add_url(struct request_queue *queue, IRP *irp) ...@@ -714,7 +734,7 @@ static NTSTATUS http_add_url(struct request_queue *queue, IRP *irp)
struct listening_socket *listening_sock; struct listening_socket *listening_sock;
char *url, *endptr; char *url, *endptr;
size_t queue_url_len, new_url_len; size_t queue_url_len, new_url_len;
ULONG true = 1, value; ULONG one = 1, value;
SOCKET s = INVALID_SOCKET; SOCKET s = INVALID_SOCKET;
TRACE("host %s, context %s.\n", debugstr_a(params->url), wine_dbgstr_longlong(params->context)); TRACE("host %s, context %s.\n", debugstr_a(params->url), wine_dbgstr_longlong(params->context));
...@@ -823,7 +843,7 @@ static NTSTATUS http_add_url(struct request_queue *queue, IRP *irp) ...@@ -823,7 +843,7 @@ static NTSTATUS http_add_url(struct request_queue *queue, IRP *irp)
listening_sock->socket = s; listening_sock->socket = s;
list_add_head(&listening_sockets, &listening_sock->entry); list_add_head(&listening_sockets, &listening_sock->entry);
ioctlsocket(s, FIONBIO, &true); ioctlsocket(s, FIONBIO, &one);
WSAEventSelect(s, request_event, FD_ACCEPT); WSAEventSelect(s, request_event, FD_ACCEPT);
} }
...@@ -1002,7 +1022,6 @@ static NTSTATUS http_send_response(struct request_queue *queue, IRP *irp) ...@@ -1002,7 +1022,6 @@ static NTSTATUS http_send_response(struct request_queue *queue, IRP *irp)
{ {
WARN("Failed to parse request; shutting down connection.\n"); WARN("Failed to parse request; shutting down connection.\n");
send_400(conn); send_400(conn);
close_connection(conn);
} }
} }
else else
......
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