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}