#![allow(clippy::type_complexity)]
use std::error::Error;
use std::future::Future;
use std::io;
use std::pin::Pin;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::task::{Context, Poll};
use futures::channel::mpsc::UnboundedSender;
use futures::channel::oneshot;
use futures::FutureExt;
use crate::util::counter::Counter;
mod accept;
mod builder;
mod config;
mod service;
mod signals;
mod socket;
mod test;
mod worker;
#[cfg(feature = "openssl")]
pub mod openssl;
#[cfg(feature = "rustls")]
pub mod rustls;
pub(crate) use self::builder::create_tcp_listener;
pub use self::builder::ServerBuilder;
pub use self::config::{ServiceConfig, ServiceRuntime};
pub use self::service::StreamServiceFactory;
pub use self::test::{build_test_server, test_server, TestServer};
#[doc(hidden)]
pub use self::socket::FromStream;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub(self) struct Token(usize);
impl Token {
pub(self) fn next(&mut self) -> Token {
let token = Token(self.0);
self.0 += 1;
token
}
}
pub fn build() -> ServerBuilder {
ServerBuilder::default()
}
pub fn max_concurrent_ssl_accept(num: usize) {
MAX_SSL_ACCEPT.store(num, Ordering::Relaxed);
}
#[allow(dead_code)]
pub(self) const ZERO: std::time::Duration = std::time::Duration::from_millis(0);
pub(self) static MAX_SSL_ACCEPT: AtomicUsize = AtomicUsize::new(256);
thread_local! {
static MAX_SSL_ACCEPT_COUNTER: Counter = Counter::new(MAX_SSL_ACCEPT.load(Ordering::Relaxed));
}
#[derive(Debug)]
pub enum SslError<E> {
Ssl(Box<dyn Error>),
Service(E),
}
#[derive(Debug)]
enum ServerCommand {
WorkerFaulted(usize),
Pause(oneshot::Sender<()>),
Resume(oneshot::Sender<()>),
Signal(signals::Signal),
Stop {
graceful: bool,
completion: Option<oneshot::Sender<()>>,
},
Notify(oneshot::Sender<()>),
}
#[derive(Debug)]
pub struct Server(
UnboundedSender<ServerCommand>,
Option<oneshot::Receiver<()>>,
);
impl Server {
fn new(tx: UnboundedSender<ServerCommand>) -> Self {
Server(tx, None)
}
pub fn build() -> ServerBuilder {
ServerBuilder::default()
}
fn signal(&self, sig: signals::Signal) {
let _ = self.0.unbounded_send(ServerCommand::Signal(sig));
}
fn worker_faulted(&self, idx: usize) {
let _ = self.0.unbounded_send(ServerCommand::WorkerFaulted(idx));
}
pub fn pause(&self) -> impl Future<Output = ()> {
let (tx, rx) = oneshot::channel();
let _ = self.0.unbounded_send(ServerCommand::Pause(tx));
rx.map(|_| ())
}
pub fn resume(&self) -> impl Future<Output = ()> {
let (tx, rx) = oneshot::channel();
let _ = self.0.unbounded_send(ServerCommand::Resume(tx));
rx.map(|_| ())
}
pub fn stop(&self, graceful: bool) -> impl Future<Output = ()> {
let (tx, rx) = oneshot::channel();
let _ = self.0.unbounded_send(ServerCommand::Stop {
graceful,
completion: Some(tx),
});
rx.map(|_| ())
}
}
impl Clone for Server {
fn clone(&self) -> Self {
Self(self.0.clone(), None)
}
}
impl Future for Server {
type Output = io::Result<()>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let this = self.get_mut();
if this.1.is_none() {
let (tx, rx) = oneshot::channel();
if this.0.unbounded_send(ServerCommand::Notify(tx)).is_err() {
return Poll::Ready(Ok(()));
}
this.1 = Some(rx);
}
match Pin::new(this.1.as_mut().unwrap()).poll(cx) {
Poll::Pending => Poll::Pending,
Poll::Ready(Ok(_)) => Poll::Ready(Ok(())),
Poll::Ready(Err(_)) => Poll::Ready(Ok(())),
}
}
}