use core::fmt;
use super::header::QuicShortHeader;
use super::long::QuicProtectedLongPacket;
const LONG_PRESERVED_MASK: u8 = 0xf0;
const SHORT_PRESERVED_MASK: u8 = 0xe0;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum QuicUnprotectedHeaderError {
PreservedBitsMismatch {
protected_first_byte: u8,
unprotected_first_byte: u8,
preserved_mask: u8,
},
PacketNumberLengthMismatch {
expected: usize,
supplied: usize,
},
ProtectedRemainderTooShort {
required: usize,
available: usize,
},
}
impl fmt::Display for QuicUnprotectedHeaderError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::PreservedBitsMismatch {
protected_first_byte,
unprotected_first_byte,
preserved_mask,
} => write!(
f,
"QUIC protected first byte {protected_first_byte:#04x} and unprotected first byte {unprotected_first_byte:#04x} differ under preserved-bit mask {preserved_mask:#04x}"
),
Self::PacketNumberLengthMismatch { expected, supplied } => write!(
f,
"QUIC unprotected packet-number width mismatch: need {expected} bytes, have {supplied}"
),
Self::ProtectedRemainderTooShort {
required,
available,
} => write!(
f,
"QUIC protected packet remainder is too short for its unprotected packet number: need {required} bytes, have {available}"
),
}
}
}
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum QuicPacketNumberLen {
One,
Two,
Three,
Four,
}
impl QuicPacketNumberLen {
pub const fn byte_len(self) -> usize {
match self {
Self::One => 1,
Self::Two => 2,
Self::Three => 3,
Self::Four => 4,
}
}
const fn from_first_byte(first_byte: u8) -> Self {
match first_byte & 0x03 {
0 => Self::One,
1 => Self::Two,
2 => Self::Three,
_ => Self::Four,
}
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct QuicTruncatedPacketNumber<'a> {
bytes: &'a [u8],
encoded_len: QuicPacketNumberLen,
}
impl<'a> QuicTruncatedPacketNumber<'a> {
const fn new(bytes: &'a [u8], encoded_len: QuicPacketNumberLen) -> Self {
Self { bytes, encoded_len }
}
pub const fn as_bytes(self) -> &'a [u8] {
self.bytes
}
pub const fn encoded_len(self) -> QuicPacketNumberLen {
self.encoded_len
}
pub fn value(self) -> u32 {
self.bytes
.iter()
.fold(0, |value, &byte| (value << 8) | u32::from(byte))
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct QuicUnprotectedLongHeader<'packet, 'unprotected> {
protected_packet: QuicProtectedLongPacket<'packet>,
unprotected_first_byte: u8,
packet_number: QuicTruncatedPacketNumber<'unprotected>,
}
impl<'packet, 'unprotected> QuicUnprotectedLongHeader<'packet, 'unprotected> {
pub fn new(
protected_packet: QuicProtectedLongPacket<'packet>,
unprotected_first_byte: u8,
unprotected_packet_number: &'unprotected [u8],
) -> Result<Self, QuicUnprotectedHeaderError> {
validate(
protected_packet.header().first_byte(),
unprotected_first_byte,
LONG_PRESERVED_MASK,
unprotected_packet_number,
protected_packet.protected_remainder().len(),
)?;
Ok(Self {
protected_packet,
unprotected_first_byte,
packet_number: QuicTruncatedPacketNumber::new(
unprotected_packet_number,
QuicPacketNumberLen::from_first_byte(unprotected_first_byte),
),
})
}
pub const fn protected_packet(self) -> QuicProtectedLongPacket<'packet> {
self.protected_packet
}
pub const fn unprotected_first_byte(self) -> u8 {
self.unprotected_first_byte
}
pub const fn packet_number(self) -> QuicTruncatedPacketNumber<'unprotected> {
self.packet_number
}
pub const fn raw_reserved_bits(self) -> u8 {
(self.unprotected_first_byte >> 2) & 0x03
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct QuicUnprotectedShortHeader<'packet, 'unprotected> {
protected_packet: QuicShortHeader<'packet>,
unprotected_first_byte: u8,
packet_number: QuicTruncatedPacketNumber<'unprotected>,
}
impl<'packet, 'unprotected> QuicUnprotectedShortHeader<'packet, 'unprotected> {
pub fn new(
protected_packet: QuicShortHeader<'packet>,
unprotected_first_byte: u8,
unprotected_packet_number: &'unprotected [u8],
) -> Result<Self, QuicUnprotectedHeaderError> {
validate(
protected_packet.first_byte(),
unprotected_first_byte,
SHORT_PRESERVED_MASK,
unprotected_packet_number,
protected_packet.protected_remainder().len(),
)?;
Ok(Self {
protected_packet,
unprotected_first_byte,
packet_number: QuicTruncatedPacketNumber::new(
unprotected_packet_number,
QuicPacketNumberLen::from_first_byte(unprotected_first_byte),
),
})
}
pub const fn protected_packet(self) -> QuicShortHeader<'packet> {
self.protected_packet
}
pub const fn unprotected_first_byte(self) -> u8 {
self.unprotected_first_byte
}
pub const fn packet_number(self) -> QuicTruncatedPacketNumber<'unprotected> {
self.packet_number
}
pub const fn raw_reserved_bits(self) -> u8 {
(self.unprotected_first_byte >> 3) & 0x03
}
pub const fn spin_bit(self) -> bool {
self.unprotected_first_byte & 0x20 != 0
}
pub const fn key_phase(self) -> bool {
self.unprotected_first_byte & 0x04 != 0
}
}
fn validate(
protected_first_byte: u8,
unprotected_first_byte: u8,
preserved_mask: u8,
unprotected_packet_number: &[u8],
protected_remainder_len: usize,
) -> Result<(), QuicUnprotectedHeaderError> {
if protected_first_byte & preserved_mask != unprotected_first_byte & preserved_mask {
return Err(QuicUnprotectedHeaderError::PreservedBitsMismatch {
protected_first_byte,
unprotected_first_byte,
preserved_mask,
});
}
let expected = QuicPacketNumberLen::from_first_byte(unprotected_first_byte).byte_len();
let supplied = unprotected_packet_number.len();
if supplied != expected {
return Err(QuicUnprotectedHeaderError::PacketNumberLengthMismatch { expected, supplied });
}
if protected_remainder_len < expected {
return Err(QuicUnprotectedHeaderError::ProtectedRemainderTooShort {
required: expected,
available: protected_remainder_len,
});
}
Ok(())
}