mirror of
https://github.com/n0-computer/noq.git
synced 2026-10-14 08:39:56 +00:00
More principled error handling for invalid frames
This commit is contained in:
@@ -2050,7 +2050,15 @@ impl Connection {
|
||||
return Ok(());
|
||||
}
|
||||
State::Closed(_) => {
|
||||
for frame in frame::Iter::new(packet.payload.freeze()) {
|
||||
for result in frame::Iter::new(packet.payload.freeze()) {
|
||||
let frame = match result {
|
||||
Ok(frame) => frame,
|
||||
Err(err) => {
|
||||
debug!("frame decoding error: {err:?}");
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
if let Frame::Padding = frame {
|
||||
continue;
|
||||
};
|
||||
@@ -2291,7 +2299,8 @@ impl Connection {
|
||||
debug_assert_ne!(packet.header.space(), SpaceId::Data);
|
||||
let payload_len = packet.payload.len();
|
||||
let mut ack_eliciting = false;
|
||||
for frame in frame::Iter::new(packet.payload.freeze()) {
|
||||
for result in frame::Iter::new(packet.payload.freeze()) {
|
||||
let frame = result?;
|
||||
let span = match frame {
|
||||
Frame::Padding => continue,
|
||||
_ => Some(trace_span!("frame", ty = %frame.ty())),
|
||||
@@ -2316,11 +2325,6 @@ impl Connection {
|
||||
self.state = State::Draining;
|
||||
return Ok(());
|
||||
}
|
||||
Frame::Invalid { ty, reason } => {
|
||||
let mut err = TransportError::FRAME_ENCODING_ERROR(reason);
|
||||
err.frame = Some(ty);
|
||||
return Err(err);
|
||||
}
|
||||
_ => {
|
||||
let mut err =
|
||||
TransportError::PROTOCOL_VIOLATION("illegal frame type in handshake");
|
||||
@@ -2349,7 +2353,8 @@ impl Connection {
|
||||
let mut close = None;
|
||||
let payload_len = payload.len();
|
||||
let mut ack_eliciting = false;
|
||||
for frame in frame::Iter::new(payload) {
|
||||
for result in frame::Iter::new(payload) {
|
||||
let frame = result?;
|
||||
let span = match frame {
|
||||
Frame::Padding => continue,
|
||||
_ => Some(trace_span!("frame", ty = %frame.ty())),
|
||||
@@ -2397,11 +2402,6 @@ impl Connection {
|
||||
}
|
||||
}
|
||||
match frame {
|
||||
Frame::Invalid { ty, reason } => {
|
||||
let mut err = TransportError::FRAME_ENCODING_ERROR(reason);
|
||||
err.frame = Some(ty);
|
||||
return Err(err);
|
||||
}
|
||||
Frame::Crypto(frame) => {
|
||||
self.read_crypto(SpaceId::Data, &frame, payload_len)?;
|
||||
}
|
||||
|
||||
@@ -82,7 +82,6 @@ impl FrameStats {
|
||||
Frame::PathResponse(_) => self.path_response += 1,
|
||||
Frame::Close(_) => self.connection_close += 1,
|
||||
Frame::HandshakeDone => self.handshake_done += 1,
|
||||
Frame::Invalid { .. } => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,7 +157,6 @@ pub enum Frame {
|
||||
PathResponse(u64),
|
||||
Close(Close),
|
||||
Datagram(Datagram),
|
||||
Invalid { ty: Type, reason: &'static str },
|
||||
HandshakeDone,
|
||||
}
|
||||
|
||||
@@ -197,7 +196,6 @@ impl Frame {
|
||||
Crypto(_) => Type::CRYPTO,
|
||||
NewToken { .. } => Type::NEW_TOKEN,
|
||||
Datagram(_) => Type(*DATAGRAM_TYS.start()),
|
||||
Invalid { ty, .. } => ty,
|
||||
HandshakeDone => Type::HANDSHAKE_DONE,
|
||||
}
|
||||
}
|
||||
@@ -721,25 +719,39 @@ impl Iter {
|
||||
}
|
||||
|
||||
impl Iterator for Iter {
|
||||
type Item = Frame;
|
||||
type Item = Result<Frame, InvalidFrame>;
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if !self.bytes.has_remaining() {
|
||||
return None;
|
||||
}
|
||||
match self.try_next() {
|
||||
Ok(x) => Some(x),
|
||||
Ok(x) => Some(Ok(x)),
|
||||
Err(e) => {
|
||||
// Corrupt frame, skip it and everything that follows
|
||||
self.bytes = io::Cursor::new(Bytes::new());
|
||||
Some(Frame::Invalid {
|
||||
ty: self.last_ty.unwrap(),
|
||||
Some(Err(InvalidFrame {
|
||||
ty: self.last_ty,
|
||||
reason: e.reason(),
|
||||
})
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct InvalidFrame {
|
||||
pub(crate) ty: Option<Type>,
|
||||
pub(crate) reason: &'static str,
|
||||
}
|
||||
|
||||
impl From<InvalidFrame> for TransportError {
|
||||
fn from(err: InvalidFrame) -> Self {
|
||||
let mut te = Self::FRAME_ENCODING_ERROR(err.reason);
|
||||
te.frame = err.ty;
|
||||
te
|
||||
}
|
||||
}
|
||||
|
||||
fn scan_ack_blocks(buf: &mut io::Cursor<Bytes>, largest: u64, n: usize) -> Result<(), IterErr> {
|
||||
let first_block = buf.get_var()?;
|
||||
let mut smallest = largest.checked_sub(first_block).ok_or(IterErr::Malformed)?;
|
||||
@@ -890,7 +902,9 @@ mod test {
|
||||
ce: 12,
|
||||
};
|
||||
Ack::encode(42, &ranges, Some(&ECN), &mut buf);
|
||||
let frames = Iter::new(Bytes::from(buf)).collect::<Vec<_>>();
|
||||
let frames = Iter::new(Bytes::from(buf))
|
||||
.collect::<Result<Vec<_>, _>>()
|
||||
.unwrap();
|
||||
assert_eq!(frames.len(), 1);
|
||||
match frames[0] {
|
||||
Frame::Ack(ref ack) => {
|
||||
|
||||
Reference in New Issue
Block a user