[PATCH 3/5] winhttp: Use a buffer for sending frame in send_frame().

Paul Gofman pgofman at codeweavers.com
Thu Jan 20 09:35:32 CST 2022


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

diff --git a/dlls/winhttp/request.c b/dlls/winhttp/request.c
index d76edfa71d7..907ee538f54 100644
--- a/dlls/winhttp/request.c
+++ b/dlls/winhttp/request.c
@@ -3063,6 +3063,7 @@ static void socket_destroy( struct object_header *hdr )
     stop_queue( &socket->recv_q );
 
     release_object( &socket->request->hdr );
+    free( socket->send_frame_buffer );
     free( socket );
 }
 
@@ -3142,10 +3143,12 @@ static DWORD send_bytes( struct socket *socket, char *bytes, int len )
 static DWORD send_frame( struct socket *socket, enum socket_opcode opcode, USHORT status, const char *buf,
                          DWORD buflen, BOOL final )
 {
-    DWORD i = 0, j, ret, offset = 2, len = buflen;
-    char hdr[14], byte, *mask = NULL;
+    DWORD i = 0, j, offset = 2, len = buflen;
+    DWORD buffer_size, ret = 0, send_size;
+    char hdr[14], *mask = NULL;
+    char *ptr;
 
-    TRACE("sending %02x frame\n", opcode);
+    TRACE( "sending %02x frame, len %u.\n", opcode, len );
 
     if (opcode == SOCKET_OPCODE_CLOSE) len += sizeof(status);
 
@@ -3171,29 +3174,56 @@ static DWORD send_frame( struct socket *socket, enum socket_opcode opcode, USHOR
         offset += 8;
     }
 
-    if ((ret = send_bytes( socket, hdr, offset ))) return ret;
+    buffer_size = len + offset;
+    if (len) buffer_size += 4;
+    assert( buffer_size - len < MAX_FRAME_BUFFER_SIZE );
+    if (buffer_size > socket->send_frame_buffer_size && socket->send_frame_buffer_size < MAX_FRAME_BUFFER_SIZE)
+    {
+        DWORD new_size;
+        void *new;
+
+        new_size = min( buffer_size, MAX_FRAME_BUFFER_SIZE );
+        if (!(new = realloc( socket->send_frame_buffer, new_size )))
+        {
+            ERR("Out of memory, buffer_size %u.\n", buffer_size);
+            return ERROR_OUTOFMEMORY;
+        }
+        socket->send_frame_buffer = new;
+        socket->send_frame_buffer_size = new_size;
+    }
+    ptr = socket->send_frame_buffer;
+
+    memcpy(ptr, hdr, offset);
+    ptr += offset;
     if (len)
     {
         mask = &hdr[offset];
         RtlGenRandom( mask, 4 );
-        if ((ret = send_bytes( socket, mask, 4 ))) return ret;
+        memcpy( ptr, mask, 4 );
+        ptr += 4;
     }
 
     if (opcode == SOCKET_OPCODE_CLOSE) /* prepend status code */
     {
-        byte = (status >> 8) ^ mask[i++ % 4];
-        if ((ret = send_bytes( socket, &byte, 1 ))) return ret;
-
-        byte = (status & 0xff) ^ mask[i++ % 4];
-        if ((ret = send_bytes( socket, &byte, 1 ))) return ret;
+        *ptr++ = (status >> 8) ^ mask[i++ % 4];
+        *ptr++ = (status & 0xff) ^ mask[i++ % 4];
     }
 
-    for (j = 0; j < buflen; j++)
+    offset = ptr - socket->send_frame_buffer;
+    send_size = offset + buflen;
+    while (1)
     {
-        byte = buf[j] ^ mask[i++ % 4];
-        if ((ret = send_bytes( socket, &byte, 1 ))) return ret;
-    }
+        j = 0;
+        while (j < buflen && offset < MAX_FRAME_BUFFER_SIZE)
+            socket->send_frame_buffer[offset++] = buf[j++] ^ mask[i++ % 4];
+
+        if ((ret = send_bytes( socket, socket->send_frame_buffer, offset ))) return ret;
 
+        if (!(send_size -= offset)) break;
+        offset = 0;
+        buf += j;
+        buflen -= j;
+    }
     return ERROR_SUCCESS;
 }
 
diff --git a/dlls/winhttp/winhttp_private.h b/dlls/winhttp/winhttp_private.h
index 1538a61da6d..557ee766735 100644
--- a/dlls/winhttp/winhttp_private.h
+++ b/dlls/winhttp/winhttp_private.h
@@ -248,6 +248,8 @@ struct socket
     USHORT status;
     char reason[123];
     DWORD reason_len;
+    char *send_frame_buffer;
+    unsigned int send_frame_buffer_size;
 };
 
 struct send_request
@@ -398,4 +400,6 @@ static inline char *strdupWA_sized( const WCHAR *src, DWORD size )
 
 extern HINSTANCE winhttp_instance DECLSPEC_HIDDEN;
 
+#define MAX_FRAME_BUFFER_SIZE 65536
+
 #endif /* _WINE_WINHTTP_PRIVATE_H_ */
-- 
2.34.1




More information about the wine-devel mailing list