[PATCH 7/9] winhttp: Process server close frame in handle_control_frame().

Paul Gofman pgofman at codeweavers.com
Mon Jan 24 18:08:02 CST 2022


Signed-off-by: Paul Gofman <pgofman at codeweavers.com>
---
 dlls/winhttp/request.c         | 27 +++++++++++++++++++++++----
 dlls/winhttp/winhttp_private.h |  2 ++
 2 files changed, 25 insertions(+), 4 deletions(-)

diff --git a/dlls/winhttp/request.c b/dlls/winhttp/request.c
index 890a5a645e7..cb2db948278 100644
--- a/dlls/winhttp/request.c
+++ b/dlls/winhttp/request.c
@@ -3509,20 +3509,24 @@ static DWORD receive_close_status( struct socket *socket, unsigned int len )
 {
     DWORD reason_len, ret;
 
+    socket->close_frame_received = TRUE;
     if ((len && (len < sizeof(socket->status) || len > sizeof(socket->status) + sizeof(socket->reason))))
-        return ERROR_WINHTTP_INVALID_SERVER_RESPONSE;
+        return (socket->close_frame_receive_err = ERROR_WINHTTP_INVALID_SERVER_RESPONSE);
 
-    if (!len) return ERROR_SUCCESS;
+    if (!len) return (socket->close_frame_receive_err = ERROR_SUCCESS);
 
     reason_len = len - sizeof(socket->status);
     if ((ret = receive_bytes( socket, (char *)&socket->status, sizeof(socket->status), &len, TRUE )))
-        return ret;
+        return (socket->close_frame_receive_err = ret);
     socket->status = RtlUshortByteSwap( socket->status );
-    return receive_bytes( socket, socket->reason, reason_len, &socket->reason_len, TRUE );
+    return (socket->close_frame_receive_err
+            = receive_bytes( socket, socket->reason, reason_len, &socket->reason_len, TRUE ));
 }
 
 static DWORD handle_control_frame( struct socket *socket )
 {
+    TRACE( "opcode %u.\n", socket->opcode );
+
     switch (socket->opcode)
     {
     case SOCKET_OPCODE_PING:
@@ -3531,6 +3535,19 @@ static DWORD handle_control_frame( struct socket *socket )
     case SOCKET_OPCODE_PONG:
         return socket_drain( socket );
 
+    case SOCKET_OPCODE_CLOSE:
+        if (socket->state != SOCKET_STATE_CLOSED)
+            WARN( "SOCKET_OPCODE_CLOSE received, socket->state %u.\n", socket->state );
+        if (socket->close_frame_received)
+        {
+            FIXME( "Close frame already received.\n" );
+            return ERROR_WINHTTP_INVALID_SERVER_RESPONSE;
+        }
+
+        receive_close_status( socket, socket->read_size );
+        socket->read_size = 0;
+        return ERROR_WINHTTP_INVALID_SERVER_RESPONSE;
+
     default:
         ERR("unhandled control opcode %02x\n", socket->opcode);
         return ERROR_WINHTTP_INVALID_SERVER_RESPONSE;
@@ -3754,6 +3771,8 @@ static DWORD socket_close( struct socket *socket )
 {
     DWORD ret, count;
 
+    if (socket->close_frame_received) return socket->close_frame_receive_err;
+
     if ((ret = socket_drain( socket ))) return ret;
 
     while (1)
diff --git a/dlls/winhttp/winhttp_private.h b/dlls/winhttp/winhttp_private.h
index ef52944e412..5eb3e97a916 100644
--- a/dlls/winhttp/winhttp_private.h
+++ b/dlls/winhttp/winhttp_private.h
@@ -246,6 +246,8 @@ struct socket
     struct queue recv_q;
     enum socket_opcode opcode;
     DWORD read_size;
+    BOOL close_frame_received;
+    DWORD close_frame_receive_err;
     USHORT status;
     char reason[123];
     DWORD reason_len;
-- 
2.34.1




More information about the wine-devel mailing list