diff --git a/src/aws-cpp-sdk-core/CMakeLists.txt b/src/aws-cpp-sdk-core/CMakeLists.txt index 924e4f2d0a9..6a6ee834027 100644 --- a/src/aws-cpp-sdk-core/CMakeLists.txt +++ b/src/aws-cpp-sdk-core/CMakeLists.txt @@ -189,69 +189,6 @@ elseif(ENABLE_WINDOWS_CLIENT) else() file(GLOB HTTP_WINDOWS_CLIENT_HEADERS "include/aws/core/http/windows/Win*.h") file(GLOB HTTP_WINDOWS_CLIENT_SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/source/http/windows/Win*.cpp") - - # Starting with Windows 10, version 1507, WinINet supports HTTP2. - # https://docs.microsoft.com/en-us/windows/desktop/WinInet/option-flags#INTERNET_OPTION_ENABLE_HTTP_PROTOCOL - # Starting with Windows 10, version 1607, WinHttp supports HTTP2. - # https://docs.microsoft.com/en-us/windows/desktop/WinHttp/option-flags#WINHTTP_OPTION_ENABLE_HTTP_PROTOCOL - set(CMAKE_REQUIRED_LIBRARIES "WinHttp.lib") - check_cxx_source_runs(" - #include - #include - int main() { - - auto handle = WinHttpOpen(L\"aws-cpp-sdk\"/*user-agent*/, - WINHTTP_ACCESS_TYPE_NO_PROXY, - nullptr/*pszProxyW*/, - nullptr/*pszProxyBypassW*/, - 0/*dwFlags*/); - - DWORD http2 = WINHTTP_PROTOCOL_FLAG_HTTP2; - if (WinHttpSetOption(handle, WINHTTP_OPTION_ENABLE_HTTP_PROTOCOL, &http2, sizeof(http2))) - { - return 0; - } - return 1; - }" WINHTTP_HAS_H2) - - check_cxx_source_runs(" - #include - #include - int main() { - - auto handle = WinHttpOpen(L\"aws-cpp-sdk\"/*user-agent*/, - WINHTTP_ACCESS_TYPE_NO_PROXY, - nullptr/*pszProxyW*/, - nullptr/*pszProxyBypassW*/, - 0/*dwFlags*/); - - DWORD http3 = WINHTTP_PROTOCOL_FLAG_HTTP3; - if (WinHttpSetOption(handle, WINHTTP_OPTION_ENABLE_HTTP_PROTOCOL, &http3, sizeof(http3))) - { - return 0; - } - return 1; - }" WINHTTP_HAS_H3) - - set(CMAKE_REQUIRED_LIBRARIES "Wininet.lib") - check_cxx_source_runs(" - #include - #include - int main() { - auto handle = InternetOpenA(\"aws-cpp-sdk\"/*lpszAgent*/, - INTERNET_OPEN_TYPE_DIRECT /*dwAccessType*/, - nullptr /*lpszProxy*/, - nullptr /*lpszProxyBypass*/, - 0 /*dwFlags*/); - DWORD http2 = HTTP_PROTOCOL_FLAG_HTTP2; - if (InternetSetOptionA(handle, INTERNET_OPTION_ENABLE_HTTP_PROTOCOL, &http2, sizeof(http2))) - { - return 0; - } - return 1; - }" WININET_HAS_H2) - unset(CMAKE_REQUIRED_LIBRARIES) - endif() elseif(USE_CRT_HTTP_CLIENT) file(GLOB CRT_HTTP_HEADERS "include/aws/core/http/crt/*.h") diff --git a/src/aws-cpp-sdk-core/source/http/windows/WinHttpSyncHttpClient.cpp b/src/aws-cpp-sdk-core/source/http/windows/WinHttpSyncHttpClient.cpp index b8ab51959b4..9c82caa6811 100644 --- a/src/aws-cpp-sdk-core/source/http/windows/WinHttpSyncHttpClient.cpp +++ b/src/aws-cpp-sdk-core/source/http/windows/WinHttpSyncHttpClient.cpp @@ -40,61 +40,55 @@ using namespace Aws::Utils::Logging; #ifndef WINHTTP_OPTION_HTTP_PROTOCOL_USED static const DWORD WINHTTP_OPTION_HTTP_PROTOCOL_USED = 134; #endif +#ifndef WINHTTP_PROTOCOL_FLAG_HTTP2 + static const DWORD WINHTTP_PROTOCOL_FLAG_HTTP2 = 0x1; +#endif +#ifndef WINHTTP_PROTOCOL_FLAG_HTTP3 + static const DWORD WINHTTP_PROTOCOL_FLAG_HTTP3 = 0x2; +#endif -DWORD ConvertHttpVersionToWinHttpVersion(const Aws::Http::Version version) +const std::initializer_list& GetWinHttpVersionsToTry(const Aws::Http::Version version) { + // Using statically declared initializer_lists because we cannot return them by value. + // All options include HTTP 1.1, which is always enabled in WinHTTP. + static std::initializer_list noPreference = {}; + static std::initializer_list http2 = { WINHTTP_PROTOCOL_FLAG_HTTP2 }; + static std::initializer_list http3 = { WINHTTP_PROTOCOL_FLAG_HTTP3 }; + static std::initializer_list http2Or3 = { WINHTTP_PROTOCOL_FLAG_HTTP3 | WINHTTP_PROTOCOL_FLAG_HTTP2, WINHTTP_PROTOCOL_FLAG_HTTP2 }; if (version == Version::HTTP_VERSION_NONE) { /* WinHTTP http version None maps to HTTP1.1, however, libCurl None maps to "let http client decide", sticking to libCurl behavior here (use highest) */ -#if defined(WINHTTP_HAS_H3) - return WINHTTP_PROTOCOL_FLAG_HTTP3; -#elif defined(WINHTTP_HAS_H2) - return WINHTTP_PROTOCOL_FLAG_HTTP2; -#else - return 0x0; -#endif + return http2Or3; } else if (version == Version::HTTP_VERSION_1_0) { - return 0x0; // HTTP 1.1 can be still used, WinHTTP does not allow disabling 1,1 + return noPreference; // HTTP 1.1 can be still used, WinHTTP does not allow disabling 1,1 } else if (version == Version::HTTP_VERSION_1_1) { - return 0x0; + return noPreference; } -#ifdef WINHTTP_HAS_H2 - else if (version == Version::HTTP_VERSION_2_0 || - version == Version::HTTP_VERSION_2TLS) + else if (version == Version::HTTP_VERSION_2_0 || version == Version::HTTP_VERSION_2TLS) { - return WINHTTP_PROTOCOL_FLAG_HTTP2; + return http2; } else if (version == Version::HTTP_VERSION_2_PRIOR_KNOWLEDGE) { AWS_LOGSTREAM_WARN("WinHttpHttp2", "Unable to set HTTP/2 with Prior Knowledge on WinHTTP, enabling regular HTTP2"); - return WINHTTP_PROTOCOL_FLAG_HTTP2; + return http2; } -#endif -#ifdef WINHTTP_HAS_H3 - else if (version == Version::HTTP_VERSION_3) + else if (version == Version::HTTP_VERSION_3) { - return WINHTTP_PROTOCOL_FLAG_HTTP3; + return http2Or3; } else if (version == Version::HTTP_VERSION_3ONLY) { - AWS_LOGSTREAM_WARN("WinHttpHttp2", "Unable to set HTTP3 only on WinHTTP"); - return WINHTTP_PROTOCOL_FLAG_HTTP3; + AWS_LOGSTREAM_WARN("WinHttpHttp2", "Unable to set HTTP3 only on WinHTTP"); + return http3; } -#endif - -#ifdef WINHTTP_HAS_H2 - AWS_LOGSTREAM_WARN("WinHttpHttp2", "Unable to map requested HTTP Version: (raw enum value) " - << static_cast::type>(version) << " defaulting to WINHTTP_PROTOCOL_FLAG_HTTP2"); - return WINHTTP_PROTOCOL_FLAG_HTTP2; -#else AWS_LOGSTREAM_WARN("WinHttpHttp2", "Unable to map requested HTTP Version: (raw enum value) " - << static_cast::type>(version) << " defaulting to None (aka 1.1 and below)"); - return 0x0; -#endif + << static_cast::type>(version) << " defaulting to WINHTTP_PROTOCOL_FLAG_HTTP2"); + return http2; } void AzWinHttpLogLastError(const char* FuncName) @@ -197,14 +191,15 @@ bool AzCallWinHttp(const char* FuncName, WinHttpFunc func, Args &&... args) static void WinHttpSetHttpVersion(void* handle, const Aws::Http::Version version) { - DWORD winHttpVersion = ConvertHttpVersionToWinHttpVersion(version); - if (winHttpVersion == 0x0) + for (DWORD winHttpVersion : GetWinHttpVersionsToTry(version)) { - return; - } - if (!AzCallWinHttp("WinHttpSetOption", WinHttpSetOption, handle, WINHTTP_OPTION_ENABLE_HTTP_PROTOCOL, &winHttpVersion, (DWORD) sizeof(winHttpVersion))) - { - AWS_LOGSTREAM_ERROR("WinHttpHttp2", "Failed to set WINHTTP_OPTION_ENABLE_HTTP_PROTOCOL to " << winHttpVersion << " on WinHttp handle: " << handle); + if (AzCallWinHttp("WinHttpSetOption", WinHttpSetOption, handle, WINHTTP_OPTION_ENABLE_HTTP_PROTOCOL, &winHttpVersion, (DWORD)sizeof(winHttpVersion))) + { + break; + } + { + AWS_LOGSTREAM_ERROR("WinHttpHttp2", "Failed to set WINHTTP_OPTION_ENABLE_HTTP_PROTOCOL to " << winHttpVersion << " on WinHttp handle: " << handle); + } } } diff --git a/src/aws-cpp-sdk-core/source/http/windows/WinINetSyncHttpClient.cpp b/src/aws-cpp-sdk-core/source/http/windows/WinINetSyncHttpClient.cpp index cb89d45f61f..b79caf4440d 100644 --- a/src/aws-cpp-sdk-core/source/http/windows/WinINetSyncHttpClient.cpp +++ b/src/aws-cpp-sdk-core/source/http/windows/WinINetSyncHttpClient.cpp @@ -27,9 +27,12 @@ using namespace Aws::Http::Standard; using namespace Aws::Utils; using namespace Aws::Utils::Logging; +#ifndef HTTP_PROTOCOL_FLAG_HTTP2 +static const DWORD HTTP_PROTOCOL_FLAG_HTTP2 = 0x2; +#endif + static void WinINetEnableHttp2(void* handle) { -#ifdef WININET_HAS_H2 DWORD http2 = HTTP_PROTOCOL_FLAG_HTTP2; if (!InternetSetOptionA(handle, INTERNET_OPTION_ENABLE_HTTP_PROTOCOL, &http2, sizeof(http2))) { @@ -39,9 +42,6 @@ static void WinINetEnableHttp2(void* handle) { AWS_LOGSTREAM_DEBUG("WinINetHttp2", "HTTP/2 enabled on WinInet handle: " << handle << "."); } -#else - AWS_UNREFERENCED_PARAM(handle); -#endif } WinINetSyncHttpClient::WinINetSyncHttpClient(const ClientConfiguration& config) :