-- v4: winhttp: Support WINHTTP_OPTION_WEB_SOCKET_SEND_BUFFER_SIZE. winhttp: Stub WINHTTP_OPTION_WEB_SOCKET_RECEIVE_BUFFER_SIZE.
From: Paul Gofman pgofman@codeweavers.com
--- dlls/winhttp/request.c | 32 ++++++++++++++++++++ dlls/winhttp/tests/winhttp.c | 53 +++++++++++++++++++++++++++++++++- dlls/winhttp/winhttp_private.h | 1 + 3 files changed, 85 insertions(+), 1 deletion(-)
diff --git a/dlls/winhttp/request.c b/dlls/winhttp/request.c index 9f769f3dc35..543532c31d8 100644 --- a/dlls/winhttp/request.c +++ b/dlls/winhttp/request.c @@ -3151,6 +3151,13 @@ static void socket_handle_closing( struct object_header *hdr )
static BOOL socket_query_option( struct object_header *hdr, DWORD option, void *buffer, DWORD *buflen ) { + switch (option) + { + case WINHTTP_OPTION_WEB_SOCKET_KEEPALIVE_INTERVAL: + SetLastError( ERROR_INVALID_PARAMETER ); + return FALSE; + } + FIXME( "unimplemented option %lu\n", option ); SetLastError( ERROR_WINHTTP_INVALID_OPTION ); return FALSE; @@ -3172,6 +3179,28 @@ static void socket_destroy( struct object_header *hdr )
static BOOL socket_set_option( struct object_header *hdr, DWORD option, void *buffer, DWORD buflen ) { + struct socket *socket = (struct socket *)hdr; + + switch (option) + { + case WINHTTP_OPTION_WEB_SOCKET_KEEPALIVE_INTERVAL: + { + DWORD interval; + + if (buflen != sizeof(DWORD) || (interval = *(DWORD *)buffer) < 15000) + { + WARN( "Invalid parameters for WINHTTP_OPTION_WEB_SOCKET_KEEPALIVE_INTERVAL.\n" ); + SetLastError( ERROR_INVALID_PARAMETER ); + return FALSE; + } + socket->keepalive_interval = interval; + netconn_set_timeout( socket->request->netconn, FALSE, socket->keepalive_interval ); + SetLastError( ERROR_SUCCESS ); + TRACE( "WINHTTP_OPTION_WEB_SOCKET_KEEPALIVE_INTERVAL %lu.\n", interval); + return TRUE; + } + } + FIXME( "unimplemented option %lu\n", option ); SetLastError( ERROR_WINHTTP_INVALID_OPTION ); return FALSE; @@ -3215,6 +3244,7 @@ HINTERNET WINAPI WinHttpWebSocketCompleteUpgrade( HINTERNET hrequest, DWORD_PTR socket->hdr.callback = request->hdr.callback; socket->hdr.notify_mask = request->hdr.notify_mask; socket->hdr.context = context; + socket->keepalive_interval = 30000; InitializeSRWLock( &socket->send_lock ); init_queue( &socket->send_q ); init_queue( &socket->recv_q ); @@ -3222,6 +3252,8 @@ HINTERNET WINAPI WinHttpWebSocketCompleteUpgrade( HINTERNET hrequest, DWORD_PTR addref_object( &request->hdr ); socket->request = request;
+ netconn_set_timeout( socket->request->netconn, FALSE, socket->keepalive_interval ); + if ((hsocket = alloc_handle( &socket->hdr ))) { send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED, &hsocket, sizeof(hsocket) ); diff --git a/dlls/winhttp/tests/winhttp.c b/dlls/winhttp/tests/winhttp.c index d1dd58fdad4..ed3d06038af 100644 --- a/dlls/winhttp/tests/winhttp.c +++ b/dlls/winhttp/tests/winhttp.c @@ -3233,7 +3233,7 @@ static void test_redirect(int port) static void test_websocket(int port) { HINTERNET session, connection, request, socket, socket2; - DWORD size, len, count, status, index, error; + DWORD size, len, count, status, index, error, value; DWORD_PTR ctx; WINHTTP_WEB_SOCKET_BUFFER_TYPE type; WCHAR header[32]; @@ -3428,6 +3428,21 @@ static void test_websocket(int port) request = WinHttpOpenRequest(connection, L"GET", L"/", NULL, NULL, NULL, 0); ok(request != NULL, "got %lu\n", GetLastError());
+ size = sizeof(value); + ret = WinHttpQueryOption(session, WINHTTP_OPTION_WEB_SOCKET_KEEPALIVE_INTERVAL, &value, &size); + ok(!ret, "got %d\n", ret); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %lu\n", GetLastError()); + + size = sizeof(value); + ret = WinHttpQueryOption(request, WINHTTP_OPTION_WEB_SOCKET_KEEPALIVE_INTERVAL, &value, &size); + ok(!ret, "got %d\n", ret); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %lu\n", GetLastError()); + + value = 20000; + ret = WinHttpSetOption(request, WINHTTP_OPTION_WEB_SOCKET_KEEPALIVE_INTERVAL, &value, sizeof(DWORD)); + ok(!ret, "got %d\n", ret); + todo_wine ok(GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE, "got %lu\n", GetLastError()); + ret = WinHttpSetOption(request, WINHTTP_OPTION_UPGRADE_TO_WEB_SOCKET, NULL, 0); ok(ret, "got %lu\n", GetLastError());
@@ -3447,6 +3462,42 @@ static void test_websocket(int port) socket = pWinHttpWebSocketCompleteUpgrade(request, 0); ok(socket != NULL, "got %lu\n", GetLastError());
+ value = 20000; + ret = WinHttpSetOption(socket, WINHTTP_OPTION_WEB_SOCKET_KEEPALIVE_INTERVAL, &value, 2); + ok(!ret, "got %d\n", ret); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %lu\n", GetLastError()); + + value = 20000; + ret = WinHttpSetOption(socket, WINHTTP_OPTION_WEB_SOCKET_KEEPALIVE_INTERVAL, &value, sizeof(DWORD) * 2); + ok(!ret, "got %d\n", ret); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %lu\n", GetLastError()); + + SetLastError(0xdeadbeef); + value = 20000; + ret = WinHttpSetOption(socket, WINHTTP_OPTION_WEB_SOCKET_KEEPALIVE_INTERVAL, &value, sizeof(DWORD)); + ok(ret, "got %lu\n", GetLastError()); + ok(!GetLastError(), "got %lu\n", GetLastError()); + + size = sizeof(value); + ret = WinHttpQueryOption(socket, WINHTTP_OPTION_WEB_SOCKET_KEEPALIVE_INTERVAL, &value, &size); + ok(!ret, "got %d\n", ret); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %lu\n", GetLastError()); + + size = 0; + ret = WinHttpQueryOption(socket, WINHTTP_OPTION_WEB_SOCKET_KEEPALIVE_INTERVAL, NULL, &size); + ok(!ret, "got %d\n", ret); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %lu\n", GetLastError()); + + value = 10000; + ret = WinHttpSetOption(socket, WINHTTP_OPTION_WEB_SOCKET_KEEPALIVE_INTERVAL, &value, sizeof(DWORD)); + ok(!ret, "got %d\n", ret); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %lu\n", GetLastError()); + + value = 10000; + ret = WinHttpSetOption(socket, WINHTTP_OPTION_WEB_SOCKET_KEEPALIVE_INTERVAL, &value, 2); + ok(!ret, "got %d\n", ret); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %lu\n", GetLastError()); + buf[0] = 0; count = 0; type = 0xdeadbeef; diff --git a/dlls/winhttp/winhttp_private.h b/dlls/winhttp/winhttp_private.h index 79941dee31a..52f9eb171ee 100644 --- a/dlls/winhttp/winhttp_private.h +++ b/dlls/winhttp/winhttp_private.h @@ -252,6 +252,7 @@ struct socket { struct object_header hdr; struct request *request; + int keepalive_interval; enum socket_state state; struct queue send_q; struct queue recv_q;
From: Paul Gofman pgofman@codeweavers.com
--- dlls/winhttp/session.c | 49 +++++++++++++++++++++++++++++++ dlls/winhttp/tests/winhttp.c | 53 ++++++++++++++++++++++++++++++++++ dlls/winhttp/winhttp_private.h | 2 ++ 3 files changed, 104 insertions(+)
diff --git a/dlls/winhttp/session.c b/dlls/winhttp/session.c index 01e95895eb3..12af5ded251 100644 --- a/dlls/winhttp/session.c +++ b/dlls/winhttp/session.c @@ -144,6 +144,13 @@ static BOOL session_query_option( struct object_header *hdr, DWORD option, void *buflen = sizeof(DWORD); return TRUE;
+ case WINHTTP_OPTION_WEB_SOCKET_RECEIVE_BUFFER_SIZE: + if (!validate_buffer( buffer, buflen, sizeof(DWORD) )) return FALSE; + + *(DWORD *)buffer = session->websocket_receive_buffer_size; + *buflen = sizeof(DWORD); + return TRUE; + default: FIXME( "unimplemented option %lu\n", option ); SetLastError( ERROR_INVALID_PARAMETER ); @@ -233,6 +240,22 @@ static BOOL session_set_option( struct object_header *hdr, DWORD option, void *b FIXME( "WINHTTP_OPTION_MAX_CONNS_PER_1_0_SERVER: %lu\n", *(DWORD *)buffer ); return TRUE;
+ case WINHTTP_OPTION_WEB_SOCKET_RECEIVE_BUFFER_SIZE: + { + DWORD buffer_size; + + if (buflen != sizeof(buffer_size)) + { + SetLastError( ERROR_INSUFFICIENT_BUFFER ); + return FALSE; + } + + buffer_size = *(DWORD *)buffer; + TRACE( "%#lx\n", buffer_size ); + session->websocket_receive_buffer_size = buffer_size; + return TRUE; + } + default: FIXME( "unimplemented option %lu\n", option ); SetLastError( ERROR_WINHTTP_INVALID_OPTION ); @@ -270,6 +293,7 @@ HINTERNET WINAPI WinHttpOpen( LPCWSTR agent, DWORD access, LPCWSTR proxy, LPCWST session->send_timeout = DEFAULT_SEND_TIMEOUT; session->receive_timeout = DEFAULT_RECEIVE_TIMEOUT; session->receive_response_timeout = DEFAULT_RECEIVE_RESPONSE_TIMEOUT; + session->websocket_receive_buffer_size = 32768; list_init( &session->cookie_cache ); InitializeCriticalSection( &session->cs ); session->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": session.cs"); @@ -842,6 +866,13 @@ static BOOL request_query_option( struct object_header *hdr, DWORD option, void *buflen = sizeof(DWORD); return TRUE;
+ case WINHTTP_OPTION_WEB_SOCKET_RECEIVE_BUFFER_SIZE: + if (!validate_buffer( buffer, buflen, sizeof(DWORD) )) return FALSE; + + *(DWORD *)buffer = request->websocket_receive_buffer_size; + *buflen = sizeof(DWORD); + return TRUE; + default: FIXME( "unimplemented option %lu\n", option ); SetLastError( ERROR_INVALID_PARAMETER ); @@ -1078,6 +1109,23 @@ static BOOL request_set_option( struct object_header *hdr, DWORD option, void *b SetLastError(ERROR_INVALID_PARAMETER); return FALSE;
+ case WINHTTP_OPTION_WEB_SOCKET_RECEIVE_BUFFER_SIZE: + { + DWORD buffer_size; + + if (buflen != sizeof(buffer_size)) + { + SetLastError( ERROR_INSUFFICIENT_BUFFER ); + return FALSE; + } + + buffer_size = *(DWORD *)buffer; + WARN( "Setting websocket receive buffer size currently has not effct, size %lu\n", buffer_size ); + request->websocket_receive_buffer_size = buffer_size; + return TRUE; + } + + default: FIXME( "unimplemented option %lu\n", option ); SetLastError( ERROR_WINHTTP_INVALID_OPTION ); @@ -1174,6 +1222,7 @@ HINTERNET WINAPI WinHttpOpenRequest( HINTERNET hconnect, const WCHAR *verb, cons request->receive_timeout = connect->session->receive_timeout; request->receive_response_timeout = connect->session->receive_response_timeout; request->max_redirects = 10; + request->websocket_receive_buffer_size = connect->session->websocket_receive_buffer_size;
if (!verb || !verb[0]) verb = L"GET"; if (!(request->verb = strdupW( verb ))) goto end; diff --git a/dlls/winhttp/tests/winhttp.c b/dlls/winhttp/tests/winhttp.c index ed3d06038af..b48e11dd753 100644 --- a/dlls/winhttp/tests/winhttp.c +++ b/dlls/winhttp/tests/winhttp.c @@ -3425,9 +3425,52 @@ static void test_websocket(int port) connection = WinHttpConnect(session, L"ws.ifelse.io", 0, 0); ok(connection != NULL, "got %lu\n", GetLastError());
+ size = 0xdeadbeef; + ret = WinHttpQueryOption(session, WINHTTP_OPTION_WEB_SOCKET_RECEIVE_BUFFER_SIZE, &value, &size); + ok(ret, "got %lu\n", GetLastError()); + ok(size == sizeof(DWORD), "got %lu.\n", size); + ok(value == 32768, "got %lu.\n", value); + + value = 65535; + ret = WinHttpSetOption(session, WINHTTP_OPTION_WEB_SOCKET_RECEIVE_BUFFER_SIZE, &value, sizeof(DWORD)); + ok(ret, "got %lu\n", GetLastError()); + request = WinHttpOpenRequest(connection, L"GET", L"/", NULL, NULL, NULL, 0); ok(request != NULL, "got %lu\n", GetLastError());
+ size = 0xdeadbeef; + ret = WinHttpQueryOption(session, WINHTTP_OPTION_WEB_SOCKET_RECEIVE_BUFFER_SIZE, &value, &size); + ok(ret, "got %lu\n", GetLastError()); + ok(size == sizeof(DWORD), "got %lu.\n", size); + ok(value == 65535 || broken( value == WINHTTP_OPTION_WEB_SOCKET_RECEIVE_BUFFER_SIZE ) /* Win8 */, "got %lu.\n", value); + + size = 0xdeadbeef; + ret = WinHttpQueryOption(request, WINHTTP_OPTION_WEB_SOCKET_RECEIVE_BUFFER_SIZE, &value, &size); + ok(ret, "got %lu\n", GetLastError()); + ok(size == sizeof(DWORD), "got %lu.\n", size); + ok(value == 65535 || broken( value == WINHTTP_OPTION_WEB_SOCKET_RECEIVE_BUFFER_SIZE ), "got %lu.\n", value); + + value = 1048576; + ret = WinHttpSetOption(request, WINHTTP_OPTION_WEB_SOCKET_RECEIVE_BUFFER_SIZE, &value, sizeof(DWORD)); + ok(ret, "got %lu\n", GetLastError()); + + size = 0xdeadbeef; + ret = WinHttpQueryOption(session, WINHTTP_OPTION_WEB_SOCKET_RECEIVE_BUFFER_SIZE, &value, &size); + ok(ret, "got %lu\n", GetLastError()); + ok(size == sizeof(DWORD), "got %lu.\n", size); + ok(value == 65535 || broken( value == WINHTTP_OPTION_WEB_SOCKET_RECEIVE_BUFFER_SIZE ) /* Win8 */, "got %lu.\n", value); + + size = 0xdeadbeef; + ret = WinHttpQueryOption(request, WINHTTP_OPTION_WEB_SOCKET_RECEIVE_BUFFER_SIZE, &value, &size); + ok(ret, "got %lu\n", GetLastError()); + ok(size == sizeof(DWORD), "got %lu.\n", size); + ok(value == 1048576, "got %lu.\n", value); + + size = 0xdeadbeef; + ret = WinHttpQueryOption(connection, WINHTTP_OPTION_WEB_SOCKET_RECEIVE_BUFFER_SIZE, &value, &size); + ok(!ret, "got %d\n", ret); + todo_wine ok(GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE, "got %lu\n", GetLastError()); + size = sizeof(value); ret = WinHttpQueryOption(session, WINHTTP_OPTION_WEB_SOCKET_KEEPALIVE_INTERVAL, &value, &size); ok(!ret, "got %d\n", ret); @@ -3462,6 +3505,16 @@ static void test_websocket(int port) socket = pWinHttpWebSocketCompleteUpgrade(request, 0); ok(socket != NULL, "got %lu\n", GetLastError());
+ size = sizeof(value); + ret = WinHttpQueryOption(socket, WINHTTP_OPTION_WEB_SOCKET_RECEIVE_BUFFER_SIZE, &value, &size); + ok(!ret, "got %d\n", ret); + todo_wine ok(GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE, "got %lu\n", GetLastError()); + + value = 65535; + ret = WinHttpSetOption(socket, WINHTTP_OPTION_WEB_SOCKET_RECEIVE_BUFFER_SIZE, &value, sizeof(DWORD)); + ok(!ret, "got %d\n", ret); + todo_wine ok(GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE, "got %lu\n", GetLastError()); + value = 20000; ret = WinHttpSetOption(socket, WINHTTP_OPTION_WEB_SOCKET_KEEPALIVE_INTERVAL, &value, 2); ok(!ret, "got %d\n", ret); diff --git a/dlls/winhttp/winhttp_private.h b/dlls/winhttp/winhttp_private.h index 52f9eb171ee..9c994037bcf 100644 --- a/dlls/winhttp/winhttp_private.h +++ b/dlls/winhttp/winhttp_private.h @@ -85,6 +85,7 @@ struct session HANDLE unload_event; DWORD secure_protocols; DWORD passport_flags; + unsigned int websocket_receive_buffer_size; };
struct connect @@ -215,6 +216,7 @@ struct request WCHAR *username; WCHAR *password; } creds[TARGET_MAX][SCHEME_MAX]; + unsigned int websocket_receive_buffer_size; };
enum socket_state
From: Paul Gofman pgofman@codeweavers.com
--- dlls/winhttp/request.c | 20 +++++++++---- dlls/winhttp/session.c | 48 +++++++++++++++++++++++++++++++ dlls/winhttp/tests/notification.c | 18 +++++++++++- dlls/winhttp/tests/winhttp.c | 39 +++++++++++++++++++++++++ dlls/winhttp/winhttp_private.h | 5 +++- 5 files changed, 123 insertions(+), 7 deletions(-)
diff --git a/dlls/winhttp/request.c b/dlls/winhttp/request.c index 543532c31d8..64f70b61a96 100644 --- a/dlls/winhttp/request.c +++ b/dlls/winhttp/request.c @@ -2165,6 +2165,14 @@ static DWORD send_request( struct request *request, const WCHAR *headers, DWORD int bytes_sent; DWORD ret, len;
+ if (request->flags & REQUEST_FLAG_WEBSOCKET_UPGRADE + && request->websocket_set_send_buffer_size < MIN_WEBSOCKET_SEND_BUFFER_SIZE) + { + WARN( "Invalid send buffer size %u.\n", request->websocket_set_send_buffer_size ); + ret = ERROR_NOT_ENOUGH_MEMORY; + goto end; + } + drain_content( request ); clear_response_headers( request );
@@ -2185,6 +2193,7 @@ static DWORD send_request( struct request *request, const WCHAR *headers, DWORD } if (request->flags & REQUEST_FLAG_WEBSOCKET_UPGRADE) { + request->websocket_send_buffer_size = request->websocket_set_send_buffer_size; process_header( request, L"Upgrade", L"websocket", WINHTTP_ADDREQ_FLAG_ADD_IF_NEW, TRUE ); process_header( request, L"Connection", L"Upgrade", WINHTTP_ADDREQ_FLAG_ADD_IF_NEW, TRUE ); process_header( request, L"Sec-WebSocket-Version", L"13", WINHTTP_ADDREQ_FLAG_ADD_IF_NEW, TRUE ); @@ -3245,6 +3254,7 @@ HINTERNET WINAPI WinHttpWebSocketCompleteUpgrade( HINTERNET hrequest, DWORD_PTR socket->hdr.notify_mask = request->hdr.notify_mask; socket->hdr.context = context; socket->keepalive_interval = 30000; + socket->send_buffer_size = request->websocket_send_buffer_size; InitializeSRWLock( &socket->send_lock ); init_queue( &socket->send_q ); init_queue( &socket->recv_q ); @@ -3316,13 +3326,13 @@ 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 (buffer_size > socket->send_frame_buffer_size && socket->send_frame_buffer_size < MAX_FRAME_BUFFER_SIZE) + assert( buffer_size - len < socket->send_buffer_size ); + if (buffer_size > socket->send_frame_buffer_size && socket->send_frame_buffer_size < socket->send_buffer_size) { DWORD new_size; void *new;
- new_size = min( buffer_size, MAX_FRAME_BUFFER_SIZE ); + new_size = min( buffer_size, socket->send_buffer_size ); if (!(new = realloc( socket->send_frame_buffer, new_size ))) { ERR( "out of memory, buffer_size %lu\n", buffer_size); @@ -3352,7 +3362,7 @@ static DWORD send_frame( struct socket *socket, enum socket_opcode opcode, USHOR socket->client_buffer_offset = 0; while (socket->send_remaining_size) { - len = min( buflen, MAX_FRAME_BUFFER_SIZE - offset ); + len = min( buflen, socket->send_buffer_size - offset ); for (i = 0; i < len; ++i) { socket->send_frame_buffer[offset++] = buf[socket->client_buffer_offset++] @@ -3396,7 +3406,7 @@ static DWORD complete_send_frame( struct socket *socket, WSAOVERLAPPED *ovr, con
while (socket->send_remaining_size) { - len = min( socket->send_remaining_size, MAX_FRAME_BUFFER_SIZE ); + len = min( socket->send_remaining_size, socket->send_buffer_size ); for (i = 0; i < len; ++i) { socket->send_frame_buffer[i] = buf[socket->client_buffer_offset++] diff --git a/dlls/winhttp/session.c b/dlls/winhttp/session.c index 12af5ded251..e95d24c1901 100644 --- a/dlls/winhttp/session.c +++ b/dlls/winhttp/session.c @@ -151,6 +151,13 @@ static BOOL session_query_option( struct object_header *hdr, DWORD option, void *buflen = sizeof(DWORD); return TRUE;
+ case WINHTTP_OPTION_WEB_SOCKET_SEND_BUFFER_SIZE: + if (!validate_buffer( buffer, buflen, sizeof(DWORD) )) return FALSE; + + *(DWORD *)buffer = session->websocket_send_buffer_size; + *buflen = sizeof(DWORD); + return TRUE; + default: FIXME( "unimplemented option %lu\n", option ); SetLastError( ERROR_INVALID_PARAMETER ); @@ -256,6 +263,22 @@ static BOOL session_set_option( struct object_header *hdr, DWORD option, void *b return TRUE; }
+ case WINHTTP_OPTION_WEB_SOCKET_SEND_BUFFER_SIZE: + { + DWORD buffer_size; + + if (buflen != sizeof(buffer_size)) + { + SetLastError( ERROR_INSUFFICIENT_BUFFER ); + return FALSE; + } + + buffer_size = *(DWORD *)buffer; + TRACE( "%#lx\n", buffer_size ); + session->websocket_send_buffer_size = buffer_size; + return TRUE; + } + default: FIXME( "unimplemented option %lu\n", option ); SetLastError( ERROR_WINHTTP_INVALID_OPTION ); @@ -294,6 +317,7 @@ HINTERNET WINAPI WinHttpOpen( LPCWSTR agent, DWORD access, LPCWSTR proxy, LPCWST session->receive_timeout = DEFAULT_RECEIVE_TIMEOUT; session->receive_response_timeout = DEFAULT_RECEIVE_RESPONSE_TIMEOUT; session->websocket_receive_buffer_size = 32768; + session->websocket_send_buffer_size = 32768; list_init( &session->cookie_cache ); InitializeCriticalSection( &session->cs ); session->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": session.cs"); @@ -873,6 +897,13 @@ static BOOL request_query_option( struct object_header *hdr, DWORD option, void *buflen = sizeof(DWORD); return TRUE;
+ case WINHTTP_OPTION_WEB_SOCKET_SEND_BUFFER_SIZE: + if (!validate_buffer( buffer, buflen, sizeof(DWORD) )) return FALSE; + + *(DWORD *)buffer = request->websocket_set_send_buffer_size; + *buflen = sizeof(DWORD); + return TRUE; + default: FIXME( "unimplemented option %lu\n", option ); SetLastError( ERROR_INVALID_PARAMETER ); @@ -1125,6 +1156,21 @@ static BOOL request_set_option( struct object_header *hdr, DWORD option, void *b return TRUE; }
+ case WINHTTP_OPTION_WEB_SOCKET_SEND_BUFFER_SIZE: + { + DWORD buffer_size; + + if (buflen != sizeof(buffer_size)) + { + SetLastError( ERROR_INSUFFICIENT_BUFFER ); + return FALSE; + } + + buffer_size = *(DWORD *)buffer; + request->websocket_set_send_buffer_size = buffer_size; + TRACE( "Websocket send buffer size %lu.\n", buffer_size); + return TRUE; + }
default: FIXME( "unimplemented option %lu\n", option ); @@ -1223,6 +1269,8 @@ HINTERNET WINAPI WinHttpOpenRequest( HINTERNET hconnect, const WCHAR *verb, cons request->receive_response_timeout = connect->session->receive_response_timeout; request->max_redirects = 10; request->websocket_receive_buffer_size = connect->session->websocket_receive_buffer_size; + request->websocket_send_buffer_size = connect->session->websocket_send_buffer_size; + request->websocket_set_send_buffer_size = request->websocket_send_buffer_size;
if (!verb || !verb[0]) verb = L"GET"; if (!(request->verb = strdupW( verb ))) goto end; diff --git a/dlls/winhttp/tests/notification.c b/dlls/winhttp/tests/notification.c index 55823b42b85..cab297d3f4c 100644 --- a/dlls/winhttp/tests/notification.c +++ b/dlls/winhttp/tests/notification.c @@ -113,6 +113,7 @@ static void CALLBACK check_notification( HINTERNET handle, DWORD_PTR context, DW
status_ok = (info->test[info->index].status == status); function_ok = (info->test[info->index].function == info->function); + ok( status_ok, "%u: expected status %#x got %#lx\n", info->line, info->test[info->index].status, status ); ok(function_ok, "%u: expected function %u got %u\n", info->line, info->test[info->index].function, info->function);
@@ -663,6 +664,7 @@ static const struct notification websocket_test[] = { { winhttp_connect, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED }, { winhttp_open_request, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED }, + { winhttp_send_request, WINHTTP_CALLBACK_STATUS_REQUEST_ERROR, NF_SIGNAL }, { winhttp_send_request, WINHTTP_CALLBACK_STATUS_RESOLVING_NAME }, { winhttp_send_request, WINHTTP_CALLBACK_STATUS_NAME_RESOLVED }, { winhttp_send_request, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER }, @@ -796,7 +798,7 @@ static void test_websocket(BOOL secure) WINHTTP_WEB_SOCKET_ASYNC_RESULT *result; WINHTTP_WEB_SOCKET_STATUS *ws_status; WINHTTP_WEB_SOCKET_BUFFER_TYPE type; - DWORD size, status, err; + DWORD size, status, err, value; BOOL ret, unload = TRUE; struct info info, *context = &info; unsigned char *big_buffer; @@ -871,6 +873,20 @@ static void test_websocket(BOOL secure) ok( ret, "got %lu\n", GetLastError() );
setup_test( &info, winhttp_send_request, __LINE__ ); + + value = 15; + ret = WinHttpSetOption(request, WINHTTP_OPTION_WEB_SOCKET_SEND_BUFFER_SIZE, &value, sizeof(DWORD)); + ok(ret, "got %lu\n", GetLastError()); + ret = WinHttpSendRequest( request, NULL, 0, NULL, 0, 0, 0 ); + err = GetLastError(); + ok( ret, "got err %lu.\n", err ); + + WaitForSingleObject( info.wait, INFINITE ); + + value = 32768; + ret = WinHttpSetOption(request, WINHTTP_OPTION_WEB_SOCKET_SEND_BUFFER_SIZE, &value, sizeof(DWORD)); + ok(ret, "got %lu\n", GetLastError()); + SetLastError( 0xdeadbeef ); ret = WinHttpSendRequest( request, NULL, 0, NULL, 0, 0, 0 ); err = GetLastError(); diff --git a/dlls/winhttp/tests/winhttp.c b/dlls/winhttp/tests/winhttp.c index b48e11dd753..45eaf1a673a 100644 --- a/dlls/winhttp/tests/winhttp.c +++ b/dlls/winhttp/tests/winhttp.c @@ -3236,6 +3236,7 @@ static void test_websocket(int port) DWORD size, len, count, status, index, error, value; DWORD_PTR ctx; WINHTTP_WEB_SOCKET_BUFFER_TYPE type; + BOOL broken_buffer_sizes = FALSE; WCHAR header[32]; char buf[128], *large_buf; USHORT close_status; @@ -3435,6 +3436,16 @@ static void test_websocket(int port) ret = WinHttpSetOption(session, WINHTTP_OPTION_WEB_SOCKET_RECEIVE_BUFFER_SIZE, &value, sizeof(DWORD)); ok(ret, "got %lu\n", GetLastError());
+ size = 0xdeadbeef; + ret = WinHttpQueryOption(session, WINHTTP_OPTION_WEB_SOCKET_SEND_BUFFER_SIZE, &value, &size); + ok(ret, "got %lu\n", GetLastError()); + ok(size == sizeof(DWORD), "got %lu.\n", size); + ok(value == 32768, "got %lu.\n", value); + + value = 15; + ret = WinHttpSetOption(session, WINHTTP_OPTION_WEB_SOCKET_SEND_BUFFER_SIZE, &value, sizeof(DWORD)); + ok(ret, "got %lu\n", GetLastError()); + request = WinHttpOpenRequest(connection, L"GET", L"/", NULL, NULL, NULL, 0); ok(request != NULL, "got %lu\n", GetLastError());
@@ -3443,6 +3454,8 @@ static void test_websocket(int port) ok(ret, "got %lu\n", GetLastError()); ok(size == sizeof(DWORD), "got %lu.\n", size); ok(value == 65535 || broken( value == WINHTTP_OPTION_WEB_SOCKET_RECEIVE_BUFFER_SIZE ) /* Win8 */, "got %lu.\n", value); + if (value == WINHTTP_OPTION_WEB_SOCKET_RECEIVE_BUFFER_SIZE) + broken_buffer_sizes = TRUE;
size = 0xdeadbeef; ret = WinHttpQueryOption(request, WINHTTP_OPTION_WEB_SOCKET_RECEIVE_BUFFER_SIZE, &value, &size); @@ -3471,6 +3484,12 @@ static void test_websocket(int port) ok(!ret, "got %d\n", ret); todo_wine ok(GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE, "got %lu\n", GetLastError());
+ size = 0xdeadbeef; + ret = WinHttpQueryOption(request, WINHTTP_OPTION_WEB_SOCKET_SEND_BUFFER_SIZE, &value, &size); + ok(ret, "got %lu\n", GetLastError()); + ok(size == sizeof(DWORD), "got %lu.\n", size); + ok(value == 15 || broken( value == WINHTTP_OPTION_WEB_SOCKET_SEND_BUFFER_SIZE ) /* Win8 */, "got %lu.\n", value); + size = sizeof(value); ret = WinHttpQueryOption(session, WINHTTP_OPTION_WEB_SOCKET_KEEPALIVE_INTERVAL, &value, &size); ok(!ret, "got %d\n", ret); @@ -3489,9 +3508,25 @@ static void test_websocket(int port) ret = WinHttpSetOption(request, WINHTTP_OPTION_UPGRADE_TO_WEB_SOCKET, NULL, 0); ok(ret, "got %lu\n", GetLastError());
+ if (!broken_buffer_sizes) + { + /* Fails because we have a too small send buffer size set, but is different on Win8. */ + ret = WinHttpSendRequest(request, NULL, 0, NULL, 0, 0, 0); + ok(!ret, "got %d\n", ret); + ok(GetLastError() == ERROR_NOT_ENOUGH_MEMORY, "got %lu\n", GetLastError()); + } + + value = 16; + ret = WinHttpSetOption(request, WINHTTP_OPTION_WEB_SOCKET_SEND_BUFFER_SIZE, &value, sizeof(DWORD)); + ok(ret, "got %lu\n", GetLastError()); + ret = WinHttpSendRequest(request, NULL, 0, NULL, 0, 0, 0); ok(ret, "got %lu\n", GetLastError());
+ value = 15; + ret = WinHttpSetOption(request, WINHTTP_OPTION_WEB_SOCKET_SEND_BUFFER_SIZE, &value, sizeof(DWORD)); + ok(ret, "got %lu\n", GetLastError()); + ret = WinHttpReceiveResponse(request, NULL); ok(ret, "got %lu\n", GetLastError());
@@ -3515,6 +3550,10 @@ static void test_websocket(int port) ok(!ret, "got %d\n", ret); todo_wine ok(GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE, "got %lu\n", GetLastError());
+ ret = WinHttpSetOption(socket, WINHTTP_OPTION_WEB_SOCKET_SEND_BUFFER_SIZE, &value, sizeof(DWORD)); + ok(!ret, "got %d\n", ret); + todo_wine ok(GetLastError() == ERROR_WINHTTP_INCORRECT_HANDLE_TYPE, "got %lu\n", GetLastError()); + value = 20000; ret = WinHttpSetOption(socket, WINHTTP_OPTION_WEB_SOCKET_KEEPALIVE_INTERVAL, &value, 2); ok(!ret, "got %d\n", ret); diff --git a/dlls/winhttp/winhttp_private.h b/dlls/winhttp/winhttp_private.h index 9c994037bcf..53947f73351 100644 --- a/dlls/winhttp/winhttp_private.h +++ b/dlls/winhttp/winhttp_private.h @@ -86,6 +86,7 @@ struct session DWORD secure_protocols; DWORD passport_flags; unsigned int websocket_receive_buffer_size; + unsigned int websocket_send_buffer_size; };
struct connect @@ -217,6 +218,7 @@ struct request WCHAR *password; } creds[TARGET_MAX][SCHEME_MAX]; unsigned int websocket_receive_buffer_size; + unsigned int websocket_send_buffer_size, websocket_set_send_buffer_size; };
enum socket_state @@ -255,6 +257,7 @@ struct socket struct object_header hdr; struct request *request; int keepalive_interval; + unsigned int send_buffer_size; enum socket_state state; struct queue send_q; struct queue recv_q; @@ -446,6 +449,6 @@ static inline char *strdupWA_sized( const WCHAR *src, DWORD size )
extern HINSTANCE winhttp_instance DECLSPEC_HIDDEN;
-#define MAX_FRAME_BUFFER_SIZE 65536 +#define MIN_WEBSOCKET_SEND_BUFFER_SIZE 16
#endif /* _WINE_WINHTTP_PRIVATE_H_ */
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=124931
Your paranoid android.
=== debian11 (build log) ===
Use of uninitialized value $Flaky in addition (+) at /home/testbot/lib/WineTestBot/LogUtils.pm line 720, <$LogFile> line 24697. Use of uninitialized value $Flaky in addition (+) at /home/testbot/lib/WineTestBot/LogUtils.pm line 720, <$LogFile> line 24697. Use of uninitialized value $Flaky in addition (+) at /home/testbot/lib/WineTestBot/LogUtils.pm line 720, <$LogFile> line 24697.
v4: - Fix Win8 test failures.
This merge request was approved by Hans Leidekker.