trillium_tls_common/lib.rs
1#![forbid(unsafe_code)]
2#![deny(
3 missing_copy_implementations,
4 missing_crate_level_docs,
5 missing_debug_implementations,
6 missing_docs,
7 nonstandard_style,
8 unused_qualifications
9)]
10
11/*!
12This crate provides the common interface for server-side tls
13[`Acceptor`]s and client-side [`Connector`]s, abstracting over various
14implementations.
15*/
16
17pub use async_trait::async_trait;
18pub use futures_lite::{AsyncRead, AsyncWrite};
19use std::{convert::Infallible, fmt::Debug, future::Future};
20pub use url::Url;
21
22/**
23This trait provides the common interface for server-side tls
24acceptors, abstracting over various implementations
25
26The only implementation provided by this crate is `()`, which is
27a noop acceptor, and passes through the `Input` type.
28
29Implementing this trait looks like:
30```rust,ignore
31use trillium_tls_common::{AsyncRead, AsyncWrite, async_trait};
32#[async_trait]
33impl<Input> Acceptor<Input> for my_tls_impl::Acceptor
34where
35 Input: AsyncRead + AsyncWrite + Send + Sync + Unpin + 'static,
36{
37 type Output = my_tls_impl::TlsStream<Input>;
38 type Error = my_tls_impl::Error;
39 async fn accept(&self, input: Input) -> Result<Self::Output, Self::Error> {
40 self.accept(input).await
41 }
42}
43```
44*/
45#[async_trait]
46pub trait Acceptor<Input>: Clone + Send + Sync + 'static
47where
48 Input: AsyncRead + AsyncWrite + Send + Sync + Unpin + 'static,
49{
50 /// The stream type. For example, TlsStream<Input>
51 type Output: AsyncRead + AsyncWrite + Send + Sync + Unpin + 'static;
52
53 /// An error type that [`Acceptor::accept`] may return
54 type Error: Debug + Send + Sync;
55
56 /**
57 Transform an Input (`AsyncRead + AsyncWrite + Send + Sync + Unpin + 'static`) into Self::Output
58
59 Async trait signature:
60 ```rust,ignore
61 async fn accept(&self, input: Input) -> Result<Self::Output, Self::Error>;
62 ```
63 */
64 async fn accept(&self, input: Input) -> Result<Self::Output, Self::Error>;
65}
66
67#[async_trait]
68impl<Input> Acceptor<Input> for ()
69where
70 Input: AsyncRead + AsyncWrite + Send + Sync + Unpin + 'static,
71{
72 type Output = Input;
73 type Error = Infallible;
74 async fn accept(&self, input: Input) -> Result<Self::Output, Self::Error> {
75 Ok(input)
76 }
77}
78
79/**
80Interface for runtime and tls adapters for the trillium client
81
82See
83[`trillium_client`](https://docs.trillium.rs/trillium_client) for more
84information on usage.
85*/
86#[async_trait]
87pub trait Connector: Clone + Send + Sync + 'static {
88 /// The async read + write type for this connector, often a TcpStream or TlSStream
89 type Transport: AsyncRead + AsyncWrite + Unpin + Send + Sync + 'static;
90
91 /// A type that can be used to configure this Connector. It will be passed into [`Connector::connect`].
92 type Config: Debug + Default + Send + Sync + Clone;
93
94 /// A SocketAddr representation of the other side of this connection
95 fn peer_addr(transport: &Self::Transport) -> std::io::Result<std::net::SocketAddr>;
96
97 /**
98 Initiate a connection to the provided url, using the configuration.
99
100 Async trait signature:
101 ```rust,ignore
102 async fn connect(url: &Url, config: &Self::Config) -> std::io::Result<Self::Transport>;
103 ```
104 */
105 async fn connect(url: &Url, config: &Self::Config) -> std::io::Result<Self::Transport>;
106
107 /**
108 Spawn and detach a task on the runtime. Although this may seem
109 unrelated to the purpose of a tcp connector, it is required as a
110 workaround for the absence of async drop in order to enable
111 keepalive connection pooling. TLS implementations that wrap a
112 runtime implementation should call through to the inner spawn.
113 */
114 fn spawn<Fut>(future: Fut)
115 where
116 Fut: Future + Send + 'static,
117 <Fut as Future>::Output: Send;
118}