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 send and recv window definition. 15 16 use ylong_http::h2::{ErrorCode, Frame, FrameFlags, H2Error, Payload, WindowUpdate}; 17 18 pub(crate) struct SendWindow { 19 // As the sending window, the client retains only its visible window size, 20 // and updates only when the SETTINGS frame and WINDOW_UPDATE frame are received from the 21 // server. 22 size: i32, 23 } 24 25 impl SendWindow { new(size: i32) -> Self26 pub(crate) fn new(size: i32) -> Self { 27 Self { size } 28 } 29 size_available(&self) -> u3230 pub(crate) fn size_available(&self) -> u32 { 31 if self.size < 0 { 32 0 33 } else { 34 self.size as u32 35 } 36 } 37 reduce_size(&mut self, size: u32)38 pub(crate) fn reduce_size(&mut self, size: u32) { 39 self.size -= size as i32; 40 } 41 increase_size(&mut self, size: u32) -> Result<(), H2Error>42 pub(crate) fn increase_size(&mut self, size: u32) -> Result<(), H2Error> { 43 let (curr, overflow) = self.size.overflowing_add(size as i32); 44 if overflow { 45 return Err(H2Error::ConnectionError(ErrorCode::FlowControlError)); 46 } 47 if curr > crate::util::h2::MAX_FLOW_CONTROL_WINDOW as i32 { 48 return Err(H2Error::ConnectionError(ErrorCode::FlowControlError)); 49 } 50 self.size = curr; 51 Ok(()) 52 } 53 send_data(&mut self, size: u32)54 pub(crate) fn send_data(&mut self, size: u32) { 55 self.size -= size as i32; 56 } 57 } 58 59 #[derive(Default)] 60 pub(crate) struct RecvWindow { 61 // The window size visible to the server. 62 // notification decreases the value when a DATA frame is received 63 // and increases the value when a WINDOW_UPDATE is sent. 64 notification: i32, 65 // The window size visible to the client. 66 // Since client is a receiving (WINDOW_UPDATE sending) window, 67 // the actual remains unchanged except for SETTINGS set by the user updates. 68 actual: i32, 69 } 70 71 impl RecvWindow { new(size: i32) -> Self72 pub(crate) fn new(size: i32) -> Self { 73 Self { 74 notification: size, 75 actual: size, 76 } 77 } 78 unreleased_size(&self) -> Option<u32>79 pub(crate) fn unreleased_size(&self) -> Option<u32> { 80 let unreleased = self.actual - self.notification; 81 if unreleased <= 0 { 82 return None; 83 } 84 if unreleased * 2 > self.notification { 85 Some(unreleased as u32) 86 } else { 87 None 88 } 89 } 90 actual_size(&self) -> i3291 pub(crate) fn actual_size(&self) -> i32 { 92 self.actual 93 } 94 notification_available(&self) -> u3295 pub(crate) fn notification_available(&self) -> u32 { 96 if self.notification < 0 { 97 0 98 } else { 99 self.notification as u32 100 } 101 } 102 reduce_actual(&mut self, size: u32)103 pub(crate) fn reduce_actual(&mut self, size: u32) { 104 self.actual -= size as i32 105 } 106 increase_actual(&mut self, size: u32)107 pub(crate) fn increase_actual(&mut self, size: u32) { 108 self.actual += size as i32 109 } 110 reduce_notification(&mut self, size: u32)111 pub(crate) fn reduce_notification(&mut self, size: u32) { 112 self.notification -= size as i32 113 } 114 increase_notification(&mut self, size: u32)115 pub(crate) fn increase_notification(&mut self, size: u32) { 116 self.notification += size as i32 117 } 118 check_window_update(&mut self, id: u32) -> Option<Frame>119 pub(crate) fn check_window_update(&mut self, id: u32) -> Option<Frame> { 120 if let Some(size) = self.unreleased_size() { 121 self.increase_notification(size); 122 let window_update = WindowUpdate::new(size); 123 let frame = Frame::new( 124 id as usize, 125 FrameFlags::new(0), 126 Payload::WindowUpdate(window_update), 127 ); 128 Some(frame) 129 } else { 130 None 131 } 132 } 133 134 // The client receiving a DATA frame means that the server has less visible 135 // Windows recv_data(&mut self, size: u32)136 pub(crate) fn recv_data(&mut self, size: u32) { 137 self.notification -= size as i32; 138 } 139 } 140