1use std::any::Any;
5use std::net::TcpListener;
6use std::sync::Arc;
7use std::sync::atomic::AtomicBool;
8use std::sync::atomic::Ordering;
9
10use async_executor::LocalExecutor;
11use async_io::Async;
12use thiserror::Error;
13
14mod conn;
15mod handler;
16mod response;
17mod settings;
18
19pub use handler::Handler;
20pub use handler::HandlerBuildError;
21pub use response::Response;
22pub use response::StatusCode;
23pub use settings::*;
24
25#[cfg(feature = "signal-hook")]
26mod signals;
27
28#[derive(Debug, Error)]
29pub enum SparsError {
30 #[error("Failed to create async listener: {0}")]
31 FailedToCreateAsyncListener(std::io::Error),
32
33 #[error("Failed to create signal handler: {0}")]
34 FailedToStartSignalHandler(std::io::Error),
35
36 #[error("Failed to join signal handler")]
37 FailedToJoinSignalHandler(Box<dyn Any + Send>),
38
39 #[error("Signal handler failed: {0}")]
40 SignalHandlerFailed(std::io::Error),
41}
42
43pub fn serve<L: TryInto<Async<TcpListener>, Error = std::io::Error>, H: Into<Arc<Handler>>>(
44 listener: L,
45 handler: H,
46) -> Result<(), SparsError> {
47 let listener = listener
48 .try_into()
49 .map_err(SparsError::FailedToCreateAsyncListener)?;
50 let stop_flag = Arc::new(AtomicBool::new(false));
51
52 #[cfg(feature = "signal-hook")]
53 let signal_handler = signals::spawn_signal_handler(Arc::clone(&stop_flag), &listener)
54 .map_err(SparsError::FailedToStartSignalHandler)?;
55
56 serve_with_stop_flag(listener, handler, stop_flag)?;
57
58 #[cfg(feature = "signal-hook")]
59 signal_handler
60 .join()
61 .map_err(SparsError::FailedToJoinSignalHandler)?
62 .map_err(SparsError::SignalHandlerFailed)?;
63
64 Ok(())
65}
66
67pub fn serve_with_stop_flag<H: Into<Arc<Handler>>>(
68 listener: Async<TcpListener>,
69 handler: H,
70 stop_flag: Arc<AtomicBool>,
71) -> Result<(), SparsError> {
72 let handler = handler.into();
73
74 let ex = LocalExecutor::new();
75
76 async_io::block_on(ex.run(async {
77 while !stop_flag.load(Ordering::SeqCst) {
78 match listener.accept().await {
79 Ok((stream, _addr)) => {
80 ex.spawn({
81 let handler = Arc::clone(&handler);
82 let stop_flag = Arc::clone(&stop_flag);
83
84 conn::handle_conn(handler, stop_flag, stream)
85 })
86 .detach();
87 }
88 Err(_e) => {
89 }
91 }
92 }
93 }));
94
95 Ok(())
96}