mirror of
https://github.com/microsoft/WSL.git
synced 2026-02-04 02:06:49 -06:00
* link: Collect WSL logs (recommended method) Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * link: Advanced Authoring Tests in C++ Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * link: CMake Documentation and Community Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * link: Collect WSL logs for networking issues Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * link: Collect WSL logs (recommended method) Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: ; otherwise, Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: a Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: access Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: accessible Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: across Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: actively Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: adapters Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: address Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: addresses Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: and Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: appropriate Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: argument Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: associated Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: attach Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: available Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: beginning Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: between Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: binaries Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: bound Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: buffer Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: buffers Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: cannot Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: canonical Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: capabilities Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: case-insensitive Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: case-sensitive Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: certified Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: command Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: committer Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: communication Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: complains Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: configuration Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: consumed Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: continue Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: converted Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: currently Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: customers Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: daemon Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: deferred Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: definitions Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: delimiter Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: delivered Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: dellink Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: derived Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: descriptor Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: destined Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: destruct Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: destructible Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: destructor Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: detach Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: differentiate Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: directories Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: disassociate Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: disposition Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: distribution Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: distro Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: duping Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: emitted Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: empty Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: environment Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: every time Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: exclusive Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: expected Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: expire Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: explicitly Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: fall back Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: false Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: fastfail Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: filesystem Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: first Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: followed Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: for Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: functionality Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: functionally Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: github Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: greater Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: guarantee Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: guaranteed Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: handles Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: hangup Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: hierarchy Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: hogwarts Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: hydrated Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: icrnl Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: implementation Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: implementing Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: initialize Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: instance Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: instantiate Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: instantiations Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: intentionally Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: interpret Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: interpreter Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: irreversibly Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: iteration Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: iterator Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: its Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: kernel Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: kmsg Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: knowledge Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: maximum Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: mirrored Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: msftconnecttest Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: multi Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: multiple Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: mutable Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: namespace Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: nonexistent Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: notifications Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: occurred Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: occurring Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: otherwise, Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: outstanding Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: overridden Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: partition Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: pass through Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: passthrough Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: performs Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: periodically Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: positional Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: precedence Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: preexisting Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: preferring Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: prepopulate Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: previous Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: privileges Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: process Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: processes Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: programmatically Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: protection Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: provided Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: reasonable Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: receive Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: received Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: red hat Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: reentrant Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: registered Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: regularly Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: relay Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: release Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: representing Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: requests Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: response Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: resurrect Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: retention Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: returned Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: security Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: semaphore Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: separate Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: separator Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: service Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: set up Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: setup Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: severely Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: should Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: signal Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: similarly Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: simple Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: simplified Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: single Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: specified Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: splitting Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: standard Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: stress Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: succeed Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: success Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: successfully Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: supplementary Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: synced Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: system Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: take Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: than Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: that opening Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: the Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: threadpool Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: to Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: true Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: truncate Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: tunneling Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: unexpected Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: uninitialize Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: unique Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: unprivileged Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: unregistered Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: untrusted Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: upgrade Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: utility Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: validating Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: variant Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: variation Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: variations Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: verify Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: visible Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: whether Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: winget Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: worker Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: written Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * spelling: wslservice Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> * format source --------- Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com> Co-authored-by: Ben Hillis <benhillis@gmail.com> Co-authored-by: Ben Hillis <benhill@ntdev.microsoft.com>
562 lines
22 KiB
C++
562 lines
22 KiB
C++
/*++
|
|
|
|
Copyright (c) Microsoft. All rights reserved.
|
|
|
|
Module Name:
|
|
|
|
LxssHttpProxy.cpp
|
|
|
|
Abstract:
|
|
|
|
This file contains HTTP proxy related classes and helper functions for proxy queries.
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#include "LxssHttpProxy.h"
|
|
|
|
#include <winhttp.h>
|
|
#include <notifications.h>
|
|
|
|
#include "WslCoreNetworkingSupport.h"
|
|
|
|
using namespace wsl::windows::common;
|
|
|
|
std::optional<LxssDynamicFunction<decltype(RegisterProxyChangeNotification)>> HttpProxyStateTracker::s_WinHttpRegisterProxyChangeNotification;
|
|
std::optional<LxssDynamicFunction<decltype(UnregisterProxyChangeNotification)>> HttpProxyStateTracker::s_WinHttpUnregisterProxyChangeNotification;
|
|
std::optional<LxssDynamicFunction<decltype(GetProxySettingsEx)>> HttpProxyStateTracker::s_WinHttpGetProxySettingsEx;
|
|
std::optional<LxssDynamicFunction<decltype(GetProxySettingsResultEx)>> HttpProxyStateTracker::s_WinHttpGetProxySettingsResultEx;
|
|
std::optional<LxssDynamicFunction<decltype(FreeProxySettingsEx)>> HttpProxyStateTracker::s_WinHttpFreeProxySettingsEx;
|
|
|
|
// Helpers for using Winhttp's APIs
|
|
HRESULT HttpProxyStateTracker::s_LoadWinHttpProxyMethods() noexcept
|
|
try
|
|
{
|
|
static wil::shared_hmodule winHttpModule;
|
|
static std::once_flag winHttpLoadFlag;
|
|
|
|
// Load Winhttp dll only once
|
|
std::call_once(winHttpLoadFlag, [&]() {
|
|
winHttpModule.reset(LoadLibraryEx(c_winhttpModuleName, nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32));
|
|
THROW_LAST_ERROR_IF(!winHttpModule);
|
|
});
|
|
|
|
// Initialize dynamic functions for the WinHttp Proxy OS APIs
|
|
// Not using the throwing constructor
|
|
// as failures should not show up in the Error logs as they can falsely flag failure to start the container
|
|
LxssDynamicFunction<decltype(RegisterProxyChangeNotification)> local_WinHttpRegisterProxyChangeNotification{DynamicFunctionErrorLogs::None};
|
|
LxssDynamicFunction<decltype(UnregisterProxyChangeNotification)> local_WinHttpUnregisterProxyChangeNotification{DynamicFunctionErrorLogs::None};
|
|
LxssDynamicFunction<decltype(GetProxySettingsEx)> local_WinHttpGetProxySettingsEx{DynamicFunctionErrorLogs::None};
|
|
LxssDynamicFunction<decltype(GetProxySettingsResultEx)> local_WinHttpGetProxySettingsResultEx{DynamicFunctionErrorLogs::None};
|
|
LxssDynamicFunction<decltype(FreeProxySettingsEx)> local_WinHttpFreeProxySettingsEx{DynamicFunctionErrorLogs::None};
|
|
|
|
// try to load each function - only save if all succeed
|
|
RETURN_IF_FAILED_EXPECTED(
|
|
local_WinHttpRegisterProxyChangeNotification.load(winHttpModule, "WinHttpRegisterProxyChangeNotification"));
|
|
RETURN_IF_FAILED_EXPECTED(
|
|
local_WinHttpUnregisterProxyChangeNotification.load(winHttpModule, "WinHttpUnregisterProxyChangeNotification"));
|
|
RETURN_IF_FAILED_EXPECTED(local_WinHttpGetProxySettingsEx.load(winHttpModule, "WinHttpGetProxySettingsEx"));
|
|
RETURN_IF_FAILED_EXPECTED(local_WinHttpGetProxySettingsResultEx.load(winHttpModule, "WinHttpGetProxySettingsResultEx"));
|
|
RETURN_IF_FAILED_EXPECTED(local_WinHttpFreeProxySettingsEx.load(winHttpModule, "WinHttpFreeProxySettingsEx"));
|
|
|
|
s_WinHttpRegisterProxyChangeNotification.emplace(std::move(local_WinHttpRegisterProxyChangeNotification));
|
|
s_WinHttpUnregisterProxyChangeNotification.emplace(std::move(local_WinHttpUnregisterProxyChangeNotification));
|
|
s_WinHttpGetProxySettingsEx.emplace(std::move(local_WinHttpGetProxySettingsEx));
|
|
s_WinHttpGetProxySettingsResultEx.emplace(std::move(local_WinHttpGetProxySettingsResultEx));
|
|
s_WinHttpFreeProxySettingsEx.emplace(std::move(local_WinHttpFreeProxySettingsEx));
|
|
return S_OK;
|
|
}
|
|
CATCH_RETURN()
|
|
|
|
void FreeHttpProxySettings(WINHTTP_PROXY_SETTINGS_EX* proxySettings) noexcept
|
|
try
|
|
{
|
|
THROW_IF_WIN32_ERROR(HttpProxyStateTracker::s_WinHttpFreeProxySettingsEx.value()(WinHttpProxySettingsTypeWsl, proxySettings));
|
|
}
|
|
CATCH_LOG()
|
|
|
|
auto CallbackStatusToString(DWORD internetStatus) noexcept
|
|
{
|
|
switch (internetStatus)
|
|
{
|
|
case WINHTTP_CALLBACK_STATUS_GETPROXYSETTINGS_COMPLETE:
|
|
return "WINHTTP_CALLBACK_STATUS_GETPROXYSETTINGS_COMPLETE";
|
|
case WINHTTP_CALLBACK_STATUS_REQUEST_ERROR:
|
|
return "WINHTTP_CALLBACK_STATUS_REQUEST_ERROR";
|
|
case WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING:
|
|
return " WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING";
|
|
default:
|
|
return "Invalid status";
|
|
}
|
|
}
|
|
|
|
// struct to contain proxy specific settings
|
|
|
|
void LogHttpProxySettings(const HttpProxySettings& settings) noexcept
|
|
try
|
|
{
|
|
WSL_LOG("OnProxyRequestComplete", TraceLoggingValue(settings.ToString().c_str(), "newProxySettings"));
|
|
}
|
|
CATCH_LOG()
|
|
|
|
HttpProxySettings::HttpProxySettings(const WINHTTP_PROXY_SETTINGS_EX& proxySettings)
|
|
{
|
|
if (WI_IsFlagSet(proxySettings.ullFlags, WINHTTP_PROXY_TYPE_PROXY))
|
|
{
|
|
Proxy = wsl::shared::string::WideToMultiByte(proxySettings.pcwszProxy);
|
|
SecureProxy = wsl::shared::string::WideToMultiByte(proxySettings.pcwszSecureProxy);
|
|
|
|
const auto proxyBypasses = wil::make_range(proxySettings.rgpcwszProxyBypasses, proxySettings.cProxyBypasses);
|
|
std::transform(std::cbegin(proxyBypasses), std::cend(proxyBypasses), std::back_inserter(ProxyBypasses), [](const auto& proxyBypass) {
|
|
return wsl::shared::string::WideToMultiByte(proxyBypass);
|
|
});
|
|
|
|
if (!ProxyBypasses.empty())
|
|
{
|
|
ProxyBypassesComma = std::accumulate(
|
|
std::next(std::cbegin(ProxyBypasses)),
|
|
std::cend(ProxyBypasses),
|
|
ProxyBypasses.front(),
|
|
[](std::string previous, const std::string& proxyBypass) { return std::move(previous) + "," + proxyBypass; });
|
|
}
|
|
}
|
|
|
|
if (WI_IsFlagSet(proxySettings.ullFlags, WINHTTP_PROXY_TYPE_AUTO_PROXY_URL))
|
|
{
|
|
PacUrl = wsl::shared::string::WideToMultiByte(proxySettings.pcwszAutoconfigUrl);
|
|
}
|
|
}
|
|
|
|
std::string HttpProxySettings::ToString() const
|
|
{
|
|
std::ostringstream httpProxySettingsString{};
|
|
httpProxySettingsString << "Proxy: " << Proxy << ", SecureProxy: " << SecureProxy << ", PacUrl: " << PacUrl
|
|
<< ", ProxyBypasses: " << ProxyBypassesComma;
|
|
return httpProxySettingsString.str();
|
|
}
|
|
|
|
bool HttpProxySettings::HasSettingsConfigured() const
|
|
{
|
|
return !(Proxy.empty() && SecureProxy.empty() && PacUrl.empty());
|
|
}
|
|
|
|
void CALLBACK HttpProxyStateTracker::s_GetProxySettingsExCallback(
|
|
_In_ HINTERNET resolver, _In_ DWORD_PTR context, _In_ DWORD internetStatus, _In_ PVOID statusInformation, _In_ DWORD) noexcept
|
|
try
|
|
{
|
|
HttpProxyStateTracker* proxyTracker = reinterpret_cast<HttpProxyStateTracker*>(context);
|
|
const WINHTTP_ASYNC_RESULT* pAsyncResult = static_cast<WINHTTP_ASYNC_RESULT*>(statusInformation);
|
|
|
|
if (!proxyTracker)
|
|
{
|
|
return;
|
|
}
|
|
|
|
WSL_LOG(
|
|
"s_GetProxySettingsExCallback-CallbackInfo", TraceLoggingValue(CallbackStatusToString(internetStatus), "internetStatus"));
|
|
|
|
// This is the last WinHttp callback for this request, received after the request handles were closed.
|
|
if (internetStatus == WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING)
|
|
{
|
|
proxyTracker->m_callbackQueue.submit([proxyTracker] { proxyTracker->RequestClosed(); });
|
|
return;
|
|
}
|
|
|
|
DWORD error = ERROR_SUCCESS;
|
|
PCSTR executionStep = "";
|
|
unique_winhttp_proxy_settings proxySettings{};
|
|
switch (internetStatus)
|
|
{
|
|
case WINHTTP_CALLBACK_STATUS_GETPROXYSETTINGS_COMPLETE:
|
|
{
|
|
executionStep = "WinHttpGetProxySettingsResultEx";
|
|
error = s_WinHttpGetProxySettingsResultEx.value()(resolver, &proxySettings);
|
|
break;
|
|
}
|
|
case WINHTTP_CALLBACK_STATUS_REQUEST_ERROR:
|
|
{
|
|
executionStep = "CallbackError";
|
|
error = pAsyncResult->dwError;
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
error = ERROR_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (SUCCEEDED_WIN32(error))
|
|
{
|
|
WSL_LOG(
|
|
"s_GetProxySettingsExCallback-Results",
|
|
TraceLoggingValue(proxySettings.pcwszProxy, "pcwszProxy"),
|
|
TraceLoggingValue(proxySettings.pcwszSecureProxy, "pcwszSecureProxy"),
|
|
TraceLoggingValue(proxySettings.pcwszAutoconfigUrl, "pcwszAutoconfigUrl"),
|
|
TraceLoggingValue(proxySettings.cProxyBypasses, "cProxyBypasses"));
|
|
}
|
|
else
|
|
{
|
|
WSL_LOG(
|
|
"WinHttpGetProxySettingsExCallbackFailed",
|
|
TraceLoggingValue(error, "result"),
|
|
TraceLoggingValue(executionStep, "executionStep"));
|
|
}
|
|
LOG_IF_WIN32_ERROR(error);
|
|
|
|
HttpProxySettings newProxySettings{proxySettings};
|
|
proxyTracker->m_callbackQueue.submit([proxyTracker, error, movedProxySettings = std::move(newProxySettings)]() mutable {
|
|
proxyTracker->RequestCompleted(error, std::move(movedProxySettings));
|
|
});
|
|
}
|
|
CATCH_LOG()
|
|
|
|
void HttpProxyStateTracker::RequestClosed() noexcept
|
|
try
|
|
{
|
|
WI_ASSERT(m_callbackQueue.isRunningInQueue());
|
|
const auto requery = m_queryState == QueryState::PendingAndQueueAdditional;
|
|
m_queryState = QueryState::NoQuery;
|
|
if (requery)
|
|
{
|
|
LOG_IF_FAILED(wil::ResultFromException([&] { QueryProxySettingsAsync(); }));
|
|
}
|
|
|
|
if (m_queryState == QueryState::NoQuery)
|
|
{
|
|
m_requestFinished.SetEvent();
|
|
}
|
|
}
|
|
CATCH_LOG()
|
|
|
|
bool HttpProxyStateTracker::AreProxyStringsIdentical(const HttpProxySettings& newSettings) const
|
|
{
|
|
if (!m_proxySettings.has_value())
|
|
{
|
|
return false;
|
|
}
|
|
// note that we do not include the UnsupportedProxyDropReason intentionally here as if that is only change we don't want to trigger a toast
|
|
return (
|
|
newSettings.Proxy == m_proxySettings->Proxy && newSettings.SecureProxy == m_proxySettings->SecureProxy &&
|
|
newSettings.ProxyBypasses == m_proxySettings->ProxyBypasses && newSettings.PacUrl == m_proxySettings->PacUrl);
|
|
}
|
|
|
|
void HttpProxyStateTracker::RequestCompleted(_In_ DWORD error, _In_ HttpProxySettings&& newProxySettings) noexcept
|
|
try
|
|
{
|
|
WI_ASSERT(m_callbackQueue.isRunningInQueue());
|
|
if (SUCCEEDED_WIN32(error))
|
|
{
|
|
auto dataLock = m_proxySettingsLock.lock();
|
|
|
|
FilterProxySettingsByNetworkConfiguration(newProxySettings, m_networkMode);
|
|
|
|
if (!AreProxyStringsIdentical(newProxySettings))
|
|
{
|
|
LogHttpProxySettings(newProxySettings);
|
|
m_proxySettings = std::move(newProxySettings);
|
|
|
|
// If there was a setting changes, and this is not the initial proxy query, notify the user to restart WSL to get new proxy changes.
|
|
if (m_initialProxyQueryCompleted.is_signaled())
|
|
{
|
|
notifications::DisplayProxyChangeNotification(m_localizedProxyChangeString);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// note that the DropReason is not included in AreProxyStringsIdentical as we don't want to toast if that is only change,
|
|
// but we still want to make sure the drop reason is updated; otherwise, we risk not reporting the correct drop reason to user
|
|
if (newProxySettings.UnsupportedProxyDropReason != m_proxySettings->UnsupportedProxyDropReason)
|
|
{
|
|
m_proxySettings->UnsupportedProxyDropReason = newProxySettings.UnsupportedProxyDropReason;
|
|
}
|
|
}
|
|
m_initialProxyQueryCompleted.SetEvent();
|
|
}
|
|
|
|
// It is guaranteed that after closing the handles, a callback with status WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
|
|
// will be issued to indicate that the callback has been cleaned up.
|
|
m_resolver.reset();
|
|
m_session.reset();
|
|
}
|
|
CATCH_LOG()
|
|
|
|
// Proxy query tracking.
|
|
void CALLBACK HttpProxyStateTracker::s_OnProxyChange(_In_ ULONGLONG flags, _In_ void* pContext) noexcept
|
|
try
|
|
{
|
|
WSL_LOG("OnProxyChange", TraceLoggingValue(flags, "flags"));
|
|
const auto proxyStateTracking = static_cast<HttpProxyStateTracker*>(pContext);
|
|
|
|
// Ensure this is a change notification.
|
|
if (WI_IsFlagClear(flags, WINHTTP_PROXY_NOTIFY_CHANGE))
|
|
{
|
|
return;
|
|
}
|
|
|
|
proxyStateTracking->m_callbackQueue.submit([proxyStateTracking] { proxyStateTracking->QueryProxySettingsAsync(); });
|
|
}
|
|
CATCH_LOG()
|
|
|
|
UnsupportedProxyReason HttpProxyStateTracker::IsUnsupportedProxy(LPCWSTR proxyString, wsl::core::NetworkingMode configuration) noexcept
|
|
try
|
|
{
|
|
if (!proxyString)
|
|
{
|
|
return UnsupportedProxyReason::Supported;
|
|
}
|
|
|
|
URL_COMPONENTS url{};
|
|
url.dwStructSize = sizeof(url); // Required for WinHttpCrackUrl
|
|
url.dwHostNameLength = -1; // Indicates what we want cracked.
|
|
const DWORD proxyLength = static_cast<DWORD>(wcslen(proxyString));
|
|
|
|
if (proxyLength == 0)
|
|
{
|
|
return UnsupportedProxyReason::Supported;
|
|
}
|
|
|
|
THROW_IF_WIN32_BOOL_FALSE(WinHttpCrackUrl(proxyString, proxyLength, 0, &url));
|
|
|
|
// lpszHostName name will still include <proxy>:port portion of proxy string http://<proxy>:port, but the hostNameLength truncates the port
|
|
std::wstring portRemoved{url.lpszHostName, url.dwHostNameLength};
|
|
|
|
// IPv6 strings can come in format http://[<IPv6 address>]:port
|
|
const auto openBracket = portRemoved.find_first_of(L"[");
|
|
if (openBracket != ::std::wstring::npos)
|
|
{
|
|
const auto closeBracket = portRemoved.find_first_of(L"]");
|
|
if (closeBracket == ::std::wstring::npos || (openBracket + 1 >= closeBracket - 1))
|
|
{
|
|
// no other of below checks can contain brackets
|
|
return UnsupportedProxyReason::Supported;
|
|
}
|
|
portRemoved = portRemoved.substr(openBracket + 1, closeBracket - 1);
|
|
}
|
|
|
|
in6_addr addrV6{};
|
|
PCWSTR pStringEnd{}; // not used by us but still required for *ToAddressW
|
|
if (SUCCEEDED_WIN32(RtlIpv6StringToAddressW(portRemoved.c_str(), &pStringEnd, &addrV6)))
|
|
{
|
|
if (configuration != wsl::core::NetworkingMode::Mirrored)
|
|
{
|
|
return UnsupportedProxyReason::Ipv6NotMirrored; // v6 is only supported in mirrored mode
|
|
}
|
|
if (IN6_IS_ADDR_LOOPBACK(&addrV6))
|
|
{
|
|
return UnsupportedProxyReason::LoopbackV6; // v6 loopback is not supported in any network configuration
|
|
}
|
|
return UnsupportedProxyReason::Supported;
|
|
}
|
|
|
|
// v4 loopback is only supported in mirrored mode
|
|
if (configuration != wsl::core::NetworkingMode::Mirrored)
|
|
{
|
|
in_addr addrV4{};
|
|
if (SUCCEEDED_WIN32(RtlIpv4StringToAddressW(portRemoved.c_str(), true, &pStringEnd, &addrV4)))
|
|
{
|
|
if (IN4_IS_ADDR_LOOPBACK(&addrV4))
|
|
{
|
|
return UnsupportedProxyReason::LoopbackNotMirrored;
|
|
}
|
|
return UnsupportedProxyReason::Supported;
|
|
}
|
|
|
|
if (wsl::shared::string::IsEqual(portRemoved, c_loopback, true) || wsl::shared::string::IsEqual(portRemoved, c_localhost, true))
|
|
{
|
|
return UnsupportedProxyReason::LoopbackNotMirrored;
|
|
}
|
|
|
|
DWORD size = 0;
|
|
std::wstring computerName{};
|
|
|
|
if (!GetComputerNameW(nullptr, &size))
|
|
{
|
|
const DWORD err = GetLastError();
|
|
THROW_WIN32_IF(err, err != ERROR_BUFFER_OVERFLOW);
|
|
}
|
|
computerName.resize(size, L'\0');
|
|
|
|
THROW_IF_WIN32_BOOL_FALSE(GetComputerNameW(computerName.data(), &size));
|
|
|
|
// remove any embedded null characters
|
|
const auto offset = computerName.find_first_of(L'\0');
|
|
if (offset != ::std::wstring::npos)
|
|
{
|
|
computerName.resize(offset);
|
|
}
|
|
|
|
if (wsl::shared::string::IsEqual(computerName, portRemoved, true))
|
|
{
|
|
return UnsupportedProxyReason::LoopbackNotMirrored;
|
|
}
|
|
}
|
|
return UnsupportedProxyReason::Supported;
|
|
}
|
|
catch (...)
|
|
{
|
|
LOG_CAUGHT_EXCEPTION();
|
|
return UnsupportedProxyReason::UnsupportedError;
|
|
}
|
|
|
|
void HttpProxyStateTracker::FilterProxySettingsByNetworkConfiguration(HttpProxySettings& settings, wsl::core::NetworkingMode mode) noexcept
|
|
try
|
|
{
|
|
const auto proxySupportState = IsUnsupportedProxy(wsl::shared::string::MultiByteToWide(settings.Proxy).c_str(), mode);
|
|
const auto secureProxySupportState = IsUnsupportedProxy(wsl::shared::string::MultiByteToWide(settings.SecureProxy).c_str(), mode);
|
|
if (proxySupportState != UnsupportedProxyReason::Supported)
|
|
{
|
|
settings.Proxy.clear();
|
|
settings.UnsupportedProxyDropReason = proxySupportState;
|
|
}
|
|
|
|
if (secureProxySupportState != UnsupportedProxyReason::Supported)
|
|
{
|
|
settings.SecureProxy.clear();
|
|
settings.UnsupportedProxyDropReason = secureProxySupportState;
|
|
}
|
|
|
|
// If we now have no proxy settings configured, we should clear the proxy bypasses too.
|
|
// Note that if one setting was cleared, but other was not, the proxy bypasses are still valid.
|
|
if (settings.Proxy.empty() && settings.SecureProxy.empty())
|
|
{
|
|
settings.ProxyBypasses.clear();
|
|
settings.ProxyBypassesComma.clear();
|
|
}
|
|
|
|
if (proxySupportState != UnsupportedProxyReason::Supported || secureProxySupportState != UnsupportedProxyReason::Supported)
|
|
{
|
|
WSL_LOG(
|
|
"AutoProxy-DropUnsupportedSetting",
|
|
TraceLoggingValue(wsl::core::ToString(mode), "InvalidNetworkConfiguration"),
|
|
TraceLoggingValue(ToString(proxySupportState), "DropHttpProxySetting"),
|
|
TraceLoggingValue(ToString(secureProxySupportState), "DropHttpsProxySetting"));
|
|
}
|
|
}
|
|
CATCH_LOG()
|
|
|
|
void HttpProxyStateTracker::QueryProxySettingsAsync()
|
|
{
|
|
PCSTR executionStep = "";
|
|
try
|
|
{
|
|
WI_ASSERT(m_callbackQueue.isRunningInQueue());
|
|
if (m_queryState == QueryState::PendingAndQueueAdditional)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (m_queryState == QueryState::Pending)
|
|
{
|
|
m_queryState = QueryState::PendingAndQueueAdditional;
|
|
WSL_LOG("Run another http proxy query after current completes");
|
|
return;
|
|
}
|
|
|
|
executionStep = "impersonate_token";
|
|
auto runAsUser = wil::impersonate_token(m_userToken.get());
|
|
|
|
executionStep = "WinHttpOpen";
|
|
//
|
|
// Open session and setup resolver handle
|
|
//
|
|
wil::unique_winhttp_hinternet session(WinHttpOpen(
|
|
nullptr, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, WINHTTP_FLAG_ASYNC));
|
|
THROW_LAST_ERROR_IF(!session.is_valid());
|
|
|
|
executionStep = "WinHttpCreateProxyResolver";
|
|
wil::unique_winhttp_hinternet resolver{};
|
|
THROW_IF_WIN32_ERROR(WinHttpCreateProxyResolver(session.get(), &resolver));
|
|
|
|
executionStep = "WinHttpSetStatusCallback";
|
|
// We need to set flag WINHTTP_CALLBACK_FLAG_HANDLES in order to get the WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
|
|
// status callback when a handle is closed.
|
|
// Using those flags will always result in 2 callbacks, 1 on success/failure, 1 when closing the requests.
|
|
// Without these we risk race conditions while deconstructing the ProxyTracker.
|
|
THROW_LAST_ERROR_IF(
|
|
WinHttpSetStatusCallback(
|
|
resolver.get(),
|
|
s_GetProxySettingsExCallback,
|
|
WINHTTP_CALLBACK_STATUS_GETPROXYSETTINGS_COMPLETE | WINHTTP_CALLBACK_STATUS_REQUEST_ERROR | WINHTTP_CALLBACK_FLAG_HANDLES,
|
|
0) == WINHTTP_INVALID_STATUS_CALLBACK);
|
|
|
|
WINHTTP_PROXY_SETTINGS_PARAM ProxySettingsParam{0, nullptr, nullptr};
|
|
|
|
executionStep = "WinHttpGetProxySettingsEx";
|
|
// Query the proxy settings
|
|
const DWORD dwError = s_WinHttpGetProxySettingsEx.value()(
|
|
resolver.get(), WinHttpProxySettingsTypeWsl, &ProxySettingsParam, reinterpret_cast<DWORD_PTR>(this));
|
|
|
|
if (dwError != ERROR_IO_PENDING && dwError != ERROR_SUCCESS)
|
|
{
|
|
THROW_WIN32(dwError);
|
|
}
|
|
|
|
// Transfer ownership of HTTP handles and track request
|
|
m_resolver = std::move(resolver);
|
|
m_session = std::move(session);
|
|
m_requestFinished.ResetEvent();
|
|
m_queryState = QueryState::Pending;
|
|
}
|
|
catch (...)
|
|
{
|
|
const auto hr = wil::ResultFromCaughtException();
|
|
WSL_LOG("QueryProxySettingsFailed", TraceLoggingHResult(hr, "result"), TraceLoggingValue(executionStep, "executionStep"));
|
|
|
|
throw;
|
|
}
|
|
}
|
|
|
|
HttpProxyStateTracker::HttpProxyStateTracker(int ProxyTimeout, HANDLE UserToken, wsl::core::NetworkingMode mode) :
|
|
m_networkMode{mode},
|
|
m_initialQueryTimeout{ProxyTimeout},
|
|
m_localizedProxyChangeString{wsl::shared::Localization::MessageHttpProxyChangeDetected()}
|
|
{
|
|
THROW_IF_WIN32_BOOL_FALSE(::DuplicateTokenEx(UserToken, MAXIMUM_ALLOWED, nullptr, SecurityImpersonation, TokenImpersonation, &m_userToken));
|
|
m_callbackQueue.submit([this] { QueryProxySettingsAsync(); });
|
|
THROW_IF_WIN32_ERROR(s_WinHttpRegisterProxyChangeNotification.value()(WINHTTP_PROXY_NOTIFY_CHANGE, s_OnProxyChange, this, &m_proxyRegistrationHandle));
|
|
}
|
|
|
|
HttpProxyStateTracker::~HttpProxyStateTracker()
|
|
{
|
|
// cancel Proxy change notifications, preventing queries from being triggered.
|
|
if (m_proxyRegistrationHandle != nullptr)
|
|
{
|
|
try
|
|
{
|
|
THROW_IF_WIN32_ERROR(s_WinHttpUnregisterProxyChangeNotification.value()(m_proxyRegistrationHandle));
|
|
}
|
|
CATCH_LOG()
|
|
}
|
|
// It is guaranteed that after closing the handles, a callback with status WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING
|
|
// will be issued and it will be the last callback for this request, making it safe to delete the ProxyStateTracker.
|
|
m_resolver.reset();
|
|
m_session.reset();
|
|
|
|
// Wait for all requests to complete. At this point no new requests can be started since we unregistered for proxy change
|
|
// notifications. Without this we risk racing proxy callbacks and them calling into a cleaned up ProxyStateTracker.
|
|
m_requestFinished.wait();
|
|
|
|
// Cancel all pending work in the queue and prevent additional requests
|
|
m_callbackQueue.cancel();
|
|
}
|
|
|
|
std::optional<HttpProxySettings> HttpProxyStateTracker::WaitForInitialProxySettings()
|
|
{
|
|
m_initialProxyQueryCompleted.wait(m_initialQueryTimeout);
|
|
auto lock = m_proxySettingsLock.lock();
|
|
return m_proxySettings;
|
|
}
|
|
|
|
void HttpProxyStateTracker::ConfigureNetworkingMode(wsl::core::NetworkingMode mode) noexcept
|
|
{
|
|
auto lock = m_proxySettingsLock.lock();
|
|
// if we fall back to NAT mode need to strip bad settings
|
|
if (m_proxySettings.has_value() && mode != m_networkMode)
|
|
{
|
|
FilterProxySettingsByNetworkConfiguration(m_proxySettings.value(), mode);
|
|
}
|
|
m_networkMode = mode;
|
|
}
|