winhttp: Support sending web socket buffer fragments.
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:
parent
11c835d471
commit
003391dec8
|
@ -3298,13 +3298,65 @@ static BOOL socket_can_receive( struct socket *socket )
|
|||
return socket->state <= SOCKET_STATE_SHUTDOWN && !socket->close_frame_received;
|
||||
}
|
||||
|
||||
static enum socket_opcode map_buffer_type( WINHTTP_WEB_SOCKET_BUFFER_TYPE type )
|
||||
static BOOL validate_buffer_type( WINHTTP_WEB_SOCKET_BUFFER_TYPE type, enum fragment_type current_fragment )
|
||||
{
|
||||
switch (current_fragment)
|
||||
{
|
||||
case SOCKET_FRAGMENT_NONE:
|
||||
return type == WINHTTP_WEB_SOCKET_BINARY_MESSAGE_BUFFER_TYPE
|
||||
|| type == WINHTTP_WEB_SOCKET_BINARY_FRAGMENT_BUFFER_TYPE
|
||||
|| type == WINHTTP_WEB_SOCKET_UTF8_MESSAGE_BUFFER_TYPE
|
||||
|| type == WINHTTP_WEB_SOCKET_UTF8_FRAGMENT_BUFFER_TYPE;
|
||||
case SOCKET_FRAGMENT_BINARY:
|
||||
return type == WINHTTP_WEB_SOCKET_BINARY_MESSAGE_BUFFER_TYPE
|
||||
|| type == WINHTTP_WEB_SOCKET_BINARY_FRAGMENT_BUFFER_TYPE;
|
||||
case SOCKET_FRAGMENT_UTF8:
|
||||
return type == WINHTTP_WEB_SOCKET_UTF8_MESSAGE_BUFFER_TYPE
|
||||
|| type == WINHTTP_WEB_SOCKET_UTF8_FRAGMENT_BUFFER_TYPE;
|
||||
}
|
||||
assert( 0 );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static enum socket_opcode map_buffer_type( struct socket *socket, WINHTTP_WEB_SOCKET_BUFFER_TYPE type )
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case WINHTTP_WEB_SOCKET_UTF8_MESSAGE_BUFFER_TYPE: return SOCKET_OPCODE_TEXT;
|
||||
case WINHTTP_WEB_SOCKET_BINARY_MESSAGE_BUFFER_TYPE: return SOCKET_OPCODE_BINARY;
|
||||
case WINHTTP_WEB_SOCKET_CLOSE_BUFFER_TYPE: return SOCKET_OPCODE_CLOSE;
|
||||
case WINHTTP_WEB_SOCKET_UTF8_MESSAGE_BUFFER_TYPE:
|
||||
if (socket->sending_fragment_type)
|
||||
{
|
||||
socket->sending_fragment_type = SOCKET_FRAGMENT_NONE;
|
||||
return SOCKET_OPCODE_CONTINUE;
|
||||
}
|
||||
return SOCKET_OPCODE_TEXT;
|
||||
|
||||
case WINHTTP_WEB_SOCKET_BINARY_MESSAGE_BUFFER_TYPE:
|
||||
if (socket->sending_fragment_type)
|
||||
{
|
||||
socket->sending_fragment_type = SOCKET_FRAGMENT_NONE;
|
||||
return SOCKET_OPCODE_CONTINUE;
|
||||
}
|
||||
return SOCKET_OPCODE_BINARY;
|
||||
|
||||
case WINHTTP_WEB_SOCKET_UTF8_FRAGMENT_BUFFER_TYPE:
|
||||
if (!socket->sending_fragment_type)
|
||||
{
|
||||
socket->sending_fragment_type = SOCKET_FRAGMENT_UTF8;
|
||||
return SOCKET_OPCODE_TEXT;
|
||||
}
|
||||
return SOCKET_OPCODE_CONTINUE;
|
||||
|
||||
case WINHTTP_WEB_SOCKET_BINARY_FRAGMENT_BUFFER_TYPE:
|
||||
if (!socket->sending_fragment_type)
|
||||
{
|
||||
socket->sending_fragment_type = SOCKET_FRAGMENT_BINARY;
|
||||
return SOCKET_OPCODE_BINARY;
|
||||
}
|
||||
return SOCKET_OPCODE_CONTINUE;
|
||||
|
||||
case WINHTTP_WEB_SOCKET_CLOSE_BUFFER_TYPE:
|
||||
return SOCKET_OPCODE_CLOSE;
|
||||
|
||||
default:
|
||||
FIXME("buffer type %u not supported\n", type);
|
||||
return SOCKET_OPCODE_INVALID;
|
||||
|
@ -3333,9 +3385,11 @@ static void socket_send_complete( struct socket *socket, DWORD ret, WINHTTP_WEB_
|
|||
static DWORD socket_send( struct socket *socket, WINHTTP_WEB_SOCKET_BUFFER_TYPE type, const void *buf, DWORD len,
|
||||
WSAOVERLAPPED *ovr )
|
||||
{
|
||||
enum socket_opcode opcode = map_buffer_type( type );
|
||||
enum socket_opcode opcode = map_buffer_type( socket, type );
|
||||
BOOL final = (type != WINHTTP_WEB_SOCKET_UTF8_FRAGMENT_BUFFER_TYPE &&
|
||||
type != WINHTTP_WEB_SOCKET_BINARY_FRAGMENT_BUFFER_TYPE);
|
||||
|
||||
return send_frame( socket, opcode, 0, buf, len, TRUE, ovr );
|
||||
return send_frame( socket, opcode, 0, buf, len, final, ovr );
|
||||
}
|
||||
|
||||
static void CALLBACK task_socket_send( TP_CALLBACK_INSTANCE *instance, void *ctx, TP_WORK *work )
|
||||
|
@ -3364,11 +3418,6 @@ DWORD WINAPI WinHttpWebSocketSend( HINTERNET hsocket, WINHTTP_WEB_SOCKET_BUFFER_
|
|||
TRACE( "%p, %u, %p, %lu\n", hsocket, type, buf, len );
|
||||
|
||||
if (len && !buf) return ERROR_INVALID_PARAMETER;
|
||||
if (type != WINHTTP_WEB_SOCKET_UTF8_MESSAGE_BUFFER_TYPE && type != WINHTTP_WEB_SOCKET_BINARY_MESSAGE_BUFFER_TYPE)
|
||||
{
|
||||
FIXME("buffer type %u not supported\n", type);
|
||||
return ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
if (!(socket = (struct socket *)grab_object( hsocket ))) return ERROR_INVALID_HANDLE;
|
||||
if (socket->hdr.type != WINHTTP_HANDLE_TYPE_SOCKET)
|
||||
|
@ -3393,6 +3442,13 @@ DWORD WINAPI WinHttpWebSocketSend( HINTERNET hsocket, WINHTTP_WEB_SOCKET_BUFFER_
|
|||
release_object( &socket->hdr );
|
||||
return ERROR_INVALID_OPERATION;
|
||||
}
|
||||
if (!validate_buffer_type( type, socket->sending_fragment_type ))
|
||||
{
|
||||
WARN( "Invalid buffer type %u, sending_fragment_type %u.\n", type, socket->sending_fragment_type );
|
||||
InterlockedExchange( &socket->pending_noncontrol_send, 0 );
|
||||
release_object( &socket->hdr );
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (!(s = malloc( sizeof(*s) )))
|
||||
{
|
||||
|
@ -3445,7 +3501,18 @@ DWORD WINAPI WinHttpWebSocketSend( HINTERNET hsocket, WINHTTP_WEB_SOCKET_BUFFER_
|
|||
ret = ERROR_SUCCESS;
|
||||
}
|
||||
}
|
||||
else ret = socket_send( socket, type, buf, len, NULL );
|
||||
else
|
||||
{
|
||||
if (validate_buffer_type( type, socket->sending_fragment_type ))
|
||||
{
|
||||
ret = socket_send( socket, type, buf, len, NULL );
|
||||
}
|
||||
else
|
||||
{
|
||||
WARN( "Invalid buffer type %u, sending_fragment_type %u.\n", type, socket->sending_fragment_type );
|
||||
ret = ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
}
|
||||
|
||||
release_object( &socket->hdr );
|
||||
return ret;
|
||||
|
|
|
@ -676,6 +676,8 @@ static const struct notification websocket_test[] =
|
|||
{ winhttp_websocket_complete_upgrade, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED, NF_SIGNAL },
|
||||
{ winhttp_websocket_send, WINHTTP_CALLBACK_STATUS_WRITE_COMPLETE, NF_MAIN_THREAD | NF_SIGNAL },
|
||||
{ winhttp_websocket_send, WINHTTP_CALLBACK_STATUS_WRITE_COMPLETE, NF_MAIN_THREAD | NF_SIGNAL },
|
||||
{ winhttp_websocket_send, WINHTTP_CALLBACK_STATUS_WRITE_COMPLETE, NF_MAIN_THREAD | NF_SIGNAL },
|
||||
{ winhttp_websocket_send, WINHTTP_CALLBACK_STATUS_WRITE_COMPLETE, NF_MAIN_THREAD | NF_SIGNAL },
|
||||
{ winhttp_websocket_shutdown, WINHTTP_CALLBACK_STATUS_SHUTDOWN_COMPLETE, NF_MAIN_THREAD | NF_SIGNAL },
|
||||
{ winhttp_websocket_receive, WINHTTP_CALLBACK_STATUS_READ_COMPLETE, NF_SAVE_BUFFER | NF_SIGNAL },
|
||||
{ winhttp_websocket_receive, WINHTTP_CALLBACK_STATUS_READ_COMPLETE, NF_SAVE_BUFFER | NF_SIGNAL },
|
||||
|
@ -867,7 +869,25 @@ static void test_websocket(BOOL secure)
|
|||
for (i = 0; i < BIG_BUFFER_SIZE; ++i) big_buffer[i] = (i & 0xff) ^ 0xcc;
|
||||
|
||||
setup_test( &info, winhttp_websocket_send, __LINE__ );
|
||||
err = pWinHttpWebSocketSend( socket, WINHTTP_WEB_SOCKET_BINARY_MESSAGE_BUFFER_TYPE, big_buffer, BIG_BUFFER_SIZE );
|
||||
err = pWinHttpWebSocketSend( socket, WINHTTP_WEB_SOCKET_BINARY_FRAGMENT_BUFFER_TYPE, big_buffer, BIG_BUFFER_SIZE / 2 );
|
||||
ok( err == ERROR_SUCCESS, "got %lu\n", err );
|
||||
WaitForSingleObject( info.wait, INFINITE );
|
||||
|
||||
err = pWinHttpWebSocketSend( socket, WINHTTP_WEB_SOCKET_UTF8_FRAGMENT_BUFFER_TYPE,
|
||||
big_buffer + BIG_BUFFER_SIZE / 2, BIG_BUFFER_SIZE / 2 );
|
||||
ok( err == ERROR_INVALID_PARAMETER, "got %lu\n", err );
|
||||
err = pWinHttpWebSocketSend( socket, WINHTTP_WEB_SOCKET_UTF8_MESSAGE_BUFFER_TYPE,
|
||||
big_buffer + BIG_BUFFER_SIZE / 2, BIG_BUFFER_SIZE / 2 );
|
||||
ok( err == ERROR_INVALID_PARAMETER, "got %lu\n", err );
|
||||
|
||||
setup_test( &info, winhttp_websocket_send, __LINE__ );
|
||||
err = pWinHttpWebSocketSend( socket, WINHTTP_WEB_SOCKET_BINARY_FRAGMENT_BUFFER_TYPE,
|
||||
big_buffer + BIG_BUFFER_SIZE / 2, BIG_BUFFER_SIZE / 2 );
|
||||
ok( err == ERROR_SUCCESS, "got %lu\n", err );
|
||||
WaitForSingleObject( info.wait, INFINITE );
|
||||
|
||||
setup_test( &info, winhttp_websocket_send, __LINE__ );
|
||||
err = pWinHttpWebSocketSend( socket, WINHTTP_WEB_SOCKET_BINARY_MESSAGE_BUFFER_TYPE, NULL, 0 );
|
||||
ok( err == ERROR_SUCCESS, "got %lu\n", err );
|
||||
WaitForSingleObject( info.wait, INFINITE );
|
||||
|
||||
|
|
|
@ -238,6 +238,13 @@ enum socket_opcode
|
|||
SOCKET_OPCODE_INVALID = 0xff,
|
||||
};
|
||||
|
||||
enum fragment_type
|
||||
{
|
||||
SOCKET_FRAGMENT_NONE,
|
||||
SOCKET_FRAGMENT_BINARY,
|
||||
SOCKET_FRAGMENT_UTF8,
|
||||
};
|
||||
|
||||
struct socket
|
||||
{
|
||||
struct object_header hdr;
|
||||
|
@ -261,6 +268,7 @@ struct socket
|
|||
unsigned int client_buffer_offset;
|
||||
SRWLOCK send_lock;
|
||||
volatile LONG pending_noncontrol_send;
|
||||
enum fragment_type sending_fragment_type;
|
||||
};
|
||||
|
||||
struct send_request
|
||||
|
|
Loading…
Reference in New Issue