20namespace proto_fuzzer {
24constexpr char kHostnameNoProxy[] =
"not-proxy.test, .proxy.test.";
25constexpr char kIpv4NoProxy[] =
"192.0.2.0/24, 127.0.0.0/8";
26constexpr char kIpv6NoProxy[] =
"2001:db8::/32, ::1/128";
27constexpr char kEnvironmentProxy[] =
"http://127.0.0.1:8080";
28constexpr char kLoopbackInterface[] =
"host!127.0.0.1";
35 : mode_(mode), setup_ok_(true), proxy_environment_active_(false), saved_http_proxy_was_set_(false) {}
45 client_transcript_.clear();
48 CURLcode result = CURLE_OK;
50 case curl::fuzzer::proto::PROXY_SOCKET_OPTION_NOPROXY_HOSTNAME:
51 result = curl_easy_setopt(easy, CURLOPT_NOPROXY, kHostnameNoProxy);
53 case curl::fuzzer::proto::PROXY_SOCKET_OPTION_NOPROXY_IPV4_CIDR:
54 result = curl_easy_setopt(easy, CURLOPT_NOPROXY, kIpv4NoProxy);
56 case curl::fuzzer::proto::PROXY_SOCKET_OPTION_NOPROXY_IPV6_CIDR:
57 result = curl_easy_setopt(easy, CURLOPT_NOPROXY, kIpv6NoProxy);
59 case curl::fuzzer::proto::PROXY_SOCKET_OPTION_ENV_HTTP_PROXY:
60 setup_ok_ = BeginProxyEnvironment();
62 result = curl_easy_setopt(easy, CURLOPT_CONNECT_TO,
nullptr);
64 if (result == CURLE_OK) {
65 result = curl_easy_setopt(easy, CURLOPT_NOPROXY,
"");
67 if (result == CURLE_OK) {
68 result = curl_easy_setopt(easy, CURLOPT_PROXY,
nullptr);
71 case curl::fuzzer::proto::PROXY_SOCKET_OPTION_DEFAULT:
72 case curl::fuzzer::proto::PROXY_SOCKET_OPTION_LOOPBACK_INTERFACE_KEEPALIVE:
76 setup_ok_ = setup_ok_ && result == CURLE_OK;
85 auto connection = std::make_unique<MockConnection>();
94 if (data ==
nullptr || size == 0 || client_transcript_.size() >= kMaxTranscriptBytes) {
97 const std::size_t remaining = kMaxTranscriptBytes - client_transcript_.size();
98 client_transcript_.append(
reinterpret_cast<const char*
>(data), std::min(size, remaining));
115bool ProxyOptionMockServer::BeginProxyEnvironment() {
116 if (proxy_environment_active_) {
119 saved_http_proxy_.clear();
120 const char* current = std::getenv(
"http_proxy");
121 saved_http_proxy_was_set_ = current !=
nullptr;
122 if (current !=
nullptr) {
123 saved_http_proxy_.assign(current);
125 proxy_environment_active_ =
true;
126 if (setenv(
"http_proxy", kEnvironmentProxy, 1) != 0) {
127 EndProxyEnvironment();
134void ProxyOptionMockServer::EndProxyEnvironment() {
135 if (!proxy_environment_active_) {
138 if (saved_http_proxy_was_set_) {
139 (void)setenv(
"http_proxy", saved_http_proxy_.c_str(), 1);
141 (void)unsetenv(
"http_proxy");
143 saved_http_proxy_.clear();
144 saved_http_proxy_was_set_ =
false;
145 proxy_environment_active_ =
false;
153 (void)curl_easy_setopt(easy, CURLOPT_CONNECT_TO,
nullptr);
154 (void)curl_easy_setopt(easy, CURLOPT_INTERFACE, kLoopbackInterface);
155 (void)curl_easy_setopt(easy, CURLOPT_TCP_KEEPALIVE, 1L);
156 (void)curl_easy_setopt(easy, CURLOPT_TCP_KEEPIDLE, 1L);
157 (void)curl_easy_setopt(easy, CURLOPT_TCP_KEEPINTVL, 1L);
158 (void)curl_easy_setopt(easy, CURLOPT_TCP_KEEPCNT, 1L);
163#if defined(PROTO_FUZZER_OBSERVE_STATE)
166 (void)option_observation;
void Install(CURL *easy) override
Install the shared socket callbacks and remember the easy handle for the later resolve/port/timeout s...
void Install(CURL *easy) override
Install the inherited owned loopback TCP listener, then require curl to perform its normal INET setup...
virtual void Install(CURL *easy)
Install the common OPENSOCKETFUNCTION / OPENSOCKETDATA / SOCKOPTFUNCTION callbacks on 'easy'.
MockConnection * connection()
virtual void ObserveState()
Default no-op for peers without protocol-specific observations.
void RunLoop(CURLM *multi, CURL *easy, const curl::fuzzer::proto::Scenario &scenario) override
Seed the mock from the scenario, then drive the perform loop until curl is done or a deterministic op...
ProxyOptionMockServer(curl::fuzzer::proto::ProxySocketOptionMode mode)
Construct an idle peer for one policy-normalized mode.
void RunLoop(CURLM *multi, CURL *easy, const curl::fuzzer::proto::Scenario &scenario) override
Refuse to perform if the scoped environment or fixed setopts failed.
void ObserveIncomingData(const unsigned char *data, std::size_t size) override
Retain a bounded request transcript for exact routing assertions.
void Install(CURL *easy) override
Install socket callbacks and one fixed routing option.
std::unique_ptr< MockConnection > CreateConnection() override
Attach the transcript observer to a fresh in-process connection.
const std::string & client_transcript() const
~ProxyOptionMockServer() override
Restore process environment after curl has released the easy handle.
void ObserveState() override
Retain protocol outcomes in coverage and introspector builds.
Closed proxy, no-proxy, interface, and TCP-option peers.