Skip to main content

trillium/
transport.rs

1use futures_lite::{AsyncRead, AsyncWrite};
2use std::{any::Any, borrow::Cow, io::Result, net::SocketAddr, time::Duration};
3
4/// # The interface that the http protocol is communicated over.
5///
6/// This trait supports several common interfaces supported by tcp
7/// streams, but also can be implemented for other stream types. All trait
8/// functions are currently optional.
9///
10/// **Note:** `Transport` uses the [`AsyncWrite`](futures_lite::AsyncWrite) and
11/// [`AsyncRead`](futures_lite::AsyncRead) traits from [`futures-lite`](futures_lite), which differ
12/// from the tokio `AsyncRead` / `AsyncWrite` traits. Runtime adapters handle bridging these at the
13/// boundary.
14#[allow(unused)]
15pub trait Transport: Any + AsyncRead + AsyncWrite + Unpin + Send + Sync + 'static {
16    /// # Sets the linger duration of this transport by setting the `SO_LINGER` option
17    ///
18    /// See [`std::net::TcpStream::set_linger`]
19    /// Optional to implement.
20    ///
21    /// # Errors
22    ///
23    /// Return an error if this transport supports setting linger and
24    /// attempting to do so is unsuccessful.
25    fn set_linger(&mut self, linger: Option<Duration>) -> Result<()> {
26        Ok(())
27    }
28
29    /// # Sets the value of the `TCP_NODELAY` option on this transport.
30    ///
31    /// See [`std::net::TcpStream::set_nodelay`].
32    /// Optional to implement.
33    ///
34    /// # Errors
35    ///
36    /// Return an error if this transport supports setting nodelay and
37    /// attempting to do so is unsuccessful.
38    fn set_nodelay(&mut self, nodelay: bool) -> Result<()> {
39        Ok(())
40    }
41
42    /// # Sets the value for the `IP_TTL` option on this transport.
43    ///
44    /// See [`std::net::TcpStream::set_ttl`]
45    /// Optional to implement
46    ///
47    /// # Errors
48    ///
49    /// Return an error if this transport supports setting ttl and
50    /// attempting to do so is unsuccessful.
51    fn set_ip_ttl(&mut self, ttl: u32) -> Result<()> {
52        Ok(())
53    }
54
55    /// # Returns the socket address of the remote peer of this transport.
56    ///
57    /// # Errors
58    ///
59    /// Return an error if this transport supports retrieving the
60    /// remote peer but attempting to do so is unsuccessful.
61    fn peer_addr(&self) -> Result<Option<SocketAddr>> {
62        Ok(None)
63    }
64
65    /// # The protocol negotiated via TLS ALPN with the peer, if any.
66    ///
67    /// Used by the runtime adapter to dispatch between HTTP/1.1 and HTTP/2 on the same TLS
68    /// listener (`Some(b"h2")` → HTTP/2, anything else → HTTP/1.1) and by the client to pick
69    /// between HTTP/1.1 and HTTP/2 when speaking to a server.
70    ///
71    /// The returned [`Cow`] borrows from `self` when the backend exposes the protocol as a
72    /// borrowed slice (e.g. rustls) and is owned when the backend copies (e.g. native-tls). The
73    /// default returns `None` so transports that don't speak TLS — or don't want to opt into
74    /// ALPN-based dispatch — don't need to implement it.
75    fn negotiated_alpn(&self) -> Option<Cow<'_, [u8]>> {
76        None
77    }
78}
79
80impl Transport for Box<dyn Transport> {
81    fn set_linger(&mut self, linger: Option<Duration>) -> Result<()> {
82        (**self).set_linger(linger)
83    }
84
85    fn set_nodelay(&mut self, nodelay: bool) -> Result<()> {
86        (**self).set_nodelay(nodelay)
87    }
88
89    fn set_ip_ttl(&mut self, ttl: u32) -> Result<()> {
90        (**self).set_ip_ttl(ttl)
91    }
92
93    fn peer_addr(&self) -> Result<Option<SocketAddr>> {
94        (**self).peer_addr()
95    }
96
97    fn negotiated_alpn(&self) -> Option<Cow<'_, [u8]>> {
98        (**self).negotiated_alpn()
99    }
100}
101
102impl Transport for trillium_http::Synthetic {}
103
104impl Transport for trillium_http::h2::H2Transport {
105    fn negotiated_alpn(&self) -> Option<Cow<'_, [u8]>> {
106        Some(Cow::Borrowed(b"h2"))
107    }
108}