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}