Network System 0.1.1
High-performance modular networking library for scalable client-server applications
Loading...
Searching...
No Matches
kcenon::network::protocols::quic::frame_parser Class Reference

Parser for QUIC frames (RFC 9000 Section 12) More...

#include <frame.h>

Collaboration diagram for kcenon::network::protocols::quic::frame_parser:
Collaboration graph

Static Public Member Functions

static auto parse (std::span< const uint8_t > data) -> Result< std::pair< frame, size_t > >
 Parse a single frame from buffer.
 
static auto parse_all (std::span< const uint8_t > data) -> Result< std::vector< frame > >
 Parse all frames from buffer.
 
static auto peek_type (std::span< const uint8_t > data) -> Result< std::pair< uint64_t, size_t > >
 Get the frame type from raw data without full parsing.
 

Static Private Member Functions

static auto parse_padding (std::span< const uint8_t > data) -> Result< std::pair< frame, size_t > >
 
static auto parse_ping (std::span< const uint8_t > data) -> Result< std::pair< frame, size_t > >
 
static auto parse_ack (std::span< const uint8_t > data, bool has_ecn) -> Result< std::pair< frame, size_t > >
 
static auto parse_reset_stream (std::span< const uint8_t > data) -> Result< std::pair< frame, size_t > >
 
static auto parse_stop_sending (std::span< const uint8_t > data) -> Result< std::pair< frame, size_t > >
 
static auto parse_crypto (std::span< const uint8_t > data) -> Result< std::pair< frame, size_t > >
 
static auto parse_new_token (std::span< const uint8_t > data) -> Result< std::pair< frame, size_t > >
 
static auto parse_stream (std::span< const uint8_t > data, uint8_t flags) -> Result< std::pair< frame, size_t > >
 
static auto parse_max_data (std::span< const uint8_t > data) -> Result< std::pair< frame, size_t > >
 
static auto parse_max_stream_data (std::span< const uint8_t > data) -> Result< std::pair< frame, size_t > >
 
static auto parse_max_streams (std::span< const uint8_t > data, bool bidi) -> Result< std::pair< frame, size_t > >
 
static auto parse_data_blocked (std::span< const uint8_t > data) -> Result< std::pair< frame, size_t > >
 
static auto parse_stream_data_blocked (std::span< const uint8_t > data) -> Result< std::pair< frame, size_t > >
 
static auto parse_streams_blocked (std::span< const uint8_t > data, bool bidi) -> Result< std::pair< frame, size_t > >
 
static auto parse_new_connection_id (std::span< const uint8_t > data) -> Result< std::pair< frame, size_t > >
 
static auto parse_retire_connection_id (std::span< const uint8_t > data) -> Result< std::pair< frame, size_t > >
 
static auto parse_path_challenge (std::span< const uint8_t > data) -> Result< std::pair< frame, size_t > >
 
static auto parse_path_response (std::span< const uint8_t > data) -> Result< std::pair< frame, size_t > >
 
static auto parse_connection_close (std::span< const uint8_t > data, bool is_app) -> Result< std::pair< frame, size_t > >
 
static auto parse_handshake_done (std::span< const uint8_t > data) -> Result< std::pair< frame, size_t > >
 

Detailed Description

Parser for QUIC frames (RFC 9000 Section 12)

Parses raw bytes into QUIC frame structures. Handles all frame types defined in RFC 9000 Section 19.

Definition at line 24 of file frame.h.

Member Function Documentation

◆ parse()

auto kcenon::network::protocols::quic::frame_parser::parse ( std::span< const uint8_t > data) -> Result<std::pair<frame, size_t>>
staticnodiscard

Parse a single frame from buffer.

Parameters
dataInput buffer containing frame data
Returns
Result containing (parsed_frame, bytes_consumed) or error

Definition at line 122 of file frame.cpp.

124{
125 if (data.empty())
126 {
127 return make_error<std::pair<frame, size_t>>(
129 "Empty frame data");
130 }
131
132 // Parse frame type
133 auto type_result = varint::decode(data);
134 if (type_result.is_err())
135 {
136 return make_error<std::pair<frame, size_t>>(
138 "Failed to decode frame type");
139 }
140
141 auto [type_value, type_len] = type_result.value();
142 auto remaining = data.subspan(type_len);
143
144 // Check for STREAM frames (0x08-0x0f)
145 if (is_stream_frame(type_value))
146 {
147 auto result = parse_stream(remaining, get_stream_flags(type_value));
148 if (result.is_err()) return result;
149 auto& [f, consumed] = result.value();
150 return ok(std::make_pair(std::move(f), type_len + consumed));
151 }
152
153 // Dispatch based on frame type
154 switch (static_cast<frame_type>(type_value))
155 {
157 return parse_padding(data);
158
159 case frame_type::ping:
160 {
161 auto result = parse_ping(remaining);
162 if (result.is_err()) return result;
163 auto& [f, consumed] = result.value();
164 return ok(std::make_pair(std::move(f), type_len + consumed));
165 }
166
167 case frame_type::ack:
168 {
169 auto result = parse_ack(remaining, false);
170 if (result.is_err()) return result;
171 auto& [f, consumed] = result.value();
172 return ok(std::make_pair(std::move(f), type_len + consumed));
173 }
174
176 {
177 auto result = parse_ack(remaining, true);
178 if (result.is_err()) return result;
179 auto& [f, consumed] = result.value();
180 return ok(std::make_pair(std::move(f), type_len + consumed));
181 }
182
184 {
185 auto result = parse_reset_stream(remaining);
186 if (result.is_err()) return result;
187 auto& [f, consumed] = result.value();
188 return ok(std::make_pair(std::move(f), type_len + consumed));
189 }
190
192 {
193 auto result = parse_stop_sending(remaining);
194 if (result.is_err()) return result;
195 auto& [f, consumed] = result.value();
196 return ok(std::make_pair(std::move(f), type_len + consumed));
197 }
198
200 {
201 auto result = parse_crypto(remaining);
202 if (result.is_err()) return result;
203 auto& [f, consumed] = result.value();
204 return ok(std::make_pair(std::move(f), type_len + consumed));
205 }
206
208 {
209 auto result = parse_new_token(remaining);
210 if (result.is_err()) return result;
211 auto& [f, consumed] = result.value();
212 return ok(std::make_pair(std::move(f), type_len + consumed));
213 }
214
216 {
217 auto result = parse_max_data(remaining);
218 if (result.is_err()) return result;
219 auto& [f, consumed] = result.value();
220 return ok(std::make_pair(std::move(f), type_len + consumed));
221 }
222
224 {
225 auto result = parse_max_stream_data(remaining);
226 if (result.is_err()) return result;
227 auto& [f, consumed] = result.value();
228 return ok(std::make_pair(std::move(f), type_len + consumed));
229 }
230
232 {
233 auto result = parse_max_streams(remaining, true);
234 if (result.is_err()) return result;
235 auto& [f, consumed] = result.value();
236 return ok(std::make_pair(std::move(f), type_len + consumed));
237 }
238
240 {
241 auto result = parse_max_streams(remaining, false);
242 if (result.is_err()) return result;
243 auto& [f, consumed] = result.value();
244 return ok(std::make_pair(std::move(f), type_len + consumed));
245 }
246
248 {
249 auto result = parse_data_blocked(remaining);
250 if (result.is_err()) return result;
251 auto& [f, consumed] = result.value();
252 return ok(std::make_pair(std::move(f), type_len + consumed));
253 }
254
256 {
257 auto result = parse_stream_data_blocked(remaining);
258 if (result.is_err()) return result;
259 auto& [f, consumed] = result.value();
260 return ok(std::make_pair(std::move(f), type_len + consumed));
261 }
262
264 {
265 auto result = parse_streams_blocked(remaining, true);
266 if (result.is_err()) return result;
267 auto& [f, consumed] = result.value();
268 return ok(std::make_pair(std::move(f), type_len + consumed));
269 }
270
272 {
273 auto result = parse_streams_blocked(remaining, false);
274 if (result.is_err()) return result;
275 auto& [f, consumed] = result.value();
276 return ok(std::make_pair(std::move(f), type_len + consumed));
277 }
278
280 {
281 auto result = parse_new_connection_id(remaining);
282 if (result.is_err()) return result;
283 auto& [f, consumed] = result.value();
284 return ok(std::make_pair(std::move(f), type_len + consumed));
285 }
286
288 {
289 auto result = parse_retire_connection_id(remaining);
290 if (result.is_err()) return result;
291 auto& [f, consumed] = result.value();
292 return ok(std::make_pair(std::move(f), type_len + consumed));
293 }
294
296 {
297 auto result = parse_path_challenge(remaining);
298 if (result.is_err()) return result;
299 auto& [f, consumed] = result.value();
300 return ok(std::make_pair(std::move(f), type_len + consumed));
301 }
302
304 {
305 auto result = parse_path_response(remaining);
306 if (result.is_err()) return result;
307 auto& [f, consumed] = result.value();
308 return ok(std::make_pair(std::move(f), type_len + consumed));
309 }
310
312 {
313 auto result = parse_connection_close(remaining, false);
314 if (result.is_err()) return result;
315 auto& [f, consumed] = result.value();
316 return ok(std::make_pair(std::move(f), type_len + consumed));
317 }
318
320 {
321 auto result = parse_connection_close(remaining, true);
322 if (result.is_err()) return result;
323 auto& [f, consumed] = result.value();
324 return ok(std::make_pair(std::move(f), type_len + consumed));
325 }
326
328 {
329 auto result = parse_handshake_done(remaining);
330 if (result.is_err()) return result;
331 auto& [f, consumed] = result.value();
332 return ok(std::make_pair(std::move(f), type_len + consumed));
333 }
334
335 default:
336 return make_error<std::pair<frame, size_t>>(
338 "Unknown frame type",
339 "type=" + std::to_string(type_value));
340 }
341}
static auto parse_connection_close(std::span< const uint8_t > data, bool is_app) -> Result< std::pair< frame, size_t > >
Definition frame.cpp:827
static auto parse_path_response(std::span< const uint8_t > data) -> Result< std::pair< frame, size_t > >
Definition frame.cpp:812
static auto parse_max_stream_data(std::span< const uint8_t > data) -> Result< std::pair< frame, size_t > >
Definition frame.cpp:646
static auto parse_ack(std::span< const uint8_t > data, bool has_ecn) -> Result< std::pair< frame, size_t > >
Definition frame.cpp:394
static auto parse_ping(std::span< const uint8_t > data) -> Result< std::pair< frame, size_t > >
Definition frame.cpp:387
static auto parse_reset_stream(std::span< const uint8_t > data) -> Result< std::pair< frame, size_t > >
Definition frame.cpp:478
static auto parse_data_blocked(std::span< const uint8_t > data) -> Result< std::pair< frame, size_t > >
Definition frame.cpp:681
static auto parse_retire_connection_id(std::span< const uint8_t > data) -> Result< std::pair< frame, size_t > >
Definition frame.cpp:784
static auto parse_max_streams(std::span< const uint8_t > data, bool bidi) -> Result< std::pair< frame, size_t > >
Definition frame.cpp:667
static auto parse_stream_data_blocked(std::span< const uint8_t > data) -> Result< std::pair< frame, size_t > >
Definition frame.cpp:694
static auto parse_stream(std::span< const uint8_t > data, uint8_t flags) -> Result< std::pair< frame, size_t > >
Definition frame.cpp:578
static auto parse_path_challenge(std::span< const uint8_t > data) -> Result< std::pair< frame, size_t > >
Definition frame.cpp:797
static auto parse_padding(std::span< const uint8_t > data) -> Result< std::pair< frame, size_t > >
Definition frame.cpp:367
static auto parse_new_connection_id(std::span< const uint8_t > data) -> Result< std::pair< frame, size_t > >
Definition frame.cpp:729
static auto parse_crypto(std::span< const uint8_t > data) -> Result< std::pair< frame, size_t > >
Definition frame.cpp:526
static auto parse_stop_sending(std::span< const uint8_t > data) -> Result< std::pair< frame, size_t > >
Definition frame.cpp:505
static auto parse_new_token(std::span< const uint8_t > data) -> Result< std::pair< frame, size_t > >
Definition frame.cpp:555
static auto parse_max_data(std::span< const uint8_t > data) -> Result< std::pair< frame, size_t > >
Definition frame.cpp:633
static auto parse_handshake_done(std::span< const uint8_t > data) -> Result< std::pair< frame, size_t > >
Definition frame.cpp:871
static auto parse_streams_blocked(std::span< const uint8_t > data, bool bidi) -> Result< std::pair< frame, size_t > >
Definition frame.cpp:715
static auto decode(std::span< const uint8_t > data) -> Result< std::pair< uint64_t, size_t > >
Decode variable-length integer from buffer.
Definition varint.cpp:146
constexpr auto is_stream_frame(uint64_t type) noexcept -> bool
Check if a frame type value represents a STREAM frame.
Definition frame_types.h:73
frame_type
QUIC frame types as defined in RFC 9000 Section 12.4.
Definition frame_types.h:25
constexpr auto get_stream_flags(uint64_t type) noexcept -> uint8_t
Extract STREAM flags from frame type.
Definition frame_types.h:81
VoidResult ok()

References kcenon::network::protocols::quic::ack, kcenon::network::protocols::quic::ack_ecn, kcenon::network::protocols::quic::connection_close, kcenon::network::protocols::quic::connection_close_app, kcenon::network::protocols::quic::crypto, kcenon::network::protocols::quic::data_blocked, kcenon::network::protocols::quic::varint::decode(), kcenon::network::protocols::quic::get_stream_flags(), kcenon::network::protocols::quic::handshake_done, kcenon::network::error_codes::common_errors::invalid_argument, kcenon::network::protocols::quic::is_stream_frame(), kcenon::network::protocols::quic::max_data, kcenon::network::protocols::quic::max_stream_data, kcenon::network::protocols::quic::max_streams_bidi, kcenon::network::protocols::quic::max_streams_uni, kcenon::network::protocols::quic::new_connection_id, kcenon::network::protocols::quic::new_token, kcenon::network::ok(), kcenon::network::protocols::quic::padding, kcenon::network::protocols::quic::path_challenge, kcenon::network::protocols::quic::path_response, kcenon::network::protocols::quic::ping, kcenon::network::protocols::quic::reset_stream, kcenon::network::protocols::quic::retire_connection_id, kcenon::network::protocols::quic::stop_sending, kcenon::network::protocols::quic::stream_data_blocked, kcenon::network::protocols::quic::streams_blocked_bidi, and kcenon::network::protocols::quic::streams_blocked_uni.

Here is the call graph for this function:

◆ parse_ack()

auto kcenon::network::protocols::quic::frame_parser::parse_ack ( std::span< const uint8_t > data,
bool has_ecn ) -> Result<std::pair<frame, size_t>>
staticnodiscardprivate

Definition at line 394 of file frame.cpp.

396{
397 size_t offset = 0;
398 ack_frame f;
399
400 // Largest Acknowledged
401 auto largest = varint::decode(data.subspan(offset));
402 if (largest.is_err()) return make_error<std::pair<frame, size_t>>(
403 error_codes::common_errors::invalid_argument, "Failed to parse largest acknowledged");
404 f.largest_acknowledged = largest.value().first;
405 offset += largest.value().second;
406
407 // ACK Delay
408 auto delay = varint::decode(data.subspan(offset));
409 if (delay.is_err()) return make_error<std::pair<frame, size_t>>(
410 error_codes::common_errors::invalid_argument, "Failed to parse ack delay");
411 f.ack_delay = delay.value().first;
412 offset += delay.value().second;
413
414 // ACK Range Count
415 auto range_count = varint::decode(data.subspan(offset));
416 if (range_count.is_err()) return make_error<std::pair<frame, size_t>>(
417 error_codes::common_errors::invalid_argument, "Failed to parse ack range count");
418 offset += range_count.value().second;
419
420 // First ACK Range
421 auto first_range = varint::decode(data.subspan(offset));
422 if (first_range.is_err()) return make_error<std::pair<frame, size_t>>(
423 error_codes::common_errors::invalid_argument, "Failed to parse first ack range");
424 offset += first_range.value().second;
425
426 // Keep the first range too: loss detection and build_ack both use
427 // ranges[0] for the range ending at largest_acknowledged.
428 f.ranges.push_back({0, first_range.value().first});
429 // Additional ranges
430 for (uint64_t i = 0; i < range_count.value().first; ++i)
431 {
432 ack_range range;
433
434 auto gap = varint::decode(data.subspan(offset));
435 if (gap.is_err()) return make_error<std::pair<frame, size_t>>(
436 error_codes::common_errors::invalid_argument, "Failed to parse ack gap");
437 range.gap = gap.value().first;
438 offset += gap.value().second;
439
440 auto length = varint::decode(data.subspan(offset));
441 if (length.is_err()) return make_error<std::pair<frame, size_t>>(
442 error_codes::common_errors::invalid_argument, "Failed to parse ack range length");
443 range.length = length.value().first;
444 offset += length.value().second;
445
446 f.ranges.push_back(range);
447 }
448
449 // ECN Counts (if present)
450 if (has_ecn)
451 {
452 ecn_counts ecn;
453
454 auto ect0 = varint::decode(data.subspan(offset));
455 if (ect0.is_err()) return make_error<std::pair<frame, size_t>>(
456 error_codes::common_errors::invalid_argument, "Failed to parse ECT(0) count");
457 ecn.ect0 = ect0.value().first;
458 offset += ect0.value().second;
459
460 auto ect1 = varint::decode(data.subspan(offset));
461 if (ect1.is_err()) return make_error<std::pair<frame, size_t>>(
462 error_codes::common_errors::invalid_argument, "Failed to parse ECT(1) count");
463 ecn.ect1 = ect1.value().first;
464 offset += ect1.value().second;
465
466 auto ecn_ce = varint::decode(data.subspan(offset));
467 if (ecn_ce.is_err()) return make_error<std::pair<frame, size_t>>(
468 error_codes::common_errors::invalid_argument, "Failed to parse ECN-CE count");
469 ecn.ecn_ce = ecn_ce.value().first;
470 offset += ecn_ce.value().second;
471
472 f.ecn = ecn;
473 }
474
475 return ok(std::make_pair(frame{f}, offset));
476}
std::variant< padding_frame, ping_frame, ack_frame, reset_stream_frame, stop_sending_frame, crypto_frame, new_token_frame, stream_frame, max_data_frame, max_stream_data_frame, max_streams_frame, data_blocked_frame, stream_data_blocked_frame, streams_blocked_frame, new_connection_id_frame, retire_connection_id_frame, path_challenge_frame, path_response_frame, connection_close_frame, handshake_done_frame > frame
Variant type holding any QUIC frame.

References kcenon::network::protocols::quic::ack_frame::ack_delay, kcenon::network::protocols::quic::varint::decode(), kcenon::network::protocols::quic::ack_frame::ecn, kcenon::network::protocols::quic::ecn_counts::ecn_ce, kcenon::network::protocols::quic::ecn_ce, kcenon::network::protocols::quic::ecn_counts::ect0, kcenon::network::protocols::quic::ect0, kcenon::network::protocols::quic::ecn_counts::ect1, kcenon::network::protocols::quic::ect1, kcenon::network::protocols::quic::ack_range::gap, kcenon::network::error_codes::common_errors::invalid_argument, kcenon::network::protocols::quic::ack_frame::largest_acknowledged, kcenon::network::protocols::quic::ack_range::length, kcenon::network::ok(), and kcenon::network::protocols::quic::ack_frame::ranges.

Here is the call graph for this function:

◆ parse_all()

auto kcenon::network::protocols::quic::frame_parser::parse_all ( std::span< const uint8_t > data) -> Result<std::vector<frame>>
staticnodiscard

Parse all frames from buffer.

Parameters
dataInput buffer containing one or more frames
Returns
Result containing vector of parsed frames or error

Definition at line 343 of file frame.cpp.

345{
346 std::vector<frame> frames;
347 size_t offset = 0;
348
349 while (offset < data.size())
350 {
351 auto result = parse(data.subspan(offset));
352 if (result.is_err())
353 {
354 return make_error<std::vector<frame>>(
356 "Failed to parse frame at offset " + std::to_string(offset));
357 }
358
359 auto& [f, consumed] = result.value();
360 frames.push_back(std::move(f));
361 offset += consumed;
362 }
363
364 return ok(std::move(frames));
365}
static auto parse(std::span< const uint8_t > data) -> Result< std::pair< frame, size_t > >
Parse a single frame from buffer.
Definition frame.cpp:122

References kcenon::network::error_codes::common_errors::invalid_argument, and kcenon::network::ok().

Referenced by kcenon::network::internal::quic_socket::handle_packet(), and kcenon::network::protocols::quic::connection::process_frames().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ parse_connection_close()

auto kcenon::network::protocols::quic::frame_parser::parse_connection_close ( std::span< const uint8_t > data,
bool is_app ) -> Result<std::pair<frame, size_t>>
staticnodiscardprivate

Definition at line 827 of file frame.cpp.

829{
830 size_t offset = 0;
831 connection_close_frame f;
832 f.is_application_error = is_app;
833
834 // Error Code
835 auto error_code = varint::decode(data.subspan(offset));
836 if (error_code.is_err()) return make_error<std::pair<frame, size_t>>(
837 error_codes::common_errors::invalid_argument, "Failed to parse error code");
838 f.error_code = error_code.value().first;
839 offset += error_code.value().second;
840
841 // Frame Type (transport close only)
842 if (!is_app)
843 {
844 auto frame_type_val = varint::decode(data.subspan(offset));
845 if (frame_type_val.is_err()) return make_error<std::pair<frame, size_t>>(
846 error_codes::common_errors::invalid_argument, "Failed to parse frame type");
847 f.frame_type = frame_type_val.value().first;
848 offset += frame_type_val.value().second;
849 }
850
851 // Reason Phrase Length
852 auto reason_len = varint::decode(data.subspan(offset));
853 if (reason_len.is_err()) return make_error<std::pair<frame, size_t>>(
854 error_codes::common_errors::invalid_argument, "Failed to parse reason phrase length");
855 offset += reason_len.value().second;
856
857 // Reason Phrase
858 if (data.size() - offset < reason_len.value().first)
859 {
860 return make_error<std::pair<frame, size_t>>(
861 error_codes::common_errors::invalid_argument, "Insufficient reason phrase data");
862 }
863
864 f.reason_phrase.assign(reinterpret_cast<const char*>(data.data() + offset),
865 reason_len.value().first);
866 offset += reason_len.value().first;
867
868 return ok(std::make_pair(frame{f}, offset));
869}
error_code
HTTP/2 error codes (RFC 7540 Section 7)
Definition frame.h:471

References kcenon::network::protocols::quic::varint::decode(), kcenon::network::protocols::quic::connection_close_frame::error_code, kcenon::network::protocols::quic::connection_close_frame::frame_type, kcenon::network::error_codes::common_errors::invalid_argument, kcenon::network::protocols::quic::connection_close_frame::is_application_error, kcenon::network::ok(), and kcenon::network::protocols::quic::connection_close_frame::reason_phrase.

Here is the call graph for this function:

◆ parse_crypto()

auto kcenon::network::protocols::quic::frame_parser::parse_crypto ( std::span< const uint8_t > data) -> Result<std::pair<frame, size_t>>
staticnodiscardprivate

Definition at line 526 of file frame.cpp.

528{
529 size_t offset = 0;
530 crypto_frame f;
531
532 auto crypto_offset = varint::decode(data.subspan(offset));
533 if (crypto_offset.is_err()) return make_error<std::pair<frame, size_t>>(
534 error_codes::common_errors::invalid_argument, "Failed to parse crypto offset");
535 f.offset = crypto_offset.value().first;
536 offset += crypto_offset.value().second;
537
538 auto length = varint::decode(data.subspan(offset));
539 if (length.is_err()) return make_error<std::pair<frame, size_t>>(
540 error_codes::common_errors::invalid_argument, "Failed to parse crypto length");
541 offset += length.value().second;
542
543 if (data.size() - offset < length.value().first)
544 {
545 return make_error<std::pair<frame, size_t>>(
546 error_codes::common_errors::invalid_argument, "Insufficient crypto data");
547 }
548
549 f.data.assign(data.begin() + offset, data.begin() + offset + length.value().first);
550 offset += length.value().first;
551
552 return ok(std::make_pair(frame{f}, offset));
553}

References kcenon::network::protocols::quic::crypto_frame::data, kcenon::network::protocols::quic::varint::decode(), kcenon::network::error_codes::common_errors::invalid_argument, kcenon::network::protocols::quic::crypto_frame::offset, and kcenon::network::ok().

Here is the call graph for this function:

◆ parse_data_blocked()

auto kcenon::network::protocols::quic::frame_parser::parse_data_blocked ( std::span< const uint8_t > data) -> Result<std::pair<frame, size_t>>
staticnodiscardprivate

Definition at line 681 of file frame.cpp.

683{
684 data_blocked_frame f;
685
686 auto max_data = varint::decode(data);
687 if (max_data.is_err()) return make_error<std::pair<frame, size_t>>(
688 error_codes::common_errors::invalid_argument, "Failed to parse max data");
689 f.maximum_data = max_data.value().first;
690
691 return ok(std::make_pair(frame{f}, max_data.value().second));
692}

References kcenon::network::protocols::quic::varint::decode(), kcenon::network::error_codes::common_errors::invalid_argument, kcenon::network::protocols::quic::max_data, kcenon::network::protocols::quic::data_blocked_frame::maximum_data, and kcenon::network::ok().

Here is the call graph for this function:

◆ parse_handshake_done()

auto kcenon::network::protocols::quic::frame_parser::parse_handshake_done ( std::span< const uint8_t > data) -> Result<std::pair<frame, size_t>>
staticnodiscardprivate

Definition at line 871 of file frame.cpp.

873{
874 return ok(std::make_pair(frame{handshake_done_frame{}}, size_t{0}));
875}

References kcenon::network::ok().

Here is the call graph for this function:

◆ parse_max_data()

auto kcenon::network::protocols::quic::frame_parser::parse_max_data ( std::span< const uint8_t > data) -> Result<std::pair<frame, size_t>>
staticnodiscardprivate

Definition at line 633 of file frame.cpp.

635{
636 max_data_frame f;
637
638 auto max_data = varint::decode(data);
639 if (max_data.is_err()) return make_error<std::pair<frame, size_t>>(
640 error_codes::common_errors::invalid_argument, "Failed to parse max data");
641 f.maximum_data = max_data.value().first;
642
643 return ok(std::make_pair(frame{f}, max_data.value().second));
644}

References kcenon::network::protocols::quic::varint::decode(), kcenon::network::error_codes::common_errors::invalid_argument, kcenon::network::protocols::quic::max_data, kcenon::network::protocols::quic::max_data_frame::maximum_data, and kcenon::network::ok().

Here is the call graph for this function:

◆ parse_max_stream_data()

auto kcenon::network::protocols::quic::frame_parser::parse_max_stream_data ( std::span< const uint8_t > data) -> Result<std::pair<frame, size_t>>
staticnodiscardprivate

Definition at line 646 of file frame.cpp.

648{
649 size_t offset = 0;
650 max_stream_data_frame f;
651
652 auto stream_id = varint::decode(data.subspan(offset));
653 if (stream_id.is_err()) return make_error<std::pair<frame, size_t>>(
654 error_codes::common_errors::invalid_argument, "Failed to parse stream id");
655 f.stream_id = stream_id.value().first;
656 offset += stream_id.value().second;
657
658 auto max_data = varint::decode(data.subspan(offset));
659 if (max_data.is_err()) return make_error<std::pair<frame, size_t>>(
660 error_codes::common_errors::invalid_argument, "Failed to parse max stream data");
661 f.maximum_stream_data = max_data.value().first;
662 offset += max_data.value().second;
663
664 return ok(std::make_pair(frame{f}, offset));
665}

References kcenon::network::protocols::quic::varint::decode(), kcenon::network::error_codes::common_errors::invalid_argument, kcenon::network::protocols::quic::max_data, kcenon::network::protocols::quic::max_stream_data_frame::maximum_stream_data, kcenon::network::ok(), and kcenon::network::protocols::quic::max_stream_data_frame::stream_id.

Here is the call graph for this function:

◆ parse_max_streams()

auto kcenon::network::protocols::quic::frame_parser::parse_max_streams ( std::span< const uint8_t > data,
bool bidi ) -> Result<std::pair<frame, size_t>>
staticnodiscardprivate

Definition at line 667 of file frame.cpp.

669{
670 max_streams_frame f;
671 f.bidirectional = bidi;
672
673 auto max_streams = varint::decode(data);
674 if (max_streams.is_err()) return make_error<std::pair<frame, size_t>>(
675 error_codes::common_errors::invalid_argument, "Failed to parse max streams");
676 f.maximum_streams = max_streams.value().first;
677
678 return ok(std::make_pair(frame{f}, max_streams.value().second));
679}

References kcenon::network::protocols::quic::max_streams_frame::bidirectional, kcenon::network::protocols::quic::varint::decode(), kcenon::network::error_codes::common_errors::invalid_argument, kcenon::network::protocols::quic::max_streams_frame::maximum_streams, and kcenon::network::ok().

Here is the call graph for this function:

◆ parse_new_connection_id()

auto kcenon::network::protocols::quic::frame_parser::parse_new_connection_id ( std::span< const uint8_t > data) -> Result<std::pair<frame, size_t>>
staticnodiscardprivate

Definition at line 729 of file frame.cpp.

731{
732 size_t offset = 0;
733 new_connection_id_frame f;
734
735 // Sequence Number
736 auto seq = varint::decode(data.subspan(offset));
737 if (seq.is_err()) return make_error<std::pair<frame, size_t>>(
738 error_codes::common_errors::invalid_argument, "Failed to parse sequence number");
739 f.sequence_number = seq.value().first;
740 offset += seq.value().second;
741
742 // Retire Prior To
743 auto retire = varint::decode(data.subspan(offset));
744 if (retire.is_err()) return make_error<std::pair<frame, size_t>>(
745 error_codes::common_errors::invalid_argument, "Failed to parse retire prior to");
746 f.retire_prior_to = retire.value().first;
747 offset += retire.value().second;
748
749 // Connection ID Length (1 byte, not varint)
750 if (data.size() <= offset)
751 {
752 return make_error<std::pair<frame, size_t>>(
753 error_codes::common_errors::invalid_argument, "Missing connection id length");
754 }
755 uint8_t cid_len = data[offset++];
756 if (cid_len > 20)
757 {
758 return make_error<std::pair<frame, size_t>>(
759 error_codes::common_errors::invalid_argument, "Connection ID too long");
760 }
761
762 // Connection ID
763 if (data.size() - offset < cid_len)
764 {
765 return make_error<std::pair<frame, size_t>>(
766 error_codes::common_errors::invalid_argument, "Insufficient connection id data");
767 }
768 f.connection_id.assign(data.begin() + offset, data.begin() + offset + cid_len);
769 offset += cid_len;
770
771 // Stateless Reset Token (16 bytes)
772 if (data.size() - offset < 16)
773 {
774 return make_error<std::pair<frame, size_t>>(
775 error_codes::common_errors::invalid_argument, "Insufficient reset token data");
776 }
777 std::copy(data.begin() + offset, data.begin() + offset + 16,
778 f.stateless_reset_token.begin());
779 offset += 16;
780
781 return ok(std::make_pair(frame{f}, offset));
782}

References kcenon::network::protocols::quic::new_connection_id_frame::connection_id, kcenon::network::protocols::quic::varint::decode(), kcenon::network::error_codes::common_errors::invalid_argument, kcenon::network::ok(), kcenon::network::protocols::quic::new_connection_id_frame::retire_prior_to, kcenon::network::protocols::quic::new_connection_id_frame::sequence_number, and kcenon::network::protocols::quic::new_connection_id_frame::stateless_reset_token.

Here is the call graph for this function:

◆ parse_new_token()

auto kcenon::network::protocols::quic::frame_parser::parse_new_token ( std::span< const uint8_t > data) -> Result<std::pair<frame, size_t>>
staticnodiscardprivate

Definition at line 555 of file frame.cpp.

557{
558 size_t offset = 0;
559 new_token_frame f;
560
561 auto length = varint::decode(data.subspan(offset));
562 if (length.is_err()) return make_error<std::pair<frame, size_t>>(
563 error_codes::common_errors::invalid_argument, "Failed to parse token length");
564 offset += length.value().second;
565
566 if (data.size() - offset < length.value().first)
567 {
568 return make_error<std::pair<frame, size_t>>(
569 error_codes::common_errors::invalid_argument, "Insufficient token data");
570 }
571
572 f.token.assign(data.begin() + offset, data.begin() + offset + length.value().first);
573 offset += length.value().first;
574
575 return ok(std::make_pair(frame{f}, offset));
576}

References kcenon::network::protocols::quic::varint::decode(), kcenon::network::error_codes::common_errors::invalid_argument, kcenon::network::ok(), and kcenon::network::protocols::quic::new_token_frame::token.

Here is the call graph for this function:

◆ parse_padding()

auto kcenon::network::protocols::quic::frame_parser::parse_padding ( std::span< const uint8_t > data) -> Result<std::pair<frame, size_t>>
staticnodiscardprivate

Definition at line 367 of file frame.cpp.

369{
370 // Count consecutive padding bytes
371 size_t count = 0;
372 while (count < data.size() && data[count] == 0x00)
373 {
374 ++count;
375 }
376
377 if (count == 0)
378 {
379 count = 1; // At least one padding byte was consumed (the type)
380 }
381
382 padding_frame f;
383 f.count = count;
384 return ok(std::make_pair(frame{f}, count));
385}

References kcenon::network::protocols::quic::padding_frame::count, and kcenon::network::ok().

Here is the call graph for this function:

◆ parse_path_challenge()

auto kcenon::network::protocols::quic::frame_parser::parse_path_challenge ( std::span< const uint8_t > data) -> Result<std::pair<frame, size_t>>
staticnodiscardprivate

Definition at line 797 of file frame.cpp.

799{
800 if (data.size() < 8)
801 {
802 return make_error<std::pair<frame, size_t>>(
803 error_codes::common_errors::invalid_argument, "Insufficient path challenge data");
804 }
805
806 path_challenge_frame f;
807 std::copy(data.begin(), data.begin() + 8, f.data.begin());
808
809 return ok(std::make_pair(frame{f}, size_t{8}));
810}

References kcenon::network::protocols::quic::path_challenge_frame::data, kcenon::network::error_codes::common_errors::invalid_argument, and kcenon::network::ok().

Here is the call graph for this function:

◆ parse_path_response()

auto kcenon::network::protocols::quic::frame_parser::parse_path_response ( std::span< const uint8_t > data) -> Result<std::pair<frame, size_t>>
staticnodiscardprivate

Definition at line 812 of file frame.cpp.

814{
815 if (data.size() < 8)
816 {
817 return make_error<std::pair<frame, size_t>>(
818 error_codes::common_errors::invalid_argument, "Insufficient path response data");
819 }
820
821 path_response_frame f;
822 std::copy(data.begin(), data.begin() + 8, f.data.begin());
823
824 return ok(std::make_pair(frame{f}, size_t{8}));
825}

References kcenon::network::protocols::quic::path_response_frame::data, kcenon::network::error_codes::common_errors::invalid_argument, and kcenon::network::ok().

Here is the call graph for this function:

◆ parse_ping()

auto kcenon::network::protocols::quic::frame_parser::parse_ping ( std::span< const uint8_t > data) -> Result<std::pair<frame, size_t>>
staticnodiscardprivate

Definition at line 387 of file frame.cpp.

389{
390 // PING frame has no payload after type
391 return ok(std::make_pair(frame{ping_frame{}}, size_t{0}));
392}

References kcenon::network::ok().

Here is the call graph for this function:

◆ parse_reset_stream()

auto kcenon::network::protocols::quic::frame_parser::parse_reset_stream ( std::span< const uint8_t > data) -> Result<std::pair<frame, size_t>>
staticnodiscardprivate

Definition at line 478 of file frame.cpp.

480{
481 size_t offset = 0;
482 reset_stream_frame f;
483
484 auto stream_id = varint::decode(data.subspan(offset));
485 if (stream_id.is_err()) return make_error<std::pair<frame, size_t>>(
486 error_codes::common_errors::invalid_argument, "Failed to parse stream id");
487 f.stream_id = stream_id.value().first;
488 offset += stream_id.value().second;
489
490 auto error_code = varint::decode(data.subspan(offset));
491 if (error_code.is_err()) return make_error<std::pair<frame, size_t>>(
492 error_codes::common_errors::invalid_argument, "Failed to parse error code");
493 f.application_error_code = error_code.value().first;
494 offset += error_code.value().second;
495
496 auto final_size = varint::decode(data.subspan(offset));
497 if (final_size.is_err()) return make_error<std::pair<frame, size_t>>(
498 error_codes::common_errors::invalid_argument, "Failed to parse final size");
499 f.final_size = final_size.value().first;
500 offset += final_size.value().second;
501
502 return ok(std::make_pair(frame{f}, offset));
503}

References kcenon::network::protocols::quic::reset_stream_frame::application_error_code, kcenon::network::protocols::quic::varint::decode(), kcenon::network::protocols::quic::reset_stream_frame::final_size, kcenon::network::error_codes::common_errors::invalid_argument, kcenon::network::ok(), and kcenon::network::protocols::quic::reset_stream_frame::stream_id.

Here is the call graph for this function:

◆ parse_retire_connection_id()

auto kcenon::network::protocols::quic::frame_parser::parse_retire_connection_id ( std::span< const uint8_t > data) -> Result<std::pair<frame, size_t>>
staticnodiscardprivate

Definition at line 784 of file frame.cpp.

786{
787 retire_connection_id_frame f;
788
789 auto seq = varint::decode(data);
790 if (seq.is_err()) return make_error<std::pair<frame, size_t>>(
791 error_codes::common_errors::invalid_argument, "Failed to parse sequence number");
792 f.sequence_number = seq.value().first;
793
794 return ok(std::make_pair(frame{f}, seq.value().second));
795}

References kcenon::network::protocols::quic::varint::decode(), kcenon::network::error_codes::common_errors::invalid_argument, kcenon::network::ok(), and kcenon::network::protocols::quic::retire_connection_id_frame::sequence_number.

Here is the call graph for this function:

◆ parse_stop_sending()

auto kcenon::network::protocols::quic::frame_parser::parse_stop_sending ( std::span< const uint8_t > data) -> Result<std::pair<frame, size_t>>
staticnodiscardprivate

Definition at line 505 of file frame.cpp.

507{
508 size_t offset = 0;
509 stop_sending_frame f;
510
511 auto stream_id = varint::decode(data.subspan(offset));
512 if (stream_id.is_err()) return make_error<std::pair<frame, size_t>>(
513 error_codes::common_errors::invalid_argument, "Failed to parse stream id");
514 f.stream_id = stream_id.value().first;
515 offset += stream_id.value().second;
516
517 auto error_code = varint::decode(data.subspan(offset));
518 if (error_code.is_err()) return make_error<std::pair<frame, size_t>>(
519 error_codes::common_errors::invalid_argument, "Failed to parse error code");
520 f.application_error_code = error_code.value().first;
521 offset += error_code.value().second;
522
523 return ok(std::make_pair(frame{f}, offset));
524}

References kcenon::network::protocols::quic::stop_sending_frame::application_error_code, kcenon::network::protocols::quic::varint::decode(), kcenon::network::error_codes::common_errors::invalid_argument, kcenon::network::ok(), and kcenon::network::protocols::quic::stop_sending_frame::stream_id.

Here is the call graph for this function:

◆ parse_stream()

auto kcenon::network::protocols::quic::frame_parser::parse_stream ( std::span< const uint8_t > data,
uint8_t flags ) -> Result<std::pair<frame, size_t>>
staticnodiscardprivate

Definition at line 578 of file frame.cpp.

580{
581 size_t offset = 0;
582 stream_frame f;
583
584 // Stream ID
585 auto stream_id = varint::decode(data.subspan(offset));
586 if (stream_id.is_err()) return make_error<std::pair<frame, size_t>>(
587 error_codes::common_errors::invalid_argument, "Failed to parse stream id");
588 f.stream_id = stream_id.value().first;
589 offset += stream_id.value().second;
590
591 // Offset (if OFF bit set)
592 if (flags & stream_flags::off)
593 {
594 auto stream_offset = varint::decode(data.subspan(offset));
595 if (stream_offset.is_err()) return make_error<std::pair<frame, size_t>>(
596 error_codes::common_errors::invalid_argument, "Failed to parse stream offset");
597 f.offset = stream_offset.value().first;
598 offset += stream_offset.value().second;
599 }
600
601 // Length (if LEN bit set)
602 uint64_t length = 0;
603 if (flags & stream_flags::len)
604 {
605 auto len_result = varint::decode(data.subspan(offset));
606 if (len_result.is_err()) return make_error<std::pair<frame, size_t>>(
607 error_codes::common_errors::invalid_argument, "Failed to parse stream length");
608 length = len_result.value().first;
609 offset += len_result.value().second;
610 }
611 else
612 {
613 // Without LEN, data extends to end of packet
614 length = data.size() - offset;
615 }
616
617 // FIN bit
618 f.fin = (flags & stream_flags::fin) != 0;
619
620 // Data
621 if (data.size() - offset < length)
622 {
623 return make_error<std::pair<frame, size_t>>(
624 error_codes::common_errors::invalid_argument, "Insufficient stream data");
625 }
626
627 f.data.assign(data.begin() + offset, data.begin() + offset + length);
628 offset += length;
629
630 return ok(std::make_pair(frame{f}, offset));
631}
constexpr uint8_t fin
Stream is finished.
Definition frame_types.h:63
constexpr uint8_t len
Length field present.
Definition frame_types.h:64
constexpr uint8_t off
Offset field present.
Definition frame_types.h:65

References kcenon::network::protocols::quic::stream_frame::data, kcenon::network::protocols::quic::varint::decode(), kcenon::network::protocols::quic::stream_flags::fin, kcenon::network::protocols::quic::stream_frame::fin, kcenon::network::error_codes::common_errors::invalid_argument, kcenon::network::protocols::quic::stream_flags::len, kcenon::network::protocols::quic::stream_flags::off, kcenon::network::protocols::quic::stream_frame::offset, kcenon::network::ok(), and kcenon::network::protocols::quic::stream_frame::stream_id.

Here is the call graph for this function:

◆ parse_stream_data_blocked()

auto kcenon::network::protocols::quic::frame_parser::parse_stream_data_blocked ( std::span< const uint8_t > data) -> Result<std::pair<frame, size_t>>
staticnodiscardprivate

Definition at line 694 of file frame.cpp.

696{
697 size_t offset = 0;
698 stream_data_blocked_frame f;
699
700 auto stream_id = varint::decode(data.subspan(offset));
701 if (stream_id.is_err()) return make_error<std::pair<frame, size_t>>(
702 error_codes::common_errors::invalid_argument, "Failed to parse stream id");
703 f.stream_id = stream_id.value().first;
704 offset += stream_id.value().second;
705
706 auto max_data = varint::decode(data.subspan(offset));
707 if (max_data.is_err()) return make_error<std::pair<frame, size_t>>(
708 error_codes::common_errors::invalid_argument, "Failed to parse max stream data");
709 f.maximum_stream_data = max_data.value().first;
710 offset += max_data.value().second;
711
712 return ok(std::make_pair(frame{f}, offset));
713}

References kcenon::network::protocols::quic::varint::decode(), kcenon::network::error_codes::common_errors::invalid_argument, kcenon::network::protocols::quic::max_data, kcenon::network::protocols::quic::stream_data_blocked_frame::maximum_stream_data, kcenon::network::ok(), and kcenon::network::protocols::quic::stream_data_blocked_frame::stream_id.

Here is the call graph for this function:

◆ parse_streams_blocked()

auto kcenon::network::protocols::quic::frame_parser::parse_streams_blocked ( std::span< const uint8_t > data,
bool bidi ) -> Result<std::pair<frame, size_t>>
staticnodiscardprivate

Definition at line 715 of file frame.cpp.

717{
718 streams_blocked_frame f;
719 f.bidirectional = bidi;
720
721 auto max_streams = varint::decode(data);
722 if (max_streams.is_err()) return make_error<std::pair<frame, size_t>>(
723 error_codes::common_errors::invalid_argument, "Failed to parse max streams");
724 f.maximum_streams = max_streams.value().first;
725
726 return ok(std::make_pair(frame{f}, max_streams.value().second));
727}

References kcenon::network::protocols::quic::streams_blocked_frame::bidirectional, kcenon::network::protocols::quic::varint::decode(), kcenon::network::error_codes::common_errors::invalid_argument, kcenon::network::protocols::quic::streams_blocked_frame::maximum_streams, and kcenon::network::ok().

Here is the call graph for this function:

◆ peek_type()

auto kcenon::network::protocols::quic::frame_parser::peek_type ( std::span< const uint8_t > data) -> Result<std::pair<uint64_t, size_t>>
staticnodiscard

Get the frame type from raw data without full parsing.

Parameters
dataInput buffer
Returns
Result containing (frame_type_value, bytes_consumed) or error

Definition at line 116 of file frame.cpp.

118{
119 return varint::decode(data);
120}

References kcenon::network::protocols::quic::varint::decode().

Here is the call graph for this function:

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