Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  frame.rs   Sprache: unbekannt

 
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Directly relating to QUIC frames.

use std::ops::RangeInclusive;

use neqo_common::{qtrace, Decoder, Encoder};

use crate::{
    cid::MAX_CONNECTION_ID_LEN,
    ecn::EcnCount,
    packet::PacketType,
    stream_id::{StreamId, StreamType},
    AppError, CloseReason, Error, Res, TransportError,
};

#[allow(clippy::module_name_repetitions)]
pub type FrameType = u64;

pub const FRAME_TYPE_PADDING: FrameType = 0x0;
pub const FRAME_TYPE_PING: FrameType = 0x1;
pub const FRAME_TYPE_ACK: FrameType = 0x2;
pub const FRAME_TYPE_ACK_ECN: FrameType = 0x3;
pub const FRAME_TYPE_RESET_STREAM: FrameType = 0x4;
pub const FRAME_TYPE_STOP_SENDING: FrameType = 0x5;
pub const FRAME_TYPE_CRYPTO: FrameType = 0x6;
pub const FRAME_TYPE_NEW_TOKEN: FrameType = 0x7;
const FRAME_TYPE_STREAM: FrameType = 0x8;
const FRAME_TYPE_STREAM_MAX: FrameType = 0xf;
pub const FRAME_TYPE_MAX_DATA: FrameType = 0x10;
pub const FRAME_TYPE_MAX_STREAM_DATA: FrameType = 0x11;
pub const FRAME_TYPE_MAX_STREAMS_BIDI: FrameType = 0x12;
pub const FRAME_TYPE_MAX_STREAMS_UNIDI: FrameType = 0x13;
pub const FRAME_TYPE_DATA_BLOCKED: FrameType = 0x14;
pub const FRAME_TYPE_STREAM_DATA_BLOCKED: FrameType = 0x15;
pub const FRAME_TYPE_STREAMS_BLOCKED_BIDI: FrameType = 0x16;
pub const FRAME_TYPE_STREAMS_BLOCKED_UNIDI: FrameType = 0x17;
pub const FRAME_TYPE_NEW_CONNECTION_ID: FrameType = 0x18;
pub const FRAME_TYPE_RETIRE_CONNECTION_ID: FrameType = 0x19;
pub const FRAME_TYPE_PATH_CHALLENGE: FrameType = 0x1a;
pub const FRAME_TYPE_PATH_RESPONSE: FrameType = 0x1b;
pub const FRAME_TYPE_CONNECTION_CLOSE_TRANSPORT: FrameType = 0x1c;
pub const FRAME_TYPE_CONNECTION_CLOSE_APPLICATION: FrameType = 0x1d;
pub const FRAME_TYPE_HANDSHAKE_DONE: FrameType = 0x1e;
// draft-ietf-quic-ack-delay
pub const FRAME_TYPE_ACK_FREQUENCY: FrameType = 0xaf;
// draft-ietf-quic-datagram
pub const FRAME_TYPE_DATAGRAM: FrameType = 0x30;
pub const FRAME_TYPE_DATAGRAM_WITH_LEN: FrameType = 0x31;
const DATAGRAM_FRAME_BIT_LEN: u64 = 0x01;

const STREAM_FRAME_BIT_FIN: u64 = 0x01;
const STREAM_FRAME_BIT_LEN: u64 = 0x02;
const STREAM_FRAME_BIT_OFF: u64 = 0x04;

#[derive(PartialEq, Eq, Debug, PartialOrd, Ord, Clone, Copy)]
pub enum CloseError {
    Transport(TransportError),
    Application(AppError),
}

impl CloseError {
    const fn frame_type_bit(self) -> u64 {
        match self {
            Self::Transport(_) => 0,
            Self::Application(_) => 1,
        }
    }

    const fn from_type_bit(bit: u64, code: u64) -> Self {
        if (bit & 0x01) == 0 {
            Self::Transport(code)
        } else {
            Self::Application(code)
        }
    }

    #[must_use]
    pub const fn code(&self) -> u64 {
        match self {
            Self::Transport(c) | Self::Application(c) => *c,
        }
    }
}

impl From<CloseReason> for CloseError {
    fn from(err: CloseReason) -> Self {
        match err {
            CloseReason::Transport(c) => Self::Transport(c.code()),
            CloseReason::Application(c) => Self::Application(c),
        }
    }
}

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,
    pub(crate) range: u64,
}

#[derive(PartialEq, Eq, Debug, Clone)]
pub enum Frame<'a> {
    Padding(u16),
    Ping,
    Ack {
        largest_acknowledged: u64,
        ack_delay: u64,
        first_ack_range: u64,
        ack_ranges: Vec<AckRange>,
        ecn_count: Option<EcnCount>,
    },
    ResetStream {
        stream_id: StreamId,
        application_error_code: AppError,
        final_size: u64,
    },
    StopSending {
        stream_id: StreamId,
        application_error_code: AppError,
    },
    Crypto {
        offset: u64,
        data: &'a [u8],
    },
    NewToken {
        token: &'a [u8],
    },
    Stream {
        stream_id: StreamId,
        offset: u64,
        data: &'a [u8],
        fin: bool,
        fill: bool,
    },
    MaxData {
        maximum_data: u64,
    },
    MaxStreamData {
        stream_id: StreamId,
        maximum_stream_data: u64,
    },
    MaxStreams {
        stream_type: StreamType,
        maximum_streams: u64,
    },
    DataBlocked {
        data_limit: u64,
    },
    StreamDataBlocked {
        stream_id: StreamId,
        stream_data_limit: u64,
    },
    StreamsBlocked {
        stream_type: StreamType,
        stream_limit: u64,
    },
    NewConnectionId {
        sequence_number: u64,
        retire_prior: u64,
        connection_id: &'a [u8],
        stateless_reset_token: &'a [u8; 16],
    },
    RetireConnectionId {
        sequence_number: u64,
    },
    PathChallenge {
        data: [u8; 8],
    },
    PathResponse {
        data: [u8; 8],
    },
    ConnectionClose {
        error_code: CloseError,
        frame_type: u64,
        // Not a reference as we use this to hold the value.
        // This is not used in optimized builds anyway.
        reason_phrase: String,
    },
    HandshakeDone,
    AckFrequency {
        /// The current ACK frequency sequence number.
        seqno: u64,
        /// The number of contiguous packets that can be received without
        /// acknowledging immediately.
        tolerance: u64,
        /// The time to delay after receiving the first packet that is
        /// not immediately acknowledged.
        delay: u64,
        /// Ignore reordering when deciding to immediately acknowledge.
        ignore_order: bool,
    },
    Datagram {
        data: &'a [u8],
        fill: bool,
    },
}

impl<'a> Frame<'a> {
    const fn get_stream_type_bit(stream_type: StreamType) -> u64 {
        match stream_type {
            StreamType::BiDi => 0,
            StreamType::UniDi => 1,
        }
    }

    const fn stream_type_from_bit(bit: u64) -> StreamType {
        if (bit & 0x01) == 0 {
            StreamType::BiDi
        } else {
            StreamType::UniDi
        }
    }

    #[must_use]
    pub const fn get_type(&self) -> FrameType {
        match self {
            Self::Padding { .. } => FRAME_TYPE_PADDING,
            Self::Ping => FRAME_TYPE_PING,
            Self::Ack { .. } => FRAME_TYPE_ACK,
            Self::ResetStream { .. } => FRAME_TYPE_RESET_STREAM,
            Self::StopSending { .. } => FRAME_TYPE_STOP_SENDING,
            Self::Crypto { .. } => FRAME_TYPE_CRYPTO,
            Self::NewToken { .. } => FRAME_TYPE_NEW_TOKEN,
            Self::Stream {
                fin, offset, fill, ..
            } => Self::stream_type(*fin, *offset > 0, *fill),
            Self::MaxData { .. } => FRAME_TYPE_MAX_DATA,
            Self::MaxStreamData { .. } => FRAME_TYPE_MAX_STREAM_DATA,
            Self::MaxStreams { stream_type, .. } => {
                FRAME_TYPE_MAX_STREAMS_BIDI + Self::get_stream_type_bit(*stream_type)
            }
            Self::DataBlocked { .. } => FRAME_TYPE_DATA_BLOCKED,
            Self::StreamDataBlocked { .. } => FRAME_TYPE_STREAM_DATA_BLOCKED,
            Self::StreamsBlocked { stream_type, .. } => {
                FRAME_TYPE_STREAMS_BLOCKED_BIDI + Self::get_stream_type_bit(*stream_type)
            }
            Self::NewConnectionId { .. } => FRAME_TYPE_NEW_CONNECTION_ID,
            Self::RetireConnectionId { .. } => FRAME_TYPE_RETIRE_CONNECTION_ID,
            Self::PathChallenge { .. } => FRAME_TYPE_PATH_CHALLENGE,
            Self::PathResponse { .. } => FRAME_TYPE_PATH_RESPONSE,
            Self::ConnectionClose { error_code, .. } => {
                FRAME_TYPE_CONNECTION_CLOSE_TRANSPORT + error_code.frame_type_bit()
            }
            Self::HandshakeDone => FRAME_TYPE_HANDSHAKE_DONE,
            Self::AckFrequency { .. } => FRAME_TYPE_ACK_FREQUENCY,
            Self::Datagram { fill, .. } => {
                if *fill {
                    FRAME_TYPE_DATAGRAM
                } else {
                    FRAME_TYPE_DATAGRAM_WITH_LEN
                }
            }
        }
    }

    #[must_use]
    pub const fn is_stream(&self) -> bool {
        matches!(
            self,
            Self::ResetStream { .. }
                | Self::StopSending { .. }
                | Self::Stream { .. }
                | Self::MaxData { .. }
                | Self::MaxStreamData { .. }
                | Self::MaxStreams { .. }
                | Self::DataBlocked { .. }
                | Self::StreamDataBlocked { .. }
                | Self::StreamsBlocked { .. }
        )
    }

    #[must_use]
    pub const fn stream_type(fin: bool, nonzero_offset: bool, fill: bool) -> u64 {
        let mut t = FRAME_TYPE_STREAM;
        if fin {
            t |= STREAM_FRAME_BIT_FIN;
        }
        if nonzero_offset {
            t |= STREAM_FRAME_BIT_OFF;
        }
        if !fill {
            t |= STREAM_FRAME_BIT_LEN;
        }
        t
    }

    /// If the frame causes a recipient to generate an ACK within its
    /// advertised maximum acknowledgement delay.
    #[must_use]
    pub const fn ack_eliciting(&self) -> bool {
        !matches!(
            self,
            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 const fn path_probing(&self) -> bool {
        matches!(
            self,
            Self::Padding { .. }
                | Self::NewConnectionId { .. }
                | Self::PathChallenge { .. }
                | Self::PathResponse { .. }
        )
    }

    /// 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,
        ack_ranges: &[AckRange],
    ) -> Res<Vec<RangeInclusive<u64>>> {
        let mut acked_ranges = Vec::with_capacity(ack_ranges.len() + 1);

        if largest_acked < first_ack_range {
            return Err(Error::FrameEncodingError);
        }
        acked_ranges.push((largest_acked - first_ack_range)..=largest_acked);
        if !ack_ranges.is_empty() && largest_acked < first_ack_range + 1 {
            return Err(Error::FrameEncodingError);
        }
        let mut cur = if ack_ranges.is_empty() {
            0
        } else {
            largest_acked - first_ack_range - 1
        };
        for r in ack_ranges {
            if cur < r.gap + 1 {
                return Err(Error::FrameEncodingError);
            }
            cur = cur - r.gap - 1;

            if cur < r.range {
                return Err(Error::FrameEncodingError);
            }
            acked_ranges.push((cur - r.range)..=cur);

            if cur > r.range + 1 {
                cur -= r.range + 1;
            } else {
                cur -= r.range;
            }
        }

        Ok(acked_ranges)
    }

    #[must_use]
    pub fn dump(&self) -> String {
        match self {
            Self::Crypto { offset, data } => {
                format!("Crypto {{ offset: {}, len: {} }}", offset, data.len())
            }
            Self::Stream {
                stream_id,
                offset,
                fill,
                data,
                fin,
            } => format!(
                "Stream {{ stream_id: {}, offset: {}, len: {}{}, fin: {} }}",
                stream_id.as_u64(),
                offset,
                if *fill { ">>" } else { "" },
                data.len(),
                fin,
            ),
            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::Crypto { .. }
            | Self::Ack { .. }
            | Self::ConnectionClose {
                error_code: CloseError::Transport(_),
                ..
            } => pt != PacketType::ZeroRtt,
            Self::NewToken { .. } | Self::ConnectionClose { .. } => pt == PacketType::Short,
            _ => pt == PacketType::ZeroRtt || pt == PacketType::Short,
        }
    }

    /// # 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
        ///
        /// Given a max UDP datagram size of 64k bytes and a minimum ACK Range size of 2
        /// bytes (2 QUIC varints), a single datagram can at most contain 32k ACK
        /// Ranges.
        ///
        /// Note that the maximum (jumbogram) Ethernet MTU of 9216 or on the
        /// Internet the regular Ethernet MTU of 1518 are more realistically to
        /// be the limiting factor. Though for simplicity the higher limit is chosen.
        const MAX_ACK_RANGE_COUNT: u64 = 32 * 1024;

        fn d<T>(v: Option<T>) -> Res<T> {
            v.ok_or(Error::NoMoreData)
        }
        fn dv(dec: &mut Decoder) -> Res<u64> {
            d(dec.decode_varint())
        }

        fn decode_ack<'a>(dec: &mut Decoder<'a>, ecn: bool) -> Res<Frame<'a>> {
            let la = dv(dec)?;
            let ad = dv(dec)?;
            let nr = dv(dec).and_then(|nr| {
                if nr < MAX_ACK_RANGE_COUNT {
                    Ok(nr)
                } else {
                    Err(Error::TooMuchData)
                }
            })?;
            let fa = dv(dec)?;
            let mut arr: Vec<AckRange> = Vec::with_capacity(usize::try_from(nr)?);
            for _ in 0..nr {
                let ar = AckRange {
                    gap: dv(dec)?,
                    range: dv(dec)?,
                };
                arr.push(ar);
            }

            // Now check for the values for ACK_ECN.
            let ecn_count = if ecn {
                Some(EcnCount::new(0, dv(dec)?, dv(dec)?, dv(dec)?))
            } else {
                None
            };

            Ok(Frame::Ack {
                largest_acknowledged: la,
                ack_delay: ad,
                first_ack_range: fa,
                ack_ranges: arr,
                ecn_count,
            })
        }

        // Check for minimal encoding of frame type.
        let pos = dec.offset();
        let t = dv(dec)?;
        // RFC 9000, Section 12.4:
        //
        // The Frame Type field uses a variable-length integer encoding [...],
        // with one exception. To ensure simple and efficient implementations of
        // frame parsing, a frame type MUST use the shortest possible encoding.
        if Encoder::varint_len(t) != dec.offset() - pos {
            return Err(Error::ProtocolViolation);
        }

        match t {
            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: dv(dec)?,
                final_size: match dec.decode_varint() {
                    Some(v) => v,
                    _ => return Err(Error::NoMoreData),
                },
            }),
            FRAME_TYPE_ACK => decode_ack(dec, false),
            FRAME_TYPE_ACK_ECN => decode_ack(dec, true),
            FRAME_TYPE_STOP_SENDING => Ok(Self::StopSending {
                stream_id: StreamId::from(dv(dec)?),
                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())? > ((1 << 62) - 1) {
                    return Err(Error::FrameEncodingError);
                }
                Ok(Self::Crypto { offset, data })
            }
            FRAME_TYPE_NEW_TOKEN => {
                let token = d(dec.decode_vvec())?;
                if token.is_empty() {
                    return Err(Error::FrameEncodingError);
                }
                Ok(Self::NewToken { token })
            }
            FRAME_TYPE_STREAM..=FRAME_TYPE_STREAM_MAX => {
                let s = dv(dec)?;
                let o = if t & STREAM_FRAME_BIT_OFF == 0 {
                    0
                } else {
                    dv(dec)?
                };
                let fill = (t & STREAM_FRAME_BIT_LEN) == 0;
                let data = if fill {
                    qtrace!("STREAM frame, extends to the end of the packet");
                    dec.decode_remainder()
                } else {
                    qtrace!("STREAM frame, with length");
                    d(dec.decode_vvec())?
                };
                if o + u64::try_from(data.len())? > ((1 << 62) - 1) {
                    return Err(Error::FrameEncodingError);
                }
                Ok(Self::Stream {
                    fin: (t & STREAM_FRAME_BIT_FIN) != 0,
                    stream_id: StreamId::from(s),
                    offset: o,
                    data,
                    fill,
                })
            }
            FRAME_TYPE_MAX_DATA => Ok(Self::MaxData {
                maximum_data: dv(dec)?,
            }),
            FRAME_TYPE_MAX_STREAM_DATA => Ok(Self::MaxStreamData {
                stream_id: StreamId::from(dv(dec)?),
                maximum_stream_data: dv(dec)?,
            }),
            FRAME_TYPE_MAX_STREAMS_BIDI | FRAME_TYPE_MAX_STREAMS_UNIDI => {
                let m = dv(dec)?;
                if m > (1 << 60) {
                    return Err(Error::StreamLimitError);
                }
                Ok(Self::MaxStreams {
                    stream_type: Self::stream_type_from_bit(t),
                    maximum_streams: m,
                })
            }
            FRAME_TYPE_DATA_BLOCKED => Ok(Self::DataBlocked {
                data_limit: dv(dec)?,
            }),
            FRAME_TYPE_STREAM_DATA_BLOCKED => Ok(Self::StreamDataBlocked {
                stream_id: dv(dec)?.into(),
                stream_data_limit: dv(dec)?,
            }),
            FRAME_TYPE_STREAMS_BLOCKED_BIDI | FRAME_TYPE_STREAMS_BLOCKED_UNIDI => {
                Ok(Self::StreamsBlocked {
                    stream_type: Self::stream_type_from_bit(t),
                    stream_limit: dv(dec)?,
                })
            }
            FRAME_TYPE_NEW_CONNECTION_ID => {
                let sequence_number = dv(dec)?;
                let retire_prior = dv(dec)?;
                let connection_id = d(dec.decode_vec(1))?;
                if connection_id.len() > MAX_CONNECTION_ID_LEN {
                    return Err(Error::DecodingFrame);
                }
                let srt = d(dec.decode(16))?;
                let stateless_reset_token = <&[_; 16]>::try_from(srt)?;

                Ok(Self::NewConnectionId {
                    sequence_number,
                    retire_prior,
                    connection_id,
                    stateless_reset_token,
                })
            }
            FRAME_TYPE_RETIRE_CONNECTION_ID => Ok(Self::RetireConnectionId {
                sequence_number: dv(dec)?,
            }),
            FRAME_TYPE_PATH_CHALLENGE => {
                let data = d(dec.decode(8))?;
                let mut datav: [u8; 8] = [0; 8];
                datav.copy_from_slice(data);
                Ok(Self::PathChallenge { data: datav })
            }
            FRAME_TYPE_PATH_RESPONSE => {
                let data = d(dec.decode(8))?;
                let mut datav: [u8; 8] = [0; 8];
                datav.copy_from_slice(data);
                Ok(Self::PathResponse { data: datav })
            }
            FRAME_TYPE_CONNECTION_CLOSE_TRANSPORT | FRAME_TYPE_CONNECTION_CLOSE_APPLICATION => {
                let error_code = CloseError::from_type_bit(t, dv(dec)?);
                let frame_type = if t == FRAME_TYPE_CONNECTION_CLOSE_TRANSPORT {
                    dv(dec)?
                } else {
                    0
                };
                // We can tolerate this copy for now.
                let reason_phrase = String::from_utf8_lossy(d(dec.decode_vvec())?).to_string();
                Ok(Self::ConnectionClose {
                    error_code,
                    frame_type,
                    reason_phrase,
                })
            }
            FRAME_TYPE_HANDSHAKE_DONE => Ok(Self::HandshakeDone),
            FRAME_TYPE_ACK_FREQUENCY => {
                let seqno = dv(dec)?;
                let tolerance = dv(dec)?;
                if tolerance == 0 {
                    return Err(Error::FrameEncodingError);
                }
                let delay = dv(dec)?;
                let ignore_order = match d(dec.decode_uint(1))? {
                    0 => false,
                    1 => true,
                    _ => return Err(Error::FrameEncodingError),
                };
                Ok(Self::AckFrequency {
                    seqno,
                    tolerance,
                    delay,
                    ignore_order,
                })
            }
            FRAME_TYPE_DATAGRAM | FRAME_TYPE_DATAGRAM_WITH_LEN => {
                let fill = (t & DATAGRAM_FRAME_BIT_LEN) == 0;
                let data = if fill {
                    qtrace!("DATAGRAM frame, extends to the end of the packet");
                    dec.decode_remainder()
                } else {
                    qtrace!("DATAGRAM frame, with length");
                    d(dec.decode_vvec())?
                };
                Ok(Self::Datagram { data, fill })
            }
            _ => Err(Error::UnknownFrameType),
        }
    }
}

#[cfg(test)]
mod tests {
    use neqo_common::{Decoder, Encoder};

    use crate::{
        cid::MAX_CONNECTION_ID_LEN,
        ecn::EcnCount,
        frame::{AckRange, Frame, FRAME_TYPE_ACK},
        CloseError, Error, StreamId, StreamType,
    };

    fn just_dec(f: &Frame, s: &str) {
        let encoded = Encoder::from_hex(s);
        let decoded = Frame::decode(&mut encoded.as_decoder()).expect("Failed to decode frame");
        assert_eq!(*f, decoded);
    }

    #[test]
    fn padding() {
        let f = Frame::Padding(1);
        just_dec(&f, "00");
        let f = Frame::Padding(2);
        just_dec(&f, "0000");
    }

    #[test]
    fn ping() {
        let f = Frame::Ping;
        just_dec(&f, "01");
    }

    #[test]
    fn ack() {
        let ar = vec![AckRange { gap: 1, range: 2 }, AckRange { gap: 3, range: 4 }];

        let f = Frame::Ack {
            largest_acknowledged: 0x1234,
            ack_delay: 0x1235,
            first_ack_range: 0x1236,
            ack_ranges: ar.clone(),
            ecn_count: None,
        };

        just_dec(&f, "025234523502523601020304");

        // Try to parse ACK_ECN without ECN values
        let enc = Encoder::from_hex("035234523502523601020304");
        let mut dec = enc.as_decoder();
        assert_eq!(Frame::decode(&mut dec).unwrap_err(), Error::NoMoreData);

        // Try to parse ACK_ECN with ECN values
        let ecn_count = Some(EcnCount::new(0, 1, 2, 3));
        let fe = Frame::Ack {
            largest_acknowledged: 0x1234,
            ack_delay: 0x1235,
            first_ack_range: 0x1236,
            ack_ranges: ar,
            ecn_count,
        };
        let enc = Encoder::from_hex("035234523502523601020304010203");
        let mut dec = enc.as_decoder();
        assert_eq!(Frame::decode(&mut dec).unwrap(), fe);
    }

    #[test]
    fn reset_stream() {
        let f = Frame::ResetStream {
            stream_id: StreamId::from(0x1234),
            application_error_code: 0x77,
            final_size: 0x3456,
        };

        just_dec(&f, "04523440777456");
    }

    #[test]
    fn stop_sending() {
        let f = Frame::StopSending {
            stream_id: StreamId::from(63),
            application_error_code: 0x77,
        };

        just_dec(&f, "053F4077");
    }

    #[test]
    fn crypto() {
        let f = Frame::Crypto {
            offset: 1,
            data: &[1, 2, 3],
        };

        just_dec(&f, "060103010203");
    }

    #[test]
    fn new_token() {
        let f = Frame::NewToken {
            token: &[0x12, 0x34, 0x56],
        };

        just_dec(&f, "0703123456");
    }

    #[test]
    fn empty_new_token() {
        let mut dec = Decoder::from(&[0x07, 0x00][..]);
        assert_eq!(
            Frame::decode(&mut dec).unwrap_err(),
            Error::FrameEncodingError
        );
    }

    #[test]
    fn stream() {
        // First, just set the length bit.
        let f = Frame::Stream {
            fin: false,
            stream_id: StreamId::from(5),
            offset: 0,
            data: &[1, 2, 3],
            fill: false,
        };

        just_dec(&f, "0a0503010203");

        // Now with offset != 0 and FIN
        let f = Frame::Stream {
            fin: true,
            stream_id: StreamId::from(5),
            offset: 1,
            data: &[1, 2, 3],
            fill: false,
        };
        just_dec(&f, "0f050103010203");

        // Now to fill the packet.
        let f = Frame::Stream {
            fin: true,
            stream_id: StreamId::from(5),
            offset: 0,
            data: &[1, 2, 3],
            fill: true,
        };
        just_dec(&f, "0905010203");
    }

    #[test]
    fn max_data() {
        let f = Frame::MaxData {
            maximum_data: 0x1234,
        };

        just_dec(&f, "105234");
    }

    #[test]
    fn max_stream_data() {
        let f = Frame::MaxStreamData {
            stream_id: StreamId::from(5),
            maximum_stream_data: 0x1234,
        };

        just_dec(&f, "11055234");
    }

    #[test]
    fn max_streams() {
        let mut f = Frame::MaxStreams {
            stream_type: StreamType::BiDi,
            maximum_streams: 0x1234,
        };

        just_dec(&f, "125234");

        f = Frame::MaxStreams {
            stream_type: StreamType::UniDi,
            maximum_streams: 0x1234,
        };

        just_dec(&f, "135234");
    }

    #[test]
    fn data_blocked() {
        let f = Frame::DataBlocked { data_limit: 0x1234 };

        just_dec(&f, "145234");
    }

    #[test]
    fn stream_data_blocked() {
        let f = Frame::StreamDataBlocked {
            stream_id: StreamId::from(5),
            stream_data_limit: 0x1234,
        };

        just_dec(&f, "15055234");
    }

    #[test]
    fn streams_blocked() {
        let mut f = Frame::StreamsBlocked {
            stream_type: StreamType::BiDi,
            stream_limit: 0x1234,
        };

        just_dec(&f, "165234");

        f = Frame::StreamsBlocked {
            stream_type: StreamType::UniDi,
            stream_limit: 0x1234,
        };

        just_dec(&f, "175234");
    }

    #[test]
    fn new_connection_id() {
        let f = Frame::NewConnectionId {
            sequence_number: 0x1234,
            retire_prior: 0,
            connection_id: &[0x01, 0x02],
            stateless_reset_token: &[9; 16],
        };

        just_dec(&f, "1852340002010209090909090909090909090909090909");
    }

    #[test]
    fn too_large_new_connection_id() {
        let mut enc = Encoder::from_hex("18523400"); // up to the CID
        enc.encode_vvec(&[0x0c; MAX_CONNECTION_ID_LEN + 10]);
        enc.encode(&[0x11; 16][..]);
        assert_eq!(
            Frame::decode(&mut enc.as_decoder()).unwrap_err(),
            Error::DecodingFrame
        );
    }

    #[test]
    fn retire_connection_id() {
        let f = Frame::RetireConnectionId {
            sequence_number: 0x1234,
        };

        just_dec(&f, "195234");
    }

    #[test]
    fn path_challenge() {
        let f = Frame::PathChallenge { data: [9; 8] };

        just_dec(&f, "1a0909090909090909");
    }

    #[test]
    fn path_response() {
        let f = Frame::PathResponse { data: [9; 8] };

        just_dec(&f, "1b0909090909090909");
    }

    #[test]
    fn connection_close_transport() {
        let f = Frame::ConnectionClose {
            error_code: CloseError::Transport(0x5678),
            frame_type: 0x1234,
            reason_phrase: String::from("\x01\x02\x03"),
        };

        just_dec(&f, "1c80005678523403010203");
    }

    #[test]
    fn connection_close_application() {
        let f = Frame::ConnectionClose {
            error_code: CloseError::Application(0x5678),
            frame_type: 0,
            reason_phrase: String::from("\x01\x02\x03"),
        };

        just_dec(&f, "1d8000567803010203");
    }

    #[test]
    fn compare() {
        let f1 = Frame::Padding(1);
        let f2 = Frame::Padding(1);
        let f3 = Frame::Crypto {
            offset: 0,
            data: &[1, 2, 3],
        };
        let f4 = Frame::Crypto {
            offset: 0,
            data: &[1, 2, 3],
        };
        let f5 = Frame::Crypto {
            offset: 1,
            data: &[1, 2, 3],
        };
        let f6 = Frame::Crypto {
            offset: 0,
            data: &[1, 2, 4],
        };

        assert_eq!(f1, f2);
        assert_ne!(f1, f3);
        assert_eq!(f3, f4);
        assert_ne!(f3, f5);
        assert_ne!(f3, f6);
    }

    #[test]
    fn decode_ack_frame() {
        let res = Frame::decode_ack_frame(7, 2, &[AckRange { gap: 0, range: 3 }]);
        assert!(res.is_ok());
        assert_eq!(res.unwrap(), vec![5..=7, 0..=3]);
    }

    #[test]
    fn ack_frequency() {
        let f = Frame::AckFrequency {
            seqno: 10,
            tolerance: 5,
            delay: 2000,
            ignore_order: true,
        };
        just_dec(&f, "40af0a0547d001");
    }

    #[test]
    fn ack_frequency_ignore_error_error() {
        let enc = Encoder::from_hex("40af0a0547d003"); // ignore_order of 3
        assert_eq!(
            Frame::decode(&mut enc.as_decoder()).unwrap_err(),
            Error::FrameEncodingError
        );
    }

    /// Hopefully this test is eventually redundant.
    #[test]
    fn ack_frequency_zero_packets() {
        let enc = Encoder::from_hex("40af0a000101"); // packets of 0
        assert_eq!(
            Frame::decode(&mut enc.as_decoder()).unwrap_err(),
            Error::FrameEncodingError
        );
    }

    #[test]
    fn datagram() {
        // Without the length bit.
        let f = Frame::Datagram {
            data: &[1, 2, 3],
            fill: true,
        };

        just_dec(&f, "30010203");

        // With the length bit.
        let f = Frame::Datagram {
            data: &[1, 2, 3],
            fill: false,
        };
        just_dec(&f, "3103010203");
    }

    #[test]
    fn frame_decode_enforces_bound_on_ack_range() {
        let mut e = Encoder::new();

        e.encode_varint(FRAME_TYPE_ACK);
        e.encode_varint(0u64); // largest acknowledged
        e.encode_varint(0u64); // ACK delay
        e.encode_varint(u32::MAX); // ACK range count = huge, but maybe available for allocation

        assert_eq!(Err(Error::TooMuchData), Frame::decode(&mut e.as_decoder()));
    }

    #[test]
    #[should_panic(expected = "Failed to decode frame")]
    fn invalid_frame_type_len() {
        let f = Frame::Datagram {
            data: &[1, 2, 3],
            fill: true,
        };

        just_dec(&f, "4030010203");
    }
}

[ Dauer der Verarbeitung: 0.35 Sekunden  (vorverarbeitet)  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge