Network System 0.1.1
High-performance modular networking library for scalable client-server applications
Loading...
Searching...
No Matches
stream.h
Go to the documentation of this file.
1// BSD 3-Clause License
2// Copyright (c) 2024, 🍀☀🌕🌥 🌊
3// See the LICENSE file in the project root for full license information.
4
5#pragma once
6
7#include "frame_types.h"
9
10#include <cstdint>
11#include <deque>
12#include <map>
13#include <mutex>
14#include <optional>
15#include <span>
16#include <vector>
17
19{
20
34namespace stream_id_type
35{
36 constexpr uint64_t client_bidi = 0x00;
37 constexpr uint64_t server_bidi = 0x01;
38 constexpr uint64_t client_uni = 0x02;
39 constexpr uint64_t server_uni = 0x03;
40
44 [[nodiscard]] constexpr auto is_client_initiated(uint64_t stream_id) noexcept -> bool
45 {
46 return (stream_id & 0x01) == 0;
47 }
48
52 [[nodiscard]] constexpr auto is_server_initiated(uint64_t stream_id) noexcept -> bool
53 {
54 return (stream_id & 0x01) == 1;
55 }
56
60 [[nodiscard]] constexpr auto is_bidirectional(uint64_t stream_id) noexcept -> bool
61 {
62 return (stream_id & 0x02) == 0;
63 }
64
68 [[nodiscard]] constexpr auto is_unidirectional(uint64_t stream_id) noexcept -> bool
69 {
70 return (stream_id & 0x02) != 0;
71 }
72
76 [[nodiscard]] constexpr auto get_type(uint64_t stream_id) noexcept -> uint64_t
77 {
78 return stream_id & 0x03;
79 }
80
84 [[nodiscard]] constexpr auto get_sequence(uint64_t stream_id) noexcept -> uint64_t
85 {
86 return stream_id >> 2;
87 }
88
92 [[nodiscard]] constexpr auto make_stream_id(uint64_t type, uint64_t sequence) noexcept -> uint64_t
93 {
94 return (sequence << 2) | (type & 0x03);
95 }
96} // namespace stream_id_type
97
102{
103 ready,
104 send,
105 data_sent,
106 reset_sent,
108 data_recvd,
109};
110
115{
116 recv,
117 size_known,
118 data_recvd,
120 data_read,
121 reset_read,
122};
123
127namespace stream_error
128{
129 constexpr int invalid_stream_id = -700;
130 constexpr int stream_not_found = -701;
131 constexpr int stream_limit_exceeded = -702;
132 constexpr int flow_control_error = -703;
133 constexpr int final_size_error = -704;
134 constexpr int stream_state_error = -705;
135 constexpr int stream_reset = -706;
136 constexpr int buffer_full = -707;
137} // namespace stream_error
138
147{
148public:
155 explicit stream(uint64_t id, bool is_local, uint64_t initial_max_data = 65536);
156
157 ~stream() = default;
158
159 // Non-copyable
160 stream(const stream&) = delete;
161 auto operator=(const stream&) -> stream& = delete;
162
163 // Movable
164 stream(stream&&) noexcept = default;
165 auto operator=(stream&&) noexcept -> stream& = default;
166
167 // ========================================================================
168 // Stream Properties
169 // ========================================================================
170
174 [[nodiscard]] auto id() const noexcept -> uint64_t { return id_; }
175
179 [[nodiscard]] auto is_local() const noexcept -> bool { return is_local_; }
180
184 [[nodiscard]] auto is_unidirectional() const noexcept -> bool
185 {
187 }
188
192 [[nodiscard]] auto is_bidirectional() const noexcept -> bool
193 {
195 }
196
197 // ========================================================================
198 // Send Side
199 // ========================================================================
200
204 [[nodiscard]] auto send_state() const noexcept -> send_stream_state { return send_state_; }
205
209 [[nodiscard]] auto can_send() const noexcept -> bool;
210
216 [[nodiscard]] auto write(std::span<const uint8_t> data) -> Result<size_t>;
217
222 [[nodiscard]] auto finish() -> VoidResult;
223
229 [[nodiscard]] auto reset(uint64_t error_code) -> VoidResult;
230
234 [[nodiscard]] auto fin_sent() const noexcept -> bool { return fin_sent_; }
235
239 [[nodiscard]] auto pending_bytes() const noexcept -> size_t { return send_buffer_.size(); }
240
246 [[nodiscard]] auto next_stream_frame(size_t max_size) -> std::optional<stream_frame>;
247
253 void acknowledge_data(uint64_t offset, uint64_t length);
254
255 // ========================================================================
256 // Receive Side
257 // ========================================================================
258
262 [[nodiscard]] auto recv_state() const noexcept -> recv_stream_state { return recv_state_; }
263
267 [[nodiscard]] auto has_data() const noexcept -> bool;
268
274 [[nodiscard]] auto read(std::span<uint8_t> buffer) -> Result<size_t>;
275
279 [[nodiscard]] auto is_fin_received() const noexcept -> bool { return recv_fin_; }
280
286 [[nodiscard]] auto stop_sending(uint64_t error_code) -> VoidResult;
287
295 [[nodiscard]] auto receive_data(uint64_t offset, std::span<const uint8_t> data, bool fin)
296 -> VoidResult;
297
304 [[nodiscard]] auto receive_reset(uint64_t error_code, uint64_t final_size) -> VoidResult;
305
311 [[nodiscard]] auto receive_stop_sending(uint64_t error_code) -> VoidResult;
312
313 // ========================================================================
314 // Flow Control
315 // ========================================================================
316
321 void set_max_send_data(uint64_t max);
322
326 [[nodiscard]] auto max_send_data() const noexcept -> uint64_t { return max_send_offset_; }
327
331 [[nodiscard]] auto available_send_window() const noexcept -> size_t;
332
337 void set_max_recv_data(uint64_t max);
338
342 [[nodiscard]] auto max_recv_data() const noexcept -> uint64_t { return max_recv_offset_; }
343
347 [[nodiscard]] auto bytes_consumed() const noexcept -> uint64_t { return recv_offset_; }
348
352 [[nodiscard]] auto should_send_max_stream_data() const noexcept -> bool;
353
358 [[nodiscard]] auto generate_max_stream_data() -> std::optional<uint64_t>;
359
360 // ========================================================================
361 // Error Information
362 // ========================================================================
363
367 [[nodiscard]] auto reset_error_code() const noexcept -> std::optional<uint64_t>
368 {
369 return reset_error_code_;
370 }
371
375 [[nodiscard]] auto stop_sending_error_code() const noexcept -> std::optional<uint64_t>
376 {
378 }
379
380private:
381 uint64_t id_;
383
384 // Send state
386 std::deque<uint8_t> send_buffer_;
387 uint64_t send_offset_{0}; // Next byte to send
388 uint64_t acked_offset_{0}; // Highest contiguously acknowledged
389 bool fin_sent_{false};
390 bool fin_acked_{false};
391
392 // Receive state
394 std::map<uint64_t, std::vector<uint8_t>> recv_buffer_; // offset -> data (for gaps)
395 std::deque<uint8_t> recv_ready_; // Contiguous data ready for reading
396 uint64_t recv_offset_{0}; // Next expected offset
397 bool recv_fin_{false};
398 std::optional<uint64_t> final_size_;
399
400 // Flow control - send
401 uint64_t max_send_offset_{0}; // Peer's MAX_STREAM_DATA
402
403 // Flow control - receive
404 uint64_t max_recv_offset_{65536}; // Our MAX_STREAM_DATA
405 uint64_t recv_window_size_{65536};
406 static constexpr double window_update_threshold_{0.5};
407
408 // Error codes
409 std::optional<uint64_t> reset_error_code_;
410 std::optional<uint64_t> stop_sending_error_code_;
411
412 // Internal helpers
413 void reassemble_data();
414 void update_send_state();
415 void update_recv_state();
416};
417
421[[nodiscard]] auto send_state_to_string(send_stream_state state) -> const char*;
422
426[[nodiscard]] auto recv_state_to_string(recv_stream_state state) -> const char*;
427
428} // namespace kcenon::network::protocols::quic
QUIC stream implementation (RFC 9000 Sections 2-4)
Definition stream.h:147
auto should_send_max_stream_data() const noexcept -> bool
Check if MAX_STREAM_DATA frame should be sent.
Definition stream.cpp:381
auto finish() -> VoidResult
Mark stream as finished (send FIN)
Definition stream.cpp:76
std::optional< uint64_t > final_size_
Definition stream.h:398
auto stop_sending_error_code() const noexcept -> std::optional< uint64_t >
Get stop sending error code (if STOP_SENDING received)
Definition stream.h:375
auto send_state() const noexcept -> send_stream_state
Get send state.
Definition stream.h:204
auto generate_max_stream_data() -> std::optional< uint64_t >
Generate MAX_STREAM_DATA frame if needed.
Definition stream.cpp:391
auto receive_reset(uint64_t error_code, uint64_t final_size) -> VoidResult
Handle received RESET_STREAM frame.
Definition stream.cpp:316
stream(stream &&) noexcept=default
auto is_local() const noexcept -> bool
Check if stream is locally initiated.
Definition stream.h:179
void set_max_recv_data(uint64_t max)
Update our MAX_STREAM_DATA (peer's send limit)
Definition stream.cpp:374
auto is_unidirectional() const noexcept -> bool
Check if stream is unidirectional.
Definition stream.h:184
auto is_fin_received() const noexcept -> bool
Check if all data has been received.
Definition stream.h:279
std::map< uint64_t, std::vector< uint8_t > > recv_buffer_
Definition stream.h:394
auto receive_data(uint64_t offset, std::span< const uint8_t > data, bool fin) -> VoidResult
Receive STREAM frame data.
Definition stream.cpp:243
auto has_data() const noexcept -> bool
Check if stream has data to read.
Definition stream.cpp:189
auto can_send() const noexcept -> bool
Check if stream can send data.
Definition stream.cpp:26
stream(uint64_t id, bool is_local, uint64_t initial_max_data=65536)
Construct a stream.
Definition stream.cpp:13
auto max_send_data() const noexcept -> uint64_t
Get peer's MAX_STREAM_DATA.
Definition stream.h:326
auto write(std::span< const uint8_t > data) -> Result< size_t >
Write data to stream.
Definition stream.cpp:42
void set_max_send_data(uint64_t max)
Set peer's MAX_STREAM_DATA (our send limit)
Definition stream.cpp:358
auto reset(uint64_t error_code) -> VoidResult
Reset the stream with error code.
Definition stream.cpp:95
auto available_send_window() const noexcept -> size_t
Get available send window.
Definition stream.cpp:365
auto recv_state() const noexcept -> recv_stream_state
Get receive state.
Definition stream.h:262
std::optional< uint64_t > stop_sending_error_code_
Definition stream.h:410
std::deque< uint8_t > recv_ready_
Definition stream.h:395
auto operator=(const stream &) -> stream &=delete
auto reset_error_code() const noexcept -> std::optional< uint64_t >
Get reset error code (if stream was reset)
Definition stream.h:367
void acknowledge_data(uint64_t offset, uint64_t length)
Acknowledge sent data.
Definition stream.cpp:169
auto max_recv_data() const noexcept -> uint64_t
Get our MAX_STREAM_DATA.
Definition stream.h:342
auto fin_sent() const noexcept -> bool
Check if FIN has been sent.
Definition stream.h:234
auto pending_bytes() const noexcept -> size_t
Get number of bytes pending to send.
Definition stream.h:239
std::deque< uint8_t > send_buffer_
Definition stream.h:386
static constexpr double window_update_threshold_
Definition stream.h:406
auto bytes_consumed() const noexcept -> uint64_t
Get bytes consumed from receive buffer.
Definition stream.h:347
std::optional< uint64_t > reset_error_code_
Definition stream.h:409
auto is_bidirectional() const noexcept -> bool
Check if stream is bidirectional.
Definition stream.h:192
auto next_stream_frame(size_t max_size) -> std::optional< stream_frame >
Get next STREAM frame to send.
Definition stream.cpp:111
auto receive_stop_sending(uint64_t error_code) -> VoidResult
Handle received STOP_SENDING frame.
Definition stream.cpp:341
auto read(std::span< uint8_t > buffer) -> Result< size_t >
Read data from stream.
Definition stream.cpp:194
constexpr auto is_unidirectional(uint64_t stream_id) noexcept -> bool
Check if stream is unidirectional.
Definition stream.h:68
constexpr auto is_server_initiated(uint64_t stream_id) noexcept -> bool
Check if stream is server-initiated.
Definition stream.h:52
constexpr auto is_bidirectional(uint64_t stream_id) noexcept -> bool
Check if stream is bidirectional.
Definition stream.h:60
constexpr auto is_client_initiated(uint64_t stream_id) noexcept -> bool
Check if stream is client-initiated.
Definition stream.h:44
constexpr auto get_type(uint64_t stream_id) noexcept -> uint64_t
Get stream type bits (0-3)
Definition stream.h:76
constexpr auto make_stream_id(uint64_t type, uint64_t sequence) noexcept -> uint64_t
Make stream ID from type and sequence number.
Definition stream.h:92
constexpr auto get_sequence(uint64_t stream_id) noexcept -> uint64_t
Get stream sequence number (stream_id >> 2)
Definition stream.h:84
auto recv_state_to_string(recv_stream_state state) -> const char *
Get string representation of receive stream state.
Definition stream.cpp:498
recv_stream_state
Stream state for receiving (RFC 9000 Section 3.2)
Definition stream.h:115
@ size_known
FIN received, final size known.
@ data_read
All data read by application (terminal)
@ reset_read
Reset acknowledged by application (terminal)
auto send_state_to_string(send_stream_state state) -> const char *
Get string representation of send stream state.
Definition stream.cpp:485
send_stream_state
Stream state for sending (RFC 9000 Section 3.1)
Definition stream.h:102
@ reset_recvd
Reset acknowledged by peer (terminal)
@ data_recvd
All data acknowledged (terminal)
Result< std::monostate > VoidResult
Network-specific error and result type definitions.