in Release/src/http/client/http_client_winhttp.cpp [791:959]
unsigned long open()
{
if (m_opened)
{
return 0;
}
pplx::extensibility::scoped_critical_section_t l(m_client_lock);
if (m_opened)
{
return 0;
}
// This object have lifetime greater than proxy_name and proxy_bypass
// which may point to its elements.
ie_proxy_config proxyIE;
DWORD access_type;
LPCTSTR proxy_name = WINHTTP_NO_PROXY_NAME;
LPCTSTR proxy_bypass = WINHTTP_NO_PROXY_BYPASS;
m_proxy_auto_config = false;
utility::string_t proxy_str;
http::uri uri;
const auto& config = client_config();
const auto& proxy = config.proxy();
if (proxy.is_default())
{
access_type = WinHttpDefaultProxyConstant();
}
else if (proxy.is_disabled())
{
access_type = WINHTTP_ACCESS_TYPE_NO_PROXY;
}
else if (proxy.is_auto_discovery())
{
access_type = WinHttpDefaultProxyConstant();
if (access_type != WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY)
{
// Windows 8 or earlier, do proxy autodetection ourselves
m_proxy_auto_config = true;
proxy_info proxyDefault;
if (!WinHttpGetDefaultProxyConfiguration(&proxyDefault) ||
proxyDefault.dwAccessType == WINHTTP_ACCESS_TYPE_NO_PROXY)
{
// ... then try to fall back on the default WinINET proxy, as
// recommended for the desktop applications (if we're not
// running under a user account, the function below will just
// fail, so there is no real need to check for this explicitly)
if (WinHttpGetIEProxyConfigForCurrentUser(&proxyIE))
{
if (proxyIE.fAutoDetect)
{
m_proxy_auto_config = true;
}
else if (proxyIE.lpszAutoConfigUrl)
{
m_proxy_auto_config = true;
m_proxy_auto_config_url = proxyIE.lpszAutoConfigUrl;
}
else if (proxyIE.lpszProxy)
{
access_type = WINHTTP_ACCESS_TYPE_NAMED_PROXY;
proxy_name = proxyIE.lpszProxy;
if (proxyIE.lpszProxyBypass)
{
proxy_bypass = proxyIE.lpszProxyBypass;
}
}
}
}
}
}
else
{
_ASSERTE(config.proxy().is_specified());
access_type = WINHTTP_ACCESS_TYPE_NAMED_PROXY;
// WinHttpOpen cannot handle trailing slash in the name, so here is some string gymnastics to keep
// WinHttpOpen happy proxy_str is intentionally declared at the function level to avoid pointing to the
// string in the destructed object
uri = config.proxy().address();
if (uri.is_port_default())
{
proxy_name = uri.host().c_str();
}
else
{
proxy_str = uri.host();
if (uri.port() > 0)
{
proxy_str.push_back(_XPLATSTR(':'));
proxy_str.append(::utility::conversions::details::to_string_t(uri.port()));
}
proxy_name = proxy_str.c_str();
}
}
// Open session.
m_hSession = WinHttpOpen(NULL, access_type, proxy_name, proxy_bypass, WINHTTP_FLAG_ASYNC);
if (!m_hSession)
{
return GetLastError();
}
{
// Set timeouts.
const int milliseconds =
(std::max)(static_cast<int>(config.timeout<std::chrono::milliseconds>().count()), 1);
if (!WinHttpSetTimeouts(m_hSession, milliseconds, milliseconds, milliseconds, milliseconds))
{
return GetLastError();
}
}
if (config.guarantee_order())
{
// Set max connection to use per server to 1.
DWORD maxConnections = 1;
if (!WinHttpSetOption(
m_hSession, WINHTTP_OPTION_MAX_CONNS_PER_SERVER, &maxConnections, sizeof(maxConnections)))
{
return GetLastError();
}
}
{
// Enable TLS 1.1 and 1.2
#if (_WIN32_WINNT >= _WIN32_WINNT_VISTA) || defined(CPPREST_FORCE_HTTP_CLIENT_WINHTTPPAL)
DWORD secure_protocols(WINHTTP_FLAG_SECURE_PROTOCOL_SSL3 | WINHTTP_FLAG_SECURE_PROTOCOL_TLS1 |
WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_1 | WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2);
if (!WinHttpSetOption(
m_hSession, WINHTTP_OPTION_SECURE_PROTOCOLS, &secure_protocols, sizeof(secure_protocols)))
{
return GetLastError();
}
#endif
}
config._invoke_nativesessionhandle_options(m_hSession);
// Register asynchronous callback.
if (WINHTTP_INVALID_STATUS_CALLBACK ==
WinHttpSetStatusCallback(m_hSession,
&winhttp_client::completion_callback,
WINHTTP_CALLBACK_FLAG_ALL_COMPLETIONS | WINHTTP_CALLBACK_FLAG_HANDLES |
WINHTTP_CALLBACK_FLAG_SECURE_FAILURE | WINHTTP_CALLBACK_FLAG_SEND_REQUEST |
WINHTTP_CALLBACK_STATUS_REDIRECT,
0))
{
return GetLastError();
}
// Open connection.
unsigned int port = m_uri.is_port_default()
? (m_secure ? INTERNET_DEFAULT_HTTPS_PORT : INTERNET_DEFAULT_HTTP_PORT)
: m_uri.port();
m_hConnection = WinHttpConnect(m_hSession, m_uri.host().c_str(), (INTERNET_PORT)port, 0);
if (m_hConnection == nullptr)
{
return GetLastError();
}
m_opened = true;
return S_OK;
}