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 = "http2")] 24 pub(crate) http2_config: http2::H2Config, 25 26 #[cfg(feature = "http3")] 27 pub(crate) http3_config: http3::H3Config, 28 } 29 30 impl HttpConfig { 31 /// Creates a new, default `HttpConfig`. 32 pub(crate) fn new() -> Self { 33 Self { 34 version: HttpVersion::Negotiate, 35 36 #[cfg(feature = "http2")] 37 http2_config: http2::H2Config::new(), 38 39 #[cfg(feature = "http3")] 40 http3_config: http3::H3Config::new(), 41 } 42 } 43 } 44 45 impl Default for HttpConfig { defaultnull46 fn default() -> Self { 47 Self::new() 48 } 49 } 50 51 /// `HTTP` version to use. 52 #[derive(PartialEq, Eq, Clone)] 53 pub enum HttpVersion { 54 /// Enforces `HTTP/1.1` or `HTTP/1.0` requests. 55 Http1, 56 57 #[cfg(feature = "http2")] 58 /// Enforce `HTTP/2.0` requests without `HTTP/1.1` Upgrade or ALPN. 59 Http2, 60 61 #[cfg(feature = "http3")] 62 /// Enforces `HTTP/3` requests. 63 Http3, 64 65 /// Negotiate the protocol version through the ALPN. 66 Negotiate, 67 } 68 69 #[cfg(feature = "http3")] 70 impl TryFrom<&[u8]> for HttpVersion { 71 type Error = ErrorKind; 72 try_fromnull73 fn try_from(value: &[u8]) -> Result<Self, Self::Error> { 74 if value == b"h1" { 75 return Ok(HttpVersion::Http1); 76 } 77 #[cfg(feature = "http2")] 78 if value == b"h2" { 79 return Ok(HttpVersion::Http2); 80 } 81 if value == b"h3" { 82 Ok(HttpVersion::Http3) 83 } else { 84 Err(ErrorKind::Other) 85 } 86 } 87 } 88 89 #[cfg(feature = "http2")] 90 pub(crate) mod http2 { 91 const DEFAULT_MAX_FRAME_SIZE: u32 = 16 * 1024; 92 const DEFAULT_HEADER_TABLE_SIZE: u32 = 4096; 93 const DEFAULT_MAX_HEADER_LIST_SIZE: u32 = 16 * 1024; 94 // window size at the client connection level 95 // The initial value specified in rfc9113 is 64kb, 96 // but the default value is 1mb for performance purposes and is synchronized 97 // using WINDOW_UPDATE after sending SETTINGS. 98 const DEFAULT_CONN_WINDOW_SIZE: u32 = 10 * 1024 * 1024; 99 const DEFAULT_STREAM_WINDOW_SIZE: u32 = 2 * 1024 * 1024; 100 101 /// Settings which can be used to configure a http2 connection. 102 #[derive(Clone)] 103 pub(crate) struct H2Config { 104 max_frame_size: u32, 105 max_header_list_size: u32, 106 header_table_size: u32, 107 init_conn_window_size: u32, 108 init_stream_window_size: u32, 109 enable_push: bool, 110 allowed_cache_frame_size: usize, 111 use_huffman: bool, 112 } 113 114 impl H2Config { 115 /// `H2Config` constructor. 116 pub(crate) fn new() -> Self { 117 Self::default() 118 } 119 120 /// Sets the SETTINGS_MAX_FRAME_SIZE. 121 pub(crate) fn set_max_frame_size(&mut self, size: u32) { 122 self.max_frame_size = size; 123 } 124 125 /// Sets the SETTINGS_MAX_HEADER_LIST_SIZE. 126 pub(crate) fn set_max_header_list_size(&mut self, size: u32) { 127 self.max_header_list_size = size; 128 } 129 130 /// Sets the SETTINGS_HEADER_TABLE_SIZE. 131 pub(crate) fn set_header_table_size(&mut self, size: u32) { 132 self.header_table_size = size; 133 } 134 135 pub(crate) fn set_conn_window_size(&mut self, size: u32) { 136 self.init_conn_window_size = size; 137 } 138 139 pub(crate) fn set_stream_window_size(&mut self, size: u32) { 140 self.init_stream_window_size = size; 141 } 142 143 pub(crate) fn set_allowed_cache_frame_size(&mut self, size: usize) { 144 self.allowed_cache_frame_size = size; 145 } 146 147 pub(crate) fn set_use_huffman_coding(&mut self, use_huffman: bool) { 148 self.use_huffman = use_huffman; 149 } 150 151 /// Gets the SETTINGS_MAX_FRAME_SIZE. 152 pub(crate) fn max_frame_size(&self) -> u32 { 153 self.max_frame_size 154 } 155 156 /// Gets the SETTINGS_MAX_HEADER_LIST_SIZE. 157 pub(crate) fn max_header_list_size(&self) -> u32 { 158 self.max_header_list_size 159 } 160 161 /// Gets the SETTINGS_MAX_FRAME_SIZE. 162 pub(crate) fn header_table_size(&self) -> u32 { 163 self.header_table_size 164 } 165 166 pub(crate) fn enable_push(&self) -> bool { 167 self.enable_push 168 } 169 170 pub(crate) fn conn_window_size(&self) -> u32 { 171 self.init_conn_window_size 172 } 173 174 pub(crate) fn stream_window_size(&self) -> u32 { 175 self.init_stream_window_size 176 } 177 178 pub(crate) fn allowed_cache_frame_size(&self) -> usize { 179 self.allowed_cache_frame_size 180 } 181 182 pub(crate) fn use_huffman_coding(&self) -> bool { 183 self.use_huffman 184 } 185 } 186 187 impl Default for H2Config { defaultnull188 fn default() -> Self { 189 Self { 190 max_frame_size: DEFAULT_MAX_FRAME_SIZE, 191 max_header_list_size: DEFAULT_MAX_HEADER_LIST_SIZE, 192 header_table_size: DEFAULT_HEADER_TABLE_SIZE, 193 init_conn_window_size: DEFAULT_CONN_WINDOW_SIZE, 194 init_stream_window_size: DEFAULT_STREAM_WINDOW_SIZE, 195 enable_push: false, 196 allowed_cache_frame_size: 5, 197 use_huffman: true, 198 } 199 } 200 } 201 } 202 203 #[cfg(feature = "http3")] 204 pub(crate) mod http3 { 205 const DEFAULT_MAX_FIELD_SECTION_SIZE: u64 = 16 * 1024; 206 const DEFAULT_QPACK_MAX_TABLE_CAPACITY: u64 = 16 * 1024; 207 const DEFAULT_QPACK_BLOCKED_STREAMS: u64 = 10; 208 209 // todo: which settings should be pub to user 210 #[derive(Clone)] 211 pub(crate) struct H3Config { 212 max_field_section_size: u64, 213 qpack_max_table_capacity: u64, 214 qpack_blocked_streams: u64, 215 connect_protocol_enabled: Option<u64>, 216 additional_settings: Option<Vec<(u64, u64)>>, 217 } 218 219 impl H3Config { 220 /// `H3Config` constructor. 221 222 pub(crate) fn new() -> Self { 223 Self::default() 224 } 225 226 pub(crate) fn set_max_field_section_size(&mut self, size: u64) { 227 self.max_field_section_size = size; 228 } 229 230 pub(crate) fn set_qpack_max_table_capacity(&mut self, size: u64) { 231 self.qpack_max_table_capacity = size; 232 } 233 234 pub(crate) fn set_qpack_blocked_streams(&mut self, size: u64) { 235 self.qpack_blocked_streams = size; 236 } 237 238 #[allow(unused)] set_connect_protocol_enablednull239 fn set_connect_protocol_enabled(&mut self, size: u64) { 240 self.connect_protocol_enabled = Some(size); 241 } 242 243 #[allow(unused)] insert_additional_settingsnull244 fn insert_additional_settings(&mut self, key: u64, value: u64) { 245 if let Some(vec) = &mut self.additional_settings { 246 vec.push((key, value)); 247 } else { 248 self.additional_settings = Some(vec![(key, value)]); 249 } 250 } 251 252 pub(crate) fn max_field_section_size(&self) -> u64 { 253 self.max_field_section_size 254 } 255 256 pub(crate) fn qpack_max_table_capacity(&self) -> u64 { 257 self.qpack_max_table_capacity 258 } 259 260 pub(crate) fn qpack_blocked_streams(&self) -> u64 { 261 self.qpack_blocked_streams 262 } 263 264 #[allow(unused)] connect_protocol_enablednull265 fn connect_protocol_enabled(&mut self) -> Option<u64> { 266 self.connect_protocol_enabled 267 } 268 269 #[allow(unused)] additional_settingsnull270 fn additional_settings(&mut self) -> Option<Vec<(u64, u64)>> { 271 self.additional_settings.clone() 272 } 273 } 274 275 impl Default for H3Config { defaultnull276 fn default() -> Self { 277 Self { 278 max_field_section_size: DEFAULT_MAX_FIELD_SECTION_SIZE, 279 qpack_max_table_capacity: DEFAULT_QPACK_MAX_TABLE_CAPACITY, 280 qpack_blocked_streams: DEFAULT_QPACK_BLOCKED_STREAMS, 281 connect_protocol_enabled: None, 282 additional_settings: None, 283 } 284 } 285 } 286 } 287