mod ack;
mod connection_close;
mod connection_id;
mod control;
mod crypto;
mod parse;
mod path;
mod stream;
mod token;
pub use ack::{QuicAckFrame, QuicAckRange, QuicAckRanges, QuicEcnCounts};
pub use connection_close::QuicConnectionCloseFrame;
pub use connection_id::{QuicNewConnectionIdFrame, QuicRetireConnectionIdFrame};
pub use control::{
QuicDataBlockedFrame, QuicMaxDataFrame, QuicMaxStreamDataFrame, QuicMaxStreamsFrame,
QuicResetStreamFrame, QuicStopSendingFrame, QuicStreamDataBlockedFrame, QuicStreamDirection,
QuicStreamsBlockedFrame,
};
pub use crypto::QuicCryptoFrame;
pub use parse::{QuicFrameField, QuicFrameParseError};
pub use path::{QuicPathChallengeFrame, QuicPathResponseFrame};
pub use stream::QuicStreamFrame;
pub use token::QuicNewTokenFrame;
use core::iter::FusedIterator;
use super::varint::QuicVarInt;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct QuicPaddingFrame<'a> {
bytes: &'a [u8],
frame_type: QuicVarInt<'a>,
}
impl<'a> QuicPaddingFrame<'a> {
pub const fn as_bytes(self) -> &'a [u8] {
self.bytes
}
pub const fn frame_type(self) -> QuicVarInt<'a> {
self.frame_type
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct QuicPingFrame<'a> {
bytes: &'a [u8],
frame_type: QuicVarInt<'a>,
}
impl<'a> QuicPingFrame<'a> {
pub const fn as_bytes(self) -> &'a [u8] {
self.bytes
}
pub const fn frame_type(self) -> QuicVarInt<'a> {
self.frame_type
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct QuicHandshakeDoneFrame<'a> {
bytes: &'a [u8],
frame_type: QuicVarInt<'a>,
}
impl<'a> QuicHandshakeDoneFrame<'a> {
pub const fn as_bytes(self) -> &'a [u8] {
self.bytes
}
pub const fn frame_type(self) -> QuicVarInt<'a> {
self.frame_type
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum QuicFrame<'a> {
Padding(QuicPaddingFrame<'a>),
Ping(QuicPingFrame<'a>),
Ack(QuicAckFrame<'a>),
NewToken(QuicNewTokenFrame<'a>),
Crypto(QuicCryptoFrame<'a>),
Stream(QuicStreamFrame<'a>),
ResetStream(QuicResetStreamFrame<'a>),
StopSending(QuicStopSendingFrame<'a>),
MaxData(QuicMaxDataFrame<'a>),
MaxStreamData(QuicMaxStreamDataFrame<'a>),
MaxStreams(QuicMaxStreamsFrame<'a>),
DataBlocked(QuicDataBlockedFrame<'a>),
StreamDataBlocked(QuicStreamDataBlockedFrame<'a>),
StreamsBlocked(QuicStreamsBlockedFrame<'a>),
NewConnectionId(QuicNewConnectionIdFrame<'a>),
RetireConnectionId(QuicRetireConnectionIdFrame<'a>),
PathChallenge(QuicPathChallengeFrame<'a>),
PathResponse(QuicPathResponseFrame<'a>),
ConnectionClose(QuicConnectionCloseFrame<'a>),
HandshakeDone(QuicHandshakeDoneFrame<'a>),
}
impl<'a> QuicFrame<'a> {
pub fn parse(bytes: &'a [u8]) -> Result<(Self, &'a [u8]), QuicFrameParseError> {
parse_at(bytes, 0)
}
pub const fn as_bytes(self) -> &'a [u8] {
match self {
Self::Padding(frame) => frame.as_bytes(),
Self::Ping(frame) => frame.as_bytes(),
Self::Ack(frame) => frame.as_bytes(),
Self::NewToken(frame) => frame.as_bytes(),
Self::Crypto(frame) => frame.as_bytes(),
Self::Stream(frame) => frame.as_bytes(),
Self::ResetStream(frame) => frame.as_bytes(),
Self::StopSending(frame) => frame.as_bytes(),
Self::MaxData(frame) => frame.as_bytes(),
Self::MaxStreamData(frame) => frame.as_bytes(),
Self::MaxStreams(frame) => frame.as_bytes(),
Self::DataBlocked(frame) => frame.as_bytes(),
Self::StreamDataBlocked(frame) => frame.as_bytes(),
Self::StreamsBlocked(frame) => frame.as_bytes(),
Self::NewConnectionId(frame) => frame.as_bytes(),
Self::RetireConnectionId(frame) => frame.as_bytes(),
Self::PathChallenge(frame) => frame.as_bytes(),
Self::PathResponse(frame) => frame.as_bytes(),
Self::ConnectionClose(frame) => frame.as_bytes(),
Self::HandshakeDone(frame) => frame.as_bytes(),
}
}
pub const fn frame_type(self) -> QuicVarInt<'a> {
match self {
Self::Padding(frame) => frame.frame_type(),
Self::Ping(frame) => frame.frame_type(),
Self::Ack(frame) => frame.frame_type(),
Self::NewToken(frame) => frame.frame_type(),
Self::Crypto(frame) => frame.frame_type(),
Self::Stream(frame) => frame.frame_type(),
Self::ResetStream(frame) => frame.frame_type(),
Self::StopSending(frame) => frame.frame_type(),
Self::MaxData(frame) => frame.frame_type(),
Self::MaxStreamData(frame) => frame.frame_type(),
Self::MaxStreams(frame) => frame.frame_type(),
Self::DataBlocked(frame) => frame.frame_type(),
Self::StreamDataBlocked(frame) => frame.frame_type(),
Self::StreamsBlocked(frame) => frame.frame_type(),
Self::NewConnectionId(frame) => frame.frame_type(),
Self::RetireConnectionId(frame) => frame.frame_type(),
Self::PathChallenge(frame) => frame.frame_type(),
Self::PathResponse(frame) => frame.frame_type(),
Self::ConnectionClose(frame) => frame.frame_type(),
Self::HandshakeDone(frame) => frame.frame_type(),
}
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct QuicFrames<'a> {
bytes: &'a [u8],
}
impl<'a> QuicFrames<'a> {
pub fn parse(bytes: &'a [u8]) -> Result<Self, QuicFrameParseError> {
if bytes.is_empty() {
return Err(QuicFrameParseError::EmptySequence);
}
for frame in QuicFrameIter::new(bytes) {
frame?;
}
Ok(Self { bytes })
}
pub const fn as_bytes(self) -> &'a [u8] {
self.bytes
}
pub const fn iter(self) -> QuicFrameIter<'a> {
QuicFrameIter::new(self.bytes)
}
}
#[derive(Clone, Debug)]
pub struct QuicFrameIter<'a> {
remaining: &'a [u8],
offset: usize,
failed: bool,
}
impl<'a> QuicFrameIter<'a> {
pub const fn new(bytes: &'a [u8]) -> Self {
Self {
remaining: bytes,
offset: 0,
failed: false,
}
}
}
impl<'a> Iterator for QuicFrameIter<'a> {
type Item = Result<QuicFrame<'a>, QuicFrameParseError>;
fn next(&mut self) -> Option<Self::Item> {
if self.failed || self.remaining.is_empty() {
return None;
}
match parse_at(self.remaining, self.offset) {
Ok((frame, suffix)) => {
let consumed = frame.as_bytes().len();
self.remaining = suffix;
self.offset += consumed;
Some(Ok(frame))
}
Err(error) => {
self.failed = true;
self.remaining = &[];
Some(Err(error))
}
}
}
}
impl FusedIterator for QuicFrameIter<'_> {}
fn parse_at<'a>(
bytes: &'a [u8],
offset: usize,
) -> Result<(QuicFrame<'a>, &'a [u8]), QuicFrameParseError> {
let frame_type = QuicVarInt::parse(bytes)
.map_err(|error| QuicFrameParseError::FrameType { offset, error })?;
let frame_len = frame_type.byte_len();
let frame_bytes = &bytes[..frame_len];
let suffix = &bytes[frame_len..];
match frame_type.value() {
0 => Ok((
QuicFrame::Padding(QuicPaddingFrame {
bytes: frame_bytes,
frame_type,
}),
suffix,
)),
1 => Ok((
QuicFrame::Ping(QuicPingFrame {
bytes: frame_bytes,
frame_type,
}),
suffix,
)),
2 | 3 => ack::parse_ack(bytes, frame_type, offset)
.map(|(frame, suffix)| (QuicFrame::Ack(frame), suffix)),
7 => token::parse_new_token(bytes, frame_type, offset)
.map(|(frame, suffix)| (QuicFrame::NewToken(frame), suffix)),
6 => crypto::parse_crypto(bytes, frame_type, offset)
.map(|(frame, suffix)| (QuicFrame::Crypto(frame), suffix)),
0x08..=0x0f => stream::parse_stream(bytes, frame_type, offset)
.map(|(frame, suffix)| (QuicFrame::Stream(frame), suffix)),
4 => control::parse_reset_stream(bytes, frame_type, offset)
.map(|(frame, suffix)| (QuicFrame::ResetStream(frame), suffix)),
5 => control::parse_stop_sending(bytes, frame_type, offset)
.map(|(frame, suffix)| (QuicFrame::StopSending(frame), suffix)),
0x10 => control::parse_max_data(bytes, frame_type, offset)
.map(|(frame, suffix)| (QuicFrame::MaxData(frame), suffix)),
0x11 => control::parse_max_stream_data(bytes, frame_type, offset)
.map(|(frame, suffix)| (QuicFrame::MaxStreamData(frame), suffix)),
0x12 => control::parse_max_streams(
bytes,
frame_type,
offset,
QuicStreamDirection::Bidirectional,
)
.map(|(frame, suffix)| (QuicFrame::MaxStreams(frame), suffix)),
0x13 => control::parse_max_streams(
bytes,
frame_type,
offset,
QuicStreamDirection::Unidirectional,
)
.map(|(frame, suffix)| (QuicFrame::MaxStreams(frame), suffix)),
0x14 => control::parse_data_blocked(bytes, frame_type, offset)
.map(|(frame, suffix)| (QuicFrame::DataBlocked(frame), suffix)),
0x15 => control::parse_stream_data_blocked(bytes, frame_type, offset)
.map(|(frame, suffix)| (QuicFrame::StreamDataBlocked(frame), suffix)),
0x16 => control::parse_streams_blocked(
bytes,
frame_type,
offset,
QuicStreamDirection::Bidirectional,
)
.map(|(frame, suffix)| (QuicFrame::StreamsBlocked(frame), suffix)),
0x17 => control::parse_streams_blocked(
bytes,
frame_type,
offset,
QuicStreamDirection::Unidirectional,
)
.map(|(frame, suffix)| (QuicFrame::StreamsBlocked(frame), suffix)),
0x18 => connection_id::parse_new_connection_id(bytes, frame_type, offset)
.map(|(frame, suffix)| (QuicFrame::NewConnectionId(frame), suffix)),
0x19 => connection_id::parse_retire_connection_id(bytes, frame_type, offset)
.map(|(frame, suffix)| (QuicFrame::RetireConnectionId(frame), suffix)),
0x1a => path::parse_path_challenge(bytes, frame_type, offset)
.map(|(frame, suffix)| (QuicFrame::PathChallenge(frame), suffix)),
0x1b => path::parse_path_response(bytes, frame_type, offset)
.map(|(frame, suffix)| (QuicFrame::PathResponse(frame), suffix)),
0x1c | 0x1d => connection_close::parse_connection_close(bytes, frame_type, offset)
.map(|(frame, suffix)| (QuicFrame::ConnectionClose(frame), suffix)),
0x1e => Ok((
QuicFrame::HandshakeDone(QuicHandshakeDoneFrame {
bytes: frame_bytes,
frame_type,
}),
suffix,
)),
value => Err(QuicFrameParseError::UnsupportedFrameType {
value,
length: frame_type.encoded_len(),
offset,
}),
}
}