trillium_async_std/server/
unix.rs1use crate::AsyncStdTransport;
2use async_std::{
3 net::{TcpListener, TcpStream},
4 os::unix::net::{UnixListener, UnixStream},
5 stream::StreamExt,
6 task::{block_on, spawn},
7};
8use std::{env, future::Future, io::Result, pin::Pin};
9use trillium::{log_error, Info};
10use trillium_server_common::{
11 Binding::{self, *},
12 Server, Stopper,
13};
14
15#[derive(Debug)]
17pub struct AsyncStdServer(Binding<TcpListener, UnixListener>);
18impl From<TcpListener> for AsyncStdServer {
19 fn from(value: TcpListener) -> Self {
20 Self(Tcp(value))
21 }
22}
23
24impl From<UnixListener> for AsyncStdServer {
25 fn from(value: UnixListener) -> Self {
26 Self(Unix(value))
27 }
28}
29impl From<std::net::TcpListener> for AsyncStdServer {
30 fn from(value: std::net::TcpListener) -> Self {
31 TcpListener::from(value).into()
32 }
33}
34impl From<std::os::unix::net::UnixListener> for AsyncStdServer {
35 fn from(value: std::os::unix::net::UnixListener) -> Self {
36 UnixListener::from(value).into()
37 }
38}
39
40#[cfg(unix)]
41impl Server for AsyncStdServer {
42 type Transport = Binding<AsyncStdTransport<TcpStream>, AsyncStdTransport<UnixStream>>;
43 const DESCRIPTION: &'static str = concat!(
44 " (",
45 env!("CARGO_PKG_NAME"),
46 " v",
47 env!("CARGO_PKG_VERSION"),
48 ")"
49 );
50
51 fn handle_signals(stop: Stopper) -> Pin<Box<dyn Future<Output = ()> + Send + 'static>> {
52 Box::pin(async move {
53 use signal_hook::consts::signal::*;
54 use signal_hook_async_std::Signals;
55
56 let signals = Signals::new([SIGINT, SIGTERM, SIGQUIT]).unwrap();
57 let mut signals = signals.fuse();
58 while signals.next().await.is_some() {
59 if stop.is_stopped() {
60 eprintln!("\nSecond interrupt, shutting down harshly");
61 std::process::exit(1);
62 } else {
63 println!("\nShutting down gracefully.\nControl-C again to force.");
64 stop.stop();
65 }
66 }
67 })
68 }
69
70 fn accept(&mut self) -> Pin<Box<dyn Future<Output = Result<Self::Transport>> + Send + '_>> {
71 Box::pin(async move {
72 match &self.0 {
73 Tcp(t) => t
74 .accept()
75 .await
76 .map(|(t, _)| Tcp(AsyncStdTransport::from(t))),
77
78 Unix(u) => u
79 .accept()
80 .await
81 .map(|(u, _)| Unix(AsyncStdTransport::from(u))),
82 }
83 })
84 }
85
86 fn listener_from_tcp(tcp: std::net::TcpListener) -> Self {
87 Self(Tcp(tcp.into()))
88 }
89
90 fn listener_from_unix(tcp: std::os::unix::net::UnixListener) -> Self {
91 Self(Unix(tcp.into()))
92 }
93
94 fn info(&self) -> Info {
95 match &self.0 {
96 Tcp(t) => t.local_addr().unwrap().into(),
97 Unix(u) => u.local_addr().unwrap().into(),
98 }
99 }
100
101 fn spawn(fut: impl Future<Output = ()> + Send + 'static) {
102 spawn(fut);
103 }
104
105 fn block_on(fut: impl Future<Output = ()> + 'static) {
106 block_on(fut);
107 }
108
109 fn clean_up(self) -> Pin<Box<dyn Future<Output = ()> + Send + 'static>> {
110 Box::pin(async move {
111 if let Unix(u) = &self.0 {
112 if let Ok(local) = u.local_addr() {
113 if let Some(path) = local.as_pathname() {
114 log::info!("deleting {:?}", &path);
115 log_error!(async_std::fs::remove_file(path).await);
116 }
117 }
118 }
119 })
120 }
121}