winhttp: Attemp sync websocket send even if data doesn't fit frame buffer.

Signed-off-by: Paul Gofman <pgofman@codeweavers.com>
Signed-off-by: Hans Leidekker <hans@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Paul Gofman 2022-01-27 02:03:07 +03:00 committed by Alexandre Julliard
parent a0e5fcdc00
commit 9861b6796f
2 changed files with 41 additions and 19 deletions

View File

@ -3145,10 +3145,10 @@ static DWORD send_bytes( struct socket *socket, char *bytes, int len, int *sent,
static DWORD send_frame( struct socket *socket, enum socket_opcode opcode, USHORT status, const char *buf,
DWORD buflen, BOOL final, WSAOVERLAPPED *ovr )
{
DWORD i = 0, j, offset = 2, len = buflen;
DWORD buffer_size, ret = 0, send_size;
char hdr[14], *mask = NULL;
DWORD i, offset = 2, len = buflen;
DWORD buffer_size, ret = 0;
int sent_size;
char hdr[14];
char *ptr;
TRACE( "sending %02x frame, len %u.\n", opcode, len );
@ -3179,7 +3179,6 @@ static DWORD send_frame( struct socket *socket, enum socket_opcode opcode, USHOR
buffer_size = len + offset + 4;
assert( buffer_size - len < MAX_FRAME_BUFFER_SIZE );
if (ovr && buffer_size > MAX_FRAME_BUFFER_SIZE) return WSAEWOULDBLOCK;
if (buffer_size > socket->send_frame_buffer_size && socket->send_frame_buffer_size < MAX_FRAME_BUFFER_SIZE)
{
DWORD new_size;
@ -3199,27 +3198,32 @@ static DWORD send_frame( struct socket *socket, enum socket_opcode opcode, USHOR
memcpy(ptr, hdr, offset);
ptr += offset;
mask = &hdr[offset];
RtlGenRandom( mask, 4 );
memcpy( ptr, mask, 4 );
RtlGenRandom( socket->mask, 4 );
memcpy( ptr, socket->mask, 4 );
ptr += 4;
socket->mask_index = 0;
if (opcode == SOCKET_OPCODE_CLOSE) /* prepend status code */
{
*ptr++ = (status >> 8) ^ mask[i++ % 4];
*ptr++ = (status & 0xff) ^ mask[i++ % 4];
*ptr++ = (status >> 8) ^ socket->mask[socket->mask_index++ % 4];
*ptr++ = (status & 0xff) ^ socket->mask[socket->mask_index++ % 4];
}
offset = ptr - socket->send_frame_buffer;
send_size = offset + buflen;
while (1)
socket->send_remaining_size = offset + buflen;
socket->client_buffer_offset = 0;
while (socket->send_remaining_size)
{
j = 0;
while (j < buflen && offset < MAX_FRAME_BUFFER_SIZE)
socket->send_frame_buffer[offset++] = buf[j++] ^ mask[i++ % 4];
len = min( buflen, MAX_FRAME_BUFFER_SIZE - offset );
for (i = 0; i < len; ++i)
{
socket->send_frame_buffer[offset++] = buf[socket->client_buffer_offset++]
^ socket->mask[socket->mask_index++ % 4];
}
sent_size = 0;
ret = send_bytes( socket, socket->send_frame_buffer, offset, &sent_size, ovr );
socket->send_remaining_size -= sent_size;
if (ret)
{
if (ovr && ret == WSA_IO_PENDING)
@ -3229,17 +3233,16 @@ static DWORD send_frame( struct socket *socket, enum socket_opcode opcode, USHOR
}
return ret;
}
if (!(send_size -= offset)) break;
assert( sent_size == offset );
offset = 0;
buf += j;
buflen -= j;
buflen -= len;
}
return ERROR_SUCCESS;
}
static DWORD complete_send_frame( struct socket *socket, WSAOVERLAPPED *ovr, const char *buf )
{
DWORD ret, retflags, len;
DWORD ret, retflags, len, i;
if (!WSAGetOverlappedResult( socket->request->netconn->socket, ovr, &len, TRUE, &retflags ))
return WSAGetLastError();
@ -3249,6 +3252,22 @@ static DWORD complete_send_frame( struct socket *socket, WSAOVERLAPPED *ovr, con
ret = send_bytes( socket, socket->send_frame_buffer, socket->bytes_in_send_frame_buffer, NULL, NULL );
if (ret) return ret;
}
assert( socket->bytes_in_send_frame_buffer <= socket->send_remaining_size );
socket->send_remaining_size -= socket->bytes_in_send_frame_buffer;
while (socket->send_remaining_size)
{
len = min( socket->send_remaining_size, MAX_FRAME_BUFFER_SIZE );
for (i = 0; i < len; ++i)
{
socket->send_frame_buffer[i] = buf[socket->client_buffer_offset++]
^ socket->mask[socket->mask_index++ % 4];
}
ret = send_bytes( socket, socket->send_frame_buffer, len, NULL, NULL );
if (ret) return ret;
socket->send_remaining_size -= len;
}
return ERROR_SUCCESS;
}
@ -3371,7 +3390,6 @@ DWORD WINAPI WinHttpWebSocketSend( HINTERNET hsocket, WINHTTP_WEB_SOCKET_BUFFER_
async_send = TRUE;
complete_async = TRUE;
}
else if (ret == WSAEWOULDBLOCK) async_send = TRUE;
}
if (async_send)

View File

@ -247,6 +247,8 @@ struct socket
struct queue recv_q;
enum socket_opcode opcode;
DWORD read_size;
char mask[4];
unsigned int mask_index;
BOOL close_frame_received;
DWORD close_frame_receive_err;
USHORT status;
@ -254,7 +256,9 @@ struct socket
DWORD reason_len;
char *send_frame_buffer;
unsigned int send_frame_buffer_size;
unsigned int send_remaining_size;
unsigned int bytes_in_send_frame_buffer;
unsigned int client_buffer_offset;
};
struct send_request