[PATCH 5/7] winhttp: Abort websocket IO on handle close.
Paul Gofman
wine at gitlab.winehq.org
Mon Jun 6 23:02:33 CDT 2022
From: Paul Gofman <pgofman at codeweavers.com>
---
dlls/winhttp/handle.c | 7 ++++++-
dlls/winhttp/net.c | 10 +++++++++-
dlls/winhttp/request.c | 27 ++++++++++++++++++++++++++-
dlls/winhttp/session.c | 3 +++
dlls/winhttp/winhttp_private.h | 2 ++
5 files changed, 46 insertions(+), 3 deletions(-)
diff --git a/dlls/winhttp/handle.c b/dlls/winhttp/handle.c
index 38959fd6456..33a4cd6bb71 100644
--- a/dlls/winhttp/handle.c
+++ b/dlls/winhttp/handle.c
@@ -142,7 +142,12 @@ BOOL free_handle( HINTERNET hinternet )
LeaveCriticalSection( &handle_cs );
- if (hdr) release_object( hdr );
+ if (hdr)
+ {
+ if (hdr->vtbl->handle_closing)
+ hdr->vtbl->handle_closing( hdr );
+ release_object( hdr );
+ }
EnterCriticalSection( &handle_cs );
if (next_handle > handle && !handles[handle]) next_handle = handle;
diff --git a/dlls/winhttp/net.c b/dlls/winhttp/net.c
index 07a65c5465f..17520a54f63 100644
--- a/dlls/winhttp/net.c
+++ b/dlls/winhttp/net.c
@@ -269,7 +269,8 @@ void netconn_close( struct netconn *conn )
free(conn->extra_buf);
DeleteSecurityContext(&conn->ssl_ctx);
}
- closesocket( conn->socket );
+ if (conn->socket != -1)
+ closesocket( conn->socket );
release_host( conn->host );
free(conn);
}
@@ -629,6 +630,13 @@ DWORD netconn_recv( struct netconn *conn, void *buf, size_t len, int flags, int
return ERROR_SUCCESS;
}
+void netconn_cancel_io( struct netconn *conn )
+{
+ SOCKET socket = InterlockedExchange( (LONG *)&conn->socket, -1 );
+
+ closesocket( socket );
+}
+
ULONG netconn_query_data_available( struct netconn *conn )
{
return conn->secure ? conn->peek_len : 0;
diff --git a/dlls/winhttp/request.c b/dlls/winhttp/request.c
index 4242551ee3b..3a239966c69 100644
--- a/dlls/winhttp/request.c
+++ b/dlls/winhttp/request.c
@@ -255,6 +255,16 @@ static void cancel_queue( struct queue *queue )
}
}
+static BOOL is_queue_empty( struct queue *queue )
+{
+ BOOL ret;
+
+ AcquireSRWLockExclusive( &queue->lock );
+ ret = list_empty( &queue->queued_tasks );
+ ReleaseSRWLockExclusive( &queue->lock );
+ return ret;
+}
+
static void free_header( struct header *header )
{
free( header->field );
@@ -1885,7 +1895,8 @@ static void finished_reading( struct request *request )
if (!request->netconn) return;
- if (request->hdr.disable_flags & WINHTTP_DISABLE_KEEP_ALIVE) close = TRUE;
+ if (request->netconn->socket == -1) close = TRUE;
+ else if (request->hdr.disable_flags & WINHTTP_DISABLE_KEEP_ALIVE) close = TRUE;
else if (!query_headers( request, WINHTTP_QUERY_CONNECTION, NULL, connection, &size, NULL ) ||
!query_headers( request, WINHTTP_QUERY_PROXY_CONNECTION, NULL, connection, &size, NULL ))
{
@@ -3121,6 +3132,19 @@ BOOL WINAPI WinHttpWriteData( HINTERNET hrequest, const void *buffer, DWORD to_w
return !ret;
}
+static void socket_handle_closing( struct object_header *hdr )
+{
+ struct socket *socket = (struct socket *)hdr;
+
+ if (socket->request->netconn->secure)
+ {
+ cancel_queue( &socket->send_q );
+ cancel_queue( &socket->recv_q );
+ }
+ if (!is_queue_empty( &socket->send_q ) || !is_queue_empty( &socket->recv_q ))
+ netconn_cancel_io( socket->request->netconn );
+}
+
static BOOL socket_query_option( struct object_header *hdr, DWORD option, void *buffer, DWORD *buflen )
{
FIXME( "unimplemented option %lu\n", option );
@@ -3151,6 +3175,7 @@ static BOOL socket_set_option( struct object_header *hdr, DWORD option, void *bu
static const struct object_vtbl socket_vtbl =
{
+ socket_handle_closing,
socket_destroy,
socket_query_option,
socket_set_option,
diff --git a/dlls/winhttp/session.c b/dlls/winhttp/session.c
index 3b00d2448d1..01e95895eb3 100644
--- a/dlls/winhttp/session.c
+++ b/dlls/winhttp/session.c
@@ -242,6 +242,7 @@ static BOOL session_set_option( struct object_header *hdr, DWORD option, void *b
static const struct object_vtbl session_vtbl =
{
+ NULL,
session_destroy,
session_query_option,
session_set_option
@@ -382,6 +383,7 @@ static BOOL connect_query_option( struct object_header *hdr, DWORD option, void
static const struct object_vtbl connect_vtbl =
{
+ NULL,
connect_destroy,
connect_query_option,
NULL
@@ -1085,6 +1087,7 @@ static BOOL request_set_option( struct object_header *hdr, DWORD option, void *b
static const struct object_vtbl request_vtbl =
{
+ NULL,
request_destroy,
request_query_option,
request_set_option
diff --git a/dlls/winhttp/winhttp_private.h b/dlls/winhttp/winhttp_private.h
index 17102107c77..98e05f068ba 100644
--- a/dlls/winhttp/winhttp_private.h
+++ b/dlls/winhttp/winhttp_private.h
@@ -30,6 +30,7 @@
struct object_header;
struct object_vtbl
{
+ void (*handle_closing) ( struct object_header * );
void (*destroy)( struct object_header * );
BOOL (*query_option)( struct object_header *, DWORD, void *, DWORD * );
BOOL (*set_option)( struct object_header *, DWORD, void *, DWORD );
@@ -370,6 +371,7 @@ DWORD netconn_recv( struct netconn *, void *, size_t, int, int * ) DECLSPEC_HIDD
DWORD netconn_resolve( WCHAR *, INTERNET_PORT, struct sockaddr_storage *, int ) DECLSPEC_HIDDEN;
DWORD netconn_secure_connect( struct netconn *, WCHAR *, DWORD, CredHandle *, BOOL ) DECLSPEC_HIDDEN;
DWORD netconn_send( struct netconn *, const void *, size_t, int *, WSAOVERLAPPED * ) DECLSPEC_HIDDEN;
+void netconn_cancel_io( struct netconn *conn ) DECLSPEC_HIDDEN;
DWORD netconn_set_timeout( struct netconn *, BOOL, int ) DECLSPEC_HIDDEN;
BOOL netconn_is_alive( struct netconn * ) DECLSPEC_HIDDEN;
const void *netconn_get_certificate( struct netconn * ) DECLSPEC_HIDDEN;
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/195
More information about the wine-devel
mailing list