#![forbid(unsafe_code)]
#![warn(missing_docs)]
use std::{net::SocketAddr, sync::Arc};
use anyhow::Result;
use hyper::server::conn::AddrIncoming;
use utils::Shutdown;
use crate::state::ServerState;
pub mod grpc;
mod listen;
pub mod session;
pub mod state;
pub mod utils;
pub mod web;
#[derive(Clone, Debug, Default)]
#[non_exhaustive]
pub struct ServerOptions {
pub secret: Option<String>,
pub override_origin: Option<String>,
pub redis_url: Option<String>,
pub host: Option<String>,
}
pub struct Server {
state: Arc<ServerState>,
shutdown: Shutdown,
}
impl Server {
pub fn new(options: ServerOptions) -> Result<Self> {
Ok(Self {
state: Arc::new(ServerState::new(options)?),
shutdown: Shutdown::new(),
})
}
pub fn state(&self) -> Arc<ServerState> {
Arc::clone(&self.state)
}
pub async fn listen(&self, incoming: AddrIncoming) -> Result<()> {
let state = self.state.clone();
let terminated = self.shutdown.wait();
tokio::spawn(async move {
let background_tasks = futures_util::future::join(
state.listen_for_transfers(),
state.close_old_sessions(),
);
tokio::select! {
_ = terminated => {}
_ = background_tasks => {}
}
});
listen::start_server(self.state(), incoming, self.shutdown.wait()).await
}
pub async fn bind(&self, addr: &SocketAddr) -> Result<()> {
self.listen(AddrIncoming::bind(addr)?).await
}
pub fn shutdown(&self) {
self.shutdown.shutdown();
self.state.shutdown();
}
}