1use arc_swap::ArcSwap;
2use boring::ssl::{
3 AlpnError, ClientHello, SelectCertError, SniError, SslAlert, SslContextRef, SslRef, SslSession,
4 SslSessionRef,
5};
6use boring::x509::X509StoreContextRef;
7use std::any::Any;
8use std::sync::Arc;
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12pub enum AlpnProtocol {
13 H1,
14 H2,
15 AcmeTls,
16}
17
18impl AlpnProtocol {
19 pub fn as_bytes(&self) -> &'static [u8] {
20 match self {
21 AlpnProtocol::H1 => b"http/1.1",
22 AlpnProtocol::H2 => b"h2",
23 AlpnProtocol::AcmeTls => b"acme-tls/1",
24 }
25 }
26}
27
28pub fn contains_alpn_protocol(client_protos: &[u8], target: AlpnProtocol) -> bool {
30 let target_bytes = target.as_bytes();
31 let mut pos = 0;
32 while pos < client_protos.len() {
33 let len = client_protos[pos] as usize;
34 pos += 1;
35 if pos + len > client_protos.len() {
36 break;
37 }
38 let proto = &client_protos[pos..pos + len];
39 if proto == target_bytes {
40 return true;
41 }
42 pos += len;
43 }
44 false
45}
46
47pub trait TlsCallbackHandler: Send + Sync + Any {
52 fn servername_callback(
56 &self,
57 _ssl: &mut SslRef,
58 _alert: &mut SslAlert,
59 ) -> Result<(), SniError> {
60 Ok(())
61 }
62
63 fn alpn_select_callback<'a>(
65 &self,
66 _ssl: &mut SslRef,
67 _client_protos: &'a [u8],
68 ) -> Result<&'a [u8], AlpnError> {
69 Err(AlpnError::NOACK)
70 }
71
72 fn select_certificate_callback(
74 &self,
75 _client_hello: ClientHello<'_>,
76 ) -> Result<(), SelectCertError> {
77 Ok(())
78 }
79
80 fn verify_callback(&self, preverify_ok: bool, _x509_ctx: &mut X509StoreContextRef) -> bool {
85 preverify_ok
87 }
88
89 fn new_session_callback(&self, _ssl: &mut SslRef, _session: SslSession) {}
93
94 fn remove_session_callback(&self, _ctx: &SslContextRef, _session: &SslSessionRef) {}
96
97 fn get_session_callback(
99 &self,
100 _ssl: &mut SslRef,
101 _session_id: &[u8],
102 ) -> Result<Option<SslSession>, boring::ssl::GetSessionPendingError> {
103 Ok(None)
104 }
105
106 fn psk_server_callback(
109 &self,
110 _ssl: &mut SslRef,
111 _identity: Option<&[u8]>,
112 _psk: &mut [u8],
113 ) -> Result<usize, boring::error::ErrorStack> {
114 Ok(0)
116 }
117
118 fn status_callback(&self, _ssl: &mut SslRef) -> Result<bool, boring::error::ErrorStack> {
121 Ok(true)
122 }
123
124 fn keylog_callback(&self, _ssl: &SslRef, _line: &str) {}
127}
128
129#[derive(Clone)]
133pub struct TlsCallback {
134 inner: Arc<ArcSwap<Option<Box<dyn TlsCallbackHandler>>>>,
135}
136
137impl Default for TlsCallback {
138 fn default() -> Self {
139 Self::new()
140 }
141}
142
143impl TlsCallback {
144 pub fn new() -> Self {
145 Self {
146 inner: Arc::new(ArcSwap::from_pointee(None)),
147 }
148 }
149
150 pub fn set_handler(&self, handler: impl TlsCallbackHandler + 'static) {
151 self.inner.store(Arc::new(Some(
152 Box::new(handler) as Box<dyn TlsCallbackHandler>
153 )));
154 }
155
156 pub fn get_handler(&self) -> Arc<Option<Box<dyn TlsCallbackHandler>>> {
157 self.inner.load().clone()
158 }
159}