Clone fewer Arcs by using statics to distribute references to the server
This commit is contained in:
parent
285768f509
commit
597bc6aa6b
31
src/lib.rs
31
src/lib.rs
|
@ -192,7 +192,6 @@ compile_error!("Please enable only one of either the `gemini_srv` or `scgi_srv`
|
||||||
compile_error!("Please enable at least one of either the `gemini_srv` or `scgi_srv` features on the kochab crate");
|
compile_error!("Please enable at least one of either the `gemini_srv` or `scgi_srv` features on the kochab crate");
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
sync::Arc,
|
|
||||||
time::Duration,
|
time::Duration,
|
||||||
future::Future,
|
future::Future,
|
||||||
};
|
};
|
||||||
|
@ -260,32 +259,32 @@ pub const REQUEST_URI_MAX_LEN: usize = 1024;
|
||||||
/// The default port for the gemini protocol
|
/// The default port for the gemini protocol
|
||||||
pub const GEMINI_PORT: u16 = 1965;
|
pub const GEMINI_PORT: u16 = 1965;
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
struct ServerInner {
|
struct ServerInner {
|
||||||
#[cfg(feature = "gemini_srv")]
|
#[cfg(feature = "gemini_srv")]
|
||||||
tls_acceptor: TlsAcceptor,
|
tls_acceptor: TlsAcceptor,
|
||||||
routes: Arc<RoutingNode<Handler>>,
|
routes: RoutingNode<Handler>,
|
||||||
timeout: Duration,
|
timeout: Duration,
|
||||||
complex_timeout: Option<Duration>,
|
complex_timeout: Option<Duration>,
|
||||||
autorewrite: bool,
|
autorewrite: bool,
|
||||||
#[cfg(feature="ratelimiting")]
|
#[cfg(feature="ratelimiting")]
|
||||||
rate_limits: Arc<RoutingNode<RateLimiter<IpAddr>>>,
|
rate_limits: RoutingNode<RateLimiter<IpAddr>>,
|
||||||
#[cfg(feature="user_management")]
|
#[cfg(feature="user_management")]
|
||||||
manager: UserManager,
|
manager: UserManager,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerInner {
|
impl ServerInner {
|
||||||
async fn serve_ip(self, listener: TcpListener) -> Result<()> {
|
async fn serve_ip(self, listener: TcpListener) -> Result<()> {
|
||||||
|
let static_self: &'static Self = Box::leak(Box::new(self));
|
||||||
|
|
||||||
#[cfg(feature = "ratelimiting")]
|
#[cfg(feature = "ratelimiting")]
|
||||||
tokio::spawn(prune_ratelimit_log(self.rate_limits.clone()));
|
tokio::spawn(prune_ratelimit_log(&static_self.rate_limits));
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let (stream, _addr) = listener.accept().await
|
let (stream, _addr) = listener.accept().await
|
||||||
.context("Failed to accept client")?;
|
.context("Failed to accept client")?;
|
||||||
let this = self.clone();
|
|
||||||
|
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
if let Err(err) = this.serve_client(stream).await {
|
if let Err(err) = static_self.serve_client(stream).await {
|
||||||
error!("{:?}", err);
|
error!("{:?}", err);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -296,16 +295,17 @@ impl ServerInner {
|
||||||
// Yeah it's code duplication, but I can't find a way around it, so this is what we're
|
// Yeah it's code duplication, but I can't find a way around it, so this is what we're
|
||||||
// getting for now
|
// getting for now
|
||||||
async fn serve_unix(self, listener: UnixListener) -> Result<()> {
|
async fn serve_unix(self, listener: UnixListener) -> Result<()> {
|
||||||
|
let static_self: &'static Self = Box::leak(Box::new(self));
|
||||||
|
|
||||||
#[cfg(feature = "ratelimiting")]
|
#[cfg(feature = "ratelimiting")]
|
||||||
tokio::spawn(prune_ratelimit_log(self.rate_limits.clone()));
|
tokio::spawn(prune_ratelimit_log(&static_self.rate_limits));
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let (stream, _addr) = listener.accept().await
|
let (stream, _addr) = listener.accept().await
|
||||||
.context("Failed to accept client")?;
|
.context("Failed to accept client")?;
|
||||||
let this = self.clone();
|
|
||||||
|
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
if let Err(err) = this.serve_client(stream).await {
|
if let Err(err) = static_self.serve_client(stream).await {
|
||||||
error!("{:?}", err);
|
error!("{:?}", err);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -962,14 +962,14 @@ impl Server {
|
||||||
let data_dir = self.data_dir;
|
let data_dir = self.data_dir;
|
||||||
|
|
||||||
Ok(ServerInner {
|
Ok(ServerInner {
|
||||||
routes: Arc::new(self.routes),
|
routes: self.routes,
|
||||||
timeout: self.timeout,
|
timeout: self.timeout,
|
||||||
complex_timeout: self.complex_body_timeout_override,
|
complex_timeout: self.complex_body_timeout_override,
|
||||||
autorewrite: self.autorewrite,
|
autorewrite: self.autorewrite,
|
||||||
#[cfg(feature = "gemini_srv")]
|
#[cfg(feature = "gemini_srv")]
|
||||||
tls_acceptor: TlsAcceptor::from(config),
|
tls_acceptor: TlsAcceptor::from(config),
|
||||||
#[cfg(feature="ratelimiting")]
|
#[cfg(feature="ratelimiting")]
|
||||||
rate_limits: Arc::new(self.rate_limits),
|
rate_limits: self.rate_limits,
|
||||||
#[cfg(feature="user_management")]
|
#[cfg(feature="user_management")]
|
||||||
manager: UserManager::new(
|
manager: UserManager::new(
|
||||||
self.database.unwrap_or_else(move|| sled::open(data_dir).unwrap())
|
self.database.unwrap_or_else(move|| sled::open(data_dir).unwrap())
|
||||||
|
@ -981,6 +981,11 @@ impl Server {
|
||||||
///
|
///
|
||||||
/// `addr` can be anything `tokio` can parse, including just a string like
|
/// `addr` can be anything `tokio` can parse, including just a string like
|
||||||
/// "localhost:1965"
|
/// "localhost:1965"
|
||||||
|
///
|
||||||
|
/// This will only ever exit with an error. It's important to note that even if the
|
||||||
|
/// function exits, the server will NOT be deallocated, since references to it in
|
||||||
|
/// concurrently running futures may still exist. As such, a loop that handles an
|
||||||
|
/// error by re-serving a new server may trigger a memory leak.
|
||||||
pub async fn serve_ip(self, addr: impl ToSocketAddrs + Send) -> Result<()> {
|
pub async fn serve_ip(self, addr: impl ToSocketAddrs + Send) -> Result<()> {
|
||||||
let server = self.build()?;
|
let server = self.build()?;
|
||||||
let socket = TcpListener::bind(addr).await?;
|
let socket = TcpListener::bind(addr).await?;
|
||||||
|
@ -992,6 +997,8 @@ impl Server {
|
||||||
///
|
///
|
||||||
/// Requires an address in the form of a path to bind to. This is only available when
|
/// Requires an address in the form of a path to bind to. This is only available when
|
||||||
/// in `scgi_srv` mode.
|
/// in `scgi_srv` mode.
|
||||||
|
///
|
||||||
|
/// Please read the details and warnings of [`serve_ip()`] for more information
|
||||||
pub async fn serve_unix(self, addr: impl AsRef<std::path::Path>) -> Result<()> {
|
pub async fn serve_unix(self, addr: impl AsRef<std::path::Path>) -> Result<()> {
|
||||||
let server = self.build()?;
|
let server = self.build()?;
|
||||||
let socket = UnixListener::bind(addr)?;
|
let socket = UnixListener::bind(addr)?;
|
||||||
|
|
Loading…
Reference in a new issue