11#[ cfg( feature = "metrics" ) ]
22use super :: metrics;
33use super :: settings:: TelemetrySettings ;
4+ use crate :: settings:: addr:: ListenAddr ;
45use crate :: telemetry:: log;
56use crate :: BootstrapResult ;
67use anyhow:: Context as _;
@@ -14,18 +15,127 @@ use std::net::SocketAddr;
1415use std:: pin:: Pin ;
1516use std:: sync:: Arc ;
1617use std:: task:: { Context , Poll } ;
18+ use tokio:: io:: { AsyncRead , AsyncWrite } ;
1719use tokio:: net:: TcpListener ;
20+ #[ cfg( unix) ]
21+ use tokio:: net:: { TcpStream , UnixListener , UnixStream } ;
1822use tokio:: sync:: watch;
1923
2024mod router;
2125
2226use router:: Router ;
27+
28+ enum TelemetryStream {
29+ Tcp ( TcpStream ) ,
30+ #[ cfg( unix) ]
31+ Unix ( UnixStream ) ,
32+ }
33+
34+ impl AsyncRead for TelemetryStream {
35+ fn poll_read (
36+ self : Pin < & mut Self > ,
37+ cx : & mut Context < ' _ > ,
38+ buf : & mut tokio:: io:: ReadBuf < ' _ > ,
39+ ) -> Poll < std:: io:: Result < ( ) > > {
40+ match self . get_mut ( ) {
41+ TelemetryStream :: Tcp ( stream) => Pin :: new ( stream) . poll_read ( cx, buf) ,
42+ #[ cfg( unix) ]
43+ TelemetryStream :: Unix ( stream) => Pin :: new ( stream) . poll_read ( cx, buf) ,
44+ }
45+ }
46+ }
47+
48+ impl AsyncWrite for TelemetryStream {
49+ fn poll_write (
50+ self : Pin < & mut Self > ,
51+ cx : & mut Context < ' _ > ,
52+ buf : & [ u8 ] ,
53+ ) -> Poll < Result < usize , std:: io:: Error > > {
54+ match self . get_mut ( ) {
55+ TelemetryStream :: Tcp ( stream) => Pin :: new ( stream) . poll_write ( cx, buf) ,
56+ #[ cfg( unix) ]
57+ TelemetryStream :: Unix ( stream) => Pin :: new ( stream) . poll_write ( cx, buf) ,
58+ }
59+ }
60+
61+ fn poll_flush ( self : Pin < & mut Self > , cx : & mut Context < ' _ > ) -> Poll < Result < ( ) , std:: io:: Error > > {
62+ match self . get_mut ( ) {
63+ TelemetryStream :: Tcp ( stream) => Pin :: new ( stream) . poll_flush ( cx) ,
64+ #[ cfg( unix) ]
65+ TelemetryStream :: Unix ( stream) => Pin :: new ( stream) . poll_flush ( cx) ,
66+ }
67+ }
68+
69+ fn poll_shutdown (
70+ self : Pin < & mut Self > ,
71+ cx : & mut Context < ' _ > ,
72+ ) -> Poll < Result < ( ) , std:: io:: Error > > {
73+ match self . get_mut ( ) {
74+ TelemetryStream :: Tcp ( stream) => Pin :: new ( stream) . poll_shutdown ( cx) ,
75+ #[ cfg( unix) ]
76+ TelemetryStream :: Unix ( stream) => Pin :: new ( stream) . poll_shutdown ( cx) ,
77+ }
78+ }
79+ }
80+
81+ enum TelemetryListener {
82+ Tcp ( TcpListener ) ,
83+ #[ cfg( unix) ]
84+ Unix ( UnixListener ) ,
85+ }
86+
87+ impl TelemetryListener {
88+ pub ( crate ) fn local_addr ( & self ) -> BootstrapResult < ListenAddr > {
89+ match self {
90+ TelemetryListener :: Tcp ( listener) => Ok ( listener. local_addr ( ) ?. into ( ) ) ,
91+ #[ cfg( unix) ]
92+ TelemetryListener :: Unix ( listener) => match listener. local_addr ( ) ?. as_pathname ( ) {
93+ Some ( path) => Ok ( path. to_path_buf ( ) . into ( ) ) ,
94+ None => Err ( anyhow:: anyhow!( "unix socket listener has no pathname" ) ) ,
95+ } ,
96+ }
97+ }
98+
99+ pub ( crate ) async fn accept ( & self ) -> std:: io:: Result < TelemetryStream > {
100+ match self {
101+ TelemetryListener :: Tcp ( listener) => listener
102+ . accept ( )
103+ . await
104+ . map ( |( conn, _) | TelemetryStream :: Tcp ( conn) ) ,
105+ #[ cfg( unix) ]
106+ TelemetryListener :: Unix ( listener) => listener
107+ . accept ( )
108+ . await
109+ . map ( |( conn, _) | TelemetryStream :: Unix ( conn) ) ,
110+ }
111+ }
112+
113+ pub ( crate ) fn poll_accept (
114+ & mut self ,
115+ cx : & mut std:: task:: Context < ' _ > ,
116+ ) -> std:: task:: Poll < std:: io:: Result < TelemetryStream > > {
117+ match self {
118+ TelemetryListener :: Tcp ( listener) => match std:: task:: ready!( listener. poll_accept( cx) ) {
119+ Ok ( ( conn, _) ) => std:: task:: Poll :: Ready ( Ok ( TelemetryStream :: Tcp ( conn) ) ) ,
120+ Err ( e) => std:: task:: Poll :: Ready ( Err ( e) ) ,
121+ } ,
122+ #[ cfg( unix) ]
123+ TelemetryListener :: Unix ( listener) => {
124+ match std:: task:: ready!( listener. poll_accept( cx) ) {
125+ Ok ( ( conn, _) ) => std:: task:: Poll :: Ready ( Ok ( TelemetryStream :: Unix ( conn) ) ) ,
126+ Err ( e) => std:: task:: Poll :: Ready ( Err ( e) ) ,
127+ }
128+ }
129+ }
130+ }
131+ }
132+
23133pub use router:: {
24134 BoxError , TelemetryRouteHandler , TelemetryRouteHandlerFuture , TelemetryServerRoute ,
25135} ;
26136
27137pub ( super ) struct TelemetryServerFuture {
28- listener : TcpListener ,
138+ listener : TelemetryListener ,
29139 router : Router ,
30140}
31141
@@ -47,27 +157,40 @@ impl TelemetryServerFuture {
47157 . map_err ( |err| anyhow:: anyhow!( err) ) ?;
48158 }
49159
50- let addr = settings. server . addr ;
51-
52- #[ cfg( feature = "settings" ) ]
53- let addr = SocketAddr :: from ( addr) ;
54-
55- let router = Router :: new ( custom_routes, settings) ;
56-
57- let listener = {
58- let std_listener = std:: net:: TcpListener :: from (
59- bind_socket ( addr) . with_context ( || format ! ( "binding to socket {addr:?}" ) ) ?,
60- ) ;
61-
62- std_listener. set_nonblocking ( true ) ?;
160+ let router = Router :: new ( custom_routes, Arc :: clone ( & settings) ) ;
161+
162+ let listener = match & settings. server . addr {
163+ ListenAddr :: Tcp ( addr) => {
164+ #[ cfg( feature = "settings" ) ]
165+ let addr = SocketAddr :: from ( * addr) ;
166+
167+ let std_listener = std:: net:: TcpListener :: from (
168+ bind_socket ( addr) . with_context ( || format ! ( "binding to TCP socket {addr:?}" ) ) ?,
169+ ) ;
170+ std_listener. set_nonblocking ( true ) ?;
171+ let tokio_listener = tokio:: net:: TcpListener :: from_std ( std_listener) ?;
172+ TelemetryListener :: Tcp ( tokio_listener)
173+ }
174+ #[ cfg( unix) ]
175+ ListenAddr :: Unix ( path) => {
176+ // Remove existing socket file if it exists to avoid bind errors
177+ if path. exists ( ) {
178+ if let Err ( e) = std:: fs:: remove_file ( path) {
179+ log:: warn!( "failed to remove existing Unix socket file" ; "path" => %path. display( ) , "error" => e) ;
180+ }
181+ }
63182
64- tokio:: net:: TcpListener :: from_std ( std_listener) ?
183+ let unix_listener = UnixListener :: bind ( path)
184+ . with_context ( || format ! ( "binding to Unix socket {path:?}" ) ) ?;
185+ TelemetryListener :: Unix ( unix_listener)
186+ }
65187 } ;
66188
67189 Ok ( Some ( TelemetryServerFuture { listener, router } ) )
68190 }
69- pub ( super ) fn local_addr ( & self ) -> SocketAddr {
70- self . listener . local_addr ( ) . unwrap ( )
191+
192+ pub ( super ) fn local_addr ( & self ) -> BootstrapResult < ListenAddr > {
193+ self . listener . local_addr ( )
71194 }
72195
73196 // Adapted from Hyper 0.14 Server stuff and axum::serve::serve.
@@ -87,15 +210,12 @@ impl TelemetryServerFuture {
87210 let ( close_tx, close_rx) = watch:: channel ( ( ) ) ;
88211 let listener = self . listener ;
89212
90- pin_mut ! ( listener) ;
91-
92213 loop {
93214 let socket = tokio:: select! {
94215 conn = listener. accept( ) => match conn {
95- Ok ( ( conn, _ ) ) => TokioIo :: new( conn) ,
216+ Ok ( conn) => TokioIo :: new( conn) ,
96217 Err ( e) => {
97218 log:: warn!( "failed to accept connection" ; "error" => e) ;
98-
99219 continue ;
100220 }
101221 } ,
@@ -140,11 +260,10 @@ impl Future for TelemetryServerFuture {
140260 let this = & mut * self ;
141261
142262 loop {
143- let socket = match ready ! ( Pin :: new ( & mut this. listener) . poll_accept( cx) ) {
144- Ok ( ( conn, _ ) ) => TokioIo :: new ( conn) ,
263+ let socket = match ready ! ( this. listener. poll_accept( cx) ) {
264+ Ok ( conn) => TokioIo :: new ( conn) ,
145265 Err ( e) => {
146266 log:: warn!( "failed to accept connection" ; "error" => e) ;
147-
148267 continue ;
149268 }
150269 } ;
0 commit comments