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 @@
*/
#include <assert.h>
#include <stdbool.h>
#include "ntstatus.h"
#define WIN32_NO_STATUS
#include "wine/http.h"
......@@ -54,6 +55,7 @@ struct connection
char *buffer;
unsigned int len, size;
bool shutdown;
/* If there is a request fully received and waiting to be read, the
* "available" parameter will be TRUE. Either there is no queue matching
......@@ -111,7 +113,7 @@ static struct list request_queues = LIST_INIT(request_queues);
static void accept_connection(SOCKET socket)
{
struct connection *conn;
ULONG true = 1;
ULONG one = 1;
SOCKET peer;
if ((peer = accept(socket, NULL, NULL)) == INVALID_SOCKET)
......@@ -134,15 +136,22 @@ static void accept_connection(SOCKET socket)
}
conn->size = 8192;
WSAEventSelect(peer, request_event, FD_READ | FD_CLOSE);
ioctlsocket(peer, FIONBIO, &true);
ioctlsocket(peer, FIONBIO, &one);
conn->socket = peer;
list_add_head(&connections, &conn->entry);
}
static void close_connection(struct connection *conn)
static void shutdown_connection(struct connection *conn)
{
free(conn->buffer);
shutdown(conn->socket, SD_BOTH);
conn->shutdown = true;
}
static void close_connection(struct connection *conn)
{
if (!conn->shutdown)
shutdown_connection(conn);
closesocket(conn->socket);
list_remove(&conn->entry);
free(conn);
......@@ -593,12 +602,24 @@ static void send_400(struct connection *conn)
strcat(buffer, response_body);
if (send(conn->socket, buffer, strlen(buffer), 0) < 0)
ERR("Failed to send 400 response, error %u.\n", WSAGetLastError());
shutdown_connection(conn);
}
static void receive_data(struct connection *conn)
{
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
* might have been woken up by the socket closing. */
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)
{
WARN("Failed to parse request; shutting down connection.\n");
send_400(conn);
close_connection(conn);
}
}
......@@ -714,7 +734,7 @@ static NTSTATUS http_add_url(struct request_queue *queue, IRP *irp)
struct listening_socket *listening_sock;
char *url, *endptr;
size_t queue_url_len, new_url_len;
ULONG true = 1, value;
ULONG one = 1, value;
SOCKET s = INVALID_SOCKET;
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)
listening_sock->socket = s;
list_add_head(&listening_sockets, &listening_sock->entry);
ioctlsocket(s, FIONBIO, &true);
ioctlsocket(s, FIONBIO, &one);
WSAEventSelect(s, request_event, FD_ACCEPT);
}
......@@ -1002,7 +1022,6 @@ static NTSTATUS http_send_response(struct request_queue *queue, IRP *irp)
{
WARN("Failed to parse request; shutting down connection.\n");
send_400(conn);
close_connection(conn);
}
}
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