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 //! http2 connection flow control. 15 16 use ylong_http::h2::{Frame, H2Error}; 17 18 use crate::util::h2::buffer::window::RecvWindow; 19 use crate::util::h2::buffer::SendWindow; 20 21 pub(crate) struct FlowControl { 22 recv_window: RecvWindow, 23 send_window: SendWindow, 24 } 25 26 impl FlowControl { new(conn_recv_window: u32, conn_send_window: u32) -> Self27 pub(crate) fn new(conn_recv_window: u32, conn_send_window: u32) -> Self { 28 FlowControl { 29 recv_window: RecvWindow::new(conn_recv_window as i32), 30 send_window: SendWindow::new(conn_send_window as i32), 31 } 32 } 33 check_conn_recv_window_update(&mut self) -> Option<Frame>34 pub(crate) fn check_conn_recv_window_update(&mut self) -> Option<Frame> { 35 self.recv_window.check_window_update(0) 36 } 37 setup_recv_window(&mut self, size: u32)38 pub(crate) fn setup_recv_window(&mut self, size: u32) { 39 let setup = size; 40 let actual = self.recv_window.actual_size() as u32; 41 if setup > actual { 42 let extra = setup - actual; 43 self.recv_window.increase_actual(extra); 44 } else { 45 let extra = actual - setup; 46 self.recv_window.reduce_actual(extra); 47 } 48 } 49 increase_send_size(&mut self, size: u32) -> Result<(), H2Error>50 pub(crate) fn increase_send_size(&mut self, size: u32) -> Result<(), H2Error> { 51 self.send_window.increase_size(size) 52 } 53 send_size_available(&self) -> usize54 pub(crate) fn send_size_available(&self) -> usize { 55 self.send_window.size_available() as usize 56 } 57 recv_notification_size_available(&self) -> u3258 pub(crate) fn recv_notification_size_available(&self) -> u32 { 59 self.recv_window.notification_available() 60 } 61 send_data(&mut self, size: u32)62 pub(crate) fn send_data(&mut self, size: u32) { 63 self.send_window.send_data(size) 64 } 65 recv_data(&mut self, size: u32)66 pub(crate) fn recv_data(&mut self, size: u32) { 67 self.recv_window.recv_data(size) 68 } 69 } 70 71 #[cfg(test)] 72 mod ut_flow_control { 73 74 use super::*; 75 76 /// UT test case for `FlowControl::new`. 77 /// 78 /// # Brief 79 /// 1. Create a new `FlowControl` instance with specific receive and send 80 /// window sizes. 81 /// 2. Asserts that the initial sizes are correctly set in both windows. 82 #[test] ut_fc_new()83 fn ut_fc_new() { 84 let fc = FlowControl::new(100, 200); 85 assert_eq!(fc.recv_window.actual_size(), 100); 86 assert_eq!(fc.send_window.size_available(), 200); 87 } 88 89 /// UT test case for `FlowControl::check_conn_recv_window_update`. 90 /// 91 /// # Brief 92 /// 1. Create a `FlowControl` instance. 93 /// 2. Simulates the behavior of `recv_window` and Asserts that 94 /// `check_conn_recv_window_update` returns `None`. 95 #[test] ut_fc_check_conn_recv_window_update()96 fn ut_fc_check_conn_recv_window_update() { 97 let mut fc = FlowControl::new(100, 200); 98 let frame = fc.check_conn_recv_window_update(); 99 assert!(frame.is_none()); 100 } 101 102 /// UT test case for `FlowControl::setup_recv_window` 103 /// 104 /// # Brief 105 /// 1. Set receive window size. 106 /// 2. Asserts that the receive window size is correctly. 107 #[test] ut_fc_setup_recv_window()108 fn ut_fc_setup_recv_window() { 109 let mut fc = FlowControl::new(100, 200); 110 fc.setup_recv_window(200); 111 assert_eq!(fc.recv_window.actual_size(), 200); 112 fc.setup_recv_window(100); 113 assert_eq!(fc.recv_window.actual_size(), 100); 114 } 115 116 /// UT test case for `FlowControl::increase_send_size`. 117 /// 118 /// # Brief 119 /// 1. Increases the send window size by a specified amount. 120 /// 2. Asserts that the size increase is successful and the window is 121 /// updated correctly. 122 #[test] ut_fc_increase_send_size()123 fn ut_fc_increase_send_size() { 124 let mut fc = FlowControl::new(100, 200); 125 let res = fc.increase_send_size(50); 126 assert!(res.is_ok()); 127 assert_eq!(fc.send_window.size_available(), 250); 128 } 129 130 /// UT test case for `FlowControl::send_size_available`. 131 /// 132 /// # Brief 133 /// 1. Check the available size for sending data in the send window. 134 /// 2. Asserts that the available size is as expected. 135 #[test] ut_fc_send_size_available()136 fn ut_fc_send_size_available() { 137 let fc = FlowControl::new(100, 200); 138 assert_eq!(fc.send_size_available(), 200); 139 } 140 141 /// UT test case for `FlowControl::recv_notification_size_available`. 142 /// 143 /// # Brief 144 /// 1. Checks the available size for receiving notificaitons in the receive 145 /// window. 146 /// 2. Asserts that the available notification size matches the value in 147 /// `recv_window`. 148 #[test] ut_fc_recv_notification_size_available()149 fn ut_fc_recv_notification_size_available() { 150 let fc = FlowControl::new(100, 200); 151 let notificaiton_size = fc.recv_notification_size_available(); 152 assert_eq!(notificaiton_size, fc.recv_window.notification_available()); 153 } 154 155 /// UT test case for `FlowControl::send_data` and `FlowControl::recv_data`. 156 /// 157 /// # Brief 158 /// 1. Sends data using the send window. 159 /// 2. Receives data using the receive window. 160 /// 3. Asserts that the available send window and available notification 161 /// size is reduced correctly. 162 #[test] ut_fc_send_and_recv_data()163 fn ut_fc_send_and_recv_data() { 164 let mut fc = FlowControl::new(100, 200); 165 fc.send_data(50); 166 fc.recv_data(50); 167 assert_eq!(fc.send_window.size_available(), 150); 168 assert_eq!(fc.recv_window.notification_available(), 50); 169 } 170 } 171