net_wire/http2/
settings.rs1use super::error::Http2ParseError;
2use super::frame::Http2Frame;
3use super::layout::{validate_type, validate_zero_stream};
4use super::types::{Http2FrameType, Http2SettingId};
5use core::iter::FusedIterator;
6
7#[derive(Clone, Copy, Debug, Eq, PartialEq)]
9pub struct Http2Setting {
10 id: Http2SettingId,
11 value: u32,
12}
13
14impl Http2Setting {
15 pub const fn new(id: Http2SettingId, value: u32) -> Self {
17 Self { id, value }
18 }
19
20 fn parse(bytes: &[u8]) -> Self {
21 Self {
22 id: Http2SettingId::new(u16::from_be_bytes([bytes[0], bytes[1]])),
23 value: u32::from_be_bytes([bytes[2], bytes[3], bytes[4], bytes[5]]),
24 }
25 }
26
27 pub(super) const fn has_valid_intrinsic_value(self) -> bool {
28 match self.id {
29 Http2SettingId::ENABLE_PUSH | Http2SettingId::ENABLE_CONNECT_PROTOCOL => {
30 self.value <= 1
31 }
32 Http2SettingId::INITIAL_WINDOW_SIZE => self.value <= 0x7fff_ffff,
33 Http2SettingId::MAX_FRAME_SIZE => self.value >= 0x4000 && self.value <= 0x00ff_ffff,
34 _ => true,
35 }
36 }
37
38 pub const fn id(self) -> Http2SettingId {
40 self.id
41 }
42
43 pub const fn value(self) -> u32 {
45 self.value
46 }
47}
48
49#[derive(Clone, Copy, Debug, Eq, PartialEq)]
51pub struct Http2Settings<'a> {
52 frame: Http2Frame<'a>,
53}
54
55impl<'a> Http2Settings<'a> {
56 pub(super) fn from_validated(frame: Http2Frame<'a>) -> Self {
57 Self { frame }
58 }
59
60 pub fn parse(bytes: &'a [u8], maximum_payload: usize) -> Result<Self, Http2ParseError> {
62 Self::from_frame(Http2Frame::parse(bytes, maximum_payload)?)
63 }
64
65 pub fn from_frame(frame: Http2Frame<'a>) -> Result<Self, Http2ParseError> {
67 validate_type(frame, Http2FrameType::SETTINGS)?;
68 validate_zero_stream(frame)?;
69 let actual = frame.payload().len();
70 if frame.flags() & 0x1 != 0 && actual != 0 {
71 return Err(Http2ParseError::SettingsAckPayload { actual });
72 }
73 if !actual.is_multiple_of(6) {
74 return Err(Http2ParseError::SettingsPayloadLength { actual });
75 }
76 for bytes in frame.payload().chunks_exact(6) {
77 let setting = Http2Setting::parse(bytes);
78 if !setting.has_valid_intrinsic_value() {
79 return Err(Http2ParseError::InvalidSettingValue {
80 id: setting.id(),
81 value: setting.value(),
82 });
83 }
84 }
85 Ok(Self { frame })
86 }
87
88 pub const fn frame(&self) -> Http2Frame<'a> {
90 self.frame
91 }
92
93 pub fn as_bytes(&self) -> &'a [u8] {
95 self.frame.as_bytes()
96 }
97
98 pub fn is_ack(&self) -> bool {
100 self.frame.flags() & 0x1 != 0
101 }
102
103 pub fn settings(&self) -> Http2SettingsIter<'a> {
105 Http2SettingsIter {
106 bytes: self.frame.payload(),
107 }
108 }
109}
110
111#[derive(Clone, Debug)]
113pub struct Http2SettingsIter<'a> {
114 bytes: &'a [u8],
115}
116
117impl<'a> Iterator for Http2SettingsIter<'a> {
118 type Item = Http2Setting;
119
120 fn next(&mut self) -> Option<Self::Item> {
121 let (setting, remaining) = self.bytes.split_first_chunk::<6>()?;
122 self.bytes = remaining;
123 Some(Http2Setting::parse(setting))
124 }
125}
126
127impl FusedIterator for Http2SettingsIter<'_> {}