Commit 55425e85 authored by Paul Gofman's avatar Paul Gofman Committed by Alexandre Julliard

winhttp: Abort websocket IO on handle close.

parent 3eda59af
...@@ -142,7 +142,12 @@ BOOL free_handle( HINTERNET hinternet ) ...@@ -142,7 +142,12 @@ BOOL free_handle( HINTERNET hinternet )
LeaveCriticalSection( &handle_cs ); 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 ); EnterCriticalSection( &handle_cs );
if (next_handle > handle && !handles[handle]) next_handle = handle; if (next_handle > handle && !handles[handle]) next_handle = handle;
......
...@@ -269,7 +269,8 @@ void netconn_close( struct netconn *conn ) ...@@ -269,7 +269,8 @@ void netconn_close( struct netconn *conn )
free(conn->extra_buf); free(conn->extra_buf);
DeleteSecurityContext(&conn->ssl_ctx); DeleteSecurityContext(&conn->ssl_ctx);
} }
closesocket( conn->socket ); if (conn->socket != -1)
closesocket( conn->socket );
release_host( conn->host ); release_host( conn->host );
free(conn); free(conn);
} }
...@@ -629,6 +630,13 @@ DWORD netconn_recv( struct netconn *conn, void *buf, size_t len, int flags, int ...@@ -629,6 +630,13 @@ DWORD netconn_recv( struct netconn *conn, void *buf, size_t len, int flags, int
return ERROR_SUCCESS; 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 ) ULONG netconn_query_data_available( struct netconn *conn )
{ {
return conn->secure ? conn->peek_len : 0; return conn->secure ? conn->peek_len : 0;
......
...@@ -231,9 +231,10 @@ static BOOL task_needs_completion( struct task_header *task_hdr ) ...@@ -231,9 +231,10 @@ static BOOL task_needs_completion( struct task_header *task_hdr )
return !InterlockedExchange( &task_hdr->completion_sent, 1 ); 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; struct task_header *task_hdr, *found;
BOOL cancelled = FALSE;
while (1) while (1)
{ {
...@@ -250,9 +251,11 @@ static void cancel_queue( struct queue *queue ) ...@@ -250,9 +251,11 @@ static void cancel_queue( struct queue *queue )
} }
ReleaseSRWLockExclusive( &queue->lock ); ReleaseSRWLockExclusive( &queue->lock );
if (!found) break; if (!found) break;
cancelled = TRUE;
found->callback( found, TRUE ); found->callback( found, TRUE );
release_task( found ); release_task( found );
} }
return cancelled;
} }
static void free_header( struct header *header ) static void free_header( struct header *header )
...@@ -1885,7 +1888,8 @@ static void finished_reading( struct request *request ) ...@@ -1885,7 +1888,8 @@ static void finished_reading( struct request *request )
if (!request->netconn) return; 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 ) || else if (!query_headers( request, WINHTTP_QUERY_CONNECTION, NULL, connection, &size, NULL ) ||
!query_headers( request, WINHTTP_QUERY_PROXY_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 ...@@ -3121,6 +3125,18 @@ BOOL WINAPI WinHttpWriteData( HINTERNET hrequest, const void *buffer, DWORD to_w
return !ret; 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 ) static BOOL socket_query_option( struct object_header *hdr, DWORD option, void *buffer, DWORD *buflen )
{ {
FIXME( "unimplemented option %lu\n", option ); FIXME( "unimplemented option %lu\n", option );
...@@ -3151,6 +3167,7 @@ static BOOL socket_set_option( struct object_header *hdr, DWORD option, void *bu ...@@ -3151,6 +3167,7 @@ static BOOL socket_set_option( struct object_header *hdr, DWORD option, void *bu
static const struct object_vtbl socket_vtbl = static const struct object_vtbl socket_vtbl =
{ {
socket_handle_closing,
socket_destroy, socket_destroy,
socket_query_option, socket_query_option,
socket_set_option, socket_set_option,
......
...@@ -242,6 +242,7 @@ static BOOL session_set_option( struct object_header *hdr, DWORD option, void *b ...@@ -242,6 +242,7 @@ static BOOL session_set_option( struct object_header *hdr, DWORD option, void *b
static const struct object_vtbl session_vtbl = static const struct object_vtbl session_vtbl =
{ {
NULL,
session_destroy, session_destroy,
session_query_option, session_query_option,
session_set_option session_set_option
...@@ -382,6 +383,7 @@ static BOOL connect_query_option( struct object_header *hdr, DWORD option, void ...@@ -382,6 +383,7 @@ static BOOL connect_query_option( struct object_header *hdr, DWORD option, void
static const struct object_vtbl connect_vtbl = static const struct object_vtbl connect_vtbl =
{ {
NULL,
connect_destroy, connect_destroy,
connect_query_option, connect_query_option,
NULL NULL
...@@ -1085,6 +1087,7 @@ static BOOL request_set_option( struct object_header *hdr, DWORD option, void *b ...@@ -1085,6 +1087,7 @@ static BOOL request_set_option( struct object_header *hdr, DWORD option, void *b
static const struct object_vtbl request_vtbl = static const struct object_vtbl request_vtbl =
{ {
NULL,
request_destroy, request_destroy,
request_query_option, request_query_option,
request_set_option request_set_option
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
struct object_header; struct object_header;
struct object_vtbl struct object_vtbl
{ {
void (*handle_closing) ( struct object_header * );
void (*destroy)( struct object_header * ); void (*destroy)( struct object_header * );
BOOL (*query_option)( struct object_header *, DWORD, void *, DWORD * ); BOOL (*query_option)( struct object_header *, DWORD, void *, DWORD * );
BOOL (*set_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 ...@@ -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_resolve( WCHAR *, INTERNET_PORT, struct sockaddr_storage *, int ) DECLSPEC_HIDDEN;
DWORD netconn_secure_connect( struct netconn *, WCHAR *, DWORD, CredHandle *, BOOL ) 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; 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; DWORD netconn_set_timeout( struct netconn *, BOOL, int ) DECLSPEC_HIDDEN;
BOOL netconn_is_alive( struct netconn * ) DECLSPEC_HIDDEN; BOOL netconn_is_alive( struct netconn * ) DECLSPEC_HIDDEN;
const void *netconn_get_certificate( struct netconn * ) DECLSPEC_HIDDEN; const void *netconn_get_certificate( struct netconn * ) DECLSPEC_HIDDEN;
......
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