curl-fuzzer C++ reference
Loading...
Searching...
No Matches
proto_fuzzer::MockServer Class Reference

Orchestrates a bounded sequence of mock HTTP exchanges: installs socket callbacks on an easy handle, assigns a response script to each new socket, and feeds queued chunks as libcurl reads them. More...

#include <mock_server.h>

Inheritance diagram for proto_fuzzer::MockServer:
proto_fuzzer::MockServerBase proto_fuzzer::ConnectUdpProxyMockServer proto_fuzzer::GopherMockServer proto_fuzzer::H2CleartextMockServer proto_fuzzer::HttpTransportMockServer proto_fuzzer::ProxyOptionMockServer proto_fuzzer::ProxyTransportMockServer proto_fuzzer::TlsMockServer proto_fuzzer::H2OriginMockServer proto_fuzzer::H2ProxyMockServer proto_fuzzer::DohHttpsRrMockServer

Public Member Functions

 MockServer (MultiDrivePolicy drive_policy=MultiDrivePolicy::kPerform)
 Construct an idle MockServer with no scripted responses or open peers.
 ~MockServer () override
 Default destructor; current and previous MockConnections clean up their server-side descriptors only after curl has been removed from the multi.
void SetScripts (const curl::fuzzer::proto::Scenario &scenario)
 Build the complete borrowed script table before entering curl.
void SetKeepConnectionsOpen (bool keep_open)
 Keep completed response sockets writable instead of half-closing them.
CURLcode DriveEasyScenario (CURL *easy, const curl::fuzzer::proto::Scenario &scenario, bool use_events=false) override
 Preload all bounded response bytes from inside OPENSOCKETFUNCTION, where the mock still owns both socketpair ends, and half-close the peer when the preload finishes.
ConnectOnlyRunStats DriveConnectOnlyScenario (CURL *easy, const curl::fuzzer::proto::Scenario &scenario) override
 Establish only the HTTP transport, then pass bounded application bytes through curl's public direct-I/O wrappers.
bool DeliverNextChunk ()
 Push the next queued chunk.
bool has_more_chunks () const
bool ServiceConnections ()
 Service one deterministic application event-loop turn by draining all available request bytes and releasing at most one response chunk.
std::size_t opened_connection_count () const
 Report how many peer sockets curl opened during the current script run.
Public Member Functions inherited from proto_fuzzer::MockServerBase
virtual ~MockServerBase ()
 Out-of-line destructor so MockConnection can stay forward-declared in the base header (its complete type is only needed where unique_ptr is instantiated for destruction).
virtual void ObserveState ()
 Default no-op for peers without protocol-specific observations.
virtual void Install (CURL *easy)
 Install the common OPENSOCKETFUNCTION / OPENSOCKETDATA / SOCKOPTFUNCTION callbacks on 'easy'.
virtual void ConfigureRequestData (ScenarioRequestData *request_data)
 Bind protocol-specific work to the request-data callbacks after their per-scenario state has been constructed.
CURLcode DriveScenario (CURL *easy, const curl::fuzzer::proto::Scenario &scenario)
 Run 'scenario' to completion on 'easy': allocate a multi, attach 'easy', delegate protocol-specific work to RunLoop, consume its completion message, and clean up.
void SetMultiObserver (MultiObserver observer)
 Register an observer invoked with the live multi handle after 'easy' is attached and before the drive loop starts.
MockConnection * connection ()

Protected Member Functions

virtual std::unique_ptr< MockConnection > CreateConnection ()
 Construct the transport used for one HTTP exchange.
void ResetConnections ()
 Release all current and retired socketpairs before resetting transport- specific state.
virtual void ObserveActiveTransfer (CURL *easy)
 Observe curl while its connection filters are still attached.
virtual bool SupportsRepeatedPollsetProbe () const
 Ordinary HTTP and compatibility peers retain the historical perform-only loop even if an append-only scenario field is present.
curl_socket_t HandleOpenSocket (curlsocktype purpose=CURLSOCKTYPE_IPCXN, struct curl_sockaddr *address=nullptr) override
 Called by the OPENSOCKETFUNCTION trampoline in the base class.
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 operation/idle budget is hit.
Protected Member Functions inherited from proto_fuzzer::MockServerBase
 MockServerBase (MultiDrivePolicy drive_policy=MultiDrivePolicy::kPerform)
 Construct an empty base instance with a fixed multi-drive policy.
virtual void HandleDetachedMulti (CurlMultiPtr multi)
 Dispose of or retain the multi after its easy handle has been removed.
virtual SocketSetupDisposition GetSocketSetupDisposition (curl_socket_t curlfd, curlsocktype purpose) const
 Describe the socket returned by HandleOpenSocket without issuing native descriptor queries.
MultiSocketDriver * multi_socket_driver ()
 Expose the callback state installed for the current socket-action drive.
std::size_t additional_handle_cleanup_count () const
void ResumeResponseIfRequested (CURL *easy)
 Resume receive-side callback output at one bounded drive boundary when the dedicated API plan requested it.
void ApplyPendingBackpressure ()
 Apply the BackpressureConfig cached by DriveScenario to the new connection_.

Additional Inherited Members

Public Types inherited from proto_fuzzer::MockServerBase
using MultiObserver = std::function<void(CURLM*)>
 Callback type used to publish the driving multi handle to observers.
Static Protected Member Functions inherited from proto_fuzzer::MockServerBase
static int WaitOnMultiFdset (CURLM *multi, CURLMcode *rc)
 Wait on curl's fdset with a short timeout.
static void ProbeMultiPollset (CURLM *multi)
 Ask curl to construct and inspect its connection-filter pollset without waiting.
static bool MultiPollsetWantsWrite (CURLM *multi, curl_socket_t socket)
 Inspect one socket's current writable interest through curl's public multi fdset API.
static bool UsesTimedDrive (const curl::fuzzer::proto::Scenario &scenario)
 Treat a non-default BackpressureConfig as an explicit request for the slower, timed drive policy.
Protected Attributes inherited from proto_fuzzer::MockServerBase
std::unique_ptr< MockConnection > connection_
 The per-scenario MockConnection, lazily created by HandleOpenSocket().
int pending_recv_buf_bytes_
 Cached SO_RCVBUF/SO_SNDBUF setting in bytes.
std::size_t pending_drain_limit_
 Cached per-call DrainIncoming byte budget.
MultiSocketDriver * multi_socket_driver_
 Non-owning pointer into DriveScenario's stack.
std::size_t additional_handle_cleanup_count_
 Number of application-created handles, excluding the caller's parent, successfully removed from the current multi and cleaned up.
bool resume_response_
 True only for an API-plan multi drive with its one-shot write callback.
MultiObserver multi_observer_
 Observer receiving the live multi handle at the start of a drive.
Static Protected Attributes inherited from proto_fuzzer::MockServerBase
static constexpr int kMaxDriveIterations = 512
 Hard operation budget for one scenario.
static constexpr int kMaxIdleIterations = 8
 Consecutive no-progress budget for ordinary scenarios.
static constexpr int kMaxTimedIdleIterations = 256
 Explicit backpressure scenarios get a larger idle budget and may use the short timed wait above.

Detailed Description

Orchestrates a bounded sequence of mock HTTP exchanges: installs socket callbacks on an easy handle, assigns a response script to each new socket, and feeds queued chunks as libcurl reads them.

HTTP in-process mock peer.

Assigns one bounded response script to each socket curl opens, allowing redirects and authentication retries to progress without permitting an unbounded connection graph. WebSocketMockServer keeps its separate single-socket model.

Definition at line 72 of file mock_server.h.

Constructor & Destructor Documentation

◆ MockServer()

proto_fuzzer::MockServer::MockServer ( MultiDrivePolicy drive_policy = MultiDrivePolicy::kPerform)
explicit

Construct an idle MockServer with no scripted responses or open peers.

DriveScenario() configures it from a Scenario before curl can open a socket; the fixed policy decides whether that scenario's ApiPlan controls the loop.

Parameters
drive_policyMulti interface loop selected for this server.

Definition at line 319 of file mock_server.cc.

Member Function Documentation

◆ CreateConnection()

std::unique_ptr< MockConnection > proto_fuzzer::MockServer::CreateConnection ( )
protectedvirtual

Construct the transport used for one HTTP exchange.

HTTPS overrides this factory with a TLS record layer while retaining the same bounded response scripts and redirect lifetimes, without copying the HTTP state machine.

Returns
a new connection, whose ok() result is checked before use.

Reimplemented in proto_fuzzer::GopherMockServer, proto_fuzzer::H2CleartextMockServer, proto_fuzzer::H2OriginMockServer, proto_fuzzer::H2ProxyMockServer, proto_fuzzer::HttpTransportMockServer, proto_fuzzer::ProxyOptionMockServer, proto_fuzzer::ProxyTransportMockServer, and proto_fuzzer::TlsMockServer.

Definition at line 377 of file mock_server.cc.

◆ DeliverNextChunk()

bool proto_fuzzer::MockServer::DeliverNextChunk ( )

Push the next queued chunk.

Called by the drive loop when curl is ready for more data.

Returns
true when a chunk was consumed from the script.

Definition at line 541 of file mock_server.cc.

◆ DriveConnectOnlyScenario()

ConnectOnlyRunStats proto_fuzzer::MockServer::DriveConnectOnlyScenario ( CURL * easy,
const curl::fuzzer::proto::Scenario & scenario )
overridevirtual

Establish only the HTTP transport, then pass bounded application bytes through curl's public direct-I/O wrappers.

Preloading makes receive readiness deterministic without a helper thread; the socketpair peer stays readable after ShutdownWrite and continues accepting the outgoing probe.

Parameters
easyConfigured easy handle whose transport this mock supplies.
scenarioSource of the bounded response and direct-I/O probe bytes.
Returns
Results and byte counts from connect, send, and receive operations.

Reimplemented from proto_fuzzer::MockServerBase.

Definition at line 496 of file mock_server.cc.

◆ DriveEasyScenario()

CURLcode proto_fuzzer::MockServer::DriveEasyScenario ( CURL * easy,
const curl::fuzzer::proto::Scenario & scenario,
bool use_events = false )
overridevirtual

Preload all bounded response bytes from inside OPENSOCKETFUNCTION, where the mock still owns both socketpair ends, and half-close the peer when the preload finishes.

This avoids a helper thread and prevents curl from waiting for the outer chunk-delivery loop. The total serialized fuzz input is capped by libFuzzer's max_len. If a non-blocking preload fills the local socket, curl observes only the successfully queued prefix and the timeouts below bound the incomplete response. This drive has no iteration budget of its own, so it reasserts those timeouts after scenario setopts and clears the option that can disable them.

Parameters
easyConfigured easy handle whose open-socket callback targets this mock.
scenarioBounded response script to preload before performing.
use_eventsSelect curl's debug event-based easy entrypoint.
Returns
Transfer result reported by curl's selected easy entrypoint.

Reimplemented from proto_fuzzer::MockServerBase.

Definition at line 471 of file mock_server.cc.

◆ HandleOpenSocket()

curl_socket_t proto_fuzzer::MockServer::HandleOpenSocket ( curlsocktype purpose = CURLSOCKTYPE_IPCXN,
struct curl_sockaddr * address = nullptr )
overrideprotectedvirtual

Called by the OPENSOCKETFUNCTION trampoline in the base class.

Creates the MockConnection, writes initial_response into it, and returns the client-side fd to hand to libcurl.

Parameters
purposeSocket role requested by curl; ordinary stream mocks do not need to distinguish outbound HTTP roles.
addressIntended destination retained by curl; the socketpair is already connected and therefore leaves it untouched.
Returns
the client-side fd to hand to libcurl, or CURL_SOCKET_BAD on failure.

Implements proto_fuzzer::MockServerBase.

Definition at line 404 of file mock_server.cc.

◆ has_more_chunks()

bool proto_fuzzer::MockServer::has_more_chunks ( ) const
Returns
true if at least one on_readable chunk has not yet been sent.

Definition at line 369 of file mock_server.cc.

◆ ObserveActiveTransfer()

void proto_fuzzer::MockServer::ObserveActiveTransfer ( CURL * easy)
protectedvirtual

Observe curl while its connection filters are still attached.

Plain HTTP has no transport-specific state to inspect; layered transports override this instead of querying stale state after the multi has been dismantled.

Parameters
easyActive easy handle, unused by the plaintext transport.

Reimplemented in proto_fuzzer::DohHttpsRrMockServer, and proto_fuzzer::TlsMockServer.

Definition at line 393 of file mock_server.cc.

◆ opened_connection_count()

std::size_t proto_fuzzer::MockServer::opened_connection_count ( ) const

Report how many peer sockets curl opened during the current script run.

Returns
Number of response scripts assigned to live or retired sockets.

Definition at line 604 of file mock_server.cc.

◆ ResetConnections()

void proto_fuzzer::MockServer::ResetConnections ( )
protected

Release all current and retired socketpairs before resetting transport- specific state.

Derived destructors call this while their borrowed state is still alive. This is separate from SetScripts because a derived class may need a stricter order than C++'s derived-member-before-base teardown.

Definition at line 383 of file mock_server.cc.

◆ RunLoop()

void proto_fuzzer::MockServer::RunLoop ( CURLM * multi,
CURL * easy,
const curl::fuzzer::proto::Scenario & scenario )
overrideprotectedvirtual

Seed the mock from the scenario, then drive the perform loop until curl is done or a deterministic operation/idle budget is hit.

Ordinary scenarios never wait; explicit backpressure scenarios may use short select() waits.

Parameters
multicaller-owned multi; 'easy' is already added.
easythe curl easy handle attached to this mock.
scenariosource of the initial_response and on_readable chunks.

Implements proto_fuzzer::MockServerBase.

Reimplemented in proto_fuzzer::ProxyOptionMockServer.

Definition at line 654 of file mock_server.cc.

◆ ServiceConnections()

bool proto_fuzzer::MockServer::ServiceConnections ( )

Service one deterministic application event-loop turn by draining all available request bytes and releasing at most one response chunk.

The shared-multi driver owns the outer loop and calls this directly; ordinary perform and socket-action drives use the same peer servicing. Draining first creates request-side space before a response can provoke another write, and releasing only one chunk preserves the scenario's mutation- controlled parser boundaries.

Returns
true when any request or response byte advanced.

Definition at line 594 of file mock_server.cc.

◆ SetKeepConnectionsOpen()

void proto_fuzzer::MockServer::SetKeepConnectionsOpen ( bool keep_open)

Keep completed response sockets writable instead of half-closing them.

The multi-transfer lane uses this to let a queued easy handle reuse an HTTP/1.1 connection; ordinary protocol drives retain close-on-completion.

Parameters
keep_openWhether the peer should suppress its response-side FIN.

Definition at line 366 of file mock_server.cc.

◆ SetScripts()

void proto_fuzzer::MockServer::SetScripts ( const curl::fuzzer::proto::Scenario & scenario)

Build the complete borrowed script table before entering curl.

The primary Connection always occupies slot zero for backwards compatibility; only three subsequent pointers are retained so protobuf mutations cannot allocate socketpairs or prolong redirects in proportion to repeated-field size. The caller must keep the Scenario alive and unmodified until the synchronous drive finishes. RunScenario provides that lifetime, making borrowing safe while avoiding copies of response bytes before curl requests the corresponding socket or chunk.

Parameters
scenarioSource of the primary and bounded follow-on scripts.

Definition at line 340 of file mock_server.cc.

◆ SupportsRepeatedPollsetProbe()

bool proto_fuzzer::MockServer::SupportsRepeatedPollsetProbe ( ) const
protectedvirtual

Ordinary HTTP and compatibility peers retain the historical perform-only loop even if an append-only scenario field is present.

Protocol subclasses opt in only when their peer can service every repeated poll turn.

Returns
False for the generic mock server.

Reimplemented in proto_fuzzer::HttpTransportMockServer, and proto_fuzzer::ProxyTransportMockServer.

Definition at line 646 of file mock_server.cc.


The documentation for this class was generated from the following files: