lib/quic/src/connection/model.zig
daab053ee43316e1809a84551d573ddd1e5bf3d2
1 const quic = @import("../root.zig");
2
3 /// Fixes, field by field, how much the connection may retain, so that a caller fills this structure
4 /// once and hands the same value to the capacity, the storage, and the connection. The connection
5 /// asks for nothing more once it is running. `Capacity.derive`, `Storage.init`, and
6 /// `Connection.init` all take the same value, and the connection compares its storage against a
7 /// capacity derived afresh, answering `StorageMismatch` when the two disagree. Derivation turns
8 /// away a zero in any field, a datagram size under 1200 bytes, and a received range count past what
9 /// one ACK frame can hold.
10 pub const Limits = struct {
11 tls_message_max: u16,
12 crypto_buffer_bytes: u20,
13 sent_records: u16,
14 received_ranges: u16,
15 datagram_bytes: u16,
16 /// Decides how much an application can hand over before waiting for the peer by sizing the
17 /// buffer that keeps stream 0 bytes while the peer has yet to acknowledge them. `write` takes
18 /// only what fits the room left there, so this figure bounds one handover. Room returns when
19 /// every earlier byte has been acknowledged, or when a reset abandons what is left.
20 stream_send_bytes: u32,
21 /// Decides both how much arriving data the connection can hold and how much it invites the peer
22 /// to send by sizing the buffer that holds arriving stream 0 bytes until an application reads
23 /// them. The window advertised for stream 0 is the lesser of that buffer and the configured
24 /// stream data limit, so the peer is invited to send only what there is room for.
25 stream_receive_bytes: u32,
26 /// Decides how much reordering the receiving half absorbs before a packet costs the connection
27 /// a round trip by sizing the table that tracks separate stretches of arrived data while the
28 /// holes between them stay unfilled. One packet past that count goes unacknowledged and lifts
29 /// the `drops.stream_ranges` counter, so the peer sends it a second time.
30 stream_receive_ranges: u16,
31 /// Decides how many STREAM frames can be outstanding at one time by sizing the table that keeps
32 /// one entry per STREAM frame until an acknowledgment or a loss resolves it. With every entry
33 /// taken, `nextChunk` offers nothing, so the connection packs no further STREAM frame until one
34 /// entry comes free.
35 stream_sent_ranges: u16,
36 };
37
38 /// Carries the identity, the parameter values, the connection ID, and the random source that one
39 /// handshake draws on. A caller passes this structure as the second argument to `Connection.init`
40 /// so that the handshake receives everything it needs. Its `role` field decides which side of the
41 /// protocol this connection plays, and the whole state machine branches on it. `Connection.init`
42 /// turns away an empty connection ID, one past 20 bytes, and an acknowledgment delay exponent
43 /// above 20. The parameter fields travel to the peer inside the TLS handshake.
44 pub const Config = struct {
45 role: quic.tls.Role,
46 identity: quic.tls.Identity,
47 expected_peer: ?quic.tls.PublicKey,
48 alpn: []const u8,
49 server_name: ?[]const u8,
50 random: quic.tls.Random,
51 local_cid: []const u8,
52 preferred_suite: quic.crypto.Suite = .aes_128_gcm_sha256,
53 max_idle_timeout: u62,
54 ack_delay_exponent: u5,
55 max_ack_delay: u14,
56 initial_max_data: u62,
57 initial_max_stream_data_bidi_local: u62,
58 initial_max_stream_data_bidi_remote: u62,
59 };
60
61 /// Names the five conditions a caller can observe from outside as handshaking, established,
62 /// closing, draining, and closed. `Connection.state` hands this status back so that a caller knows
63 /// whether to keep driving the connection. While a connection is closing or draining, `nextTimeout`
64 /// offers only its close deadline, and a closed one offers nothing. A closing connection works
65 /// through CONNECTION_CLOSE frames and passes over the rest.
66 pub const Status = enum {
67 handshaking,
68 established,
69 closing,
70 draining,
71 closed,
72 };
73
74 /// `Connection.closeReason` hands this structure back to report what ended the connection, and
75 /// whether this endpoint or the peer decided it. The structure carries the numeric code, whether
76 /// that code came from the application, the frame type if one applies, and the reason text. The
77 /// reason text points into the connection's own storage, so it lives as long as that storage does.
78 pub const CloseReason = struct {
79 error_code: u62,
80 application: bool,
81 frame_type: ?u62,
82 reason: []const u8,
83 remote: bool,
84 };
85
86 pub const DropStats = struct {
87 malformed: u64 = 0,
88 unauthenticated: u64 = 0,
89 unsupported: u64 = 0,
90 unavailable_keys: u64 = 0,
91 wrong_connection: u64 = 0,
92 duplicate: u64 = 0,
93 undersized_initial: u64 = 0,
94 oversized: u64 = 0,
95 /// Counts the packets that went unacknowledged because the reassembly table had no room left,
96 /// so a caller learns that the table and the network cost a packet.
97 stream_ranges: u64 = 0,
98 };
99
100 /// Counts the stream and flow control frames that crossed in one direction, carried by `Stats` for
101 /// each direction so that a caller can see which frames moved. The structure has a field for STREAM
102 /// frames and their bytes, for RESET_STREAM and STOP_SENDING, for the three MAX frames, and for the
103 /// three BLOCKED frames.
104 pub const StreamFrameStats = struct {
105 stream_frames: u64 = 0,
106 stream_bytes: u64 = 0,
107 reset_stream: u64 = 0,
108 stop_sending: u64 = 0,
109 max_data: u64 = 0,
110 max_stream_data: u64 = 0,
111 max_streams: u64 = 0,
112 data_blocked: u64 = 0,
113 stream_data_blocked: u64 = 0,
114 streams_blocked: u64 = 0,
115 };
116
117 /// Reports what has happened to stream 0 in both directions, returned by `Connection.streamStats`
118 /// for an open stream so that an application can see how far its data has traveled. The structure
119 /// carries the bytes written, sent, released, received, and read, the final size each side settled
120 /// on, and the codes a reset or a stop carried.
121 pub const StreamStats = struct {
122 bytes_written: u62,
123 bytes_sent: u62,
124 /// Counts the bytes the send buffer has given up, whether an acknowledgment or a reset freed
125 /// them, so an application learns how much of the send buffer has come free for the next
126 /// handover.
127 bytes_released: u62,
128 bytes_received: u62,
129 bytes_read: u62,
130 send_final_size: ?u62,
131 receive_final_size: ?u62,
132 reset_sent_code: ?u62,
133 reset_received_code: ?u62,
134 stop_sending_sent_code: ?u62,
135 };
136
137 /// Counts datagrams, packets, failed authentications, and drops over the life of one connection,
138 /// returned by `Connection.stats` so that a caller sees what the connection did with each datagram.
139 /// Every counter holds at its maximum once it reaches it. The structure nests one frame counter per
140 /// direction and the drop counters.
141 pub const Stats = struct {
142 datagrams_sent: u64 = 0,
143 datagrams_received: u64 = 0,
144 packets_sent: u64 = 0,
145 packets_received: u64 = 0,
146 ack_frames_sent: u64 = 0,
147 handshake_done_sent: u64 = 0,
148 handshake_done_received: u64 = 0,
149 failed_authentications: u64 = 0,
150 /// Counts what loss detection removed, packet by packet and byte by byte, so that a caller
151 /// learns how much loss detection has taken out of the flight.
152 packets_lost: u64 = 0,
153 bytes_lost: u64 = 0,
154 /// Counts the probe deadlines that passed without one, so that a caller learns how often the
155 /// connection had to prod the peer for an acknowledgment.
156 probe_timeouts: u64 = 0,
157 stream_sent: StreamFrameStats = .{},
158 stream_received: StreamFrameStats = .{},
159 drops: DropStats = .{},
160 };
161
162 pub const TransportError = struct {
163 pub const no_error: u62 = 0x00;
164 pub const internal_error: u62 = 0x01;
165 pub const flow_control_error: u62 = 0x03;
166 pub const stream_limit_error: u62 = 0x04;
167 pub const stream_state_error: u62 = 0x05;
168 pub const final_size_error: u62 = 0x06;
169 pub const frame_encoding_error: u62 = 0x07;
170 pub const transport_parameter_error: u62 = 0x08;
171 pub const protocol_violation: u62 = 0x0a;
172 pub const application_error: u62 = 0x0c;
173 pub const crypto_buffer_exceeded: u62 = 0x0d;
174 pub const key_update_error: u62 = 0x0e;
175 pub const aead_limit_reached: u62 = 0x0f;
176 };