Skip to main content

net_wire/quic/builder/
mod.rs

1//! Caller-buffer builders for QUIC packets.
2
3use core::fmt;
4
5use super::packet::header::{QuicConnectionIdField, QuicVersion};
6use super::varint::QuicVarIntBuildError;
7
8mod long;
9mod short;
10mod terminal;
11
12/// Identifies a QUIC variable-length integer field during packet construction.
13#[derive(Clone, Copy, Debug, Eq, PartialEq)]
14pub enum QuicPacketBuildField {
15    /// The Initial packet token-length field.
16    TokenLength,
17    /// The protected packet-length field.
18    ProtectedLength,
19}
20
21/// Failure to build a QUIC packet in caller-owned storage.
22#[derive(Clone, Copy, Debug, Eq, PartialEq)]
23pub enum QuicPacketBuildError {
24    /// The supplied unused-bit value exceeds the packet form's maximum.
25    UnusedBitsOutOfRange {
26        /// Greatest permitted unused-bit value.
27        maximum: u8,
28        /// Supplied unused-bit value.
29        actual: u8,
30    },
31    /// The supplied protected-low-bit value exceeds the maximum permitted value.
32    ProtectedLowBitsOutOfRange {
33        /// Greatest permitted protected-low-bit value.
34        maximum: u8,
35        /// Supplied protected-low-bit value.
36        actual: u8,
37    },
38    /// Packet construction supports only QUIC v1 and v2.
39    UnsupportedVersion {
40        /// Supplied raw version.
41        version: QuicVersion,
42    },
43    /// A connection ID cannot be represented by this packet form.
44    ConnectionIdTooLong {
45        /// Connection-ID field that is too long.
46        field: QuicConnectionIdField,
47        /// Greatest permitted byte length.
48        maximum: usize,
49        /// Supplied byte length.
50        actual: usize,
51    },
52    /// A Version Negotiation packet requires at least one advertised version.
53    EmptyVersionList,
54    /// A Retry packet requires at least one token byte.
55    EmptyRetryToken,
56    /// A protected packet remainder is too short to contain a packet number and payload.
57    ProtectedRemainderTooShort {
58        /// Minimum protected remainder byte length.
59        minimum: usize,
60        /// Supplied protected remainder byte length.
61        actual: usize,
62    },
63    /// A packet variable-length field cannot represent its requested value or width.
64    VarInt {
65        /// Field that could not be encoded.
66        field: QuicPacketBuildField,
67        /// Exact variable-integer construction failure.
68        error: QuicVarIntBuildError,
69    },
70    /// Packet-size arithmetic cannot represent an intermediate total.
71    LengthOverflow {
72        /// Named packet-size component being added.
73        component: &'static str,
74        /// Accumulated byte length before adding the component.
75        offset: usize,
76        /// Component byte length.
77        length: usize,
78    },
79    /// The caller buffer cannot contain the complete packet.
80    BufferTooShort {
81        /// Complete packet byte length required.
82        required: usize,
83        /// Bytes available in the caller buffer.
84        available: usize,
85    },
86}
87
88impl fmt::Display for QuicPacketBuildError {
89    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
90        match self {
91            Self::UnusedBitsOutOfRange { maximum, actual } => write!(
92                f,
93                "QUIC unused bits value {actual:#04x} exceeds maximum {maximum:#04x}"
94            ),
95            Self::ProtectedLowBitsOutOfRange { maximum, actual } => write!(
96                f,
97                "QUIC protected low bits value {actual:#04x} exceeds maximum {maximum:#04x}"
98            ),
99            Self::UnsupportedVersion { version } => write!(
100                f,
101                "QUIC packet construction does not support version {:#010x}",
102                version.raw()
103            ),
104            Self::ConnectionIdTooLong {
105                field,
106                maximum,
107                actual,
108            } => write!(
109                f,
110                "QUIC {field:?} connection ID length {actual} exceeds maximum {maximum}"
111            ),
112            Self::EmptyVersionList => write!(
113                f,
114                "QUIC Version Negotiation construction requires a nonempty version list"
115            ),
116            Self::EmptyRetryToken => {
117                write!(f, "QUIC Retry construction requires a nonempty Retry Token")
118            }
119            Self::ProtectedRemainderTooShort { minimum, actual } => write!(
120                f,
121                "QUIC protected packet remainder is too short: need at least {minimum} bytes, have {actual}"
122            ),
123            Self::VarInt { field, error } => {
124                write!(f, "QUIC {field:?} field cannot be encoded: {error}")
125            }
126            Self::LengthOverflow {
127                component,
128                offset,
129                length,
130            } => write!(
131                f,
132                "QUIC packet size overflows while adding {component}: offset {offset} plus length {length}"
133            ),
134            Self::BufferTooShort {
135                required,
136                available,
137            } => write!(
138                f,
139                "QUIC packet destination is too short: need {required} bytes, have {available}"
140            ),
141        }
142    }
143}
144
145pub use long::{QuicHandshakePacketBuilder, QuicInitialPacketBuilder, QuicZeroRttPacketBuilder};
146pub use short::QuicShortPacketBuilder;
147pub use terminal::{QuicRetryPacketBuilder, QuicVersionNegotiationPacketBuilder};