tiny_http/
connection.rs

1//! Abstractions of Tcp and Unix socket types
2
3#[cfg(unix)]
4use std::os::unix::net as unix_net;
5use std::{
6    net::{Shutdown, SocketAddr, TcpListener, TcpStream, ToSocketAddrs},
7    path::PathBuf,
8};
9
10/// Unified listener. Either a [`TcpListener`] or [`std::os::unix::net::UnixListener`]
11pub enum Listener {
12    Tcp(TcpListener),
13    #[cfg(unix)]
14    Unix(unix_net::UnixListener),
15}
16impl Listener {
17    pub(crate) fn local_addr(&self) -> std::io::Result<ListenAddr> {
18        match self {
19            Self::Tcp(l) => l.local_addr().map(ListenAddr::from),
20            #[cfg(unix)]
21            Self::Unix(l) => l.local_addr().map(ListenAddr::from),
22        }
23    }
24
25    pub(crate) fn accept(&self) -> std::io::Result<(Connection, Option<SocketAddr>)> {
26        match self {
27            Self::Tcp(l) => l
28                .accept()
29                .map(|(conn, addr)| (Connection::from(conn), Some(addr))),
30            #[cfg(unix)]
31            Self::Unix(l) => l.accept().map(|(conn, _)| (Connection::from(conn), None)),
32        }
33    }
34}
35impl From<TcpListener> for Listener {
36    fn from(s: TcpListener) -> Self {
37        Self::Tcp(s)
38    }
39}
40#[cfg(unix)]
41impl From<unix_net::UnixListener> for Listener {
42    fn from(s: unix_net::UnixListener) -> Self {
43        Self::Unix(s)
44    }
45}
46
47/// Unified connection. Either a [`TcpStream`] or [`std::os::unix::net::UnixStream`].
48#[derive(Debug)]
49pub(crate) enum Connection {
50    Tcp(TcpStream),
51    #[cfg(unix)]
52    Unix(unix_net::UnixStream),
53}
54impl std::io::Read for Connection {
55    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
56        match self {
57            Self::Tcp(s) => s.read(buf),
58            #[cfg(unix)]
59            Self::Unix(s) => s.read(buf),
60        }
61    }
62}
63impl std::io::Write for Connection {
64    fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
65        match self {
66            Self::Tcp(s) => s.write(buf),
67            #[cfg(unix)]
68            Self::Unix(s) => s.write(buf),
69        }
70    }
71
72    fn flush(&mut self) -> std::io::Result<()> {
73        match self {
74            Self::Tcp(s) => s.flush(),
75            #[cfg(unix)]
76            Self::Unix(s) => s.flush(),
77        }
78    }
79}
80impl Connection {
81    /// Gets the peer's address. Some for TCP, None for Unix sockets.
82    pub(crate) fn peer_addr(&mut self) -> std::io::Result<Option<SocketAddr>> {
83        match self {
84            Self::Tcp(s) => s.peer_addr().map(Some),
85            #[cfg(unix)]
86            Self::Unix(_) => Ok(None),
87        }
88    }
89
90    pub(crate) fn shutdown(&self, how: Shutdown) -> std::io::Result<()> {
91        match self {
92            Self::Tcp(s) => s.shutdown(how),
93            #[cfg(unix)]
94            Self::Unix(s) => s.shutdown(how),
95        }
96    }
97
98    pub(crate) fn try_clone(&self) -> std::io::Result<Self> {
99        match self {
100            Self::Tcp(s) => s.try_clone().map(Self::from),
101            #[cfg(unix)]
102            Self::Unix(s) => s.try_clone().map(Self::from),
103        }
104    }
105}
106impl From<TcpStream> for Connection {
107    fn from(s: TcpStream) -> Self {
108        Self::Tcp(s)
109    }
110}
111#[cfg(unix)]
112impl From<unix_net::UnixStream> for Connection {
113    fn from(s: unix_net::UnixStream) -> Self {
114        Self::Unix(s)
115    }
116}
117
118#[derive(Debug, Clone)]
119pub enum ConfigListenAddr {
120    IP(Vec<SocketAddr>),
121    #[cfg(unix)]
122    // TODO: use SocketAddr when bind_addr is stabilized
123    Unix(std::path::PathBuf),
124}
125impl ConfigListenAddr {
126    pub fn from_socket_addrs<A: ToSocketAddrs>(addrs: A) -> std::io::Result<Self> {
127        addrs.to_socket_addrs().map(|it| Self::IP(it.collect()))
128    }
129
130    #[cfg(unix)]
131    pub fn unix_from_path<P: Into<PathBuf>>(path: P) -> Self {
132        Self::Unix(path.into())
133    }
134
135    pub(crate) fn bind(&self) -> std::io::Result<Listener> {
136        match self {
137            Self::IP(a) => TcpListener::bind(a.as_slice()).map(Listener::from),
138            #[cfg(unix)]
139            Self::Unix(a) => unix_net::UnixListener::bind(a).map(Listener::from),
140        }
141    }
142}
143
144/// Unified listen socket address. Either a [`SocketAddr`] or [`std::os::unix::net::SocketAddr`].
145#[derive(Debug, Clone)]
146pub enum ListenAddr {
147    IP(SocketAddr),
148    #[cfg(unix)]
149    Unix(unix_net::SocketAddr),
150}
151impl ListenAddr {
152    pub fn to_ip(self) -> Option<SocketAddr> {
153        match self {
154            Self::IP(s) => Some(s),
155            #[cfg(unix)]
156            Self::Unix(_) => None,
157        }
158    }
159
160    /// Gets the Unix socket address.
161    ///
162    /// This is also available on non-Unix platforms, for ease of use, but always returns `None`.
163    #[cfg(unix)]
164    pub fn to_unix(self) -> Option<unix_net::SocketAddr> {
165        match self {
166            Self::IP(_) => None,
167            Self::Unix(s) => Some(s),
168        }
169    }
170    #[cfg(not(unix))]
171    pub fn to_unix(self) -> Option<SocketAddr> {
172        None
173    }
174}
175impl From<SocketAddr> for ListenAddr {
176    fn from(s: SocketAddr) -> Self {
177        Self::IP(s)
178    }
179}
180#[cfg(unix)]
181impl From<unix_net::SocketAddr> for ListenAddr {
182    fn from(s: unix_net::SocketAddr) -> Self {
183        Self::Unix(s)
184    }
185}
186impl std::fmt::Display for ListenAddr {
187    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
188        match self {
189            Self::IP(s) => s.fmt(f),
190            #[cfg(unix)]
191            Self::Unix(s) => std::fmt::Debug::fmt(s, f),
192        }
193    }
194}