[PATCH 1/9] winhttp: Return ERROR_INVALID_OPERATION when websocket is in the wrong state.

Paul Gofman pgofman at codeweavers.com
Mon Jan 24 18:07:56 CST 2022


Signed-off-by: Paul Gofman <pgofman at 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 );
 
-- 
2.34.1




More information about the wine-devel mailing list