• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 //! HTTP configure module.
15 #[cfg(feature = "http3")]
16 use crate::ErrorKind;
17 
18 /// Options and flags which can be used to configure `HTTP` related logic.
19 #[derive(Clone)]
20 pub(crate) struct HttpConfig {
21     pub(crate) version: HttpVersion,
22 
23     #[cfg(feature = "http1_1")]
24     pub(crate) http1_config: http1::H1Config,
25 
26     #[cfg(feature = "http2")]
27     pub(crate) http2_config: http2::H2Config,
28 
29     #[cfg(feature = "http3")]
30     pub(crate) http3_config: http3::H3Config,
31 }
32 
33 impl HttpConfig {
34     /// Creates a new, default `HttpConfig`.
new() -> Self35     pub(crate) fn new() -> Self {
36         Self {
37             version: HttpVersion::Negotiate,
38 
39             #[cfg(feature = "http1_1")]
40             http1_config: http1::H1Config::default(),
41 
42             #[cfg(feature = "http2")]
43             http2_config: http2::H2Config::new(),
44 
45             #[cfg(feature = "http3")]
46             http3_config: http3::H3Config::new(),
47         }
48     }
49 }
50 
51 impl Default for HttpConfig {
default() -> Self52     fn default() -> Self {
53         Self::new()
54     }
55 }
56 
57 /// `HTTP` version to use.
58 #[derive(PartialEq, Eq, Clone)]
59 pub enum HttpVersion {
60     /// Enforces `HTTP/1.1` or `HTTP/1.0` requests.
61     Http1,
62 
63     #[cfg(feature = "http2")]
64     /// Enforce `HTTP/2.0` requests without `HTTP/1.1` Upgrade or ALPN.
65     Http2,
66 
67     #[cfg(feature = "http3")]
68     /// Enforces `HTTP/3` requests.
69     Http3,
70 
71     /// Negotiate the protocol version through the ALPN.
72     Negotiate,
73 }
74 
75 #[cfg(feature = "http3")]
76 impl TryFrom<&[u8]> for HttpVersion {
77     type Error = ErrorKind;
78 
try_from(value: &[u8]) -> Result<Self, Self::Error>79     fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
80         if value == b"h1" {
81             return Ok(HttpVersion::Http1);
82         }
83         #[cfg(feature = "http2")]
84         if value == b"h2" {
85             return Ok(HttpVersion::Http2);
86         }
87         if value == b"h3" {
88             Ok(HttpVersion::Http3)
89         } else {
90             Err(ErrorKind::Other)
91         }
92     }
93 }
94 
95 #[cfg(feature = "http1_1")]
96 pub(crate) mod http1 {
97     const DEFAULT_MAX_CONN_NUM: usize = 6;
98 
99     #[derive(Clone)]
100     pub(crate) struct H1Config {
101         max_conn_num: usize,
102     }
103 
104     impl H1Config {
set_max_conn_num(&mut self, num: usize)105         pub(crate) fn set_max_conn_num(&mut self, num: usize) {
106             self.max_conn_num = num
107         }
108 
max_conn_num(&self) -> usize109         pub(crate) fn max_conn_num(&self) -> usize {
110             self.max_conn_num
111         }
112     }
113 
114     impl Default for H1Config {
default() -> Self115         fn default() -> Self {
116             Self {
117                 max_conn_num: DEFAULT_MAX_CONN_NUM,
118             }
119         }
120     }
121 }
122 
123 #[cfg(feature = "http2")]
124 pub(crate) mod http2 {
125     const DEFAULT_MAX_FRAME_SIZE: u32 = 16 * 1024;
126     const DEFAULT_HEADER_TABLE_SIZE: u32 = 4096;
127     const DEFAULT_MAX_HEADER_LIST_SIZE: u32 = 16 * 1024;
128     // window size at the client connection level
129     // The initial value specified in rfc9113 is 64kb,
130     // but the default value is 1mb for performance purposes and is synchronized
131     // using WINDOW_UPDATE after sending SETTINGS.
132     const DEFAULT_CONN_WINDOW_SIZE: u32 = 10 * 1024 * 1024;
133     const DEFAULT_STREAM_WINDOW_SIZE: u32 = 2 * 1024 * 1024;
134 
135     /// Settings which can be used to configure a http2 connection.
136     #[derive(Clone)]
137     pub(crate) struct H2Config {
138         max_frame_size: u32,
139         max_header_list_size: u32,
140         header_table_size: u32,
141         init_conn_window_size: u32,
142         init_stream_window_size: u32,
143         enable_push: bool,
144         allowed_cache_frame_size: usize,
145         use_huffman: bool,
146     }
147 
148     impl H2Config {
149         /// `H2Config` constructor.
new() -> Self150         pub(crate) fn new() -> Self {
151             Self::default()
152         }
153 
154         /// Sets the SETTINGS_MAX_FRAME_SIZE.
set_max_frame_size(&mut self, size: u32)155         pub(crate) fn set_max_frame_size(&mut self, size: u32) {
156             self.max_frame_size = size;
157         }
158 
159         /// Sets the SETTINGS_MAX_HEADER_LIST_SIZE.
set_max_header_list_size(&mut self, size: u32)160         pub(crate) fn set_max_header_list_size(&mut self, size: u32) {
161             self.max_header_list_size = size;
162         }
163 
164         /// Sets the SETTINGS_HEADER_TABLE_SIZE.
set_header_table_size(&mut self, size: u32)165         pub(crate) fn set_header_table_size(&mut self, size: u32) {
166             self.header_table_size = size;
167         }
168 
set_conn_window_size(&mut self, size: u32)169         pub(crate) fn set_conn_window_size(&mut self, size: u32) {
170             self.init_conn_window_size = size;
171         }
172 
set_stream_window_size(&mut self, size: u32)173         pub(crate) fn set_stream_window_size(&mut self, size: u32) {
174             self.init_stream_window_size = size;
175         }
176 
set_allowed_cache_frame_size(&mut self, size: usize)177         pub(crate) fn set_allowed_cache_frame_size(&mut self, size: usize) {
178             self.allowed_cache_frame_size = size;
179         }
180 
set_use_huffman_coding(&mut self, use_huffman: bool)181         pub(crate) fn set_use_huffman_coding(&mut self, use_huffman: bool) {
182             self.use_huffman = use_huffman;
183         }
184 
185         /// Gets the SETTINGS_MAX_FRAME_SIZE.
max_frame_size(&self) -> u32186         pub(crate) fn max_frame_size(&self) -> u32 {
187             self.max_frame_size
188         }
189 
190         /// Gets the SETTINGS_MAX_HEADER_LIST_SIZE.
max_header_list_size(&self) -> u32191         pub(crate) fn max_header_list_size(&self) -> u32 {
192             self.max_header_list_size
193         }
194 
195         /// Gets the SETTINGS_MAX_FRAME_SIZE.
header_table_size(&self) -> u32196         pub(crate) fn header_table_size(&self) -> u32 {
197             self.header_table_size
198         }
199 
enable_push(&self) -> bool200         pub(crate) fn enable_push(&self) -> bool {
201             self.enable_push
202         }
203 
conn_window_size(&self) -> u32204         pub(crate) fn conn_window_size(&self) -> u32 {
205             self.init_conn_window_size
206         }
207 
stream_window_size(&self) -> u32208         pub(crate) fn stream_window_size(&self) -> u32 {
209             self.init_stream_window_size
210         }
211 
allowed_cache_frame_size(&self) -> usize212         pub(crate) fn allowed_cache_frame_size(&self) -> usize {
213             self.allowed_cache_frame_size
214         }
215 
use_huffman_coding(&self) -> bool216         pub(crate) fn use_huffman_coding(&self) -> bool {
217             self.use_huffman
218         }
219     }
220 
221     impl Default for H2Config {
default() -> Self222         fn default() -> Self {
223             Self {
224                 max_frame_size: DEFAULT_MAX_FRAME_SIZE,
225                 max_header_list_size: DEFAULT_MAX_HEADER_LIST_SIZE,
226                 header_table_size: DEFAULT_HEADER_TABLE_SIZE,
227                 init_conn_window_size: DEFAULT_CONN_WINDOW_SIZE,
228                 init_stream_window_size: DEFAULT_STREAM_WINDOW_SIZE,
229                 enable_push: false,
230                 allowed_cache_frame_size: 5,
231                 use_huffman: true,
232             }
233         }
234     }
235 }
236 
237 #[cfg(feature = "http3")]
238 pub(crate) mod http3 {
239     const DEFAULT_MAX_FIELD_SECTION_SIZE: u64 = 16 * 1024;
240     const DEFAULT_QPACK_MAX_TABLE_CAPACITY: u64 = 16 * 1024;
241     const DEFAULT_QPACK_BLOCKED_STREAMS: u64 = 10;
242 
243     // todo: which settings should be pub to user
244     #[derive(Clone)]
245     pub(crate) struct H3Config {
246         max_field_section_size: u64,
247         qpack_max_table_capacity: u64,
248         qpack_blocked_streams: u64,
249         connect_protocol_enabled: Option<u64>,
250         additional_settings: Option<Vec<(u64, u64)>>,
251     }
252 
253     impl H3Config {
254         /// `H3Config` constructor.
255 
new() -> Self256         pub(crate) fn new() -> Self {
257             Self::default()
258         }
259 
set_max_field_section_size(&mut self, size: u64)260         pub(crate) fn set_max_field_section_size(&mut self, size: u64) {
261             self.max_field_section_size = size;
262         }
263 
set_qpack_max_table_capacity(&mut self, size: u64)264         pub(crate) fn set_qpack_max_table_capacity(&mut self, size: u64) {
265             self.qpack_max_table_capacity = size;
266         }
267 
set_qpack_blocked_streams(&mut self, size: u64)268         pub(crate) fn set_qpack_blocked_streams(&mut self, size: u64) {
269             self.qpack_blocked_streams = size;
270         }
271 
272         #[allow(unused)]
set_connect_protocol_enabled(&mut self, size: u64)273         fn set_connect_protocol_enabled(&mut self, size: u64) {
274             self.connect_protocol_enabled = Some(size);
275         }
276 
277         #[allow(unused)]
insert_additional_settings(&mut self, key: u64, value: u64)278         fn insert_additional_settings(&mut self, key: u64, value: u64) {
279             if let Some(vec) = &mut self.additional_settings {
280                 vec.push((key, value));
281             } else {
282                 self.additional_settings = Some(vec![(key, value)]);
283             }
284         }
285 
max_field_section_size(&self) -> u64286         pub(crate) fn max_field_section_size(&self) -> u64 {
287             self.max_field_section_size
288         }
289 
qpack_max_table_capacity(&self) -> u64290         pub(crate) fn qpack_max_table_capacity(&self) -> u64 {
291             self.qpack_max_table_capacity
292         }
293 
qpack_blocked_streams(&self) -> u64294         pub(crate) fn qpack_blocked_streams(&self) -> u64 {
295             self.qpack_blocked_streams
296         }
297 
298         #[allow(unused)]
connect_protocol_enabled(&mut self) -> Option<u64>299         fn connect_protocol_enabled(&mut self) -> Option<u64> {
300             self.connect_protocol_enabled
301         }
302 
303         #[allow(unused)]
additional_settings(&mut self) -> Option<Vec<(u64, u64)>>304         fn additional_settings(&mut self) -> Option<Vec<(u64, u64)>> {
305             self.additional_settings.clone()
306         }
307     }
308 
309     impl Default for H3Config {
default() -> Self310         fn default() -> Self {
311             Self {
312                 max_field_section_size: DEFAULT_MAX_FIELD_SECTION_SIZE,
313                 qpack_max_table_capacity: DEFAULT_QPACK_MAX_TABLE_CAPACITY,
314                 qpack_blocked_streams: DEFAULT_QPACK_BLOCKED_STREAMS,
315                 connect_protocol_enabled: None,
316                 additional_settings: None,
317             }
318         }
319     }
320 }
321