hyper_openssl/client/
cache.rs
1use linked_hash_set::LinkedHashSet;
2#[cfg(ossl111)]
3use openssl::ssl::SslVersion;
4use openssl::ssl::{SslSession, SslSessionRef};
5use std::borrow::Borrow;
6use std::collections::hash_map::Entry;
7use std::collections::HashMap;
8use std::hash::{Hash, Hasher};
9
10#[derive(Hash, PartialEq, Eq, Clone)]
11pub struct SessionKey {
12 pub host: String,
13 pub port: u16,
14}
15
16#[derive(Clone)]
17struct HashSession(SslSession);
18
19impl PartialEq for HashSession {
20 fn eq(&self, other: &HashSession) -> bool {
21 self.0.id() == other.0.id()
22 }
23}
24
25impl Eq for HashSession {}
26
27impl Hash for HashSession {
28 fn hash<H>(&self, state: &mut H)
29 where
30 H: Hasher,
31 {
32 self.0.id().hash(state)
33 }
34}
35
36impl Borrow<[u8]> for HashSession {
37 fn borrow(&self) -> &[u8] {
38 self.0.id()
39 }
40}
41
42pub struct SessionCache {
43 sessions: HashMap<SessionKey, LinkedHashSet<HashSession>>,
44 reverse: HashMap<HashSession, SessionKey>,
45}
46
47impl SessionCache {
48 pub fn new() -> SessionCache {
49 SessionCache {
50 sessions: HashMap::new(),
51 reverse: HashMap::new(),
52 }
53 }
54
55 pub fn insert(&mut self, key: SessionKey, session: SslSession) {
56 let session = HashSession(session);
57
58 self.sessions
59 .entry(key.clone())
60 .or_default()
61 .insert(session.clone());
62 self.reverse.insert(session, key);
63 }
64
65 pub fn get(&mut self, key: &SessionKey) -> Option<SslSession> {
66 let sessions = self.sessions.get_mut(key)?;
67 let session = sessions.front().cloned()?.0;
68
69 #[cfg(ossl111)]
70 {
71 if session.protocol_version() == SslVersion::TLS1_3 {
75 self.remove(&session);
76 }
77 }
78
79 Some(session)
80 }
81
82 pub fn remove(&mut self, session: &SslSessionRef) {
83 let key = match self.reverse.remove(session.id()) {
84 Some(key) => key,
85 None => return,
86 };
87
88 if let Entry::Occupied(mut sessions) = self.sessions.entry(key) {
89 sessions.get_mut().remove(session.id());
90 if sessions.get().is_empty() {
91 sessions.remove();
92 }
93 }
94 }
95}