summaryrefslogtreecommitdiffstats
path: root/third_party/rust/neqo-transport/src/frame.rs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--third_party/rust/neqo-transport/src/frame.rs86
1 files changed, 58 insertions, 28 deletions
diff --git a/third_party/rust/neqo-transport/src/frame.rs b/third_party/rust/neqo-transport/src/frame.rs
index b3bb024a2c..d84eb61ce8 100644
--- a/third_party/rust/neqo-transport/src/frame.rs
+++ b/third_party/rust/neqo-transport/src/frame.rs
@@ -20,7 +20,7 @@ use crate::{
#[allow(clippy::module_name_repetitions)]
pub type FrameType = u64;
-const FRAME_TYPE_PADDING: FrameType = 0x0;
+pub const FRAME_TYPE_PADDING: FrameType = 0x0;
pub const FRAME_TYPE_PING: FrameType = 0x1;
pub const FRAME_TYPE_ACK: FrameType = 0x2;
const FRAME_TYPE_ACK_ECN: FrameType = 0x3;
@@ -95,6 +95,12 @@ impl From<ConnectionError> for CloseError {
}
}
+impl From<std::array::TryFromSliceError> for Error {
+ fn from(_err: std::array::TryFromSliceError) -> Self {
+ Self::FrameEncodingError
+ }
+}
+
#[derive(PartialEq, Eq, Debug, Default, Clone)]
pub struct AckRange {
pub(crate) gap: u64,
@@ -103,7 +109,7 @@ pub struct AckRange {
#[derive(PartialEq, Eq, Debug, Clone)]
pub enum Frame<'a> {
- Padding,
+ Padding(u16),
Ping,
Ack {
largest_acknowledged: u64,
@@ -213,9 +219,10 @@ impl<'a> Frame<'a> {
}
}
+ #[must_use]
pub fn get_type(&self) -> FrameType {
match self {
- Self::Padding => FRAME_TYPE_PADDING,
+ Self::Padding { .. } => FRAME_TYPE_PADDING,
Self::Ping => FRAME_TYPE_PING,
Self::Ack { .. } => FRAME_TYPE_ACK, // We don't do ACK ECN.
Self::ResetStream { .. } => FRAME_TYPE_RESET_STREAM,
@@ -254,6 +261,7 @@ impl<'a> Frame<'a> {
}
}
+ #[must_use]
pub fn is_stream(&self) -> bool {
matches!(
self,
@@ -269,6 +277,7 @@ impl<'a> Frame<'a> {
)
}
+ #[must_use]
pub fn stream_type(fin: bool, nonzero_offset: bool, fill: bool) -> u64 {
let mut t = FRAME_TYPE_STREAM;
if fin {
@@ -285,19 +294,21 @@ impl<'a> Frame<'a> {
/// If the frame causes a recipient to generate an ACK within its
/// advertised maximum acknowledgement delay.
+ #[must_use]
pub fn ack_eliciting(&self) -> bool {
!matches!(
self,
- Self::Ack { .. } | Self::Padding | Self::ConnectionClose { .. }
+ Self::Ack { .. } | Self::Padding { .. } | Self::ConnectionClose { .. }
)
}
/// If the frame can be sent in a path probe
/// without initiating migration to that path.
+ #[must_use]
pub fn path_probing(&self) -> bool {
matches!(
self,
- Self::Padding
+ Self::Padding { .. }
| Self::NewConnectionId { .. }
| Self::PathChallenge { .. }
| Self::PathResponse { .. }
@@ -307,6 +318,10 @@ impl<'a> Frame<'a> {
/// Converts `AckRanges` as encoded in a ACK frame (see -transport
/// 19.3.1) into ranges of acked packets (end, start), inclusive of
/// start and end values.
+ ///
+ /// # Errors
+ ///
+ /// Returns an error if the ranges are invalid.
pub fn decode_ack_frame(
largest_acked: u64,
first_ack_range: u64,
@@ -347,36 +362,36 @@ impl<'a> Frame<'a> {
Ok(acked_ranges)
}
- pub fn dump(&self) -> Option<String> {
+ #[must_use]
+ pub fn dump(&self) -> String {
match self {
- Self::Crypto { offset, data } => Some(format!(
- "Crypto {{ offset: {}, len: {} }}",
- offset,
- data.len()
- )),
+ Self::Crypto { offset, data } => {
+ format!("Crypto {{ offset: {}, len: {} }}", offset, data.len())
+ }
Self::Stream {
stream_id,
offset,
fill,
data,
fin,
- } => Some(format!(
+ } => format!(
"Stream {{ stream_id: {}, offset: {}, len: {}{}, fin: {} }}",
stream_id.as_u64(),
offset,
if *fill { ">>" } else { "" },
data.len(),
fin,
- )),
- Self::Padding => None,
- Self::Datagram { data, .. } => Some(format!("Datagram {{ len: {} }}", data.len())),
- _ => Some(format!("{self:?}")),
+ ),
+ Self::Padding(length) => format!("Padding {{ len: {length} }}"),
+ Self::Datagram { data, .. } => format!("Datagram {{ len: {} }}", data.len()),
+ _ => format!("{self:?}"),
}
}
+ #[must_use]
pub fn is_allowed(&self, pt: PacketType) -> bool {
match self {
- Self::Padding | Self::Ping => true,
+ Self::Padding { .. } | Self::Ping => true,
Self::Crypto { .. }
| Self::Ack { .. }
| Self::ConnectionClose {
@@ -388,6 +403,9 @@ impl<'a> Frame<'a> {
}
}
+ /// # Errors
+ ///
+ /// Returns an error if the frame cannot be decoded.
#[allow(clippy::too_many_lines)] // Yeah, but it's a nice match statement.
pub fn decode(dec: &mut Decoder<'a>) -> Res<Self> {
/// Maximum ACK Range Count in ACK Frame
@@ -409,13 +427,23 @@ impl<'a> Frame<'a> {
}
// TODO(ekr@rtfm.com): check for minimal encoding
- let t = d(dec.decode_varint())?;
+ let t = dv(dec)?;
match t {
- FRAME_TYPE_PADDING => Ok(Self::Padding),
+ FRAME_TYPE_PADDING => {
+ let mut length: u16 = 1;
+ while let Some(b) = dec.peek_byte() {
+ if u64::from(b) != FRAME_TYPE_PADDING {
+ break;
+ }
+ length += 1;
+ dec.skip(1);
+ }
+ Ok(Self::Padding(length))
+ }
FRAME_TYPE_PING => Ok(Self::Ping),
FRAME_TYPE_RESET_STREAM => Ok(Self::ResetStream {
stream_id: StreamId::from(dv(dec)?),
- application_error_code: d(dec.decode_varint())?,
+ application_error_code: dv(dec)?,
final_size: match dec.decode_varint() {
Some(v) => v,
_ => return Err(Error::NoMoreData),
@@ -457,12 +485,12 @@ impl<'a> Frame<'a> {
}
FRAME_TYPE_STOP_SENDING => Ok(Self::StopSending {
stream_id: StreamId::from(dv(dec)?),
- application_error_code: d(dec.decode_varint())?,
+ application_error_code: dv(dec)?,
}),
FRAME_TYPE_CRYPTO => {
let offset = dv(dec)?;
let data = d(dec.decode_vvec())?;
- if offset + u64::try_from(data.len()).unwrap() > ((1 << 62) - 1) {
+ if offset + u64::try_from(data.len())? > ((1 << 62) - 1) {
return Err(Error::FrameEncodingError);
}
Ok(Self::Crypto { offset, data })
@@ -489,7 +517,7 @@ impl<'a> Frame<'a> {
qtrace!("STREAM frame, with length");
d(dec.decode_vvec())?
};
- if o + u64::try_from(data.len()).unwrap() > ((1 << 62) - 1) {
+ if o + u64::try_from(data.len())? > ((1 << 62) - 1) {
return Err(Error::FrameEncodingError);
}
Ok(Self::Stream {
@@ -538,7 +566,7 @@ impl<'a> Frame<'a> {
return Err(Error::DecodingFrame);
}
let srt = d(dec.decode(16))?;
- let stateless_reset_token = <&[_; 16]>::try_from(srt).unwrap();
+ let stateless_reset_token = <&[_; 16]>::try_from(srt)?;
Ok(Self::NewConnectionId {
sequence_number,
@@ -563,7 +591,7 @@ impl<'a> Frame<'a> {
Ok(Self::PathResponse { data: datav })
}
FRAME_TYPE_CONNECTION_CLOSE_TRANSPORT | FRAME_TYPE_CONNECTION_CLOSE_APPLICATION => {
- let error_code = CloseError::from_type_bit(t, d(dec.decode_varint())?);
+ let error_code = CloseError::from_type_bit(t, dv(dec)?);
let frame_type = if t == FRAME_TYPE_CONNECTION_CLOSE_TRANSPORT {
dv(dec)?
} else {
@@ -631,8 +659,10 @@ mod tests {
#[test]
fn padding() {
- let f = Frame::Padding;
+ let f = Frame::Padding(1);
just_dec(&f, "00");
+ let f = Frame::Padding(2);
+ just_dec(&f, "0000");
}
#[test]
@@ -888,8 +918,8 @@ mod tests {
#[test]
fn test_compare() {
- let f1 = Frame::Padding;
- let f2 = Frame::Padding;
+ let f1 = Frame::Padding(1);
+ let f2 = Frame::Padding(1);
let f3 = Frame::Crypto {
offset: 0,
data: &[1, 2, 3],