mod accept;
mod io;
mod tls;
use std::process::ExitCode;
use std::time::Duration;
use tokio::net::{TcpListener, ToSocketAddrs};
use crate::app::{ServiceAdapter, Via};
use crate::error::Error;
use accept::accept;
use io::IoWithPermit;
use tls::TcpAcceptor;
#[cfg(feature = "native-tls")]
use tls::NativeTlsAcceptor;
#[cfg(feature = "rustls-23")]
use tls::RustlsAcceptor;
pub struct Server<App> {
app: Via<App>,
config: ServerConfig,
}
#[derive(Debug)]
pub(crate) struct ServerConfig {
keep_alive: bool,
max_buf_size: usize,
max_connections: usize,
max_request_size: usize,
shutdown_timeout: Duration,
#[cfg(any(feature = "native-tls", feature = "rustls-23"))]
tls_handshake_timeout: Duration,
#[cfg(any(feature = "native-tls", feature = "rustls-23"))]
http2_max_concurrent_streams: Option<u32>,
#[cfg(any(feature = "native-tls", feature = "rustls-23"))]
http2_max_send_buf_size: usize,
}
impl<App> Server<App>
where
App: Send + Sync + 'static,
{
pub fn new(app: Via<App>) -> Self {
Self {
app,
config: Default::default(),
}
}
pub fn keep_alive(mut self, keep_alive: bool) -> Self {
self.config.keep_alive = keep_alive;
self
}
pub fn max_buf_size(mut self, max_buf_size: usize) -> Self {
self.config.max_buf_size = max_buf_size;
self
}
pub fn max_connections(mut self, max_connections: usize) -> Self {
self.config.max_connections = max_connections;
self
}
pub fn max_request_size(mut self, max_request_size: usize) -> Self {
self.config.max_request_size = max_request_size;
self
}
pub fn shutdown_timeout(mut self, shutdown_timeout: Duration) -> Self {
self.config.shutdown_timeout = shutdown_timeout;
self
}
pub async fn listen(self, address: impl ToSocketAddrs) -> Result<ExitCode, Error> {
let future = accept(
TcpAcceptor,
TcpListener::bind(address).await?,
ServiceAdapter::new(self.config, self.app),
);
Ok(future.await)
}
#[cfg(feature = "native-tls")]
pub async fn listen_native_tls(
self,
address: impl ToSocketAddrs,
identity: native_tls::Identity,
) -> Result<ExitCode, Error> {
let future = accept(
NativeTlsAcceptor::new(identity),
TcpListener::bind(address).await?,
ServiceAdapter::new(self.config, self.app),
);
Ok(future.await)
}
#[cfg(feature = "rustls-23")]
pub async fn listen_rustls_23(
self,
address: impl ToSocketAddrs,
rustls_config: rustls::ServerConfig,
) -> Result<ExitCode, Error> {
let future = accept(
RustlsAcceptor::new(rustls_config),
TcpListener::bind(address).await?,
ServiceAdapter::new(self.config, self.app),
);
Ok(future.await)
}
}
#[cfg(any(feature = "native-tls", feature = "rustls-23"))]
impl<App> Server<App> {
pub fn http2_max_concurrent_streams(mut self, max_concurrent_streams: Option<u32>) -> Self {
self.config.http2_max_concurrent_streams = max_concurrent_streams;
self
}
pub fn http2_max_send_buf_size(mut self, max_send_buf_size: usize) -> Self {
self.config.http2_max_send_buf_size = max_send_buf_size;
self
}
pub fn tls_handshake_timeout(mut self, tls_handshake_timeout: Duration) -> Self {
if tls_handshake_timeout.is_zero() {
panic!("tls_handshake_timeout must be > 0");
}
self.config.tls_handshake_timeout = tls_handshake_timeout;
self
}
}
impl ServerConfig {
pub fn keep_alive(&self) -> bool {
self.keep_alive
}
pub fn max_buf_size(&self) -> usize {
self.max_buf_size
}
pub fn max_connections(&self) -> usize {
self.max_connections
}
pub fn max_request_size(&self) -> usize {
self.max_request_size
}
pub fn shutdown_timeout(&self) -> Duration {
self.shutdown_timeout
}
}
#[cfg(any(feature = "native-tls", feature = "rustls-23"))]
impl ServerConfig {
pub fn http2_max_concurrent_streams(&self) -> Option<u32> {
self.http2_max_concurrent_streams
}
pub fn http2_max_send_buf_size(&self) -> usize {
self.http2_max_send_buf_size
}
pub fn tls_handshake_timeout(&self) -> Duration {
self.tls_handshake_timeout
}
}
impl Default for ServerConfig {
fn default() -> Self {
Self {
keep_alive: true,
max_buf_size: 16384, max_connections: 1000,
max_request_size: 104_857_600, shutdown_timeout: Duration::from_secs(10),
#[cfg(any(feature = "native-tls", feature = "rustls-23"))]
http2_max_concurrent_streams: Some(64),
#[cfg(any(feature = "native-tls", feature = "rustls-23"))]
http2_max_send_buf_size: 65536,
#[cfg(any(feature = "native-tls", feature = "rustls-23"))]
tls_handshake_timeout: Duration::from_secs(5),
}
}
}