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 use std::collections::HashMap; 15 use std::str; 16 use std::str::FromStr; 17 use std::sync::{Arc, Mutex}; 18 use std::time::{Duration, Instant}; 19 20 use ylong_http::request::uri::{Host, Port}; 21 22 use crate::async_impl::Response; 23 use crate::util::config::HttpVersion; 24 use crate::util::pool::PoolKey; 25 use crate::util::request::RequestArc; 26 27 const DEFAULT_MAX_AGE: u64 = 24 * 60 * 60; 28 29 #[derive(Clone)] 30 pub(crate) struct AltService { 31 pub(crate) http_version: HttpVersion, 32 // todo: use this later 33 #[allow(unused)] 34 pub(crate) src_host: Host, 35 pub(crate) host: Option<Host>, 36 pub(crate) port: Port, 37 pub(crate) lifetime: Instant, 38 } 39 40 pub(crate) struct AltServiceMap { 41 inner: Arc<Mutex<HashMap<PoolKey, Vec<AltService>>>>, 42 } 43 44 impl AltServiceMap { 45 pub(crate) fn get_alt_svcs(&self, key: &PoolKey) -> Option<Vec<AltService>> { 46 let mut lock = self.inner.lock().unwrap(); 47 let vec = lock.get_mut(key)?; 48 vec.retain(|alt_scv| alt_scv.lifetime >= Instant::now()); 49 Some(vec.clone()) 50 } 51 parse_alt_svcnull52 fn parse_alt_svc(src_host: &Host, values: &[u8]) -> Option<AltService> { 53 // The alt_value/parameters are divided by ';' 54 let mut value_it = values.split(|c| *c == b';'); 55 // the first value_it is alpn="[host]:port" 56 let alternative = value_it.next()?; 57 let mut words = alternative.split(|c| *c == b'='); 58 59 let http_version = words.next()?.try_into().ok()?; 60 let mut host_port = words.next()?; 61 host_port = &host_port[1..host_port.len() - 1]; 62 let index = host_port.iter().position(|&x| x == b':')?; 63 let (host, port) = if index == 0 { 64 ( 65 None, 66 Port::from_str(str::from_utf8(&host_port[1..]).ok()?).ok()?, 67 ) 68 } else { 69 ( 70 Some(Host::from_str(str::from_utf8(&host_port[..index]).ok()?).ok()?), 71 Port::from_str(str::from_utf8(&host_port[(index + 1)..]).ok()?).ok()?, 72 ) 73 }; 74 75 let mut seconds = DEFAULT_MAX_AGE; 76 77 for para in value_it { 78 let para = str::from_utf8(para).ok()?.trim().as_bytes(); 79 // parameter: token "=" ( token / quoted-string ) 80 let mut para_it = para.split(|c| *c == b'='); 81 // only support ma now 82 if para_it.next()? == b"ma" { 83 let para = str::from_utf8(para_it.next()?).ok()?; 84 seconds = para.parse::<u64>().ok()?; 85 break; 86 } 87 } 88 89 Some(AltService { 90 http_version, 91 src_host: src_host.clone(), 92 host, 93 port, 94 lifetime: Instant::now().checked_add(Duration::from_secs(seconds))?, 95 }) 96 } 97 98 pub(crate) fn set_alt_svcs(&self, mut request: RequestArc, response: &Response) { 99 let mut lock = self.inner.lock().unwrap(); 100 let uri = request.ref_mut().uri(); 101 let Some(scheme) = uri.scheme() else { 102 return; 103 }; 104 let Some(authority) = uri.authority() else { 105 return; 106 }; 107 let Some(host) = uri.host() else { 108 return; 109 }; 110 let key = PoolKey::new(scheme.clone(), authority.clone()); 111 match response.headers().get("Alt-Svc") { 112 None => {} 113 Some(values) => { 114 let mut new_alt_svcs = Vec::new(); 115 for value in values.iter() { 116 let slice = value.as_slice(); 117 if slice == "clear".as_bytes() { 118 lock.remove(&key); 119 return; 120 } 121 // Alt_Svcs are divided by ',' 122 for slice in slice.split(|c| *c == b',') { 123 if let Some(alt_svc) = Self::parse_alt_svc(host, slice) { 124 new_alt_svcs.push(alt_svc); 125 } 126 } 127 } 128 lock.insert(key, new_alt_svcs); 129 } 130 } 131 } 132 133 pub(crate) fn new() -> Self { 134 Self { 135 inner: Arc::new(Mutex::new(HashMap::new())), 136 } 137 } 138 } 139