Paul Gofman : winhttp: Abort websocket IO on handle close.

Alexandre Julliard julliard at winehq.org
Wed Jun 8 15:56:05 CDT 2022


Module: wine
Branch: master
Commit: 55425e85ab0d80d467e6d6261ea39931820b3ed0
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=55425e85ab0d80d467e6d6261ea39931820b3ed0

Author: Paul Gofman <pgofman at codeweavers.com>
Date:   Fri Jun  3 17:33:50 2022 -0500

winhttp: Abort websocket IO on handle close.

Signed-off-by: Paul Gofman <pgofman at codeweavers.com>

---

 dlls/winhttp/handle.c          |  7 ++++++-
 dlls/winhttp/net.c             | 10 +++++++++-
 dlls/winhttp/request.c         | 21 +++++++++++++++++++--
 dlls/winhttp/session.c         |  3 +++
 dlls/winhttp/winhttp_private.h |  2 ++
 5 files changed, 39 insertions(+), 4 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..269af0826c0 100644
--- a/dlls/winhttp/request.c
+++ b/dlls/winhttp/request.c
@@ -231,9 +231,10 @@ static BOOL task_needs_completion( struct task_header *task_hdr )
     return !InterlockedExchange( &task_hdr->completion_sent, 1 );
 }
 
-static void cancel_queue( struct queue *queue )
+static BOOL cancel_queue( struct queue *queue )
 {
     struct task_header *task_hdr, *found;
+    BOOL cancelled = FALSE;
 
     while (1)
     {
@@ -250,9 +251,11 @@ static void cancel_queue( struct queue *queue )
         }
         ReleaseSRWLockExclusive( &queue->lock );
         if (!found) break;
+        cancelled = TRUE;
         found->callback( found, TRUE );
         release_task( found );
     }
+    return cancelled;
 }
 
 static void free_header( struct header *header )
@@ -1885,7 +1888,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 +3125,18 @@ 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;
+    BOOL pending_tasks;
+
+    pending_tasks = cancel_queue( &socket->send_q );
+    pending_tasks = cancel_queue( &socket->recv_q ) || pending_tasks;
+
+    if (pending_tasks)
+        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 +3167,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;




More information about the wine-cvs mailing list