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