monoio_transports/connectors/
mod.rs

1//! Defines core traits and types for creating and composing network connectors.
2//!
3//! This module provides the following key components:
4//!
5//! - The [`Connector`] trait for establishing connections
6//! - The [`ConnectorExt`] trait for adding timeout functionality
7//! - The [`TransportConnMetadata`] trait for retrieving connection metadata
8mod l4_connector;
9#[cfg(feature = "hyper")]
10pub mod pollio;
11mod tls_connector;
12
13use std::{future::Future, time::Duration};
14
15pub use l4_connector::*;
16pub use tls_connector::*;
17
18/// The [`Connector`] trait defines an interface for establishing connections.
19/// This trait is designed to be composable, allowing for the creation of modular
20/// and stackable connectors. Each connector in the stack can add its own layer
21/// of functionality, such as TCP connection, Unix Domain Socket (UDS) connection,
22/// TLS encryption, or HTTP protocol handling.
23///
24/// # Type Parameters
25///
26/// - `K`: The key type used to identify the connection target.
27///
28/// # Associated Types
29///
30/// - `Connection`: The type of the established connection.
31/// - `Error`: The error type that may occur during connection.
32///
33/// # Examples
34///
35/// Here are examples of how to stack different connectors:
36///
37/// ## HTTP over Unix Domain Socket
38///
39/// ```rust
40/// use http::request;
41/// use monoio_http::{common::body::HttpBody, h1::payload::Payload};
42/// use monoio_transports::{
43///     connectors::{Connector, UnixConnector},
44///     http::HttpConnector,
45/// };
46///
47/// #[monoio::main]
48/// async fn main() -> Result<(), monoio_transports::TransportError> {
49///     let connector: HttpConnector<UnixConnector, _, _> = HttpConnector::default();
50///     let mut conn = connector.connect("./examples/uds.sock").await?;
51///
52///     let req = request::Builder::new()
53///         .uri("/get")
54///         .header("Host", "test")
55///         .body(HttpBody::H1(Payload::None))
56///         .unwrap();
57///
58///     let (res, _) = conn.send_request(req).await;
59///     let resp = res?;
60///     assert_eq!(200, resp.status());
61///
62///     Ok(())
63/// }
64/// ```
65///
66/// ## HTTPS over TCP
67///
68/// ```rust
69/// use monoio_transports::{
70///     connectors::{Connector, TcpConnector, TcpTlsAddr, TlsConnector},
71///     http::HttpConnector,
72/// };
73///
74/// #[monoio::main]
75/// async fn main() -> Result<(), monoio_transports::TransportError> {
76///     let connector: HttpConnector<TlsConnector<TcpConnector>, _, _> =
77///         HttpConnector::build_tls_http2_only();
78///
79///     let addr: TcpTlsAddr = "https://example.com".try_into()?;
80///     let conn = connector.connect(addr).await?;
81///
82///     // Use the connection...
83///
84///     Ok(())
85/// }
86/// ```
87///
88/// These examples demonstrate how connectors can be stacked to create
89/// different connection types (HTTP over UDS, HTTPS over TCP) using the
90/// same `Connector` trait.
91pub trait Connector<K> {
92    type Connection;
93    type Error;
94
95    /// Attempts to establish a connection.
96    ///
97    /// # Parameters
98    ///
99    /// - `key`: The key identifying the connection target.
100    ///
101    /// # Returns
102    ///
103    /// A `Future` that resolves to a `Result` containing either the established
104    /// connection or an error.
105    fn connect(&self, key: K) -> impl Future<Output = Result<Self::Connection, Self::Error>>;
106}
107
108/// Extends the `Connector` trait with timeout functionality.
109///
110/// This trait is automatically implemented for all types that implement `Connector<K>`.
111pub trait ConnectorExt<K>: Connector<K> {
112    fn connect_with_timeout(
113        &self,
114        key: K,
115        timeout: Duration,
116    ) -> impl Future<Output = Result<Result<Self::Connection, Self::Error>, monoio::time::error::Elapsed>>;
117}
118
119impl<K, T: Connector<K>> ConnectorExt<K> for T {
120    #[inline]
121    fn connect_with_timeout(
122        &self,
123        key: K,
124        timeout: Duration,
125    ) -> impl Future<Output = Result<Result<Self::Connection, Self::Error>, monoio::time::error::Elapsed>>
126    {
127        monoio::time::timeout(timeout, self.connect(key))
128    }
129}
130
131/// Provides additional information about the connection.
132///
133/// This trait is useful for transport connectors like TLS, TCP, UDS, etc.
134pub trait TransportConnMetadata {
135    /// The type of metadata associated with this connection.
136    type Metadata;
137
138    /// Retrieves the metadata from the connection.
139    ///
140    /// # Returns
141    ///
142    /// An instance of the associated type `Metadata`.
143    fn get_conn_metadata(&self) -> Self::Metadata;
144}
145
146/// Represents the Application-Layer Protocol Negotiation (ALPN) protocol.
147#[derive(Default, Copy, Clone)]
148pub enum Alpn {
149    /// HTTP/2 protocol
150    HTTP2,
151    /// HTTP/1.1 protocol
152    HTTP11,
153    /// No ALPN protocol specified (default)
154    #[default]
155    None,
156}
157
158/// Holds metadata for a transport connection.
159///
160/// Currently only holds the ALPN protocol information.
161#[derive(Default, Copy, Clone)]
162pub struct TransportConnMeta {
163    alpn: Alpn,
164}
165
166impl TransportConnMeta {
167    /// Sets the ALPN protocol based on the provided byte vector.
168    ///
169    /// # Arguments
170    ///
171    /// * `alpn` - An optional vector of bytes representing the ALPN protocol.
172    ///
173    /// # Notes
174    ///
175    /// Sets `Alpn::HTTP2` if the vector contains "h2", otherwise sets `Alpn::None`.
176    pub fn set_alpn(&mut self, alpn: Option<Vec<u8>>) {
177        self.alpn = match alpn {
178            Some(p) if p == b"h2" => Alpn::HTTP2,
179            _ => Alpn::None,
180        }
181    }
182
183    /// Checks if the ALPN protocol is set to HTTP/2.
184    ///
185    /// # Returns
186    ///
187    /// `true` if the ALPN protocol is HTTP/2, `false` otherwise.
188    pub fn is_alpn_h2(&self) -> bool {
189        matches!(self.alpn, Alpn::HTTP2)
190    }
191}