Signed-off-by: Paul Gofman pgofman@codeweavers.com --- The main idea behind this series is to address a few things regarind socket shutdown and close: - avoid directly sending shutdown frame from WinHttpWebSocketClose() which doesn't cope nicely with sync / async send duality; - address the case of closing websocket which has receive waiting. - changing the socket status right away before the close or shutdown operation is complete through the queue (which is needed to straigten up the above and the following later bit which didn't fit in this series).
In theory we could maybe cancel socket I/O on the socket to abort receive instead of teaching socket receive to read the close status but that seems harder to synchronize and I suppose that would complicate the things considerably without a clear advantage.
The remaining part of WinHttpWebSocketClose() changes which didn't fit in in this patch series concerns the way the callback is sent when receive operation is pending during WinHttpWebSocketClose() call. Windows always calls the callback synchronously during WinHttpWebSocketClose() with dwResult 0 and dwError ERROR_WINHTTP_OPERATION_CANCELLED, the async receive thread does not call any callback in this case.
dlls/winhttp/request.c | 10 +++++----- dlls/winhttp/tests/notification.c | 15 ++++++++++++++- 2 files changed, 19 insertions(+), 6 deletions(-)
diff --git a/dlls/winhttp/request.c b/dlls/winhttp/request.c index 31e65a68359..fc2c06bd11f 100644 --- a/dlls/winhttp/request.c +++ b/dlls/winhttp/request.c @@ -3324,7 +3324,7 @@ DWORD WINAPI WinHttpWebSocketSend( HINTERNET hsocket, WINHTTP_WEB_SOCKET_BUFFER_ if (socket->state != SOCKET_STATE_OPEN) { release_object( &socket->hdr ); - return ERROR_WINHTTP_INCORRECT_HANDLE_STATE; + return ERROR_INVALID_OPERATION; }
if (socket->request->connect->hdr.flags & WINHTTP_FLAG_ASYNC) @@ -3625,7 +3625,7 @@ DWORD WINAPI WinHttpWebSocketReceive( HINTERNET hsocket, void *buf, DWORD len, D if (socket->state > SOCKET_STATE_SHUTDOWN) { release_object( &socket->hdr ); - return ERROR_WINHTTP_INCORRECT_HANDLE_STATE; + return ERROR_INVALID_OPERATION; }
if (socket->request->connect->hdr.flags & WINHTTP_FLAG_ASYNC) @@ -3704,7 +3704,7 @@ DWORD WINAPI WinHttpWebSocketShutdown( HINTERNET hsocket, USHORT status, void *r if (socket->state >= SOCKET_STATE_SHUTDOWN) { release_object( &socket->hdr ); - return ERROR_WINHTTP_INCORRECT_HANDLE_STATE; + return ERROR_INVALID_OPERATION; }
if (socket->request->connect->hdr.flags & WINHTTP_FLAG_ASYNC) @@ -3814,7 +3814,7 @@ DWORD WINAPI WinHttpWebSocketClose( HINTERNET hsocket, USHORT status, void *reas if (socket->state >= SOCKET_STATE_CLOSED) { release_object( &socket->hdr ); - return ERROR_WINHTTP_INCORRECT_HANDLE_STATE; + return ERROR_INVALID_OPERATION; }
if (socket->request->connect->hdr.flags & WINHTTP_FLAG_ASYNC) @@ -3859,7 +3859,7 @@ DWORD WINAPI WinHttpWebSocketQueryCloseStatus( HINTERNET hsocket, USHORT *status if (socket->state < SOCKET_STATE_CLOSED) { release_object( &socket->hdr ); - return ERROR_WINHTTP_INCORRECT_HANDLE_STATE; + return ERROR_INVALID_OPERATION; }
*status = socket->status; diff --git a/dlls/winhttp/tests/notification.c b/dlls/winhttp/tests/notification.c index e919159ba98..0c3ff98c342 100644 --- a/dlls/winhttp/tests/notification.c +++ b/dlls/winhttp/tests/notification.c @@ -816,6 +816,12 @@ static void test_websocket(BOOL secure) ok( err == ERROR_SUCCESS, "got %u\n", err ); WaitForSingleObject( info.wait, INFINITE );
+ err = pWinHttpWebSocketShutdown( socket, 1000, (void *)"success", sizeof("success") ); + ok( err == ERROR_INVALID_OPERATION, "got %u\n", err ); + err = pWinHttpWebSocketSend( socket, WINHTTP_WEB_SOCKET_BINARY_MESSAGE_BUFFER_TYPE, + (void*)"hello", sizeof("hello") ); + ok( err == ERROR_INVALID_OPERATION, "got %u\n", err ); + setup_test( &info, winhttp_websocket_receive, __LINE__ ); buffer[0] = 0; size = 0xdeadbeef; @@ -838,8 +844,15 @@ static void test_websocket(BOOL secure) ok( type == 0xdeadbeef, "got %u\n", type ); ok( buffer[0] == 'h', "unexpected data\n" );
+ close_status = 0xdead; + size = sizeof(buffer) + 1; + err = pWinHttpWebSocketQueryCloseStatus( socket, &close_status, buffer, sizeof(buffer), &size ); + ok( err == ERROR_INVALID_OPERATION, "got %u\n", err ); + ok( close_status == 0xdead, "got %u\n", close_status ); + ok( size == sizeof(buffer) + 1, "got %u\n", size ); + setup_test( &info, winhttp_websocket_close, __LINE__ ); - ret = pWinHttpWebSocketClose( socket, 1000, (void *)"success", sizeof("success") ); + err = pWinHttpWebSocketClose( socket, 1000, (void *)"success", sizeof("success") ); ok( err == ERROR_SUCCESS, "got %u\n", err ); WaitForSingleObject( info.wait, INFINITE );