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.
This commit is contained in:
parent
25bcb9d363
commit
2bad8d9f63
1 changed files with 26 additions and 7 deletions
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue