1use std::time::Duration;
6
7pub trait Listener: Send + 'static {
9 type Io: tokio::io::AsyncRead + tokio::io::AsyncWrite + Unpin + Send + 'static;
11
12 type Addr: Clone + Send + Sync + 'static;
15
16 fn accept(&mut self) -> impl std::future::Future<Output = (Self::Io, Self::Addr)> + Send;
21
22 fn local_addr(&self) -> std::io::Result<Self::Addr>;
24}
25
26pub trait ListenerExt: Listener + Sized {
28 fn tap_io<F>(self, tap_fn: F) -> TapIo<Self, F>
48 where
49 F: FnMut(&mut Self::Io) + Send + 'static,
50 {
51 TapIo {
52 listener: self,
53 tap_fn,
54 }
55 }
56}
57
58impl<L: Listener> ListenerExt for L {}
59
60impl Listener for tokio::net::TcpListener {
61 type Io = tokio::net::TcpStream;
62 type Addr = std::net::SocketAddr;
63
64 async fn accept(&mut self) -> (Self::Io, Self::Addr) {
65 loop {
66 match Self::accept(self).await {
67 Ok(tup) => return tup,
68 Err(e) => handle_accept_error(e).await,
69 }
70 }
71 }
72
73 #[inline]
74 fn local_addr(&self) -> std::io::Result<Self::Addr> {
75 Self::local_addr(self)
76 }
77}
78
79#[derive(Debug)]
80pub struct TcpListenerWithOptions {
81 inner: tokio::net::TcpListener,
82 keepalive: Option<Duration>,
83}
84
85impl TcpListenerWithOptions {
86 pub fn new<A: std::net::ToSocketAddrs>(
87 addr: A,
88 keepalive: Option<Duration>,
89 ) -> Result<Self, crate::BoxError> {
90 let std_listener = std::net::TcpListener::bind(addr)?;
91 std_listener.set_nonblocking(true)?;
92 let listener = tokio::net::TcpListener::from_std(std_listener)?;
93
94 Ok(Self::from_listener(listener, keepalive))
95 }
96
97 pub fn from_listener(listener: tokio::net::TcpListener, keepalive: Option<Duration>) -> Self {
99 Self {
100 inner: listener,
101 keepalive,
102 }
103 }
104
105 fn set_accepted_socket_options(&self, stream: &tokio::net::TcpStream) {
107 if let Err(e) = stream.set_nodelay(true) {
108 tracing::warn!("error trying to set TCP nodelay: {}", e);
109 }
110
111 if let Some(timeout) = self.keepalive {
112 let sock_ref = socket2::SockRef::from(&stream);
113 let sock_keepalive = socket2::TcpKeepalive::new().with_time(timeout);
114
115 if let Err(e) = sock_ref.set_tcp_keepalive(&sock_keepalive) {
116 tracing::warn!("error trying to set TCP keepalive: {}", e);
117 }
118 }
119 }
120}
121
122impl Listener for TcpListenerWithOptions {
123 type Io = tokio::net::TcpStream;
124 type Addr = std::net::SocketAddr;
125
126 async fn accept(&mut self) -> (Self::Io, Self::Addr) {
127 let (io, addr) = Listener::accept(&mut self.inner).await;
128 self.set_accepted_socket_options(&io);
129 (io, addr)
130 }
131
132 #[inline]
133 fn local_addr(&self) -> std::io::Result<Self::Addr> {
134 Listener::local_addr(&self.inner)
135 }
136}
137
138pub struct TapIo<L, F> {
163 listener: L,
164 tap_fn: F,
165}
166
167impl<L, F> std::fmt::Debug for TapIo<L, F>
168where
169 L: Listener + std::fmt::Debug,
170{
171 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
172 f.debug_struct("TapIo")
173 .field("listener", &self.listener)
174 .finish_non_exhaustive()
175 }
176}
177
178impl<L, F> Listener for TapIo<L, F>
179where
180 L: Listener,
181 F: FnMut(&mut L::Io) + Send + 'static,
182{
183 type Io = L::Io;
184 type Addr = L::Addr;
185
186 async fn accept(&mut self) -> (Self::Io, Self::Addr) {
187 let (mut io, addr) = self.listener.accept().await;
188 (self.tap_fn)(&mut io);
189 (io, addr)
190 }
191
192 fn local_addr(&self) -> std::io::Result<Self::Addr> {
193 self.listener.local_addr()
194 }
195}
196
197async fn handle_accept_error(e: std::io::Error) {
198 if is_connection_error(&e) {
199 return;
200 }
201
202 tracing::error!("accept error: {e}");
214 tokio::time::sleep(Duration::from_secs(1)).await;
215}
216
217fn is_connection_error(e: &std::io::Error) -> bool {
218 use std::io::ErrorKind;
219
220 matches!(
221 e.kind(),
222 ErrorKind::ConnectionRefused
223 | ErrorKind::ConnectionAborted
224 | ErrorKind::ConnectionReset
225 | ErrorKind::BrokenPipe
226 | ErrorKind::Interrupted
227 | ErrorKind::WouldBlock
228 | ErrorKind::TimedOut
229 )
230}