pub(crate) mod auth;
pub(crate) mod cache;
pub(crate) mod compression;
pub(crate) mod http;
pub(crate) mod server;
pub(crate) mod types;
pub(crate) mod websocket;
use std::io;
use std::net::Ipv6Addr;
use std::path::PathBuf;
use std::sync::Arc;
use tokio::sync::Semaphore;
use tokio::sync::mpsc;
use tokio_stream::wrappers::ReceiverStream;
use warp::Filter;
const TASK_BUF: usize = 16;
const DEFAULT_CACHE_SIZE_MB: usize = 10;
#[derive(Debug, Clone)]
pub struct ServerConfig {
pub domains: Vec<String>,
pub email: Vec<String>,
pub cache: Option<PathBuf>,
pub limit: u32,
pub filelimit: usize,
pub wwwroot: PathBuf,
pub staging: bool,
pub port: u16,
pub redirect: bool,
pub max_cache_size_mb: Option<usize>,
}
pub async fn run(config: ServerConfig) -> io::Result<()> {
let limit = config.limit;
let www_root_dir = config.wwwroot;
let filelimit = config.filelimit;
let max_cache_size_mb = match config.max_cache_size_mb {
Some(size) => size,
None => DEFAULT_CACHE_SIZE_MB,
};
let semaphore = Arc::new(Semaphore::new(filelimit));
let (tx, rx) = mpsc::channel::<types::WsEvent>(TASK_BUF);
let rx = ReceiverStream::new(rx);
websocket::spawn_event_loop(rx, limit);
let addr = format!("[{}]:{}", Ipv6Addr::UNSPECIFIED, config.port)
.parse()
.unwrap();
let tcp_incoming = server::create_tcp_incoming(addr)?;
let tls_incoming = server::create_tls_incoming(
config.domains.clone(),
config.email,
config.cache,
config.staging,
tcp_incoming,
semaphore.clone(),
);
if config.redirect {
http::spawn_http_redirect_server(config.domains.clone());
}
let ws = websocket::create_ws_handler(tx.clone());
let compression_cache = cache::create_cache(max_cache_size_mb);
let index = http::create_http_file_routes(
config.domains,
www_root_dir,
semaphore.clone(),
compression_cache,
);
let tlsroutes = ws.or(index);
server::serve_tls(tls_incoming, tlsroutes).await;
unreachable!()
}