1use std::{io, sync::Arc};
2
3use xitca_io::net::{Stream, TcpListener};
4
5#[cfg(unix)]
6use xitca_io::net::UnixListener;
7
8use tracing::info;
9#[cfg(feature = "quic")]
10use xitca_io::net::{QuicListener, QuicListenerBuilder};
11
12pub trait Listen: Send + Sync {
57 fn accept(&self) -> impl Future<Output = io::Result<Stream>> + Send;
58}
59
60mod _seal {
61 use core::{future::Future, pin::Pin};
62
63 use super::*;
64
65 type BoxFuture<'f, T> = Pin<Box<dyn Future<Output = T> + Send + 'f>>;
66
67 #[doc(hidden)]
68 pub trait ListenDyn: Send + Sync {
70 fn accept_dyn(&self) -> BoxFuture<io::Result<Stream>>;
71 }
72
73 impl<S> ListenDyn for S
74 where
75 S: Listen,
76 {
77 #[inline]
78 fn accept_dyn(&self) -> BoxFuture<io::Result<Stream>> {
79 Box::pin(Listen::accept(self))
80 }
81 }
82}
83
84pub(crate) type ListenerDyn = Arc<dyn _seal::ListenDyn>;
85
86impl Listen for TcpListener {
87 async fn accept(&self) -> io::Result<Stream> {
88 let (stream, addr) = self.accept().await?;
89 let stream = stream.into_std()?;
90 Ok(Stream::Tcp(stream, addr))
91 }
92}
93
94#[cfg(unix)]
95impl Listen for UnixListener {
96 async fn accept(&self) -> io::Result<Stream> {
97 let (stream, _) = self.accept().await?;
98 let stream = stream.into_std()?;
99 let addr = stream.peer_addr()?;
100 Ok(Stream::Unix(stream, addr))
101 }
102}
103
104#[cfg(feature = "quic")]
105impl Listen for QuicListener {
106 async fn accept(&self) -> io::Result<Stream> {
107 let stream = self.accept().await?;
108 let addr = stream.peer_addr();
109 Ok(Stream::Udp(stream, addr))
110 }
111}
112
113pub trait IntoListener: Send {
118 type Listener: Listen;
119
120 fn into_listener(self) -> io::Result<Self::Listener>;
121}
122
123impl IntoListener for std::net::TcpListener {
124 type Listener = TcpListener;
125
126 fn into_listener(self) -> io::Result<Self::Listener> {
127 self.set_nonblocking(true)?;
128 let listener = TcpListener::from_std(self)?;
129 info!("Started Tcp listening on: {:?}", listener.local_addr().ok());
130 Ok(listener)
131 }
132}
133
134#[cfg(unix)]
135impl IntoListener for std::os::unix::net::UnixListener {
136 type Listener = UnixListener;
137
138 fn into_listener(self) -> io::Result<Self::Listener> {
139 self.set_nonblocking(true)?;
140 let listener = UnixListener::from_std(self)?;
141 info!("Started Unix listening on: {:?}", listener.local_addr().ok());
142 Ok(listener)
143 }
144}
145
146#[cfg(feature = "quic")]
147impl IntoListener for QuicListenerBuilder {
148 type Listener = QuicListener;
149
150 fn into_listener(self) -> io::Result<Self::Listener> {
151 let udp = self.build()?;
152 info!("Started Udp listening on: {:?}", udp.endpoint().local_addr().ok());
153 Ok(udp)
154 }
155}