1 // Copyright (c) 2023 Huawei Device Co., Ltd.
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 //     http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 
14 use std::convert::TryFrom;
15 
16 use crate::error::HttpError;
17 use crate::h2::{ErrorCode, H2Error, Parts, PseudoHeaders};
18 use crate::headers;
19 
20 /// Mask for the END_STREAM flag.
21 /// When set, indicates that the sender will not send further frames for this
22 /// stream.
23 pub(crate) const END_STREAM_MASK: u8 = 0x01;
24 
25 /// Mask for the RST_STREAM flag.
26 /// When set, indicates that the stream is being terminated.
27 pub(crate) const RST_STREAM_MASK: u8 = 0x03;
28 
29 /// Mask for the END_HEADERS flag.
30 /// When set, indicates that this frame contains an entire header block and not
31 /// a fragment.
32 pub(crate) const END_HEADERS_MASK: u8 = 0x04;
33 
34 /// Mask for the PADDED flag.
35 /// When set, indicates that the frame payload is followed by a padding field.
36 pub(crate) const PADDED_MASK: u8 = 0x08;
37 
38 /// Mask for the HEADERS_PRIORITY flag.
39 /// When set, indicates that the headers frame also contains the priority
40 /// information.
41 pub(crate) const HEADERS_PRIORITY_MASK: u8 = 0x20;
42 
43 /// Mask for the ACK flag
44 pub(crate) const ACK_MASK: u8 = 0x1;
45 
46 /// HTTP/2 frame structure, including the stream ID, flags, and payload
47 /// information. The frame type information is represented by the `Payload`
48 /// type. This structure represents the fundamental unit of communication in
49 /// HTTP/2.
50 #[derive(Clone)]
51 pub struct Frame {
52     id: StreamId,
53     flags: FrameFlags,
54     payload: Payload,
55 }
56 
57 /// Enum representing the type of HTTP/2 frame.
58 /// Each HTTP/2 frame type serves a unique role in the communication process.
59 #[derive(PartialEq, Eq, Debug)]
60 pub enum FrameType {
61     Data = 0x0,
62     Headers = 0x1,
63     Priority = 0x2,
64     RstStream = 0x03,
65     Settings = 0x4,
66     PushPromise = 0x5,
67     Ping = 0x6,
68     Goaway = 0x7,
69     WindowUpdate = 0x8,
70     Continuation = 0x9,
71     // add more frame types as needed
72 }
73 
74 /// Enum representing the payload of an HTTP/2 frame.
75 /// The payload differs based on the type of frame.
76 #[derive(Clone)]
77 pub enum Payload {
78     /// HEADERS frame payload.
79     Headers(Headers),
80     /// DATA frame payload.
81     Data(Data),
82     /// PRIORITY frame payload.
83     Priority(Priority),
84     /// RST_STREAM frame payload.
85     RstStream(RstStream),
86     /// PING frame payload.
87     Ping(Ping),
88     /// SETTINGS frame payload.
89     Settings(Settings),
90     /// GOAWAY frame payload.
91     Goaway(Goaway),
92     /// WINDOW_UPDATE frame payload.
93     WindowUpdate(WindowUpdate),
94     /// PUSH_PROMISE
95     PushPromise(PushPromise),
96 }
97 
98 /// Enum representing the different settings that can be included in a SETTINGS
99 /// frame. Each setting has a different role in the HTTP/2 communication
100 /// process.
101 #[derive(Clone, PartialEq, Eq, Debug)]
102 pub enum Setting {
103     /// SETTINGS_HEADER_TABLE_SIZE
104     HeaderTableSize(u32),
105     /// SETTINGS_ENABLE_PUSH
106     EnablePush(bool),
107     /// SETTINGS_MAX_CONCURRENT_STREAMS
108     MaxConcurrentStreams(u32),
109     /// SETTINGS_INITIAL_WINDOW_SIZE
110     InitialWindowSize(u32),
111     /// SETTINGS_MAX_FRAME_SIZE
112     MaxFrameSize(u32),
113     /// SETTINGS_MAX_HEADER_LIST_SIZE
114     MaxHeaderListSize(u32),
115 }
116 
117 type StreamId = usize;
118 
119 /// HTTP/2 frame flags.
120 #[derive(Clone)]
121 pub struct FrameFlags(u8);
122 
123 /// HTTP/2 HEADERS frame's payload, contains pseudo headers and other headers.
124 #[derive(Clone)]
125 pub struct Headers {
126     parts: Parts,
127 }
128 
129 /// HTTP/2 DATA frame's payload, contains all content after padding is removed.
130 /// The DATA frame defines the payload data of an HTTP/2 request or response.
131 #[derive(Clone)]
132 pub struct Data {
133     data: Vec<u8>,
134 }
135 
136 /// Represents the PRIORITY frame payload.
137 /// The PRIORITY frame specifies the sender-advised priority of a stream.
138 #[derive(Clone)]
139 pub struct Priority {
140     exclusive: bool,
141     stream_dependency: u32,
142     weight: u8,
143 }
144 
145 /// The RST_STREAM frame allows for immediate termination of a stream.
146 /// RST_STREAM is sent to request cancellation of a stream or to indicate an
147 /// error situation.
148 #[derive(Clone)]
149 pub struct RstStream {
150     error_code: u32,
151 }
152 
153 /// Represents the PING frame payload.
154 /// The PING frame is a mechanism for measuring a minimal round-trip time from
155 /// the sender.
156 #[derive(Clone)]
157 pub struct Ping {
158     /// The opaque data of PING
159     pub data: [u8; 8],
160 }
161 
162 /// Represents the SETTINGS frame payload.
163 /// The SETTINGS frame conveys configuration parameters that affect how
164 /// endpoints communicate.
165 #[derive(Clone)]
166 pub struct Settings {
167     settings: Vec<Setting>,
168 }
169 
170 /// Represents the GOAWAY frame payload.
171 /// The GOAWAY frame is used to initiate shutdown of a connection or to signal
172 /// serious error conditions.
173 #[derive(Clone)]
174 pub struct Goaway {
175     error_code: u32,
176     last_stream_id: StreamId,
177     debug_data: Vec<u8>,
178 }
179 
180 /// Represents the WINDOW_UPDATE frame payload.
181 /// The WINDOW_UPDATE frame is used to implement flow control in HTTP/2.
182 #[derive(Clone)]
183 pub struct WindowUpdate {
184     window_size_increment: u32,
185 }
186 
187 /// Represents the PUSH_PROMISE frame payload.
188 /// The PUSH_PROMISE frame is used to notify the peer endpoint in advance of
189 /// streams the sender intends to initiate.
190 #[derive(Clone)]
191 pub struct PushPromise {
192     promised_stream_id: u32,
193     parts: Parts,
194 }
195 
196 /// A Builder of SETTINGS payload.
197 pub struct SettingsBuilder {
198     settings: Vec<Setting>,
199 }
200 
201 impl Frame {
202     /// Returns the stream identifier (`StreamId`) of the frame.
stream_id(&self) -> StreamId203     pub fn stream_id(&self) -> StreamId {
204         self.id
205     }
206 
207     /// Constructs a new `Frame` with the given `StreamId`, `FrameFlags`,
208     /// `Payload`.
new(id: StreamId, flags: FrameFlags, payload: Payload) -> Self209     pub fn new(id: StreamId, flags: FrameFlags, payload: Payload) -> Self {
210         Frame { id, flags, payload }
211     }
212 
213     /// Returns a reference to the frame's flags (`FrameFlags`).
flags(&self) -> &FrameFlags214     pub fn flags(&self) -> &FrameFlags {
215         &self.flags
216     }
217 
218     /// Returns a reference to the frame's payload (`Payload`).
payload(&self) -> &Payload219     pub fn payload(&self) -> &Payload {
220         &self.payload
221     }
222 
223     /// Returns a mutable reference to the frame's payload (`Payload`).
224     /// This can be used to modify the payload of the frame.
payload_mut(&mut self) -> &mut Payload225     pub(crate) fn payload_mut(&mut self) -> &mut Payload {
226         &mut self.payload
227     }
228 }
229 
230 impl FrameFlags {
231     /// Creates a new `FrameFlags` instance with the given `flags` byte.
new(flags: u8) -> Self232     pub fn new(flags: u8) -> Self {
233         FrameFlags(flags)
234     }
235 
236     /// Creates a new `FrameFlags` instance with no flags set.
empty() -> Self237     pub fn empty() -> Self {
238         FrameFlags(0)
239     }
240 
241     /// Judges the END_FLOW Flag is true.
is_end_stream(&self) -> bool242     pub fn is_end_stream(&self) -> bool {
243         self.0 & END_STREAM_MASK == END_STREAM_MASK
244     }
245 
246     /// Judges the END_HEADERS Flag is true.
is_end_headers(&self) -> bool247     pub fn is_end_headers(&self) -> bool {
248         self.0 & END_HEADERS_MASK == END_HEADERS_MASK
249     }
250 
251     /// Judges the PADDED Flag is true.
is_padded(&self) -> bool252     pub fn is_padded(&self) -> bool {
253         self.0 & PADDED_MASK == PADDED_MASK
254     }
255 
256     /// Judge the ACK flag is true.
is_ack(&self) -> bool257     pub fn is_ack(&self) -> bool {
258         self.0 & ACK_MASK == ACK_MASK
259     }
260 
261     /// Get Flags octet.
bits(&self) -> u8262     pub fn bits(&self) -> u8 {
263         self.0
264     }
265 
266     /// Sets the END_STREAM flag.
set_end_stream(&mut self, end_stream: bool)267     pub fn set_end_stream(&mut self, end_stream: bool) {
268         if end_stream {
269             self.0 |= END_STREAM_MASK;
270         } else {
271             self.0 &= !END_STREAM_MASK;
272         }
273     }
274 
275     /// Sets the END_HEADERS flag.
set_end_headers(&mut self, end_headers: bool)276     pub fn set_end_headers(&mut self, end_headers: bool) {
277         if end_headers {
278             self.0 |= END_HEADERS_MASK;
279         } else {
280             self.0 &= !END_HEADERS_MASK;
281         }
282     }
283 
284     /// Sets the PADDED flag.
set_padded(&mut self, padded: bool)285     pub fn set_padded(&mut self, padded: bool) {
286         if padded {
287             self.0 |= PADDED_MASK;
288         } else {
289             self.0 &= !PADDED_MASK;
290         }
291     }
292 }
293 
294 impl Payload {
295     /// Returns a reference to the Headers if the Payload is of the Headers
296     /// variant. If the Payload is not of the Headers variant, returns None.
as_headers(&self) -> Option<&Headers>297     pub(crate) fn as_headers(&self) -> Option<&Headers> {
298         if let Payload::Headers(headers) = self {
299             Some(headers)
300         } else {
301             None
302         }
303     }
304 
305     /// Returns the type of the frame (`FrameType`) that this payload would be
306     /// associated with. The returned `FrameType` is determined based on the
307     /// variant of the Payload.
frame_type(&self) -> FrameType308     pub fn frame_type(&self) -> FrameType {
309         match self {
310             Payload::Headers(_) => FrameType::Headers,
311             Payload::Data(_) => FrameType::Data,
312             Payload::Priority(_) => FrameType::Priority,
313             Payload::Ping(_) => FrameType::Ping,
314             Payload::RstStream(_) => FrameType::RstStream,
315             Payload::Settings(_) => FrameType::Settings,
316             Payload::Goaway(_) => FrameType::Goaway,
317             Payload::WindowUpdate(_) => FrameType::WindowUpdate,
318             Payload::PushPromise(_) => FrameType::PushPromise,
319         }
320     }
321 }
322 
323 impl Headers {
324     /// Creates a new Headers instance from the provided Parts.
new(parts: Parts) -> Self325     pub fn new(parts: Parts) -> Self {
326         Headers { parts }
327     }
328 
329     /// Returns pseudo headers and other headers as tuples.
parts(&self) -> (&PseudoHeaders, &headers::Headers)330     pub fn parts(&self) -> (&PseudoHeaders, &headers::Headers) {
331         self.parts.parts()
332     }
333 
334     /// Returns a copy of the internal parts of the Headers.
get_parts(&self) -> Parts335     pub(crate) fn get_parts(&self) -> Parts {
336         self.parts.clone()
337     }
338 }
339 
340 impl Data {
341     /// Creates a new Data instance containing the provided data.
new(data: Vec<u8>) -> Self342     pub fn new(data: Vec<u8>) -> Self {
343         Data { data }
344     }
345 
346     /// Return the `Vec` that contains the data payload.
data(&self) -> &Vec<u8>347     pub fn data(&self) -> &Vec<u8> {
348         &self.data
349     }
350 
351     /// Returns the number of bytes in the `Data` payload.
size(&self) -> usize352     pub fn size(&self) -> usize {
353         self.data.len()
354     }
355 }
356 
357 impl Settings {
358     /// Creates a new Settings instance containing the provided settings.
new(settings: Vec<Setting>) -> Self359     pub fn new(settings: Vec<Setting>) -> Self {
360         Settings { settings }
361     }
362 
363     /// Returns a slice of the settings.
get_settings(&self) -> &[Setting]364     pub fn get_settings(&self) -> &[Setting] {
365         &self.settings
366     }
367 
368     /// Adds or updates a setting.
update_setting(&mut self, setting: Setting)369     pub(crate) fn update_setting(&mut self, setting: Setting) {
370         let setting_id = setting.setting_identifier();
371         if let Some(existing_setting) = self
372             .settings
373             .iter_mut()
374             .find(|s| s.setting_identifier() == setting_id)
375         {
376             *existing_setting = setting;
377         } else {
378             self.settings.push(setting);
379         }
380     }
381 
382     /// Returns the total length of the settings when encoded.
encoded_len(&self) -> usize383     pub fn encoded_len(&self) -> usize {
384         let settings_count = self.settings.len();
385         // Each setting has a 2-byte ID and a 4-byte value
386         let setting_size = 6;
387         settings_count * setting_size
388     }
389 
390     /// Returns a ACK SETTINGS frame.
ack() -> Frame391     pub fn ack() -> Frame {
392         Frame::new(
393             0,
394             FrameFlags::new(0x1),
395             Payload::Settings(Settings::new(vec![])),
396         )
397     }
398 }
399 
400 impl Setting {
401     /// Returns the identifier associated with the setting.
setting_identifier(&self) -> u16402     pub fn setting_identifier(&self) -> u16 {
403         match self {
404             Setting::HeaderTableSize(_) => 0x01,
405             Setting::EnablePush(_) => 0x02,
406             Setting::MaxConcurrentStreams(_) => 0x03,
407             Setting::InitialWindowSize(_) => 0x04,
408             Setting::MaxFrameSize(_) => 0x05,
409             Setting::MaxHeaderListSize(_) => 0x06,
410         }
411     }
412 }
413 
414 impl SettingsBuilder {
415     /// `SettingsBuilder` constructor.
new() -> Self416     pub fn new() -> Self {
417         SettingsBuilder { settings: vec![] }
418     }
419 
420     /// SETTINGS_HEADER_TABLE_SIZE (0x01) setting.
header_table_size(mut self, size: u32) -> Self421     pub fn header_table_size(mut self, size: u32) -> Self {
422         self.settings.push(Setting::HeaderTableSize(size));
423         self
424     }
425 
426     /// SETTINGS_ENABLE_PUSH (0x02) setting.
enable_push(mut self, is_enable: bool) -> Self427     pub fn enable_push(mut self, is_enable: bool) -> Self {
428         self.settings.push(Setting::EnablePush(is_enable));
429         self
430     }
431 
432     /// SETTINGS_INITIAL_WINDOW_SIZE(0x04) setting.
initial_window_size(mut self, size: u32) -> Self433     pub fn initial_window_size(mut self, size: u32) -> Self {
434         self.settings.push(Setting::InitialWindowSize(size));
435         self
436     }
437 
438     /// SETTINGS_MAX_FRAME_SIZE (0x05) setting.
max_frame_size(mut self, size: u32) -> Self439     pub fn max_frame_size(mut self, size: u32) -> Self {
440         self.settings.push(Setting::MaxFrameSize(size));
441         self
442     }
443 
444     /// SETTINGS_MAX_HEADER_LIST_SIZE (0x06) setting.
max_header_list_size(mut self, size: u32) -> Self445     pub fn max_header_list_size(mut self, size: u32) -> Self {
446         self.settings.push(Setting::MaxHeaderListSize(size));
447         self
448     }
449 
450     /// Consumes the Builder and constructs a SETTINGS payload.
451     ///
452     /// # Examples
453     ///
454     /// ```
455     /// use ylong_http::h2::SettingsBuilder;
456     ///
457     /// let settings = SettingsBuilder::new()
458     ///     .enable_push(true)
459     ///     .header_table_size(4096)
460     ///     .max_frame_size(2 << 13)
461     ///     .build();
462     /// ```
build(self) -> Settings463     pub fn build(self) -> Settings {
464         Settings::new(self.settings)
465     }
466 }
467 
468 impl Default for SettingsBuilder {
default() -> Self469     fn default() -> Self {
470         Self::new()
471     }
472 }
473 
474 impl Goaway {
475     /// Creates a new Goaway instance with the provided error code, last stream
476     /// ID, and debug data.
new(error_code: u32, last_stream_id: StreamId, debug_data: Vec<u8>) -> Self477     pub fn new(error_code: u32, last_stream_id: StreamId, debug_data: Vec<u8>) -> Self {
478         Goaway {
479             error_code,
480             last_stream_id,
481             debug_data,
482         }
483     }
484 
485     /// Returns a slice of the debug data.
get_debug_data(&self) -> &[u8]486     pub fn get_debug_data(&self) -> &[u8] {
487         &self.debug_data
488     }
489 
490     /// Returns the identifier of the last stream processed by the sender.
get_last_stream_id(&self) -> StreamId491     pub fn get_last_stream_id(&self) -> StreamId {
492         self.last_stream_id
493     }
494 
495     /// Returns the error code.
get_error_code(&self) -> u32496     pub fn get_error_code(&self) -> u32 {
497         self.error_code
498     }
499 
500     /// Returns the total length of the Goaway frame when encoded.
encoded_len(&self) -> usize501     pub fn encoded_len(&self) -> usize {
502         8 + self.debug_data.len() // 4-byte Last-Stream-ID + 4-byte Error Code +
503                                   // Debug Data length
504     }
505 }
506 
507 impl WindowUpdate {
508     /// Creates a new WindowUpdate instance with the provided window size
509     /// increment.
new(window_size_increment: u32) -> Self510     pub fn new(window_size_increment: u32) -> Self {
511         WindowUpdate {
512             window_size_increment,
513         }
514     }
515 
516     /// Returns the window size increment.
get_increment(&self) -> u32517     pub fn get_increment(&self) -> u32 {
518         self.window_size_increment
519     }
520 
521     /// Returns the length of the WindowUpdate frame when encoded.
encoded_len(&self) -> usize522     pub fn encoded_len(&self) -> usize {
523         4 // 4-byte window size increment
524     }
525 }
526 
527 impl Priority {
528     /// Creates a new Priority instance with the provided exclusive flag, stream
529     /// dependency, and weight.
new(exclusive: bool, stream_dependency: u32, weight: u8) -> Self530     pub fn new(exclusive: bool, stream_dependency: u32, weight: u8) -> Self {
531         Priority {
532             exclusive,
533             stream_dependency,
534             weight,
535         }
536     }
537 
538     /// Returns whether the stream is exclusive.
get_exclusive(&self) -> bool539     pub fn get_exclusive(&self) -> bool {
540         self.exclusive
541     }
542 
543     /// Returns the stream dependency.
get_stream_dependency(&self) -> u32544     pub fn get_stream_dependency(&self) -> u32 {
545         self.stream_dependency
546     }
547 
548     /// Returns the weight of the stream.
get_weight(&self) -> u8549     pub fn get_weight(&self) -> u8 {
550         self.weight
551     }
552 }
553 
554 impl RstStream {
555     /// Creates a new RstStream instance with the provided error code.
new(error_code: u32) -> Self556     pub fn new(error_code: u32) -> Self {
557         Self { error_code }
558     }
559 
560     /// Returns the error code associated with the RstStream.
error_code(&self) -> u32561     pub fn error_code(&self) -> u32 {
562         self.error_code
563     }
564 
565     /// GET the `ErrorCode` of `RstStream`
error(&self, id: u32) -> Result<H2Error, H2Error>566     pub fn error(&self, id: u32) -> Result<H2Error, H2Error> {
567         Ok(H2Error::StreamError(
568             id,
569             ErrorCode::try_from(self.error_code)?,
570         ))
571     }
572 
573     /// Returns whether error code is 0.
is_no_error(&self) -> bool574     pub fn is_no_error(&self) -> bool {
575         self.error_code == 0
576     }
577 }
578 
579 impl Ping {
580     /// Creates a new Ping instance with the provided data.
581     pub fn new(data: [u8; 8]) -> Self {
582         Ping { data }
583     }
584 
585     /// Returns the data associated with the Ping.
data(&self) -> [u8586     pub fn data(&self) -> [u8; 8] {
587         self.data
588     }
589 
590     /// Returns a ACK PING frame.
ack(ping: Ping) -> Frame591     pub fn ack(ping: Ping) -> Frame {
592         Frame::new(0, FrameFlags::new(0x1), Payload::Ping(ping))
593     }
594 }
595 
596 impl PushPromise {
597     /// `PushPromise` constructor.
new(promised_stream_id: u32, parts: Parts) -> Self598     pub fn new(promised_stream_id: u32, parts: Parts) -> Self {
599         Self {
600             promised_stream_id,
601             parts,
602         }
603     }
604 }
605 
606 #[cfg(test)]
607 mod ut_frame {
608     use super::*;
609     use crate::h2::Parts;
610 
611     /// UT test cases for `SettingsBuilder`.
612     ///
613     /// # Brief
614     /// 1. Creates a `SettingsBuilder`.
615     /// 2. Sets various setting parameters using builder methods.
616     /// 3. Builds a `Settings` object.
617     /// 4. Gets a reference to the underlying `Vec<Setting>` from the `Settings`
618     ///    object.
619     /// 5. Iterates over each setting in the `Vec<Setting>` and checks whether
620     ///    it matches the expected value.
621     #[test]
ut_settings_builder()622     fn ut_settings_builder() {
623         let settings = SettingsBuilder::new()
624             .header_table_size(4096)
625             .enable_push(true)
626             .max_frame_size(16384)
627             .max_header_list_size(8192)
628             .build();
629 
630         let mut setting_iter = settings.get_settings().iter();
631         // Check that the first setting is as expected
632         assert_eq!(setting_iter.next(), Some(&Setting::HeaderTableSize(4096)));
633         // Check that the second setting is as expected
634         assert_eq!(setting_iter.next(), Some(&Setting::EnablePush(true)));
635         // Check that the third setting is as expected
636         assert_eq!(setting_iter.next(), Some(&Setting::MaxFrameSize(16384)));
637         // Check that the fourth setting is as expected
638         assert_eq!(setting_iter.next(), Some(&Setting::MaxHeaderListSize(8192)));
639         // Check that there are no more settings
640         assert_eq!(setting_iter.next(), None);
641     }
642 
643     /// UT test cases for `Ping`.
644     ///
645     /// # Brief
646     /// 1. Creates a `Ping` instance with specific data.
647     /// 2. Checks if the data of the `Ping` instance is correct.
648     #[test]
ut_ping()649     fn ut_ping() {
650         let data = [1, 2, 3, 4, 5, 6, 7, 8];
651         let ping = Ping::new(data);
652         assert_eq!(ping.data(), data);
653     }
654 
655     /// UT test cases for `Setting`.
656     ///
657     /// # Brief
658     /// 1. Creates a `Setting` instance for each possible variant with a
659     ///    specific value.
660     /// 2. Checks if the identifier of the `Setting` instance is correct.
661     #[test]
ut_setting()662     fn ut_setting() {
663         let setting_header_table_size = Setting::HeaderTableSize(4096);
664         assert_eq!(setting_header_table_size.setting_identifier(), 0x01);
665 
666         let setting_enable_push = Setting::EnablePush(true);
667         assert_eq!(setting_enable_push.setting_identifier(), 0x02);
668 
669         let setting_max_concurrent_streams = Setting::MaxConcurrentStreams(100);
670         assert_eq!(setting_max_concurrent_streams.setting_identifier(), 0x03);
671 
672         let setting_initial_window_size = Setting::InitialWindowSize(5000);
673         assert_eq!(setting_initial_window_size.setting_identifier(), 0x04);
674 
675         let setting_max_frame_size = Setting::MaxFrameSize(16384);
676         assert_eq!(setting_max_frame_size.setting_identifier(), 0x05);
677 
678         let setting_max_header_list_size = Setting::MaxHeaderListSize(8192);
679         assert_eq!(setting_max_header_list_size.setting_identifier(), 0x06);
680     }
681 
682     /// UT test cases for `Settings`.
683     ///
684     /// # Brief
685     /// 1. Creates a `Settings` instance with a list of settings.
686     /// 2. Checks if the list of settings in the `Settings` instance is correct.
687     /// 3. Checks if the encoded length of the settings is correct.
688     #[test]
ut_settings()689     fn ut_settings() {
690         let settings_list = vec![
691             Setting::HeaderTableSize(4096),
692             Setting::EnablePush(true),
693             Setting::MaxFrameSize(16384),
694             Setting::MaxHeaderListSize(8192),
695         ];
696         let settings = Settings::new(settings_list.clone());
697         assert_eq!(settings.get_settings(), settings_list.as_slice());
698 
699         let encoded_len = settings.encoded_len();
700         assert_eq!(encoded_len, settings_list.len() * 6);
701     }
702 
703     /// UT test cases for `Payload`.
704     ///
705     /// # Brief
706     /// 1. Creates an instance of `Payload` for each possible variant.
707     /// 2. Checks if the `frame_type` of the `Payload` instance is correct.
708     /// 3. Checks if `as_headers` method returns Some or None correctly.
709     #[test]
ut_payload()710     fn ut_payload() {
711         let payload_headers = Payload::Headers(Headers::new(Parts::new()));
712         assert_eq!(payload_headers.frame_type(), FrameType::Headers);
713         assert!(payload_headers.as_headers().is_some());
714 
715         let payload_data = Payload::Data(Data::new(b"hh".to_vec()));
716         assert_eq!(payload_data.frame_type(), FrameType::Data);
717         assert!(payload_data.as_headers().is_none());
718 
719         let payload_priority = Payload::Priority(Priority::new(true, 1, 10));
720         assert_eq!(payload_priority.frame_type(), FrameType::Priority);
721         assert!(payload_priority.as_headers().is_none());
722 
723         let payload_rst_stream = Payload::RstStream(RstStream::new(20));
724         assert_eq!(payload_rst_stream.frame_type(), FrameType::RstStream);
725         assert!(payload_rst_stream.as_headers().is_none());
726 
727         let payload_ping = Payload::Ping(Ping::new([0; 8]));
728         assert_eq!(payload_ping.frame_type(), FrameType::Ping);
729         assert!(payload_ping.as_headers().is_none());
730 
731         let payload_goaway = Payload::Goaway(Goaway::new(30, 20, vec![0; 0]));
732         assert_eq!(payload_goaway.frame_type(), FrameType::Goaway);
733         assert!(payload_goaway.as_headers().is_none());
734 
735         let payload_window_update = Payload::WindowUpdate(WindowUpdate::new(1024));
736         assert_eq!(payload_window_update.frame_type(), FrameType::WindowUpdate);
737         assert!(payload_window_update.as_headers().is_none());
738 
739         let payload_push_promise = Payload::PushPromise(PushPromise::new(3, Parts::new()));
740         assert_eq!(payload_push_promise.frame_type(), FrameType::PushPromise);
741         assert!(payload_push_promise.as_headers().is_none());
742     }
743 }
744