[PATCH v2 0/2] MR1528: winhttp: Improve WinHttpGetProxyForUrl() execution time when wpad is not available
Fixes Marvel Snap being unable to connect to servers (part of it, another part is wmic patches), and maybe improves wait times in many other apps. Typically "http://wpad/..." (which is commonly requested as lpszAutoConfigUrl for WinHttpGetProxyForUrl) is not available and WinHttpGetProxyForUrl() is hanging for a really long time resolving this name in download_script(). On Windows 10 here the name resolution timeout is about 9sec (and I could not find a way to configure it for a longer timeout). On Linux default DNS timeouts are typically longer. Yet, while WinHttpGetProxyForUrl() execution time is not consistent here, when I run it right after reboot or after network interface reconnection it typically takes ~4-7 seconds to complete on the first run. Then, testing it again shortly after yields no noticeable timeout. I suppose Windows caches and manages that globally in some service, so maximum possible 9 seconds name resolution timeout is rarely hit. Since proxy config URL, if available, is supposed to be in the local network, having the timeout of 5 seconds for name resolution looks more than enough to me. -- v2: winhttp: Cache script in download_script(). winhttp: Set name resolution timeout in download_script(). https://gitlab.winehq.org/wine/wine/-/merge_requests/1528
From: Paul Gofman <pgofman(a)codeweavers.com> --- dlls/winhttp/session.c | 1 + 1 file changed, 1 insertion(+) diff --git a/dlls/winhttp/session.c b/dlls/winhttp/session.c index fa8ccd7a9de..3d99e9b0ac6 100644 --- a/dlls/winhttp/session.c +++ b/dlls/winhttp/session.c @@ -1922,6 +1922,7 @@ static char *download_script( const WCHAR *url, DWORD *out_size ) hostname[uc.dwHostNameLength] = 0; if (!(ses = WinHttpOpen( NULL, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0 ))) goto done; + WinHttpSetTimeouts( ses, 5000, 60000, 30000, 30000 ); if (!(con = WinHttpConnect( ses, hostname, uc.nPort, 0 ))) goto done; if (uc.nScheme == INTERNET_SCHEME_HTTPS) flags |= WINHTTP_FLAG_SECURE; if (!(req = WinHttpOpenRequest( con, NULL, uc.lpszUrlPath, NULL, NULL, acceptW, flags ))) goto done; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/1528
From: Paul Gofman <pgofman(a)codeweavers.com> --- dlls/winhttp/session.c | 54 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/dlls/winhttp/session.c b/dlls/winhttp/session.c index 3d99e9b0ac6..8aa99f0ece7 100644 --- a/dlls/winhttp/session.c +++ b/dlls/winhttp/session.c @@ -1901,6 +1901,50 @@ static BOOL parse_script_result( const char *result, WINHTTP_PROXY_INFO *info ) return TRUE; } +static SRWLOCK cache_lock = SRWLOCK_INIT; +static DWORD cached_script_size; +static ULONGLONG cache_update_time; +static char *cached_script; +static WCHAR *cached_url; + +static BOOL get_cached_script( const WCHAR *url, char **buffer, DWORD *out_size ) +{ + BOOL ret = FALSE; + + *buffer = NULL; + *out_size = 0; + + AcquireSRWLockExclusive( &cache_lock ); + if (cached_url && !wcscmp( cached_url, url ) && GetTickCount64() - cache_update_time < 60000) + { + ret = TRUE; + if (cached_script && (*buffer = malloc( cached_script_size ))) + { + memcpy( *buffer, cached_script, cached_script_size ); + *out_size = cached_script_size; + } + } + ReleaseSRWLockExclusive( &cache_lock ); + return ret; +} + +static void cache_script( const WCHAR *url, char *buffer, DWORD size ) +{ + AcquireSRWLockExclusive( &cache_lock ); + free( cached_url ); + free( cached_script ); + cached_script_size = 0; + cached_script = NULL; + + if ((cached_url = wcsdup( url )) && buffer && (cached_script = malloc( size ))) + { + memcpy( cached_script, buffer, size ); + cached_script_size = size; + } + cache_update_time = GetTickCount64(); + ReleaseSRWLockExclusive( &cache_lock ); +} + static char *download_script( const WCHAR *url, DWORD *out_size ) { static const WCHAR *acceptW[] = {L"*/*", NULL}; @@ -1908,9 +1952,14 @@ static char *download_script( const WCHAR *url, DWORD *out_size ) WCHAR *hostname; URL_COMPONENTSW uc; DWORD status, size = sizeof(status), offset, to_read, bytes_read, flags = 0; - char *tmp, *buffer = NULL; + char *tmp, *buffer; - *out_size = 0; + if (get_cached_script( url, &buffer, out_size )) + { + TRACE( "Returning cached result.\n" ); + if (!buffer) SetLastError( ERROR_WINHTTP_UNABLE_TO_DOWNLOAD_SCRIPT ); + return buffer; + } memset( &uc, 0, sizeof(uc) ); uc.dwStructSize = sizeof(uc); @@ -1957,6 +2006,7 @@ done: WinHttpCloseHandle( con ); WinHttpCloseHandle( ses ); free( hostname ); + cache_script( url, buffer, *out_size ); if (!buffer) SetLastError( ERROR_WINHTTP_UNABLE_TO_DOWNLOAD_SCRIPT ); return buffer; } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/1528
v2: - Use helper functions for cache access; - Use GetTickCount64() instead of GetTickCount(); - Check for wcsdup() failure. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/1528#note_17351
This merge request was approved by Hans Leidekker. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/1528
participants (3)
-
Hans Leidekker (@hans) -
Paul Gofman -
Paul Gofman (@gofman)