use bytes::Bytes;
use crate::codec;
use crate::codec::Decoder;
use crate::codec::Encoder;
use crate::error::Error;
use crate::packet::PacketType;
#[cfg(feature = "qlog")]
use crate::qlog;
#[cfg(feature = "qlog")]
use crate::qlog::events::ErrorSpace;
#[cfg(feature = "qlog")]
use crate::qlog::events::QuicFrame;
#[cfg(feature = "qlog")]
use crate::qlog::events::StreamType;
use crate::ranges::RangeSet;
use crate::token::ResetToken;
use crate::ConnectionId;
use crate::Result;
pub(crate) const MAX_STREAM_SIZE: u64 = 1 << 62;
pub(crate) const MAX_CRYPTO_OVERHEAD: usize = 8;
pub(crate) const MAX_STREAM_OVERHEAD: usize = 19;
#[derive(Clone, PartialEq, Eq)]
pub enum Frame {
Paddings { len: usize },
Ping { pmtu_probe: Option<(usize, usize)> },
Ack {
ack_delay: u64,
ack_ranges: RangeSet,
ecn_counts: Option<EcnCounts>,
},
ResetStream {
stream_id: u64,
error_code: u64,
final_size: u64,
},
StopSending { stream_id: u64, error_code: u64 },
Crypto {
offset: u64,
length: usize,
data: Bytes,
},
NewToken { token: Vec<u8> },
Stream {
stream_id: u64,
offset: u64,
length: usize,
fin: bool,
data: Bytes,
},
MaxData { max: u64 },
MaxStreamData { stream_id: u64, max: u64 },
MaxStreams { bidi: bool, max: u64 },
DataBlocked { max: u64 },
StreamDataBlocked { stream_id: u64, max: u64 },
StreamsBlocked { bidi: bool, max: u64 },
NewConnectionId {
seq_num: u64,
retire_prior_to: u64,
conn_id: ConnectionId,
reset_token: ResetToken,
},
RetireConnectionId { seq_num: u64 },
PathChallenge { data: [u8; 8] },
PathResponse { data: [u8; 8] },
ConnectionClose {
error_code: u64,
frame_type: u64,
reason: Vec<u8>,
},
ApplicationClose { error_code: u64, reason: Vec<u8> },
HandshakeDone,
PathAbandon {
dcid_seq_num: u64,
error_code: u64,
reason: Vec<u8>,
},
PathStatus {
dcid_seq_num: u64,
seq_num: u64,
status: u64,
},
}
impl Frame {
pub fn from_bytes(buf: &mut bytes::Bytes, pkt: PacketType) -> Result<(Frame, usize)> {
let mut b = buf.as_ref();
let len = b.len();
let frame_type = b.read_varint()?;
let frame = match frame_type {
0x00 => {
let mut len = 1;
while !b.is_empty() && b[0] == 0x00 {
b.read_u8()?;
len += 1;
}
Frame::Paddings { len }
}
0x01 => Frame::Ping { pmtu_probe: None },
0x02..=0x03 => {
let (frame, len) = parse_ack_frame(frame_type, b)?;
b.skip(len)?;
frame
}
0x04 => Frame::ResetStream {
stream_id: b.read_varint()?,
error_code: b.read_varint()?,
final_size: b.read_varint()?,
},
0x05 => Frame::StopSending {
stream_id: b.read_varint()?,
error_code: b.read_varint()?,
},
0x06 => {
let offset = b.read_varint()?;
let length = b.read_varint()? as usize;
if length > b.len() {
return Err(Error::BufferTooShort);
}
let start = buf.len() - b.len();
let data = buf.slice(start..(start + length));
b.skip(length)?;
Frame::Crypto {
offset,
length,
data,
}
}
0x07 => Frame::NewToken {
token: b.read_with_varint_length()?.to_vec(),
},
0x08..=0x0f => {
let first = frame_type as u8;
let stream_id = b.read_varint()?;
let offset = if first & 0x04 != 0 {
b.read_varint()?
} else {
0
};
let length = if first & 0x02 != 0 {
b.read_varint()? as usize
} else {
b.len()
};
if offset + length as u64 >= MAX_STREAM_SIZE {
return Err(Error::FrameEncodingError);
}
let fin = first & 0x01 != 0;
if length > b.len() {
return Err(Error::BufferTooShort);
}
let start = buf.len() - b.len();
let data = buf.slice(start..(start + length));
b.skip(length)?;
Frame::Stream {
stream_id,
offset,
length,
fin,
data,
}
}
0x10 => Frame::MaxData {
max: b.read_varint()?,
},
0x11 => Frame::MaxStreamData {
stream_id: b.read_varint()?,
max: b.read_varint()?,
},
0x12 => Frame::MaxStreams {
bidi: true,
max: b.read_varint()?,
},
0x13 => Frame::MaxStreams {
bidi: false,
max: b.read_varint()?,
},
0x14 => Frame::DataBlocked {
max: b.read_varint()?,
},
0x15 => Frame::StreamDataBlocked {
stream_id: b.read_varint()?,
max: b.read_varint()?,
},
0x16 => Frame::StreamsBlocked {
bidi: true,
max: b.read_varint()?,
},
0x17 => Frame::StreamsBlocked {
bidi: false,
max: b.read_varint()?,
},
0x18 => {
let seq_num = b.read_varint()?;
let retire_prior_to = b.read_varint()?;
let cid = b.read_with_u8_length()?;
Frame::NewConnectionId {
seq_num,
retire_prior_to,
conn_id: ConnectionId::new(&cid),
reset_token: ResetToken(
b.read(16)?.try_into().map_err(|_| Error::BufferTooShort)?,
),
}
}
0x19 => Frame::RetireConnectionId {
seq_num: b.read_varint()?,
},
0x1a => Frame::PathChallenge {
data: b.read(8)?.try_into().map_err(|_| Error::BufferTooShort)?,
},
0x1b => Frame::PathResponse {
data: b.read(8)?.try_into().map_err(|_| Error::BufferTooShort)?,
},
0x1c => Frame::ConnectionClose {
error_code: b.read_varint()?,
frame_type: b.read_varint()?,
reason: b.read_with_varint_length()?.to_vec(),
},
0x1d => Frame::ApplicationClose {
error_code: b.read_varint()?,
reason: b.read_with_varint_length()?.to_vec(),
},
0x1e => Frame::HandshakeDone,
0x15228c05 => Frame::PathAbandon {
dcid_seq_num: b.read_varint()?,
error_code: b.read_varint()?,
reason: b.read_with_varint_length()?.to_vec(),
},
0x15228c06 => Frame::PathStatus {
dcid_seq_num: b.read_varint()?,
seq_num: b.read_varint()?,
status: b.read_varint()?,
},
_ => return Err(Error::FrameEncodingError),
};
if !Frame::validate_frame(pkt, &frame) {
return Err(Error::InvalidPacket);
}
Ok((frame, len - b.len()))
}
fn validate_frame(pkt_type: PacketType, frame: &Frame) -> bool {
match (pkt_type, &frame) {
(_, Frame::Paddings { .. }) | (_, Frame::Ping { .. }) => true,
(PacketType::ZeroRTT, Frame::Ack { .. }) => false,
(PacketType::ZeroRTT, Frame::Crypto { .. }) => false,
(PacketType::ZeroRTT, Frame::HandshakeDone) => false,
(PacketType::ZeroRTT, Frame::NewToken { .. }) => false,
(PacketType::ZeroRTT, Frame::PathResponse { .. }) => false,
(PacketType::ZeroRTT, Frame::RetireConnectionId { .. }) => false,
(PacketType::ZeroRTT, Frame::ConnectionClose { .. }) => false,
(_, Frame::Ack { .. }) => true,
(_, Frame::Crypto { .. }) => true,
(_, Frame::ConnectionClose { .. }) => true,
(PacketType::OneRTT, _) => true,
(PacketType::ZeroRTT, _) => true,
(..) => false,
}
}
pub fn to_bytes(&self, mut b: &mut [u8]) -> Result<usize> {
let len = b.len();
match self {
Frame::Paddings { len } => {
let mut left = *len;
while left > 0 {
b.write_varint(0x00)?;
left -= 1;
}
}
Frame::Ping { .. } => {
b.write_varint(0x01)?;
}
Frame::Ack {
ack_delay,
ack_ranges,
ecn_counts,
} => {
if ecn_counts.is_none() {
b.write_varint(0x02)?;
} else {
b.write_varint(0x03)?;
}
let mut it = ack_ranges.iter().rev();
let first = it.next().unwrap();
let ack_range_len = (first.end - 1) - first.start;
b.write_varint(first.end - 1)?;
b.write_varint(*ack_delay)?;
b.write_varint(it.len() as u64)?;
b.write_varint(ack_range_len)?;
let mut smallest_ack = first.start;
for ack_range in it {
let gap = smallest_ack - ack_range.end - 1;
let ack_range_len = (ack_range.end - 1) - ack_range.start;
b.write_varint(gap)?;
b.write_varint(ack_range_len)?;
smallest_ack = ack_range.start;
}
if let Some(ecn) = ecn_counts {
b.write_varint(ecn.ect0_count)?;
b.write_varint(ecn.ect1_count)?;
b.write_varint(ecn.ecn_ce_count)?;
}
}
Frame::ResetStream {
stream_id,
error_code,
final_size,
} => {
b.write_varint(0x04)?;
b.write_varint(*stream_id)?;
b.write_varint(*error_code)?;
b.write_varint(*final_size)?;
}
Frame::StopSending {
stream_id,
error_code,
} => {
b.write_varint(0x05)?;
b.write_varint(*stream_id)?;
b.write_varint(*error_code)?;
}
Frame::Crypto {
offset,
length,
data,
} => {
let written = encode_crypto_header(*offset, *length as u64, b)?;
b = &mut b[written..];
b.write(data.as_ref())?;
}
Frame::NewToken { token } => {
b.write_varint(0x07)?;
b.write_varint(token.len() as u64)?;
b.write(token)?;
}
Frame::Stream {
stream_id,
offset,
length,
fin,
data,
} => {
let written = encode_stream_header(*stream_id, *offset, *length as u64, *fin, b)?;
b = &mut b[written..];
b.write(data.as_ref())?;
}
Frame::MaxData { max } => {
b.write_varint(0x10)?;
b.write_varint(*max)?;
}
Frame::MaxStreamData { stream_id, max } => {
b.write_varint(0x11)?;
b.write_varint(*stream_id)?;
b.write_varint(*max)?;
}
Frame::MaxStreams { bidi, max } => {
let t = if *bidi { 0x12 } else { 0x13 };
b.write_varint(t)?;
b.write_varint(*max)?;
}
Frame::DataBlocked { max } => {
b.write_varint(0x14)?;
b.write_varint(*max)?;
}
Frame::StreamDataBlocked { stream_id, max } => {
b.write_varint(0x15)?;
b.write_varint(*stream_id)?;
b.write_varint(*max)?;
}
Frame::StreamsBlocked { bidi, max } => {
let t = if *bidi { 0x16 } else { 0x17 };
b.write_varint(t)?;
b.write_varint(*max)?;
}
Frame::NewConnectionId {
seq_num,
retire_prior_to,
conn_id,
reset_token,
} => {
b.write_varint(0x18)?;
b.write_varint(*seq_num)?;
b.write_varint(*retire_prior_to)?;
b.write_u8(conn_id.len() as u8)?;
b.write(conn_id.as_ref())?;
b.write(reset_token.as_ref())?;
}
Frame::RetireConnectionId { seq_num } => {
b.write_varint(0x19)?;
b.write_varint(*seq_num)?;
}
Frame::PathChallenge { data } => {
b.write_varint(0x1a)?;
b.write(data.as_ref())?;
}
Frame::PathResponse { data } => {
b.write_varint(0x1b)?;
b.write(data.as_ref())?;
}
Frame::ConnectionClose {
error_code,
frame_type,
reason,
} => {
b.write_varint(0x1c)?;
b.write_varint(*error_code)?;
b.write_varint(*frame_type)?;
b.write_varint(reason.len() as u64)?;
b.write(reason.as_ref())?;
}
Frame::ApplicationClose { error_code, reason } => {
b.write_varint(0x1d)?;
b.write_varint(*error_code)?;
b.write_varint(reason.len() as u64)?;
b.write(reason.as_ref())?;
}
Frame::HandshakeDone => {
b.write_varint(0x1e)?;
}
Frame::PathAbandon {
dcid_seq_num,
error_code,
reason,
} => {
b.write_varint(0x15228c05)?;
b.write_varint(*dcid_seq_num)?;
b.write_varint(*error_code)?;
b.write_varint(reason.len() as u64)?;
b.write(reason.as_ref())?;
}
Frame::PathStatus {
dcid_seq_num,
seq_num,
status,
} => {
b.write_varint(0x15228c06)?;
b.write_varint(*dcid_seq_num)?;
b.write_varint(*seq_num)?;
b.write_varint(*status)?;
}
}
Ok(len - b.len())
}
pub fn wire_len(&self) -> usize {
match self {
Frame::Paddings { len } => *len,
Frame::Ping { .. } => 1,
Frame::Ack {
ack_delay,
ack_ranges,
ecn_counts,
} => {
let mut it = ack_ranges.iter().rev();
let first = it.next().unwrap();
let ack_block = (first.end - 1) - first.start;
let mut len = 1
+ codec::encode_varint_len(first.end - 1)
+ codec::encode_varint_len(*ack_delay)
+ codec::encode_varint_len(it.len() as u64)
+ codec::encode_varint_len(ack_block);
let mut smallest_ack = first.start;
for block in it {
let gap = smallest_ack - block.end - 1;
let ack_block = (block.end - 1) - block.start;
len += codec::encode_varint_len(gap) + codec::encode_varint_len(ack_block);
smallest_ack = block.start;
}
if let Some(ecn) = ecn_counts {
len += codec::encode_varint_len(ecn.ect0_count)
+ codec::encode_varint_len(ecn.ect1_count)
+ codec::encode_varint_len(ecn.ecn_ce_count);
}
len
}
Frame::ResetStream {
stream_id,
error_code,
final_size,
} => {
1 + codec::encode_varint_len(*stream_id)
+ codec::encode_varint_len(*error_code)
+ codec::encode_varint_len(*final_size)
}
Frame::StopSending {
stream_id,
error_code,
} => 1 + codec::encode_varint_len(*stream_id) + codec::encode_varint_len(*error_code),
Frame::Crypto { offset, data, .. } => {
1 + codec::encode_varint_len(*offset) + 2 + data.len()
}
Frame::NewToken { token } => {
1 + codec::encode_varint_len(token.len() as u64) + token.len()
}
Frame::Stream {
stream_id,
offset,
data,
..
} => {
1 + codec::encode_varint_len(*stream_id)
+ codec::encode_varint_len(*offset)
+ 2
+ data.len()
}
Frame::MaxData { max } => 1 + codec::encode_varint_len(*max),
Frame::MaxStreamData { stream_id, max } => {
1 + codec::encode_varint_len(*stream_id) + codec::encode_varint_len(*max)
}
Frame::MaxStreams { max, .. } => 1 + codec::encode_varint_len(*max),
Frame::DataBlocked { max } => 1 + codec::encode_varint_len(*max),
Frame::StreamDataBlocked { stream_id, max } => {
1 + codec::encode_varint_len(*stream_id) + codec::encode_varint_len(*max)
}
Frame::StreamsBlocked { max, .. } => 1 + codec::encode_varint_len(*max),
Frame::NewConnectionId {
seq_num,
retire_prior_to,
conn_id,
reset_token,
} => {
1 + codec::encode_varint_len(*seq_num)
+ codec::encode_varint_len(*retire_prior_to)
+ 1
+ conn_id.len()
+ reset_token.as_ref().len()
}
Frame::RetireConnectionId { seq_num } => 1 + codec::encode_varint_len(*seq_num),
Frame::PathChallenge { .. } => 1 + 8,
Frame::PathResponse { .. } => 1 + 8,
Frame::ConnectionClose {
frame_type,
error_code,
reason,
..
} => {
1 + codec::encode_varint_len(*error_code)
+ codec::encode_varint_len(*frame_type)
+ codec::encode_varint_len(reason.len() as u64)
+ reason.len()
}
Frame::ApplicationClose { reason, error_code } => {
1 + codec::encode_varint_len(*error_code)
+ codec::encode_varint_len(reason.len() as u64)
+ reason.len()
}
Frame::HandshakeDone => 1,
Frame::PathAbandon {
dcid_seq_num,
error_code,
reason,
..
} => {
4 + codec::encode_varint_len(*dcid_seq_num)
+ codec::encode_varint_len(*error_code)
+ codec::encode_varint_len(reason.len() as u64)
+ reason.len()
}
Frame::PathStatus {
dcid_seq_num,
seq_num,
status,
..
} => {
4 + codec::encode_varint_len(*dcid_seq_num)
+ codec::encode_varint_len(*seq_num)
+ codec::encode_varint_len(*status)
}
}
}
#[cfg(feature = "qlog")]
pub fn to_qlog(&self) -> QuicFrame {
match self {
Frame::Paddings { .. } => QuicFrame::Padding,
Frame::Ping { .. } => QuicFrame::Ping,
Frame::Ack {
ack_delay,
ack_ranges,
ecn_counts,
} => {
let ack_delay = *ack_delay as f32 / 1000.0;
let ack_ranges = qlog::events::AckedRanges::Double(
ack_ranges.iter().map(|r| (r.start, r.end - 1)).collect(),
);
let (ect0, ect1, ce) = match ecn_counts {
Some(ecn) => (
Some(ecn.ect0_count),
Some(ecn.ect1_count),
Some(ecn.ecn_ce_count),
),
None => (None, None, None),
};
QuicFrame::Ack {
ack_delay: Some(ack_delay),
acked_ranges: Some(ack_ranges),
ect1,
ect0,
ce,
}
}
Frame::ResetStream {
stream_id,
error_code,
final_size,
} => QuicFrame::ResetStream {
stream_id: *stream_id,
error_code: *error_code,
final_size: *final_size,
},
Frame::StopSending {
stream_id,
error_code,
} => QuicFrame::StopSending {
stream_id: *stream_id,
error_code: *error_code,
},
Frame::Crypto { offset, length, .. } => QuicFrame::Crypto {
offset: *offset,
length: *length as u64,
},
Frame::NewToken { .. } => QuicFrame::NewToken {
token: qlog::events::Token {
token_type: Some(qlog::events::TokenType::Resumption),
raw: None,
details: None,
},
},
Frame::Stream {
stream_id,
offset,
length,
fin,
..
} => QuicFrame::Stream {
stream_id: *stream_id,
offset: *offset,
length: *length as u64,
fin: Some(*fin),
raw: None,
},
Frame::MaxData { max } => QuicFrame::MaxData { maximum: *max },
Frame::MaxStreamData { stream_id, max } => QuicFrame::MaxStreamData {
stream_id: *stream_id,
maximum: *max,
},
Frame::MaxStreams { bidi, max } => QuicFrame::MaxStreams {
stream_type: if *bidi {
StreamType::Bidirectional
} else {
StreamType::Unidirectional
},
maximum: *max,
},
Frame::DataBlocked { max } => QuicFrame::DataBlocked { limit: *max },
Frame::StreamDataBlocked { stream_id, max } => QuicFrame::StreamDataBlocked {
stream_id: *stream_id,
limit: *max,
},
Frame::StreamsBlocked { bidi, max } => QuicFrame::StreamsBlocked {
stream_type: if *bidi {
StreamType::Bidirectional
} else {
StreamType::Unidirectional
},
limit: *max,
},
Frame::NewConnectionId {
seq_num,
retire_prior_to,
conn_id,
reset_token,
} => QuicFrame::NewConnectionId {
sequence_number: *seq_num as u32,
retire_prior_to: *retire_prior_to as u32,
connection_id_length: Some(conn_id.len() as u8),
connection_id: format!("{:?}", conn_id),
stateless_reset_token: Some(format!("{:?}", reset_token)),
},
Frame::RetireConnectionId { seq_num } => QuicFrame::RetireConnectionId {
sequence_number: *seq_num as u32,
},
Frame::PathChallenge { .. } => QuicFrame::PathChallenge { data: None },
Frame::PathResponse { .. } => QuicFrame::PathResponse { data: None },
Frame::ConnectionClose {
error_code, reason, ..
} => QuicFrame::ConnectionClose {
error_space: Some(ErrorSpace::TransportError),
error_code: Some(*error_code),
error_code_value: None,
reason: Some(String::from_utf8(reason.clone()).unwrap()),
trigger_frame_type: None,
},
Frame::ApplicationClose { error_code, reason } => QuicFrame::ConnectionClose {
error_space: Some(qlog::events::ErrorSpace::ApplicationError),
error_code: Some(*error_code),
error_code_value: None,
reason: Some(String::from_utf8(reason.clone()).unwrap()),
trigger_frame_type: None,
},
Frame::HandshakeDone => QuicFrame::HandshakeDone,
Frame::PathAbandon { .. } => QuicFrame::Unknown {
raw_frame_type: 0x15228c05,
frame_type_value: None,
raw: None,
},
Frame::PathStatus { .. } => QuicFrame::Unknown {
raw_frame_type: 0x15228c06,
frame_type_value: None,
raw: None,
},
}
}
pub fn ack_eliciting(&self) -> bool {
!matches!(
self,
Frame::Paddings { .. }
| Frame::Ack { .. }
| Frame::ApplicationClose { .. }
| Frame::ConnectionClose { .. }
)
}
pub fn probing(&self) -> bool {
matches!(
self,
Frame::Paddings { .. }
| Frame::NewConnectionId { .. }
| Frame::PathChallenge { .. }
| Frame::PathResponse { .. }
)
}
}
impl std::fmt::Debug for Frame {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
Frame::Paddings { len } => {
write!(f, "PADDINGS len={len}")?;
}
Frame::Ping { .. } => {
write!(f, "PING")?;
}
Frame::Ack {
ack_delay,
ack_ranges,
ecn_counts,
} => {
write!(
f,
"ACK delay={ack_delay} ranges={ack_ranges:?} ecn_counts={ecn_counts:?}"
)?;
}
Frame::ResetStream {
stream_id,
error_code,
final_size,
} => {
write!(
f,
"RESET_STREAM id={stream_id} err={error_code:x} size={final_size}"
)?;
}
Frame::StopSending {
stream_id,
error_code,
} => {
write!(f, "STOP_SENDING id={stream_id} err={error_code:x}")?;
}
Frame::Crypto { offset, length, .. } => {
write!(f, "CRYPTO off={} len={}", offset, length)?;
}
Frame::NewToken { .. } => {
write!(f, "NEW_TOKEN")?;
}
Frame::Stream {
stream_id,
offset,
length,
fin,
..
} => {
write!(
f,
"STREAM id={} off={} len={} fin={}",
stream_id, offset, length, fin
)?;
}
Frame::MaxData { max } => {
write!(f, "MAX_DATA max={max}")?;
}
Frame::MaxStreamData { stream_id, max } => {
write!(f, "MAX_STREAM_DATA id={stream_id} max={max}")?;
}
Frame::MaxStreams { bidi, max } => {
write!(f, "MAX_STREAMS bidi={bidi} max={max}")?;
}
Frame::DataBlocked { max } => {
write!(f, "DATA_BLOCKED max={max}")?;
}
Frame::StreamDataBlocked { stream_id, max } => {
write!(f, "STREAM_DATA_BLOCKED id={stream_id} max={max}")?;
}
Frame::StreamsBlocked { bidi, max } => {
write!(f, "STREAMS_BLOCKED bidi={bidi} max={max}")?;
}
Frame::NewConnectionId {
seq_num,
retire_prior_to,
conn_id,
reset_token,
} => {
write!(
f,
"NEW_CONNECTION_ID seq={seq_num} retire_prior_to={retire_prior_to} \
cid={conn_id:02x?} reset_token={reset_token:?}",
)?;
}
Frame::RetireConnectionId { seq_num } => {
write!(f, "RETIRE_CONNECTION_ID seq={seq_num}")?;
}
Frame::PathChallenge { data } => {
write!(f, "PATH_CHALLENGE data={data:02x?}")?;
}
Frame::PathResponse { data } => {
write!(f, "PATH_RESPONSE data={data:02x?}")?;
}
Frame::ConnectionClose {
error_code,
frame_type,
reason,
} => {
write!(
f,
"CONNECTION_CLOSE err={error_code:x} frame={frame_type:x} reason={reason:x?}"
)?;
}
Frame::ApplicationClose { error_code, reason } => {
write!(f, "APPLICATION_CLOSE err={error_code:x} reason={reason:x?}")?;
}
Frame::HandshakeDone => {
write!(f, "HANDSHAKE_DONE")?;
}
Frame::PathAbandon {
dcid_seq_num,
error_code,
reason,
} => {
write!(
f,
"PATH_ABANDON dcid_seq_num={dcid_seq_num:x} err={error_code:x} reason={reason:x?}",
)?;
}
Frame::PathStatus {
dcid_seq_num,
seq_num,
status,
} => {
write!(
f,
"PATH_STATUS dcid_seq_num={dcid_seq_num:x} seq_num={seq_num:x} status={status:x}",
)?;
}
}
Ok(())
}
}
pub fn crypto_header_wire_len(offset: u64) -> usize {
1 + codec::encode_varint_len(offset) + 2
}
pub fn encode_crypto_header(offset: u64, length: u64, mut b: &mut [u8]) -> Result<usize> {
let len = b.len();
b.write_varint(0x06)?;
b.write_varint(offset)?;
b.write_varint_with_len(length, 2)?;
Ok(len - b.len())
}
pub fn stream_header_wire_len(stream_id: u64, offset: u64) -> usize {
1 + codec::encode_varint_len(stream_id) + codec::encode_varint_len(offset) + 2
}
pub fn encode_stream_header(
stream_id: u64,
offset: u64,
length: u64,
fin: bool,
mut b: &mut [u8],
) -> Result<usize> {
let len = b.len();
let mut frame_type: u8 = 0b00001110; if fin {
frame_type |= 0x01;
}
b.write_varint(u64::from(frame_type))?;
b.write_varint(stream_id)?;
b.write_varint(offset)?;
b.write_varint_with_len(length, 2)?;
Ok(len - b.len())
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct EcnCounts {
ect0_count: u64,
ect1_count: u64,
ecn_ce_count: u64,
}
fn parse_ack_frame(frame_type: u64, mut b: &[u8]) -> Result<(Frame, usize)> {
let len = b.len();
let mut ack_ranges = RangeSet::default();
let first = frame_type as u8;
let largest_ack = b.read_varint()?;
let ack_delay = b.read_varint()?;
let range_count = b.read_varint()?;
let ack_range_len = b.read_varint()?;
if largest_ack < ack_range_len {
return Err(Error::FrameEncodingError);
}
let mut smallest_ack = largest_ack - ack_range_len;
ack_ranges.insert(smallest_ack..largest_ack + 1);
for _i in 0..range_count {
let gap = b.read_varint()?;
if smallest_ack < 2 + gap {
return Err(Error::FrameEncodingError);
}
let largest_ack = (smallest_ack - gap) - 2;
let ack_range_len = b.read_varint()?;
if largest_ack < ack_range_len {
return Err(Error::FrameEncodingError);
}
smallest_ack = largest_ack - ack_range_len;
ack_ranges.insert(smallest_ack..largest_ack + 1);
}
let ecn_counts = if first & 0x01 != 0 {
Some(EcnCounts {
ect0_count: b.read_varint()?,
ect1_count: b.read_varint()?,
ecn_ce_count: b.read_varint()?,
})
} else {
None
};
Ok((
Frame::Ack {
ack_delay,
ack_ranges,
ecn_counts,
},
len - b.len(),
))
}
#[cfg(test)]
mod tests {
use super::*;
use bytes::BytesMut;
#[test]
fn paddings() -> Result<()> {
let frame = Frame::Paddings { len: 128 };
assert_eq!(format!("{:?}", &frame), "PADDINGS len=128");
let mut buf = [0; 128];
let len = frame.to_bytes(&mut buf[..])?;
assert_eq!(len, frame.wire_len());
assert_eq!(len, 128);
let mut buf = Bytes::copy_from_slice(&buf);
assert_eq!(
(frame, 128),
Frame::from_bytes(&mut buf, PacketType::OneRTT)?
);
assert!(Frame::from_bytes(&mut buf, PacketType::Initial).is_ok());
assert!(Frame::from_bytes(&mut buf, PacketType::Handshake).is_ok());
assert!(Frame::from_bytes(&mut buf, PacketType::ZeroRTT).is_ok());
Ok(())
}
#[test]
fn ping() -> Result<()> {
let frame = Frame::Ping { pmtu_probe: None };
assert_eq!(format!("{:?}", &frame), "PING");
let mut buf = [0; 128];
let len = frame.to_bytes(&mut buf[..])?;
assert_eq!(len, frame.wire_len());
assert_eq!(len, 1);
assert_eq!(&buf[..len], [0x01]);
let mut buf = Bytes::copy_from_slice(&buf);
assert_eq!((frame, 1), Frame::from_bytes(&mut buf, PacketType::OneRTT)?);
assert!(Frame::from_bytes(&mut buf, PacketType::Initial).is_ok());
assert!(Frame::from_bytes(&mut buf, PacketType::Handshake).is_ok());
assert!(Frame::from_bytes(&mut buf, PacketType::ZeroRTT).is_ok());
Ok(())
}
#[test]
fn ack() -> Result<()> {
let mut ranges = RangeSet::default();
ranges.insert(0..8);
ranges.insert(10..15);
ranges.insert(21..30);
let frame = Frame::Ack {
ack_delay: 200000,
ack_ranges: ranges,
ecn_counts: Some(EcnCounts {
ect0_count: 1,
ect1_count: 2,
ecn_ce_count: 3,
}),
};
assert_eq!(
format!("{:?}", &frame),
"ACK delay=200000 \
ranges=[0..7, 10..14, 21..29] \
ecn_counts=Some(EcnCounts \
{ ect0_count: 1, ect1_count: 2, ecn_ce_count: 3 })"
);
let mut buf = [0; 128];
let len = frame.to_bytes(&mut buf[..])?;
assert_eq!(len, frame.wire_len());
assert_eq!(len, 15);
let mut buf = Bytes::copy_from_slice(&buf);
assert_eq!(
(frame, 15),
Frame::from_bytes(&mut buf, PacketType::OneRTT)?
);
assert!(Frame::from_bytes(&mut buf, PacketType::Initial).is_ok());
assert!(Frame::from_bytes(&mut buf, PacketType::Handshake).is_ok());
assert!(Frame::from_bytes(&mut buf, PacketType::ZeroRTT).is_err());
Ok(())
}
#[test]
fn reset_stream() -> Result<()> {
let frame = Frame::ResetStream {
stream_id: 120,
error_code: 3,
final_size: 4192,
};
assert_eq!(
format!("{:?}", &frame),
"RESET_STREAM id=120 err=3 size=4192"
);
let mut buf = [0; 128];
let len = frame.to_bytes(&mut buf[..])?;
assert_eq!(len, frame.wire_len());
assert_eq!(len, 6);
let mut buf = Bytes::copy_from_slice(&buf);
assert_eq!((frame, 6), Frame::from_bytes(&mut buf, PacketType::OneRTT)?);
assert!(Frame::from_bytes(&mut buf, PacketType::ZeroRTT).is_ok());
assert!(Frame::from_bytes(&mut buf, PacketType::Initial).is_err());
assert!(Frame::from_bytes(&mut buf, PacketType::Handshake).is_err());
Ok(())
}
#[test]
fn stop_sending() -> Result<()> {
let frame = Frame::StopSending {
stream_id: 120,
error_code: 3,
};
assert_eq!(format!("{:?}", &frame), "STOP_SENDING id=120 err=3");
let mut buf = [0; 128];
let len = frame.to_bytes(&mut buf[..])?;
assert_eq!(len, frame.wire_len());
assert_eq!(len, 4);
let mut buf = Bytes::copy_from_slice(&buf);
assert_eq!((frame, 4), Frame::from_bytes(&mut buf, PacketType::OneRTT)?);
assert!(Frame::from_bytes(&mut buf, PacketType::ZeroRTT).is_ok());
assert!(Frame::from_bytes(&mut buf, PacketType::Initial).is_err());
assert!(Frame::from_bytes(&mut buf, PacketType::Handshake).is_err());
Ok(())
}
#[test]
fn crypto() -> Result<()> {
let data = Bytes::copy_from_slice(&[5; 50]);
let frame = Frame::Crypto {
offset: 1000,
length: 50,
data,
};
assert_eq!(format!("{:?}", &frame), "CRYPTO off=1000 len=50");
let mut buf = [0; 128];
let len = frame.to_bytes(&mut buf[..])?;
assert_eq!(len, frame.wire_len());
assert_eq!(len, 55);
assert_eq!(crypto_header_wire_len(800), 5);
let mut buf = Bytes::copy_from_slice(&buf);
assert_eq!(
(frame, 55),
Frame::from_bytes(&mut buf, PacketType::OneRTT)?
);
assert!(Frame::from_bytes(&mut buf, PacketType::ZeroRTT).is_err());
assert!(Frame::from_bytes(&mut buf, PacketType::Initial).is_ok());
assert!(Frame::from_bytes(&mut buf, PacketType::Handshake).is_ok());
Ok(())
}
#[test]
fn new_token() -> Result<()> {
let frame = Frame::NewToken {
token: Vec::from("a stub address token"),
};
assert_eq!(format!("{:?}", &frame), "NEW_TOKEN");
let mut buf = [0; 128];
let len = frame.to_bytes(&mut buf[..])?;
assert_eq!(len, frame.wire_len());
assert_eq!(len, 22);
let mut buf = Bytes::copy_from_slice(&buf);
assert_eq!(
(frame, 22),
Frame::from_bytes(&mut buf, PacketType::OneRTT)?
);
assert!(Frame::from_bytes(&mut buf, PacketType::ZeroRTT).is_err());
assert!(Frame::from_bytes(&mut buf, PacketType::Initial).is_err());
assert!(Frame::from_bytes(&mut buf, PacketType::Handshake).is_err());
Ok(())
}
#[test]
fn stream() -> Result<()> {
let data = Bytes::copy_from_slice(&[7; 80]);
let frame = Frame::Stream {
stream_id: 4,
offset: 800,
length: 80,
fin: false,
data,
};
assert_eq!(
format!("{:?}", &frame),
"STREAM id=4 off=800 len=80 fin=false"
);
let mut buf = [0; 128];
let len = frame.to_bytes(&mut buf[..])?;
assert_eq!(len, frame.wire_len());
assert_eq!(len, 86);
assert_eq!(stream_header_wire_len(4, 800), 6);
let mut buf = Bytes::copy_from_slice(&buf);
assert_eq!(
(frame, 86),
Frame::from_bytes(&mut buf, PacketType::OneRTT)?
);
assert!(Frame::from_bytes(&mut buf, PacketType::ZeroRTT).is_ok());
assert!(Frame::from_bytes(&mut buf, PacketType::Initial).is_err());
assert!(Frame::from_bytes(&mut buf, PacketType::Handshake).is_err());
Ok(())
}
#[test]
fn max_data() -> Result<()> {
let frame = Frame::MaxData { max: 128000 };
assert_eq!(format!("{:?}", &frame), "MAX_DATA max=128000");
let mut buf = [0; 128];
let len = frame.to_bytes(&mut buf[..])?;
assert_eq!(len, frame.wire_len());
assert_eq!(len, 5);
let mut buf = Bytes::copy_from_slice(&buf);
assert_eq!((frame, 5), Frame::from_bytes(&mut buf, PacketType::OneRTT)?);
assert!(Frame::from_bytes(&mut buf, PacketType::ZeroRTT).is_ok());
assert!(Frame::from_bytes(&mut buf, PacketType::Initial).is_err());
assert!(Frame::from_bytes(&mut buf, PacketType::Handshake).is_err());
Ok(())
}
#[test]
fn max_stream_data() -> Result<()> {
let frame = Frame::MaxStreamData {
stream_id: 8,
max: 128000,
};
assert_eq!(format!("{:?}", &frame), "MAX_STREAM_DATA id=8 max=128000");
let mut buf = [0; 128];
let len = frame.to_bytes(&mut buf[..])?;
assert_eq!(len, frame.wire_len());
assert_eq!(len, 6);
let mut buf = Bytes::copy_from_slice(&buf);
assert_eq!((frame, 6), Frame::from_bytes(&mut buf, PacketType::OneRTT)?);
assert!(Frame::from_bytes(&mut buf, PacketType::ZeroRTT).is_ok());
assert!(Frame::from_bytes(&mut buf, PacketType::Initial).is_err());
assert!(Frame::from_bytes(&mut buf, PacketType::Handshake).is_err());
Ok(())
}
#[test]
fn max_streams_bidi() -> Result<()> {
let frame = Frame::MaxStreams {
bidi: true,
max: 100,
};
assert_eq!(format!("{:?}", &frame), "MAX_STREAMS bidi=true max=100");
let mut buf = [0; 128];
let len = frame.to_bytes(&mut buf[..])?;
assert_eq!(len, frame.wire_len());
assert_eq!(len, 3);
let mut buf = Bytes::copy_from_slice(&buf);
assert_eq!((frame, 3), Frame::from_bytes(&mut buf, PacketType::OneRTT)?);
assert!(Frame::from_bytes(&mut buf, PacketType::ZeroRTT).is_ok());
assert!(Frame::from_bytes(&mut buf, PacketType::Initial).is_err());
assert!(Frame::from_bytes(&mut buf, PacketType::Handshake).is_err());
Ok(())
}
#[test]
fn max_streams_uni() -> Result<()> {
let frame = Frame::MaxStreams {
bidi: false,
max: 200,
};
assert_eq!(format!("{:?}", &frame), "MAX_STREAMS bidi=false max=200");
let mut buf = [0; 128];
let len = frame.to_bytes(&mut buf[..])?;
assert_eq!(len, frame.wire_len());
assert_eq!(len, 3);
let mut buf = Bytes::copy_from_slice(&buf);
assert_eq!((frame, 3), Frame::from_bytes(&mut buf, PacketType::OneRTT)?);
assert!(Frame::from_bytes(&mut buf, PacketType::ZeroRTT).is_ok());
assert!(Frame::from_bytes(&mut buf, PacketType::Initial).is_err());
assert!(Frame::from_bytes(&mut buf, PacketType::Handshake).is_err());
Ok(())
}
#[test]
fn data_blocked() -> Result<()> {
let frame = Frame::DataBlocked { max: 2049 };
assert_eq!(format!("{:?}", &frame), "DATA_BLOCKED max=2049");
let mut buf = [0; 128];
let len = frame.to_bytes(&mut buf[..])?;
assert_eq!(len, frame.wire_len());
assert_eq!(len, 3);
let mut buf = Bytes::copy_from_slice(&buf);
assert_eq!((frame, 3), Frame::from_bytes(&mut buf, PacketType::OneRTT)?);
assert!(Frame::from_bytes(&mut buf, PacketType::ZeroRTT).is_ok());
assert!(Frame::from_bytes(&mut buf, PacketType::Initial).is_err());
assert!(Frame::from_bytes(&mut buf, PacketType::Handshake).is_err());
Ok(())
}
#[test]
fn stream_data_blocked() -> Result<()> {
let frame = Frame::StreamDataBlocked {
stream_id: 8,
max: 2049,
};
assert_eq!(format!("{:?}", &frame), "STREAM_DATA_BLOCKED id=8 max=2049");
let mut buf = [0; 128];
let len = frame.to_bytes(&mut buf[..])?;
assert_eq!(len, frame.wire_len());
assert_eq!(len, 4);
let mut buf = Bytes::copy_from_slice(&buf);
assert_eq!((frame, 4), Frame::from_bytes(&mut buf, PacketType::OneRTT)?);
assert!(Frame::from_bytes(&mut buf, PacketType::ZeroRTT).is_ok());
assert!(Frame::from_bytes(&mut buf, PacketType::Initial).is_err());
assert!(Frame::from_bytes(&mut buf, PacketType::Handshake).is_err());
Ok(())
}
#[test]
fn streams_blocked_bidi() -> Result<()> {
let frame = Frame::StreamsBlocked {
bidi: true,
max: 200,
};
assert_eq!(format!("{:?}", &frame), "STREAMS_BLOCKED bidi=true max=200");
let mut buf = [0; 128];
let len = frame.to_bytes(&mut buf[..])?;
assert_eq!(len, frame.wire_len());
assert_eq!(len, 3);
let mut buf = Bytes::copy_from_slice(&buf);
assert_eq!((frame, 3), Frame::from_bytes(&mut buf, PacketType::OneRTT)?);
assert!(Frame::from_bytes(&mut buf, PacketType::ZeroRTT).is_ok());
assert!(Frame::from_bytes(&mut buf, PacketType::Initial).is_err());
assert!(Frame::from_bytes(&mut buf, PacketType::Handshake).is_err());
Ok(())
}
#[test]
fn streams_blocked_uni() -> Result<()> {
let frame = Frame::StreamsBlocked {
bidi: false,
max: 200,
};
assert_eq!(
format!("{:?}", &frame),
"STREAMS_BLOCKED bidi=false max=200"
);
let mut buf = [0; 128];
let len = frame.to_bytes(&mut buf[..])?;
assert_eq!(len, frame.wire_len());
assert_eq!(len, 3);
let mut buf = Bytes::copy_from_slice(&buf);
assert_eq!((frame, 3), Frame::from_bytes(&mut buf, PacketType::OneRTT)?);
assert!(Frame::from_bytes(&mut buf, PacketType::ZeroRTT).is_ok());
assert!(Frame::from_bytes(&mut buf, PacketType::Initial).is_err());
assert!(Frame::from_bytes(&mut buf, PacketType::Handshake).is_err());
Ok(())
}
#[test]
fn new_connection_id() -> Result<()> {
let frame = Frame::NewConnectionId {
seq_num: 20,
retire_prior_to: 19,
conn_id: ConnectionId {
len: 20,
data: [1; 20],
},
reset_token: ResetToken([2; 16]),
};
assert_eq!(
format!("{:?}", &frame),
"NEW_CONNECTION_ID \
seq=20 retire_prior_to=19 \
cid=0101010101010101010101010101010101010101 \
reset_token=02020202020202020202020202020202"
);
let mut buf = [0; 128];
let len = frame.to_bytes(&mut buf[..])?;
assert_eq!(len, frame.wire_len());
assert_eq!(len, 40);
let mut buf = Bytes::copy_from_slice(&buf);
assert_eq!(
(frame, 40),
Frame::from_bytes(&mut buf, PacketType::OneRTT)?
);
assert!(Frame::from_bytes(&mut buf, PacketType::ZeroRTT).is_ok());
assert!(Frame::from_bytes(&mut buf, PacketType::Initial).is_err());
assert!(Frame::from_bytes(&mut buf, PacketType::Handshake).is_err());
Ok(())
}
#[test]
fn retire_connection_id() -> Result<()> {
let frame = Frame::RetireConnectionId { seq_num: 100 };
assert_eq!(format!("{:?}", &frame), "RETIRE_CONNECTION_ID seq=100");
let mut buf = [0; 128];
let len = frame.to_bytes(&mut buf[..])?;
assert_eq!(len, frame.wire_len());
assert_eq!(len, 3);
let mut buf = Bytes::copy_from_slice(&buf);
assert_eq!((frame, 3), Frame::from_bytes(&mut buf, PacketType::OneRTT)?);
assert!(Frame::from_bytes(&mut buf, PacketType::ZeroRTT).is_err());
assert!(Frame::from_bytes(&mut buf, PacketType::Initial).is_err());
assert!(Frame::from_bytes(&mut buf, PacketType::Handshake).is_err());
Ok(())
}
#[test]
fn path_challenge() -> Result<()> {
let frame = Frame::PathChallenge { data: [1; 8] };
assert_eq!(
format!("{:?}", &frame),
"PATH_CHALLENGE \
data=[01, 01, 01, 01, 01, 01, 01, 01]"
);
let mut buf = [0; 128];
let len = frame.to_bytes(&mut buf[..])?;
assert_eq!(len, frame.wire_len());
assert_eq!(len, 9);
let mut buf = Bytes::copy_from_slice(&buf);
assert_eq!((frame, 9), Frame::from_bytes(&mut buf, PacketType::OneRTT)?);
assert!(Frame::from_bytes(&mut buf, PacketType::ZeroRTT).is_ok());
assert!(Frame::from_bytes(&mut buf, PacketType::Initial).is_err());
assert!(Frame::from_bytes(&mut buf, PacketType::Handshake).is_err());
Ok(())
}
#[test]
fn path_response() -> Result<()> {
let frame = Frame::PathResponse { data: [2; 8] };
assert_eq!(
format!("{:?}", &frame),
"PATH_RESPONSE \
data=[02, 02, 02, 02, 02, 02, 02, 02]"
);
let mut buf = [0; 128];
let len = frame.to_bytes(&mut buf[..])?;
assert_eq!(len, frame.wire_len());
assert_eq!(len, 9);
let mut buf = Bytes::copy_from_slice(&buf);
assert_eq!((frame, 9), Frame::from_bytes(&mut buf, PacketType::OneRTT)?);
assert!(Frame::from_bytes(&mut buf, PacketType::ZeroRTT).is_err());
assert!(Frame::from_bytes(&mut buf, PacketType::Initial).is_err());
assert!(Frame::from_bytes(&mut buf, PacketType::Handshake).is_err());
Ok(())
}
#[test]
fn connection_close() -> Result<()> {
let frame = Frame::ConnectionClose {
error_code: 0xe,
frame_type: 2,
reason: vec![1, 2, 3, 4],
};
assert_eq!(
format!("{:?}", &frame),
"CONNECTION_CLOSE err=e frame=2 reason=[1, 2, 3, 4]"
);
let mut buf = [0; 128];
let len = frame.to_bytes(&mut buf[..])?;
assert_eq!(len, frame.wire_len());
assert_eq!(len, 8);
let mut buf = Bytes::copy_from_slice(&buf);
assert_eq!((frame, 8), Frame::from_bytes(&mut buf, PacketType::OneRTT)?);
assert!(Frame::from_bytes(&mut buf, PacketType::ZeroRTT).is_err());
assert!(Frame::from_bytes(&mut buf, PacketType::Initial).is_ok());
assert!(Frame::from_bytes(&mut buf, PacketType::Handshake).is_ok());
Ok(())
}
#[test]
fn application_close() -> Result<()> {
let frame = Frame::ApplicationClose {
error_code: 0xe,
reason: vec![1, 2, 3, 4],
};
assert_eq!(
format!("{:?}", &frame),
"APPLICATION_CLOSE err=e reason=[1, 2, 3, 4]"
);
let mut buf = [0; 128];
let len = frame.to_bytes(&mut buf[..])?;
assert_eq!(len, frame.wire_len());
assert_eq!(len, 7);
let mut buf = Bytes::copy_from_slice(&buf);
assert_eq!((frame, 7), Frame::from_bytes(&mut buf, PacketType::OneRTT)?);
assert!(Frame::from_bytes(&mut buf, PacketType::ZeroRTT).is_ok());
assert!(Frame::from_bytes(&mut buf, PacketType::Initial).is_err());
assert!(Frame::from_bytes(&mut buf, PacketType::Handshake).is_err());
Ok(())
}
#[test]
fn handshake_done() -> Result<()> {
let frame = Frame::HandshakeDone;
assert_eq!(format!("{:?}", &frame), "HANDSHAKE_DONE");
let mut buf = [0; 128];
let len = frame.to_bytes(&mut buf[..])?;
assert_eq!(len, frame.wire_len());
assert_eq!(len, 1);
let mut buf = Bytes::copy_from_slice(&buf);
assert_eq!((frame, 1), Frame::from_bytes(&mut buf, PacketType::OneRTT)?);
assert!(Frame::from_bytes(&mut buf, PacketType::ZeroRTT).is_err());
assert!(Frame::from_bytes(&mut buf, PacketType::Initial).is_err());
assert!(Frame::from_bytes(&mut buf, PacketType::Handshake).is_err());
Ok(())
}
#[test]
fn path_abandon() -> Result<()> {
let frame = Frame::PathAbandon {
dcid_seq_num: 1,
error_code: 0xf,
reason: vec![1, 2, 3, 4],
};
assert_eq!(
format!("{:?}", &frame),
"PATH_ABANDON dcid_seq_num=1 err=f reason=[1, 2, 3, 4]"
);
let mut buf = [0; 128];
let len = frame.to_bytes(&mut buf[..])?;
assert_eq!(len, frame.wire_len());
assert_eq!(len, 11);
let mut buf = Bytes::copy_from_slice(&buf);
assert_eq!(
(frame, 11),
Frame::from_bytes(&mut buf, PacketType::OneRTT)?
);
assert!(Frame::from_bytes(&mut buf, PacketType::ZeroRTT).is_ok());
assert!(Frame::from_bytes(&mut buf, PacketType::Initial).is_err());
assert!(Frame::from_bytes(&mut buf, PacketType::Handshake).is_err());
Ok(())
}
#[test]
fn path_status() -> Result<()> {
let frame = Frame::PathStatus {
dcid_seq_num: 1,
seq_num: 2,
status: 3,
};
assert_eq!(
format!("{:?}", &frame),
"PATH_STATUS dcid_seq_num=1 seq_num=2 status=3"
);
let mut buf = [0; 128];
let len = frame.to_bytes(&mut buf[..])?;
assert_eq!(len, frame.wire_len());
assert_eq!(len, 7);
let mut buf = Bytes::copy_from_slice(&buf);
assert_eq!((frame, 7), Frame::from_bytes(&mut buf, PacketType::OneRTT)?);
assert!(Frame::from_bytes(&mut buf, PacketType::ZeroRTT).is_ok());
assert!(Frame::from_bytes(&mut buf, PacketType::Initial).is_err());
assert!(Frame::from_bytes(&mut buf, PacketType::Handshake).is_err());
Ok(())
}
#[test]
fn special_frames() -> Result<()> {
assert_eq!(
Frame::Ack {
ack_delay: 200000,
ack_ranges: RangeSet::default(),
ecn_counts: None,
}
.ack_eliciting(),
false
);
assert_eq!(
Frame::ApplicationClose {
error_code: 0x3,
reason: vec![1, 2, 3]
}
.ack_eliciting(),
false
);
assert_eq!(
Frame::ConnectionClose {
error_code: 0x3,
frame_type: 1,
reason: vec![1, 2, 3]
}
.ack_eliciting(),
false
);
assert_eq!(
Frame::NewConnectionId {
seq_num: 1,
retire_prior_to: 1,
conn_id: ConnectionId::random(),
reset_token: ResetToken([0xa; 16])
}
.probing(),
true
);
assert_eq!(Frame::PathChallenge { data: [1; 8] }.probing(), true);
assert_eq!(Frame::PathResponse { data: [1; 8] }.probing(), true);
Ok(())
}
#[test]
fn stream_buffer_too_short() -> Result<()> {
let mut buf = Bytes::from_static(&[
0x0e, 0x00, 0x00, 0x1c, 0x80, 0x00, 0xcf, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00,
]);
assert_eq!(
Frame::from_bytes(&mut buf, PacketType::OneRTT),
Err(Error::BufferTooShort)
);
Ok(())
}
}