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