Eine aufbereitete Darstellung der Quelle

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

Benutzer

Quelle  hframe.rs

  Sprache: Rust
 

// 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.

use std::fmt::{Debug, Write as _};

use neqo_common::{Buffer, Decoder, Encoder};
use neqo_transport::StreamId;
use nss::random;

use crate::{Error, Priority, PushId, Res, frames::reader::FrameDecoder, settings::HSettings};

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct HFrameType(pub u64);

impl HFrameType {
    pub const DATA: Self = Self(0x0);
    pub const HEADERS: Self = Self(0x1);
    pub const CANCEL_PUSH: Self = Self(0x3);
    pub const SETTINGS: Self = Self(0x4);
    pub const PUSH_PROMISE: Self = Self(0x5);
    pub const GOAWAY: Self = Self(0x7);
    pub const MAX_PUSH_ID: Self = Self(0xd);
    pub const PRIORITY_UPDATE_REQUEST: Self = Self(0xf0700);
    pub const PRIORITY_UPDATE_PUSH: Self = Self(0xf0701);

    /// See <https://www.rfc-editor.org/rfc/rfc9114.html#section-11.2.1> for these reserved types.
    pub const RESERVED: &[Self] = &[Self(0x2), Self(0x6), Self(0x8), Self(0x9)];
}

impl From<HFrameType> for u64 {
    fn from(t: HFrameType) -> Self {
        t.0
    }
}

// data for DATA frame is not read into HFrame::Data.
#[derive(PartialEq, Eq, Debug)]
pub enum HFrame {
    Data {
        len: u64, // length of the data
    },
    Headers {
        header_block: Vec<u8>,
    },
    CancelPush {
        push_id: PushId,
    },
    Settings {
        settings: HSettings,
    },
    PushPromise {
        push_id: PushId,
        header_block: Vec<u8>,
    },
    Goaway {
        stream_id: StreamId,
    },
    MaxPushId {
        push_id: PushId,
    },
    Grease,
    PriorityUpdateRequest {
        element_id: u64,
        priority: Priority,
    },
    PriorityUpdatePush {
        element_id: u64,
        priority: Priority,
    },
}

impl HFrame {
    fn get_type(&self) -> HFrameType {
        match self {
            Self::Data { .. } => HFrameType::DATA,
            Self::Headers { .. } => HFrameType::HEADERS,
            Self::CancelPush { .. } => HFrameType::CANCEL_PUSH,
            Self::Settings { .. } => HFrameType::SETTINGS,
            Self::PushPromise { .. } => HFrameType::PUSH_PROMISE,
            Self::Goaway { .. } => HFrameType::GOAWAY,
            Self::MaxPushId { .. } => HFrameType::MAX_PUSH_ID,
            Self::PriorityUpdateRequest { .. } => HFrameType::PRIORITY_UPDATE_REQUEST,
            Self::PriorityUpdatePush { .. } => HFrameType::PRIORITY_UPDATE_PUSH,
            Self::Grease => {
                let r = u64::from_ne_bytes(random::<8>());
                // Zero out the top 7 bits: 2 for being a varint; 5 to account for the *0x1f.
                HFrameType((r >> 7) * 0x1f + 0x21)
            }
        }
    }

    pub fn encode<B: Buffer>(&self, enc: &mut Encoder<B>) {
        enc.encode_varint(self.get_type());

        match self {
            Self::Data { len } => {
                // DATA frame only encode the length here.
                enc.encode_varint(*len);
            }
            Self::Headers { header_block } => {
                enc.encode_vvec(header_block);
            }
            Self::CancelPush { push_id } => {
                enc.encode_vvec_with(|enc_inner| {
                    enc_inner.encode_varint(*push_id);
                });
            }
            Self::Settings { settings } => {
                settings.encode_frame_contents(enc);
            }
            Self::PushPromise {
                push_id,
                header_block,
            } => {
                enc.encode_varint(
                    (header_block.len() + (Encoder::varint_len(u64::from(*push_id)))) as u64,
                );
                enc.encode_varint(*push_id);
                enc.encode(header_block);
            }
            Self::Goaway { stream_id } => {
                enc.encode_vvec_with(|enc_inner| {
                    enc_inner.encode_varint(stream_id.as_u64());
                });
            }
            Self::MaxPushId { push_id } => {
                enc.encode_vvec_with(|enc_inner| {
                    enc_inner.encode_varint(*push_id);
                });
            }
            Self::Grease => {
                // Encode some number of random bytes.
                let r = random::<8>();
                enc.encode_vvec(&r[1..usize::from(1 + (r[0] & 0x7))]);
            }
            Self::PriorityUpdateRequest {
                element_id,
                priority,
            }
            | Self::PriorityUpdatePush {
                element_id,
                priority,
            } => {
                enc.encode_vvec_with(|enc_inner| {
                    enc_inner.encode_varint(*element_id);
                    write!(enc_inner, "{priority}").expect("write OK");
                });
            }
        }
    }
}

impl FrameDecoder<Selffor HFrame {
    #[cfg(feature = "build-fuzzing-corpus")]
    const FUZZING_CORPUS: Option<&'static str> = Some("hframe");

    fn frame_type_allowed(frame_type: HFrameType) -> Res<()> {
        if HFrameType::RESERVED.contains(&frame_type) {
            return Err(Error::HttpFrameUnexpected);
        }
        Ok(())
    }

    fn decode(frame_type: HFrameType, frame_len: u64, data: Option<&[u8]>) -> Res<Option<Self>> {
        if frame_type == HFrameType::DATA {
            Ok(Some(Self::Data { len: frame_len }))
        } else if let Some(payload) = data {
            let mut dec = Decoder::from(payload);
            Ok(match frame_type {
                HFrameType::DATA => unreachable!("DATA frame has been handled already"),
                HFrameType::HEADERS => Some(Self::Headers {
                    header_block: dec.decode_remainder().to_vec(),
                }),
                HFrameType::CANCEL_PUSH => Some(Self::CancelPush {
                    push_id: dec.decode_varint().ok_or(Error::HttpFrame)?.into(),
                }),
                HFrameType::SETTINGS => {
                    let mut settings = HSettings::default();
                    settings.decode_frame_contents(&mut dec).map_err(|e| {
                        if e == Error::HttpSettings {
                            e
                        } else {
                            Error::HttpFrame
                        }
                    })?;
                    Some(Self::Settings { settings })
                }
                HFrameType::PUSH_PROMISE => Some(Self::PushPromise {
                    push_id: dec.decode_varint().ok_or(Error::HttpFrame)?.into(),
                    header_block: dec.decode_remainder().to_vec(),
                }),
                HFrameType::GOAWAY => Some(Self::Goaway {
                    stream_id: StreamId::new(dec.decode_varint().ok_or(Error::HttpFrame)?),
                }),
                HFrameType::MAX_PUSH_ID => Some(Self::MaxPushId {
                    push_id: dec.decode_varint().ok_or(Error::HttpFrame)?.into(),
                }),
                HFrameType::PRIORITY_UPDATE_REQUEST | HFrameType::PRIORITY_UPDATE_PUSH => {
                    let element_id = dec.decode_varint().ok_or(Error::HttpFrame)?;
                    let priority = dec.decode_remainder();
                    let priority = Priority::from_bytes(priority)?;
                    if frame_type == HFrameType::PRIORITY_UPDATE_REQUEST {
                        Some(Self::PriorityUpdateRequest {
                            element_id,
                            priority,
                        })
                    } else {
                        Some(Self::PriorityUpdatePush {
                            element_id,
                            priority,
                        })
                    }
                }
                _ => None,
            })
        } else {
            Ok(None)
        }
    }

    fn is_known_type(frame_type: HFrameType) -> bool {
        matches!(
            frame_type,
            HFrameType::DATA
                | HFrameType::HEADERS
                | HFrameType::CANCEL_PUSH
                | HFrameType::SETTINGS
                | HFrameType::PUSH_PROMISE
                | HFrameType::GOAWAY
                | HFrameType::MAX_PUSH_ID
                | HFrameType::PRIORITY_UPDATE_REQUEST
                | HFrameType::PRIORITY_UPDATE_PUSH
        )
    }
}

Messung V0.5 in Prozent
C=80 H=97 G=88

¤ Dauer der Verarbeitung: 0.15 Sekunden  (vorverarbeitet am  2026-08-27) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Statistik
#Sources=434850
#Domains=661743