curl-fuzzer C++ reference
Loading...
Searching...
No Matches
mock_server.h
Go to the documentation of this file.
1/*
2 * Copyright (C) Max Dymond, <cmeister2@gmail.com>, et al.
3 *
4 * SPDX-License-Identifier: curl
5 */
6
10
11#ifndef PROTO_FUZZER_MOCK_SERVER_H_
12#define PROTO_FUZZER_MOCK_SERVER_H_
13
14#include <curl/curl.h>
15
16#include <array>
17#include <cstddef>
18#include <memory>
19#include <string>
20#include <vector>
21
22#include "curl_fuzzer.pb.h"
26
27namespace proto_fuzzer {
28
30 public:
32 virtual ~MockConnection();
33
34 MockConnection(const MockConnection&) = delete;
35 MockConnection& operator=(const MockConnection&) = delete;
36
37 virtual bool ok() const;
38 curl_socket_t take_client_fd();
39 int server_fd() const;
40
41 std::size_t client_send_buffer_size() const;
42
43 bool EnsureClientSendBufferSize(std::size_t minimum);
44
46
47 virtual bool WriteAll(const unsigned char* data, std::size_t size);
48 virtual std::size_t DrainIncoming();
50 void ReadAvailable(std::string* out);
51 virtual void ShutdownWrite();
52
53 void ApplyBackpressure(int recv_buf_bytes, std::size_t drain_limit);
54
55 protected:
56 explicit MockConnection(int adopted_server_fd);
57
58 void NotifyIncomingData(const unsigned char* data, std::size_t size);
59
60 private:
61 int server_fd_;
62 int client_fd_;
63 std::size_t drain_limit_;
64 IncomingDataObserver* incoming_data_observer_;
65};
66
72class MockServer : public MockServerBase {
73 public:
75 ~MockServer() override;
76
77 void SetScripts(const curl::fuzzer::proto::Scenario& scenario);
78
79 void SetKeepConnectionsOpen(bool keep_open);
80
81 CURLcode DriveEasyScenario(CURL* easy, const curl::fuzzer::proto::Scenario& scenario,
82 bool use_events = false) override;
83
84 ConnectOnlyRunStats DriveConnectOnlyScenario(CURL* easy, const curl::fuzzer::proto::Scenario& scenario) override;
85
86 bool DeliverNextChunk();
87 bool has_more_chunks() const;
88
89 bool ServiceConnections();
90
91 std::size_t opened_connection_count() const;
92
93 protected:
94 virtual std::unique_ptr<MockConnection> CreateConnection();
95
96 void ResetConnections();
97
98 virtual void ObserveActiveTransfer(CURL* easy);
99
100 // Whether this peer can service repeated zero-timeout public polls.
101 virtual bool SupportsRepeatedPollsetProbe() const;
102
103 curl_socket_t HandleOpenSocket(curlsocktype purpose = CURLSOCKTYPE_IPCXN,
104 struct curl_sockaddr* address = nullptr) override;
105 void RunLoop(CURLM* multi, CURL* easy, const curl::fuzzer::proto::Scenario& scenario) override;
106
107 private:
113 struct ConnectionScript {
114 const curl::fuzzer::proto::Connection* connection = nullptr;
115 std::size_t raw_chunk_count = 0;
116 std::size_t frame_chunk_count = 0;
117 std::size_t next_chunk = 0;
118
120 std::size_t chunk_count() const { return raw_chunk_count + frame_chunk_count; }
121 };
122
123 std::size_t DrainIncomingConnections();
124
125 void RunSocketActionLoop(CURLM* multi, CURL* easy);
126
127 std::array<ConnectionScript, scenario_limits::kMaxConnections> scripts_;
128 std::size_t script_count_;
129 std::size_t next_script_;
130 ConnectionScript* active_script_;
131
135 bool preload_all_chunks_;
136
139 bool keep_connections_open_;
140
145 std::vector<std::unique_ptr<MockConnection>> previous_connections_;
146};
147
148} // namespace proto_fuzzer
149
150#endif // PROTO_FUZZER_MOCK_SERVER_H_
Receives bytes after any transport decoding.
bool EnsureClientSendBufferSize(std::size_t minimum)
Ensure curl's endpoint reports at least minimum bytes of send buffer, requesting a larger SO_SNDBUF w...
virtual bool WriteAll(const unsigned char *data, std::size_t size)
Write 'size' bytes from 'data' to the server fd, looping until the whole buffer is sent or a short/fa...
void ReadAvailable(std::string *out)
Non-blocking read: append whatever bytes are currently available on the server fd to 'out'.
virtual void ShutdownWrite()
Signal end-of-response to libcurl by half-closing the write side.
virtual bool ok() const
void NotifyIncomingData(const unsigned char *data, std::size_t size)
Forward one application-data fragment to the optional observer.
virtual std::size_t DrainIncoming()
Advance incoming transport work according to the configured per-call limit.
void SetIncomingDataObserver(IncomingDataObserver *observer)
Register a non-owning sink for bytes consumed from curl.
MockConnection()
Construct a non-blocking AF_UNIX/SOCK_STREAM socketpair.
std::size_t client_send_buffer_size() const
Query the capacity curl's endpoint reports for queued client writes while this object still owns that...
virtual ~MockConnection()
Close the server-side fd (and the client-side fd if it was never handed off via take_client_fd()).
bool FillClientSendBuffer()
Saturate curl's endpoint before ownership is transferred.
void ApplyBackpressure(int recv_buf_bytes, std::size_t drain_limit)
Apply deterministic backpressure knobs before traffic begins.
curl_socket_t take_client_fd()
Hand the client-side fd to libcurl.
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 soc...
void ResetConnections()
Release all current and retired socketpairs before resetting transport- specific state.
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...
std::size_t opened_connection_count() const
Report how many peer sockets curl opened during the current script run.
bool ServiceConnections()
Service one deterministic application event-loop turn by draining all available request bytes and rel...
~MockServer() override
Default destructor; current and previous MockConnections clean up their server-side descriptors only ...
void SetKeepConnectionsOpen(bool keep_open)
Keep completed response sockets writable instead of half-closing them.
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...
void SetScripts(const curl::fuzzer::proto::Scenario &scenario)
Build the complete borrowed script table before entering curl.
virtual std::unique_ptr< MockConnection > CreateConnection()
Construct the transport used for one HTTP exchange.
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 ...
MockServer(MultiDrivePolicy drive_policy=MultiDrivePolicy::kPerform)
Construct an idle MockServer with no scripted responses or open peers.
curl_socket_t HandleOpenSocket(curlsocktype purpose=CURLSOCKTYPE_IPCXN, struct curl_sockaddr *address=nullptr) override
Called by the OPENSOCKETFUNCTION trampoline in the base class.
bool DeliverNextChunk()
Push the next queued chunk.
Optional observer for application bytes consumed by mock peers.
MockServerBase — common plumbing shared by every protocol-specific mock server.
MultiDrivePolicy
Fixed policy for interpreting a scenario's multi-drive fields.
@ kPerform
Use the ordinary curl_multi_perform loop.
Shared complexity limits for structured scenarios.
Results from the bounded CONNECT_ONLY public-API probe.