tls_api/
acceptor_box.rs

1use std::fmt;
2use std::marker;
3
4use crate::assert_send;
5use crate::assert_sync;
6use crate::AsyncSocket;
7use crate::AsyncSocketBox;
8use crate::BoxFuture;
9use crate::ImplInfo;
10use crate::TlsAcceptor;
11use crate::TlsAcceptorBuilder;
12use crate::TlsStream;
13
14// Type
15
16/// Similar to [`TlsAcceptor`], but it is dynamic, does not require type parameter.
17///
18/// This can be obtained with [`TlsAcceptor::TYPE_DYN`].
19pub trait TlsAcceptorType: fmt::Debug + fmt::Display + Sync + 'static {
20    /// Whether this acceptor type is implemented.
21    ///
22    /// For example, `tls-api-security-framework` is available on Linux,
23    /// but all operations result in error, so `implemented()` returns `false`
24    /// for that implementation.
25    fn implemented(&self) -> bool;
26    /// Whether this implementation supports ALPN negotiation.
27    fn supports_alpn(&self) -> bool;
28    /// Whether this implementation supports construction of acceptor using
29    /// a pair of a DER certificate and file pair.
30    fn supports_der_keys(&self) -> bool;
31    /// Whether this implementation supports construction of acceptor using
32    /// PKCS #12 file.
33    fn supports_pkcs12_keys(&self) -> bool;
34    /// Unspecified version information about this implementation.
35    fn info(&self) -> ImplInfo;
36
37    /// New builder from given server key.
38    ///
39    /// This operation is guaranteed to fail if not [`TlsAcceptorType::supports_der_keys`].
40    fn builder_from_der_key(
41        &self,
42        cert: &[u8],
43        key: &[u8],
44    ) -> anyhow::Result<TlsAcceptorBuilderBox>;
45
46    /// New builder from given server key.
47    ///
48    /// This operation is guaranteed to fail if not [`TlsAcceptorType::supports_pkcs12_keys`].
49    fn builder_from_pkcs12(
50        &self,
51        pkcs12: &[u8],
52        passphrase: &str,
53    ) -> anyhow::Result<TlsAcceptorBuilderBox>;
54}
55
56pub(crate) struct TlsAcceptorTypeImpl<A: TlsAcceptor>(pub marker::PhantomData<A>);
57
58impl<A: TlsAcceptor> fmt::Debug for TlsAcceptorTypeImpl<A> {
59    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
60        fmt::Debug::fmt(&A::info(), f)
61    }
62}
63
64impl<A: TlsAcceptor> fmt::Display for TlsAcceptorTypeImpl<A> {
65    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
66        fmt::Debug::fmt(&A::info(), f)
67    }
68}
69
70impl<A: TlsAcceptor> TlsAcceptorType for TlsAcceptorTypeImpl<A> {
71    fn implemented(&self) -> bool {
72        A::IMPLEMENTED
73    }
74
75    fn supports_alpn(&self) -> bool {
76        A::SUPPORTS_ALPN
77    }
78
79    fn supports_der_keys(&self) -> bool {
80        A::SUPPORTS_DER_KEYS
81    }
82
83    fn supports_pkcs12_keys(&self) -> bool {
84        A::SUPPORTS_PKCS12_KEYS
85    }
86
87    fn info(&self) -> ImplInfo {
88        A::info()
89    }
90
91    fn builder_from_der_key(
92        &self,
93        cert: &[u8],
94        key: &[u8],
95    ) -> anyhow::Result<TlsAcceptorBuilderBox> {
96        let builder = A::builder_from_der_key(cert, key)?;
97        Ok(TlsAcceptorBuilderBox(Box::new(builder)))
98    }
99
100    fn builder_from_pkcs12(
101        &self,
102        pkcs12: &[u8],
103        passphrase: &str,
104    ) -> anyhow::Result<TlsAcceptorBuilderBox> {
105        let builder = A::builder_from_pkcs12(pkcs12, passphrase)?;
106        Ok(TlsAcceptorBuilderBox(Box::new(builder)))
107    }
108}
109
110// Builder
111
112trait TlsAcceptorBuilderDyn: Send + 'static {
113    fn type_dyn(&self) -> &'static dyn TlsAcceptorType;
114
115    fn set_alpn_protocols(&mut self, protocols: &[&[u8]]) -> anyhow::Result<()>;
116
117    fn build(self: Box<Self>) -> anyhow::Result<TlsAcceptorBox>;
118}
119
120impl<A: TlsAcceptorBuilder> TlsAcceptorBuilderDyn for A {
121    fn type_dyn(&self) -> &'static dyn TlsAcceptorType {
122        <A::Acceptor as TlsAcceptor>::TYPE_DYN
123    }
124
125    fn set_alpn_protocols(&mut self, protocols: &[&[u8]]) -> anyhow::Result<()> {
126        (*self).set_alpn_protocols(protocols)
127    }
128
129    fn build(self: Box<Self>) -> anyhow::Result<TlsAcceptorBox> {
130        Ok(TlsAcceptorBox(Box::new((*self).build()?)))
131    }
132}
133
134/// Dynamic version of [`TlsAcceptorBuilder`].
135pub struct TlsAcceptorBuilderBox(Box<dyn TlsAcceptorBuilderDyn>);
136
137impl TlsAcceptorBuilderBox {
138    /// Dynamic (without type parameter) version of the acceptor.
139    ///
140    /// This function returns an acceptor type, which can be used to constructor acceptors.
141    pub fn type_dyn(&self) -> &'static dyn TlsAcceptorType {
142        self.0.type_dyn()
143    }
144
145    /// Specify ALPN protocols for negotiation.
146    ///
147    /// This operation returns an error if the implemenation does not support ALPN.
148    ///
149    /// Whether ALPN is supported, can be queried using [`TlsAcceptor::SUPPORTS_ALPN`].
150    pub fn set_alpn_protocols(&mut self, protocols: &[&[u8]]) -> anyhow::Result<()> {
151        self.0.set_alpn_protocols(protocols)
152    }
153
154    /// Finish the acceptor construction.
155    pub fn build(self) -> anyhow::Result<TlsAcceptorBox> {
156        self.0.build()
157    }
158}
159
160// Acceptor
161
162trait TlsAcceptorDyn: Send + Sync + 'static {
163    fn type_dyn(&self) -> &'static dyn TlsAcceptorType;
164
165    fn accept(&self, socket: AsyncSocketBox) -> BoxFuture<'_, anyhow::Result<TlsStream>>;
166}
167
168impl<A: TlsAcceptor> TlsAcceptorDyn for A {
169    fn type_dyn(&self) -> &'static dyn TlsAcceptorType {
170        A::TYPE_DYN
171    }
172
173    fn accept(&self, socket: AsyncSocketBox) -> BoxFuture<'_, anyhow::Result<TlsStream>> {
174        self.accept(socket)
175    }
176}
177
178/// Dynamic version of [`TlsAcceptor`].
179///
180/// This can be constructed either with:
181/// * [`TlsAcceptor::into_dyn`]
182/// * [`TlsAcceptorBuilderBox::build`]
183pub struct TlsAcceptorBox(Box<dyn TlsAcceptorDyn>);
184
185impl TlsAcceptorBox {
186    pub(crate) fn new<A: TlsAcceptor>(acceptor: A) -> TlsAcceptorBox {
187        TlsAcceptorBox(Box::new(acceptor))
188    }
189
190    /// Dynamic (without type parameter) version of the acceptor.
191    ///
192    /// This function returns a connector type, which can be used to constructor connectors.
193    pub fn type_dyn(&self) -> &'static dyn TlsAcceptorType {
194        self.0.type_dyn()
195    }
196
197    /// Accept a connection.
198    ///
199    /// This operation returns a future which is resolved when the negotiation is complete,
200    /// and the stream is ready to send and receive.
201    pub fn accept<S: AsyncSocket>(&self, socket: S) -> BoxFuture<'_, anyhow::Result<TlsStream>> {
202        self.0.accept(AsyncSocketBox::new(socket))
203    }
204}
205
206fn _assert_kinds() {
207    assert_send::<TlsAcceptorBuilderBox>();
208    assert_send::<TlsAcceptorBox>();
209    assert_sync::<TlsAcceptorBox>();
210}