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