|
curl-fuzzer C++ reference
|
Services curl's single-connection, line-based SMTP exchange. More...
#include <smtp_mock_server.h>
Public Member Functions | |
| SmtpMockServer (curl::fuzzer::proto::SmtpProbeMode mode=curl::fuzzer::proto::SMTP_PROBE_DEFAULT) | |
| Begin without a borrowed protobuf or open socketpair. | |
| ~SmtpMockServer () override | |
| Release the server-owned socketpair half after curl has returned its client descriptor. | |
| void | ObserveState () override |
| Retain protocol outcomes in coverage and introspector builds. | |
| void | ConfigureClient (CURL *easy) const |
| Apply only closed, harness-owned client controls. | |
| Public Member Functions inherited from proto_fuzzer::PingpongMockServer | |
| ~PingpongMockServer () override | |
| Release the server-owned socketpair half after curl has returned its client descriptor. | |
| const std::string & | control_transcript () const |
| Expose the bounded command capture from the most recent drive so tests can verify protocol states without coupling assertions to curl debug output. | |
| const std::string & | uploaded_data () const |
| Expose a bounded prefix of bytes drained during the most recent body phase while continuing to drain every client byte, so test observability cannot create backpressure. | |
| std::size_t | active_pollset_probe_count () const |
| Report how many requested zero-timeout multi-poll probes ran during the most recent drive. | |
| std::size_t | writable_pollset_probe_count () const |
| Report how often curl retained writable interest while the peer held an incomplete control command. | |
| 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 | 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. | |
| virtual CURLcode | DriveEasyScenario (CURL *easy, const curl::fuzzer::proto::Scenario &scenario, bool use_events=false) |
| Run through the public easy entrypoint when a protocol mock can preload all peer work before curl takes control. | |
| virtual ConnectOnlyRunStats | DriveConnectOnlyScenario (CURL *easy, const curl::fuzzer::proto::Scenario &scenario) |
| Establish a CONNECT_ONLY transport, then perform bounded direct I/O. | |
| 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 | |
| std::unique_ptr< MockConnection > | CreateConnection () override |
| Create the default plaintext transport for the SMTP exchange. | |
| void | HandleLine (std::string_view line) override |
| Advance one reply for every complete command. | |
| void | ResetProtocolState () override |
| Reset SMTP's recipient bookkeeping for a new drive. | |
| void | QueueShutdownReply () override |
| Queue a 221 before the shared transport half-closes. | |
| Protected Member Functions inherited from proto_fuzzer::PingpongMockServer | |
| PingpongMockServer (MultiDrivePolicy drive_policy=MultiDrivePolicy::kPerform) | |
| Construct the shared transport state without a borrowed protobuf or open socketpair. | |
| void | BeginMarkerBody (std::string_view terminator) |
| Enter marker-terminated body mode. | |
| void | BeginLiteralBody (std::size_t length) |
| Enter length-announced literal body mode. | |
| void | BeginExactBody (std::size_t length) |
| Enter exact-length body mode. | |
| void | BeginOpaqueDrain () |
| Enter an opaque drain after a transport upgrade. | |
| virtual void | HandleBodyComplete () |
| Called after a body phase reached its terminator and the parser returned to command mode. | |
| curl_socket_t | HandleOpenSocket (curlsocktype purpose=CURLSOCKTYPE_IPCXN, struct curl_sockaddr *address=nullptr) override |
| Create the single control socketpair and queue the server greeting. | |
| void | RunLoop (CURLM *multi, CURL *easy, const curl::fuzzer::proto::Scenario &scenario) override |
| Alternate curl transitions with immediate peer service until the transfer completes or deterministic idle/operation caps win. | |
| void | HandleDetachedMulti (CurlMultiPtr multi) override |
| Give curl's graceful shutdown one last chance to emit its teardown command while the peer still owns its read half, then release the multi as the base class would. | |
| void | ObserveIncomingData (const unsigned char *data, std::size_t size) override |
| Append decoded application bytes to the pending parser buffer. | |
| const curl::fuzzer::proto::Scenario * | scenario () const |
| Borrowed scenario for the synchronous drive, or nullptr outside RunLoop(). | |
| const std::string * | NextControlReply () |
| Return the next command-aligned response within the shared response-count budget. | |
| bool | WriteControlBytes (std::string_view bytes) |
| Keep failed peer writes local to the mock. | |
| bool | WriteNextReply () |
| Consume the next scripted reply. | |
| void | ShutdownControlWrite () |
| Half-close the server-to-client direction while retaining the read half. | |
| 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 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::PingpongMockServer | |
| static std::string_view | FirstToken (std::string_view line) |
| Remove optional leading horizontal whitespace and return the first token without allocating. | |
| static std::string_view | SecondToken (std::string_view line) |
| Skip the first token and return the second whitespace-delimited token without allocating. | |
| static bool | TokenEquals (std::string_view token, std::string_view expected_uppercase) |
| Fold only ASCII lowercase command letters. | |
| 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. | |
Services curl's single-connection, line-based SMTP exchange.
SMTP needs neither a data channel nor a second script per socket: curl sends one command at a time and waits for the matching response. This peer therefore treats Scenario.connection as a client-line-aligned reply script. initial_response is the 220 greeting; each on_readable entry is the reply to the next command or SASL continuation (EHLO/HELO, AUTH, MAIL FROM, RCPT TO, DATA, and finally the reply after the message body).
The one exception to the command/reply rhythm is the message body. After a 354 reply to DATA, curl writes the bounded upload script followed by the SMTP end-of-body marker. Those bytes arrive on the same control socket and are not commands, so the shared pingpong transport drains them until it observes "\r\n.\r\n". The post-body 250 is queued at DATA-acceptance time because curl's blocking smtp_done() wait cannot be serviced by the outer loop.
Subclasses replace the transport through CreateConnection(). The implicit- TLS SMTPS peer uses that hook to wrap the identical command exchange in a verified OpenSSL connection; incoming bytes are observed after transport decoding so the state machine does not depend on the carrier.
Definition at line 43 of file smtp_mock_server.h.
|
explicit |
Begin without a borrowed protobuf or open socketpair.
RunLoop borrows a Scenario only for the synchronous DriveScenario call in which socket callbacks can run.
| mode | Closed SMTP transport probe selected by target policy. |
Definition at line 28 of file smtp_mock_server.cc.
|
overridedefault |
Release the server-owned socketpair half after curl has returned its client descriptor.
The out-of-line destructor keeps MockConnection's complete type local to this translation unit.
| void proto_fuzzer::SmtpMockServer::ConfigureClient | ( | CURL * | easy | ) | const |
Apply only closed, harness-owned client controls.
The ordinary scenario option list has already run when the production runner calls this hook.
| easy | Easy handle configured for the SMTP transfer. |
Definition at line 55 of file smtp_mock_server.cc.
|
overrideprotectedvirtual |
Create the default plaintext transport for the SMTP exchange.
The SMTPS subclass overrides this factory while retaining the command/reply parser.
Reimplemented from proto_fuzzer::PingpongMockServer.
Reimplemented in proto_fuzzer::SmtpsMockServer.
Definition at line 80 of file smtp_mock_server.cc.
|
overrideprotectedvirtual |
Advance one reply for every complete command.
A successful DATA reply switches the parser into body-draining mode. The reply that follows DATA is queued immediately: curl's smtp_done() runs a blocking POSTDATA wait inside curl_multi_perform, so the outer peer service loop cannot run after the body has been written. Pre-queuing it, as the FTP peer does for its final transfer reply, keeps that wait deterministic without changing the order curl observes (354 first, then the post-body response).
| command | One newline-terminated command from curl. |
Implements proto_fuzzer::PingpongMockServer.
Definition at line 163 of file smtp_mock_server.cc.
|
overrideprotectedvirtual |
Queue a 221 before the shared transport half-closes.
SMTP's blocking QUIT read has a one-second timeout when no reply is available, so even an unfinished transfer gets a liveness reply; any real scripted response already consumed by curl still determines the transfer result.
Reimplemented from proto_fuzzer::PingpongMockServer.
Definition at line 234 of file smtp_mock_server.cc.
|
overrideprotectedvirtual |
Reset SMTP's recipient bookkeeping for a new drive.
The shared base has already cleared the transport, reply cursor, transcript, upload capture, and any in-flight body phase.
Reimplemented from proto_fuzzer::PingpongMockServer.
Definition at line 85 of file smtp_mock_server.cc.