Skip to main content

ergon_io/
any.rs

1//! One endpoint type for both protocols, so WebSocket and HTTP connections
2//! share one driver (one `poll` per loop iteration).
3
4use std::net::SocketAddr;
5
6use crate::RxMeta;
7use crate::endpoint::sealed::{Deliver, DialIo, Io};
8use crate::endpoint::{ConnId, ConnMut};
9use crate::error::Result;
10use crate::http::{HttpConn, HttpDial, HttpHandler};
11use crate::ws_conn::{WsConn, WsDial, WsHandler};
12
13/// A WebSocket or an HTTP connection.
14pub enum AnyConn {
15    /// WebSocket.
16    Ws(WsConn),
17    /// HTTP/1.1.
18    Http(HttpConn),
19}
20
21impl AnyConn {
22    /// The WebSocket connection, if it is one.
23    pub const fn ws(&mut self) -> Option<&mut WsConn> {
24        match self {
25            Self::Ws(c) => Some(c),
26            Self::Http(_) => None,
27        }
28    }
29
30    /// The HTTP connection, if it is one.
31    pub const fn http(&mut self) -> Option<&mut HttpConn> {
32        match self {
33            Self::Http(c) => Some(c),
34            Self::Ws(_) => None,
35        }
36    }
37
38    /// What the quick-ACK route check found for this connection
39    /// ([`crate::route::RouteCheck::Pending`] while ergon-io's warning
40    /// thread is still looking it up).
41    #[must_use]
42    pub fn route(&self) -> &crate::route::RouteCheck {
43        match self {
44            Self::Ws(c) => c.route(),
45            Self::Http(c) => c.route(),
46        }
47    }
48}
49
50/// A driver-owned [`AnyConn`]: the protocol-specific handle.
51impl ConnMut<'_, AnyConn> {
52    /// The WebSocket connection, if it is one.
53    pub fn ws(&mut self) -> Option<ConnMut<'_, WsConn>> {
54        self.inner().ws().map(ConnMut::new)
55    }
56
57    /// The HTTP connection, if it is one.
58    pub fn http(&mut self) -> Option<ConnMut<'_, HttpConn>> {
59        self.inner().http().map(ConnMut::new)
60    }
61}
62
63impl Io for AnyConn {
64    const DEADLINES: bool = true;
65
66    #[inline]
67    fn fd(&self) -> std::os::fd::RawFd {
68        match self {
69            Self::Ws(c) => c.fd(),
70            Self::Http(c) => c.fd(),
71        }
72    }
73    #[inline]
74    fn rx_space(&mut self) -> &mut [u8] {
75        match self {
76            Self::Ws(c) => c.rx_space(),
77            Self::Http(c) => c.rx_space(),
78        }
79    }
80    #[inline]
81    fn tx_queue(&mut self) -> &mut Vec<u8> {
82        match self {
83            Self::Ws(c) => c.tx_queue(),
84            Self::Http(c) => c.tx_queue(),
85        }
86    }
87    fn has_buffered_input(&self) -> bool {
88        match self {
89            Self::Ws(c) => c.has_buffered_input(),
90            Self::Http(c) => c.has_buffered_input(),
91        }
92    }
93    fn set_route(&mut self, route: crate::endpoint::sealed::RouteSlot) {
94        match self {
95            Self::Ws(c) => c.set_route(route),
96            Self::Http(c) => c.set_route(route),
97        }
98    }
99    fn route_state(&self) -> &crate::endpoint::sealed::RouteSlot {
100        match self {
101            Self::Ws(c) => c.route_state(),
102            Self::Http(c) => c.route_state(),
103        }
104    }
105    fn expire(&mut self, now_ns: i64) -> Result<()> {
106        match self {
107            Self::Ws(c) => c.expire(now_ns),
108            Self::Http(c) => c.expire(now_ns),
109        }
110    }
111    fn close_reason(&mut self, error: crate::error::Error) -> crate::error::Error {
112        match self {
113            Self::Ws(c) => c.close_reason(error),
114            Self::Http(c) => c.close_reason(error),
115        }
116    }
117    #[inline]
118    fn on_handed(&mut self, n: usize) {
119        match self {
120            Self::Ws(c) => c.on_handed(n),
121            Self::Http(c) => c.on_handed(n),
122        }
123    }
124}
125
126impl<H: WsHandler + HttpHandler> Deliver<H> for AnyConn {
127    #[inline]
128    fn on_received(
129        &mut self,
130        id: ConnId,
131        n: usize,
132        meta: &RxMeta,
133        handler: &mut H,
134    ) -> Result<usize> {
135        match self {
136            Self::Ws(c) => c.on_received(id, n, meta, handler),
137            Self::Http(c) => c.on_received(id, n, meta, handler),
138        }
139    }
140}
141
142/// A WebSocket or an HTTP dial, for `Driver<AnyConn>::connect`.
143pub enum AnyDial {
144    /// WebSocket.
145    Ws(WsDial),
146    /// HTTP/1.1.
147    Http(HttpDial),
148}
149
150impl From<WsDial> for AnyDial {
151    fn from(d: WsDial) -> Self {
152        Self::Ws(d)
153    }
154}
155
156impl From<HttpDial> for AnyDial {
157    fn from(d: HttpDial) -> Self {
158        Self::Http(d)
159    }
160}
161
162impl DialIo for AnyDial {
163    type Conn = AnyConn;
164
165    fn host(&self) -> &str {
166        match self {
167            Self::Ws(d) => d.host(),
168            Self::Http(d) => d.host(),
169        }
170    }
171    fn port(&self) -> u16 {
172        match self {
173            Self::Ws(d) => d.port(),
174            Self::Http(d) => d.port(),
175        }
176    }
177    fn addr(&self) -> Option<SocketAddr> {
178        match self {
179            Self::Ws(d) => d.addr(),
180            Self::Http(d) => d.addr(),
181        }
182    }
183    fn start(&mut self, addr: SocketAddr) -> Result<()> {
184        match self {
185            Self::Ws(d) => d.start(addr),
186            Self::Http(d) => d.start(addr),
187        }
188    }
189    fn step(&mut self) -> Result<Option<AnyConn>> {
190        match self {
191            Self::Ws(d) => Ok(d.step()?.map(AnyConn::Ws)),
192            Self::Http(d) => Ok(d.step()?.map(AnyConn::Http)),
193        }
194    }
195    fn gate_route(&mut self) {
196        match self {
197            Self::Ws(d) => d.gate_route(),
198            Self::Http(d) => d.gate_route(),
199        }
200    }
201    fn awaiting_route(&self) -> Option<std::os::fd::RawFd> {
202        match self {
203            Self::Ws(d) => d.awaiting_route(),
204            Self::Http(d) => d.awaiting_route(),
205        }
206    }
207    fn route_checked(&mut self, check: crate::route::RouteCheck) {
208        match self {
209            Self::Ws(d) => d.route_checked(check),
210            Self::Http(d) => d.route_checked(check),
211        }
212    }
213}