ntex_server/net/
socket.rs1use std::{fmt, io, net};
2
3use ntex_io::Io;
4use ntex_service::cfg::SharedCfg;
5
6use super::Token;
7
8#[derive(Debug)]
10pub enum Stream {
11 Tcp(net::TcpStream),
13 #[cfg(unix)]
15 Uds(std::os::unix::net::UnixStream),
16}
17
18impl Stream {
19 pub(crate) fn convert(self, cfg: SharedCfg) -> Result<Io, io::Error> {
20 match self {
21 Stream::Tcp(stream) => ntex_net::from_tcp_stream(stream, cfg),
22 #[cfg(unix)]
23 Stream::Uds(stream) => ntex_net::from_unix_stream(stream, cfg),
24 }
25 }
26}
27
28#[derive(Debug)]
30pub struct Connection {
31 pub(crate) io: Stream,
32 pub(crate) token: Token,
33}
34
35pub enum Listener {
36 Tcp(net::TcpListener),
37 #[cfg(unix)]
38 Uds(std::os::unix::net::UnixListener),
39}
40
41impl fmt::Debug for Listener {
42 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
43 match *self {
44 Listener::Tcp(ref lst) => write!(f, "{lst:?}"),
45 #[cfg(unix)]
46 Listener::Uds(ref lst) => write!(f, "{lst:?}"),
47 }
48 }
49}
50
51impl fmt::Display for Listener {
52 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
53 match *self {
54 Listener::Tcp(ref lst) => write!(f, "{}", lst.local_addr().ok().unwrap()),
55 #[cfg(unix)]
56 Listener::Uds(ref lst) => {
57 write!(f, "{:?}", lst.local_addr().ok().unwrap())
58 }
59 }
60 }
61}
62
63pub(crate) enum SocketAddr {
64 Tcp(net::SocketAddr),
65 #[cfg(unix)]
66 Uds(std::os::unix::net::SocketAddr),
67}
68
69impl fmt::Display for SocketAddr {
70 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
71 match *self {
72 SocketAddr::Tcp(ref addr) => write!(f, "{addr}"),
73 #[cfg(unix)]
74 SocketAddr::Uds(ref addr) => write!(f, "{addr:?}"),
75 }
76 }
77}
78
79impl fmt::Debug for SocketAddr {
80 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
81 match *self {
82 SocketAddr::Tcp(ref addr) => write!(f, "{addr:?}"),
83 #[cfg(unix)]
84 SocketAddr::Uds(ref addr) => write!(f, "{addr:?}"),
85 }
86 }
87}
88
89impl Listener {
90 pub(super) fn from_tcp(lst: net::TcpListener) -> Self {
91 let _ = lst.set_nonblocking(true);
92 Listener::Tcp(lst)
93 }
94
95 #[cfg(unix)]
96 pub(super) fn from_uds(lst: std::os::unix::net::UnixListener) -> Self {
97 let _ = lst.set_nonblocking(true);
98 Listener::Uds(lst)
99 }
100
101 pub(crate) fn local_addr(&self) -> SocketAddr {
102 match self {
103 Listener::Tcp(lst) => SocketAddr::Tcp(lst.local_addr().unwrap()),
104 #[cfg(unix)]
105 Listener::Uds(lst) => SocketAddr::Uds(lst.local_addr().unwrap()),
106 }
107 }
108
109 pub(crate) fn accept(&self) -> io::Result<Option<Stream>> {
110 match *self {
111 Listener::Tcp(ref lst) => lst.accept().map(|(stream, _)| Some(Stream::Tcp(stream))),
112 #[cfg(unix)]
113 Listener::Uds(ref lst) => lst.accept().map(|(stream, _)| Some(Stream::Uds(stream))),
114 }
115 }
116
117 pub(crate) fn remove_source(&self) {
118 match *self {
119 Listener::Tcp(_) => (),
120 #[cfg(unix)]
121 Listener::Uds(ref lst) => {
122 if let Ok(addr) = lst.local_addr()
124 && let Some(path) = addr.as_pathname()
125 {
126 let _ = std::fs::remove_file(path);
127 }
128 }
129 }
130 }
131}
132
133#[cfg(unix)]
134mod listener_impl {
135 use std::os::fd::{AsFd, BorrowedFd};
136 use std::os::unix::io::{AsRawFd, RawFd};
137
138 impl AsFd for super::Listener {
139 fn as_fd(&self) -> BorrowedFd<'_> {
140 match *self {
141 super::Listener::Tcp(ref lst) => lst.as_fd(),
142 super::Listener::Uds(ref lst) => lst.as_fd(),
143 }
144 }
145 }
146
147 impl AsRawFd for super::Listener {
148 fn as_raw_fd(&self) -> RawFd {
149 match *self {
150 super::Listener::Tcp(ref lst) => lst.as_raw_fd(),
151 super::Listener::Uds(ref lst) => lst.as_raw_fd(),
152 }
153 }
154 }
155}
156
157#[cfg(windows)]
158mod listener_impl {
159 use std::os::windows::io::{AsRawSocket, AsSocket, BorrowedSocket, RawSocket};
160
161 impl AsSocket for super::Listener {
162 fn as_socket(&self) -> BorrowedSocket<'_> {
163 match *self {
164 super::Listener::Tcp(ref lst) => lst.as_socket(),
165 }
166 }
167 }
168
169 impl AsRawSocket for super::Listener {
170 fn as_raw_socket(&self) -> RawSocket {
171 match *self {
172 super::Listener::Tcp(ref lst) => lst.as_raw_socket(),
173 }
174 }
175 }
176}
177
178#[cfg(test)]
179mod tests {
180 use super::*;
181
182 #[test]
183 fn socket_addr() {
184 use socket2::{Domain, SockAddr, Socket, Type};
185
186 let addr = SocketAddr::Tcp("127.0.0.1:8080".parse().unwrap());
187 assert!(format!("{addr:?}").contains("127.0.0.1:8080"));
188 assert_eq!(format!("{addr}"), "127.0.0.1:8080");
189
190 let addr: net::SocketAddr = "127.0.0.1:0".parse().unwrap();
191 let socket = Socket::new(Domain::IPV4, Type::STREAM, None).unwrap();
192 socket.set_reuse_address(true).unwrap();
193 socket.bind(&SockAddr::from(addr)).unwrap();
194 let lst = Listener::Tcp(net::TcpListener::from(socket));
195 assert!(format!("{lst:?}").contains("TcpListener"));
196 assert!(format!("{lst}").contains("127.0.0.1"));
197 }
198
199 #[test]
200 #[cfg(unix)]
201 fn uds() {
202 use std::os::unix::net::UnixListener;
203
204 let _ = std::fs::remove_file("/tmp/sock.xxxxx");
205 if let Ok(lst) = UnixListener::bind("/tmp/sock.xxxxx") {
206 let addr = lst.local_addr().expect("Couldn't get local address");
207 let a = SocketAddr::Uds(addr);
208 assert!(format!("{a:?}").contains("/tmp/sock.xxxxx"));
209 assert!(format!("{a}").contains("/tmp/sock.xxxxx"));
210
211 let lst = Listener::Uds(lst);
212 assert!(format!("{lst:?}").contains("/tmp/sock.xxxxx"));
213 assert!(format!("{lst}").contains("/tmp/sock.xxxxx"));
214 }
215 }
216}