curl-fuzzer C++ reference
Loading...
Searching...
No Matches
mqtt_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
9
10#ifndef PROTO_FUZZER_MQTT_MOCK_SERVER_H_
11#define PROTO_FUZZER_MQTT_MOCK_SERVER_H_
12
13#include <curl/curl.h>
14
15#include <cstddef>
16#include <memory>
17#include <string>
18#include <string_view>
19
20#include "curl_fuzzer.pb.h"
24
25namespace proto_fuzzer {
26
57class MqttMockServer : public MockServerBase, public IncomingDataObserver {
58 public:
59 explicit MqttMockServer(curl::fuzzer::proto::MqttProbeMode mode = curl::fuzzer::proto::MQTT_PROBE_DEFAULT);
60
61 ~MqttMockServer() override;
62
63 void ObserveState() override;
64
65 MqttMockServer(const MqttMockServer&) = delete;
66 MqttMockServer& operator=(const MqttMockServer&) = delete;
67
68 // Bounded raw capture of complete client packets, including their fixed
69 // headers. Tests use it to assert CONNECT/CONNECT acknowledgement order
70 // without parsing curl's debug output.
71 const std::string& packet_transcript() const;
72
73 // Bounded topic capture from the first PUBLISH packet.
74 const std::string& published_topic() const;
75
76 // Bounded payload capture from the first PUBLISH packet.
77 const std::string& published_payload() const;
78
79 std::size_t packet_count() const;
80
81 std::size_t connect_count() const;
82
83 std::size_t publish_count() const;
84
85 std::size_t subscribe_count() const;
86
87 // Number of PUBLISH packets whose fixed-header QoS bits requested QoS 1.
88 std::size_t qos1_publish_count() const;
89
90 // Number of requested zero-timeout multi-poll probes made while the most
91 // recent transfer and MQTT socket were both active.
92 std::size_t active_pollset_probe_count() const;
93
94 protected:
95 virtual std::unique_ptr<MockConnection> CreateConnection();
96
97 curl_socket_t HandleOpenSocket(curlsocktype purpose = CURLSOCKTYPE_IPCXN,
98 struct curl_sockaddr* address = nullptr) override;
99
100 void RunLoop(CURLM* multi, CURL* easy, const curl::fuzzer::proto::Scenario& scenario) override;
101
102 void ObserveIncomingData(const unsigned char* data, std::size_t size) override;
103
104 private:
106 enum class ParseResult {
107 kNeedMore,
108 kInvalid,
109 kComplete,
110 };
111
112 // Decode a fixed header whose first byte is already present at offset zero.
113 // Returns complete, need-more-data, or invalid (>4 length bytes).
114 static ParseResult ParseRemainingLength(std::string_view bytes, std::size_t* header_size,
115 std::size_t* remaining_length);
116
117 void ResetForScenario(const curl::fuzzer::proto::Scenario& scenario);
118
119 static void ApplyScriptBackpressure(MockConnection* connection, const curl::fuzzer::proto::Connection& script);
120
121 bool ServiceClientConnection();
122
123 void HandleClientPacket(unsigned char first_byte, std::string_view body);
124
125 bool ReleaseNextServerChunk();
126
127 bool WriteServerBytes(std::string_view bytes);
128
129 static void CapturePrefix(std::string_view source, std::size_t limit, std::string* destination);
130
131 void FinishConnections();
132
133 void ApplyProbeOptions(CURL* easy) const;
134
138 static constexpr std::size_t kMaxPacketBytes = 64 * 1024;
139
141 static constexpr std::size_t kMaxCapturedPacketBytes = 64 * 1024;
142 static constexpr std::size_t kMaxCapturedPayloadBytes = 2 * scenario_limits::kMaxMetadataBytes;
143
147 static constexpr int kMaxPacketsPerService = 16;
148
150 const curl::fuzzer::proto::MqttProbeMode mode_;
151
153 const curl::fuzzer::proto::Scenario* scenario_;
155 std::size_t server_chunk_count_;
157 std::size_t next_server_chunk_;
159 std::size_t packet_count_;
160 std::size_t connect_count_;
161 std::size_t publish_count_;
162 std::size_t subscribe_count_;
163 std::size_t qos1_publish_count_;
165 std::size_t active_pollset_probe_count_;
167 std::string pending_client_bytes_;
169 std::string packet_transcript_;
171 std::string published_topic_;
173 std::string published_payload_;
175 bool release_script_chunks_;
177 bool protocol_error_;
179 bool socket_opened_;
180};
181
182} // namespace proto_fuzzer
183
184#endif // PROTO_FUZZER_MQTT_MOCK_SERVER_H_
Receives bytes after any transport decoding.
Owns one half of a socketpair used to feed canned responses to libcurl.
Definition mock_server.h:29
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 ...
std::size_t packet_count() const
const std::string & published_topic() const
std::size_t qos1_publish_count() const
std::size_t subscribe_count() const
void ObserveIncomingData(const unsigned char *data, std::size_t size) override
Append decoded application bytes to the pending parser buffer.
void ObserveState() override
Retain protocol outcomes in coverage and introspector builds.
std::size_t connect_count() const
virtual std::unique_ptr< MockConnection > CreateConnection()
Create the default plaintext transport for the MQTT packet exchange.
const std::string & packet_transcript() const
curl_socket_t HandleOpenSocket(curlsocktype purpose=CURLSOCKTYPE_IPCXN, struct curl_sockaddr *address=nullptr) override
Create the single MQTT socketpair and queue the scenario's first server bytes.
MqttMockServer(curl::fuzzer::proto::MqttProbeMode mode=curl::fuzzer::proto::MQTT_PROBE_DEFAULT)
Begin without a borrowed protobuf or open socketpair.
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 publish_count() const
const std::string & published_payload() const
~MqttMockServer() override
Release the server-owned socketpair half after curl has returned its client descriptor.
Optional observer for application bytes consumed by mock peers.
MockServerBase — common plumbing shared by every protocol-specific mock server.
Shared complexity limits for structured scenarios.
constexpr std::size_t kMaxMetadataBytes
Metadata reaches NUL-terminated APIs, where giant suffixes add no coverage.