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