Module: wine Branch: master Commit: 7d8730f8c5d36dbe450ba415d1d3a0ba119289e8 URL: http://source.winehq.org/git/wine.git/?a=commit;h=7d8730f8c5d36dbe450ba415d1...
Author: Hans Leidekker hans@codeweavers.com Date: Fri Nov 25 14:55:13 2011 +0100
winhttp: Resolve the server name only on the first request.
---
dlls/winhttp/request.c | 63 +++++++++++++++++++++++-------------- dlls/winhttp/session.c | 6 ++-- dlls/winhttp/tests/notification.c | 59 ++++++++++++++++++++++++++++++++++ dlls/winhttp/winhttp_private.h | 1 + 4 files changed, 102 insertions(+), 27 deletions(-)
diff --git a/dlls/winhttp/request.c b/dlls/winhttp/request.c index a56572d..f610dde 100644 --- a/dlls/winhttp/request.c +++ b/dlls/winhttp/request.c @@ -909,53 +909,68 @@ static BOOL secure_proxy_connect( request_t *request ) #define INET6_ADDRSTRLEN 46 #endif
+static WCHAR *addr_to_str( const struct sockaddr *addr ) +{ + char buf[INET6_ADDRSTRLEN]; + const void *src; + + switch (addr->sa_family) + { + case AF_INET: + src = &((struct sockaddr_in *)addr)->sin_addr; + break; + case AF_INET6: + src = &((struct sockaddr_in6 *)addr)->sin6_addr; + break; + default: + WARN("unsupported address family %d\n", addr->sa_family); + return NULL; + } + if (!inet_ntop( addr->sa_family, src, buf, sizeof(buf) )) return NULL; + return strdupAW( buf ); +} + static BOOL open_connection( request_t *request ) { connect_t *connect; - const void *addr; - char address[INET6_ADDRSTRLEN]; - WCHAR *addressW; + WCHAR *addressW = NULL; INTERNET_PORT port; socklen_t slen; + struct sockaddr *saddr; + DWORD len;
if (netconn_connected( &request->netconn )) return TRUE;
connect = request->connect; port = connect->serverport ? connect->serverport : (request->hdr.flags & WINHTTP_FLAG_SECURE ? 443 : 80); + saddr = (struct sockaddr *)&connect->sockaddr; + slen = sizeof(struct sockaddr);
- send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_RESOLVING_NAME, connect->servername, strlenW(connect->servername) + 1 ); - - slen = sizeof(connect->sockaddr); - if (!netconn_resolve( connect->servername, port, (struct sockaddr *)&connect->sockaddr, &slen, request->resolve_timeout )) return FALSE; - switch (connect->sockaddr.ss_family) + if (!connect->resolved) { - case AF_INET: - addr = &((struct sockaddr_in *)&connect->sockaddr)->sin_addr; - break; - case AF_INET6: - addr = &((struct sockaddr_in6 *)&connect->sockaddr)->sin6_addr; - break; - default: - WARN("unsupported address family %d\n", connect->sockaddr.ss_family); - return FALSE; - } - inet_ntop( connect->sockaddr.ss_family, addr, address, sizeof(address) ); - addressW = strdupAW( address ); + len = strlenW( connect->servername ) + 1; + send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_RESOLVING_NAME, connect->servername, len );
- send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_NAME_RESOLVED, addressW, strlenW(addressW) + 1 ); + if (!netconn_resolve( connect->servername, port, saddr, &slen, request->resolve_timeout )) return FALSE; + connect->resolved = TRUE;
- TRACE("connecting to %s:%u\n", address, port); + if (!(addressW = addr_to_str( saddr ))) return FALSE; + len = strlenW( addressW ) + 1; + send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_NAME_RESOLVED, addressW, len ); + } + if (!addressW && !(addressW = addr_to_str( saddr ))) return FALSE; + TRACE("connecting to %s:%u\n", debugstr_w(addressW), port);
send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER, addressW, 0 );
- if (!netconn_create( &request->netconn, connect->sockaddr.ss_family, SOCK_STREAM, 0 )) + if (!netconn_create( &request->netconn, saddr->sa_family, SOCK_STREAM, 0 )) { heap_free( addressW ); return FALSE; } netconn_set_timeout( &request->netconn, TRUE, request->send_timeout ); netconn_set_timeout( &request->netconn, FALSE, request->recv_timeout ); - if (!netconn_connect( &request->netconn, (struct sockaddr *)&connect->sockaddr, slen, request->connect_timeout )) + if (!netconn_connect( &request->netconn, saddr, slen, request->connect_timeout )) { netconn_close( &request->netconn ); heap_free( addressW ); diff --git a/dlls/winhttp/session.c b/dlls/winhttp/session.c index 110de80..0f9e782 100644 --- a/dlls/winhttp/session.c +++ b/dlls/winhttp/session.c @@ -423,7 +423,7 @@ BOOL set_server_for_hostname( connect_t *connect, LPCWSTR server, INTERNET_PORT session->proxy_server, colon - session->proxy_server - 1 )) { heap_free( connect->servername ); - connect->sockaddr.ss_family = 0xffff; + connect->resolved = FALSE; if (!(connect->servername = heap_alloc( (colon - session->proxy_server + 1) * sizeof(WCHAR) ))) { @@ -445,7 +445,7 @@ BOOL set_server_for_hostname( connect_t *connect, LPCWSTR server, INTERNET_PORT session->proxy_server )) { heap_free( connect->servername ); - connect->sockaddr.ss_family = 0xffff; + connect->resolved = FALSE; if (!(connect->servername = strdupW( session->proxy_server ))) { ret = FALSE; @@ -458,7 +458,7 @@ BOOL set_server_for_hostname( connect_t *connect, LPCWSTR server, INTERNET_PORT else if (server) { heap_free( connect->servername ); - connect->sockaddr.ss_family = 0xffff; + connect->resolved = FALSE; if (!(connect->servername = strdupW( server ))) { ret = FALSE; diff --git a/dlls/winhttp/tests/notification.c b/dlls/winhttp/tests/notification.c index 7ceede7..84a3569 100644 --- a/dlls/winhttp/tests/notification.c +++ b/dlls/winhttp/tests/notification.c @@ -135,6 +135,16 @@ static const struct notification cache_test[] = { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION, 0, 1 }, { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED, 0, 1 }, { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING, 0, 1 }, + { winhttp_open_request, WINHTTP_CALLBACK_STATUS_HANDLE_CREATED, 0 }, + { winhttp_send_request, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER, 0 }, + { winhttp_send_request, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER, 0 }, + { winhttp_send_request, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST, 0 }, + { winhttp_send_request, WINHTTP_CALLBACK_STATUS_REQUEST_SENT, 0 }, + { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE, 0 }, + { winhttp_receive_response, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED, 0 }, + { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION, 0, 1 }, + { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED, 0, 1 }, + { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING, 0, 1 }, { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING, 1, 1 }, { winhttp_close_handle, WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING, 1, 1 } }; @@ -190,6 +200,32 @@ static void test_connection_cache( void )
setup_test( &info, winhttp_close_handle, __LINE__ ); WinHttpCloseHandle( req ); + + setup_test( &info, winhttp_open_request, __LINE__ ); + req = WinHttpOpenRequest( con, NULL, NULL, NULL, NULL, NULL, 0 ); + ok(req != NULL, "failed to open a request %u\n", GetLastError()); + + ret = WinHttpSetOption( req, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(struct info *) ); + ok(ret, "failed to set context value %u\n", GetLastError()); + + setup_test( &info, winhttp_send_request, __LINE__ ); + ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 ); + ok(ret, "failed to send request %u\n", GetLastError()); + + setup_test( &info, winhttp_receive_response, __LINE__ ); + ret = WinHttpReceiveResponse( req, NULL ); + ok(ret, "failed to receive response %u\n", GetLastError()); + + size = sizeof(status); + ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL ); + ok(ret, "failed unexpectedly %u\n", GetLastError()); + ok(status == 200, "request failed unexpectedly %u\n", status); + + setup_test( &info, winhttp_close_handle, __LINE__ ); + WinHttpCloseHandle( req ); + + setup_test( &info, winhttp_close_handle, __LINE__ ); + WinHttpCloseHandle( req ); WinHttpCloseHandle( con ); WinHttpCloseHandle( ses );
@@ -231,6 +267,29 @@ static void test_connection_cache( void )
setup_test( &info, winhttp_close_handle, __LINE__ ); WinHttpCloseHandle( req ); + + setup_test( &info, winhttp_open_request, __LINE__ ); + req = WinHttpOpenRequest( con, NULL, NULL, NULL, NULL, NULL, 0 ); + ok(req != NULL, "failed to open a request %u\n", GetLastError()); + + ret = WinHttpSetOption( req, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(struct info *) ); + ok(ret, "failed to set context value %u\n", GetLastError()); + + setup_test( &info, winhttp_send_request, __LINE__ ); + ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 ); + ok(ret, "failed to send request %u\n", GetLastError()); + + setup_test( &info, winhttp_receive_response, __LINE__ ); + ret = WinHttpReceiveResponse( req, NULL ); + ok(ret, "failed to receive response %u\n", GetLastError()); + + size = sizeof(status); + ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL ); + ok(ret, "failed unexpectedly %u\n", GetLastError()); + ok(status == 200, "request failed unexpectedly %u\n", status); + + setup_test( &info, winhttp_close_handle, __LINE__ ); + WinHttpCloseHandle( req ); WinHttpCloseHandle( con ); WinHttpCloseHandle( ses ); } diff --git a/dlls/winhttp/winhttp_private.h b/dlls/winhttp/winhttp_private.h index fbd5032..7105553 100644 --- a/dlls/winhttp/winhttp_private.h +++ b/dlls/winhttp/winhttp_private.h @@ -119,6 +119,7 @@ typedef struct INTERNET_PORT hostport; INTERNET_PORT serverport; struct sockaddr_storage sockaddr; + BOOL resolved; } connect_t;
typedef struct