Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
3eda59af
Commit
3eda59af
authored
Jun 06, 2022
by
Paul Gofman
Committed by
Alexandre Julliard
Jun 08, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
winhttp: Replace pending read cancel in WinHttpWebSocketClose() with a generic cancel_queue().
Signed-off-by:
Paul Gofman
<
pgofman@codeweavers.com
>
parent
66ff3594
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
78 additions
and
33 deletions
+78
-33
request.c
dlls/winhttp/request.c
+76
-32
winhttp_private.h
dlls/winhttp/winhttp_private.h
+2
-1
No files found.
dlls/winhttp/request.c
View file @
3eda59af
...
...
@@ -182,7 +182,7 @@ static void CALLBACK task_callback( TP_CALLBACK_INSTANCE *instance, void *ctx )
task
=
get_next_task
(
queue
,
NULL
);
while
(
task
)
{
task
->
callback
(
task
);
task
->
callback
(
task
,
FALSE
);
/* Queue object may be freed by release_object() unless there is another task referencing it. */
next_task
=
get_next_task
(
queue
,
task
);
release_object
(
task
->
obj
);
...
...
@@ -199,6 +199,7 @@ static DWORD queue_task( struct queue *queue, TASK_CALLBACK task, struct task_he
TRACE
(
"queueing %p in %p
\n
"
,
task_hdr
,
queue
);
task_hdr
->
callback
=
task
;
task_hdr
->
completion_sent
=
0
;
task_hdr
->
refs
=
1
;
task_hdr
->
obj
=
obj
;
addref_object
(
obj
);
...
...
@@ -225,6 +226,35 @@ static DWORD queue_task( struct queue *queue, TASK_CALLBACK task, struct task_he
return
ERROR_SUCCESS
;
}
static
BOOL
task_needs_completion
(
struct
task_header
*
task_hdr
)
{
return
!
InterlockedExchange
(
&
task_hdr
->
completion_sent
,
1
);
}
static
void
cancel_queue
(
struct
queue
*
queue
)
{
struct
task_header
*
task_hdr
,
*
found
;
while
(
1
)
{
AcquireSRWLockExclusive
(
&
queue
->
lock
);
found
=
NULL
;
LIST_FOR_EACH_ENTRY
(
task_hdr
,
&
queue
->
queued_tasks
,
struct
task_header
,
entry
)
{
if
(
task_needs_completion
(
task_hdr
))
{
found
=
task_hdr
;
addref_task
(
found
);
break
;
}
}
ReleaseSRWLockExclusive
(
&
queue
->
lock
);
if
(
!
found
)
break
;
found
->
callback
(
found
,
TRUE
);
release_task
(
found
);
}
}
static
void
free_header
(
struct
header
*
header
)
{
free
(
header
->
field
);
...
...
@@ -2231,11 +2261,13 @@ end:
return
ret
;
}
static
void
task_send_request
(
void
*
ctx
)
static
void
task_send_request
(
void
*
ctx
,
BOOL
abort
)
{
struct
send_request
*
s
=
ctx
;
struct
request
*
request
=
(
struct
request
*
)
s
->
task_hdr
.
obj
;
if
(
abort
)
return
;
TRACE
(
"running %p
\n
"
,
ctx
);
send_request
(
request
,
s
->
headers
,
s
->
headers_len
,
s
->
optional
,
s
->
optional_len
,
s
->
total_len
,
s
->
context
,
TRUE
);
...
...
@@ -2813,11 +2845,13 @@ static DWORD receive_response( struct request *request, BOOL async )
return
ret
;
}
static
void
task_receive_response
(
void
*
ctx
)
static
void
task_receive_response
(
void
*
ctx
,
BOOL
abort
)
{
struct
receive_response
*
r
=
ctx
;
struct
request
*
request
=
(
struct
request
*
)
r
->
task_hdr
.
obj
;
if
(
abort
)
return
;
TRACE
(
"running %p
\n
"
,
ctx
);
receive_response
(
request
,
TRUE
);
}
...
...
@@ -2905,11 +2939,13 @@ done:
return
ret
;
}
static
void
task_query_data_available
(
void
*
ctx
)
static
void
task_query_data_available
(
void
*
ctx
,
BOOL
abort
)
{
struct
query_data
*
q
=
ctx
;
struct
request
*
request
=
(
struct
request
*
)
q
->
task_hdr
.
obj
;
if
(
abort
)
return
;
TRACE
(
"running %p
\n
"
,
ctx
);
query_data_available
(
request
,
q
->
available
,
TRUE
);
}
...
...
@@ -2956,11 +2992,13 @@ BOOL WINAPI WinHttpQueryDataAvailable( HINTERNET hrequest, LPDWORD available )
return
!
ret
||
ret
==
ERROR_IO_PENDING
;
}
static
void
task_read_data
(
void
*
ctx
)
static
void
task_read_data
(
void
*
ctx
,
BOOL
abort
)
{
struct
read_data
*
r
=
ctx
;
struct
request
*
request
=
(
struct
request
*
)
r
->
task_hdr
.
obj
;
if
(
abort
)
return
;
TRACE
(
"running %p
\n
"
,
ctx
);
read_data
(
request
,
r
->
buffer
,
r
->
to_read
,
r
->
read
,
TRUE
);
}
...
...
@@ -3031,11 +3069,13 @@ static DWORD write_data( struct request *request, const void *buffer, DWORD to_w
return
ret
;
}
static
void
task_write_data
(
void
*
ctx
)
static
void
task_write_data
(
void
*
ctx
,
BOOL
abort
)
{
struct
write_data
*
w
=
ctx
;
struct
request
*
request
=
(
struct
request
*
)
w
->
task_hdr
.
obj
;
if
(
abort
)
return
;
TRACE
(
"running %p
\n
"
,
ctx
);
write_data
(
request
,
w
->
buffer
,
w
->
to_write
,
w
->
written
,
TRUE
);
}
...
...
@@ -3315,13 +3355,10 @@ static void send_io_complete( struct object_header *hdr )
}
/* returns FALSE if sending callback should be omitted. */
static
BOOL
receive_io_complete
(
struct
socket
*
socket
)
static
void
receive_io_complete
(
struct
socket
*
socket
)
{
LONG
count
=
InterlockedDecrement
(
&
socket
->
hdr
.
pending_receives
);
assert
(
count
>=
0
||
socket
->
state
==
SOCKET_STATE_CLOSED
);
/* count is reset to zero during websocket close so if count went negative
* then WinHttpWebSocketClose() is to send the callback. */
return
count
>=
0
;
assert
(
count
>=
0
);
}
static
BOOL
socket_can_send
(
struct
socket
*
socket
)
...
...
@@ -3428,12 +3465,14 @@ static DWORD socket_send( struct socket *socket, WINHTTP_WEB_SOCKET_BUFFER_TYPE
return
send_frame
(
socket
,
opcode
,
0
,
buf
,
len
,
final
,
ovr
);
}
static
void
task_socket_send
(
void
*
ctx
)
static
void
task_socket_send
(
void
*
ctx
,
BOOL
abort
)
{
struct
socket_send
*
s
=
ctx
;
struct
socket
*
socket
=
(
struct
socket
*
)
s
->
task_hdr
.
obj
;
DWORD
ret
;
if
(
abort
)
return
;
TRACE
(
"running %p
\n
"
,
ctx
);
if
(
s
->
complete_async
)
ret
=
complete_send_frame
(
socket
,
&
s
->
ovr
,
s
->
buf
);
...
...
@@ -3623,11 +3662,13 @@ static DWORD receive_frame( struct socket *socket, DWORD *ret_len, enum socket_o
return
ERROR_SUCCESS
;
}
static
void
task_socket_send_pong
(
void
*
ctx
)
static
void
task_socket_send_pong
(
void
*
ctx
,
BOOL
abort
)
{
struct
socket_send
*
s
=
ctx
;
struct
socket
*
socket
=
(
struct
socket
*
)
s
->
task_hdr
.
obj
;
if
(
abort
)
return
;
TRACE
(
"running %p
\n
"
,
ctx
);
if
(
s
->
complete_async
)
complete_send_frame
(
socket
,
&
s
->
ovr
,
NULL
);
...
...
@@ -3858,17 +3899,23 @@ static void socket_receive_complete( struct socket *socket, DWORD ret, WINHTTP_W
}
}
static
void
task_socket_receive
(
void
*
ctx
)
static
void
task_socket_receive
(
void
*
ctx
,
BOOL
abort
)
{
struct
socket_receive
*
r
=
ctx
;
struct
socket
*
socket
=
(
struct
socket
*
)
r
->
task_hdr
.
obj
;
DWORD
ret
,
count
;
WINHTTP_WEB_SOCKET_BUFFER_TYPE
type
;
if
(
abort
)
{
socket_receive_complete
(
socket
,
ERROR_WINHTTP_OPERATION_CANCELLED
,
0
,
0
);
return
;
}
TRACE
(
"running %p
\n
"
,
ctx
);
ret
=
socket_receive
(
socket
,
r
->
buf
,
r
->
len
,
&
count
,
&
type
);
if
(
receive_io_complete
(
socket
))
receive_io_complete
(
socket
);
if
(
task_needs_completion
(
&
r
->
task_hdr
))
socket_receive_complete
(
socket
,
ret
,
type
,
count
);
}
...
...
@@ -3939,12 +3986,14 @@ static void socket_shutdown_complete( struct socket *socket, DWORD ret )
}
}
static
void
task_socket_shutdown
(
void
*
ctx
)
static
void
task_socket_shutdown
(
void
*
ctx
,
BOOL
abort
)
{
struct
socket_shutdown
*
s
=
ctx
;
struct
socket
*
socket
=
(
struct
socket
*
)
s
->
task_hdr
.
obj
;
DWORD
ret
;
if
(
abort
)
return
;
TRACE
(
"running %p
\n
"
,
ctx
);
if
(
s
->
complete_async
)
ret
=
complete_send_frame
(
socket
,
&
s
->
ovr
,
s
->
reason
);
...
...
@@ -4073,15 +4122,18 @@ static void socket_close_complete( struct socket *socket, DWORD ret )
}
}
static
void
task_socket_close
(
void
*
ctx
)
static
void
task_socket_close
(
void
*
ctx
,
BOOL
abort
)
{
struct
socket_shutdown
*
s
=
ctx
;
struct
socket
*
socket
=
(
struct
socket
*
)
s
->
task_hdr
.
obj
;
DWORD
ret
;
if
(
abort
)
return
;
TRACE
(
"running %p
\n
"
,
ctx
);
ret
=
socket_close
(
socket
);
receive_io_complete
(
socket
);
socket_close_complete
(
socket
,
ret
);
}
...
...
@@ -4113,25 +4165,14 @@ DWORD WINAPI WinHttpWebSocketClose( HINTERNET hsocket, USHORT status, void *reas
if
(
socket
->
request
->
connect
->
hdr
.
flags
&
WINHTTP_FLAG_ASYNC
)
{
/* When closing the socket pending receives are cancelled. Setting socket->hdr.pending_receives to zero
* will prevent pending receives from sending callbacks. */
pending_receives
=
InterlockedExchange
(
&
socket
->
hdr
.
pending_receives
,
0
);
assert
(
pending_receives
>=
0
);
if
(
pending_receives
)
{
WINHTTP_WEB_SOCKET_ASYNC_RESULT
result
;
result
.
AsyncResult
.
dwResult
=
0
;
result
.
AsyncResult
.
dwError
=
ERROR_WINHTTP_OPERATION_CANCELLED
;
result
.
Operation
=
WINHTTP_WEB_SOCKET_RECEIVE_OPERATION
;
send_callback
(
&
socket
->
hdr
,
WINHTTP_CALLBACK_STATUS_REQUEST_ERROR
,
&
result
,
sizeof
(
result
)
);
}
pending_receives
=
InterlockedIncrement
(
&
socket
->
hdr
.
pending_receives
);
cancel_queue
(
&
socket
->
recv_q
);
}
if
(
prev_state
<
SOCKET_STATE_SHUTDOWN
&&
(
ret
=
send_socket_shutdown
(
socket
,
status
,
reason
,
len
,
FALSE
)))
goto
done
;
if
(
!
pending_receives
&&
socket
->
close_frame_received
)
if
(
pending_receives
==
1
&&
socket
->
close_frame_received
)
{
if
(
socket
->
request
->
connect
->
hdr
.
flags
&
WINHTTP_FLAG_ASYNC
)
socket_close_complete
(
socket
,
socket
->
close_frame_receive_err
);
...
...
@@ -4144,7 +4185,10 @@ DWORD WINAPI WinHttpWebSocketClose( HINTERNET hsocket, USHORT status, void *reas
if
(
!
(
s
=
calloc
(
1
,
sizeof
(
*
s
)
)))
return
FALSE
;
if
((
ret
=
queue_task
(
&
socket
->
recv_q
,
task_socket_close
,
&
s
->
task_hdr
,
&
socket
->
hdr
)))
{
InterlockedDecrement
(
&
socket
->
hdr
.
pending_receives
);
free
(
s
);
}
}
else
ret
=
socket_close
(
socket
);
...
...
dlls/winhttp/winhttp_private.h
View file @
3eda59af
...
...
@@ -274,7 +274,7 @@ struct socket
BOOL
last_receive_final
;
};
typedef
void
(
*
TASK_CALLBACK
)(
void
*
ctx
);
typedef
void
(
*
TASK_CALLBACK
)(
void
*
ctx
,
BOOL
abort
);
struct
task_header
{
...
...
@@ -282,6 +282,7 @@ struct task_header
TASK_CALLBACK
callback
;
struct
object_header
*
obj
;
volatile
LONG
refs
;
volatile
LONG
completion_sent
;
};
struct
send_request
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment