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