use std::marker::PhantomData;
use std::pin::Pin;
use std::task::{Context, Poll, ready};
use std::{fmt, io};
use tracing::Instrument;
use tracing::debug;
use tracing::instrument::Instrumented;
use crate::BoxError;
use crate::{notify, services::MakeServiceRef};
pub use self::builder::{NeedsAcceptor, NeedsExecutor, NeedsProtocol, NeedsService};
pub use self::conn::drivers::{ConnectionDriver, ServerExecutor};
pub use self::conn::drivers::{GracefulConnectionDriver, GracefulServerExecutor};
pub use self::conn::Accept;
pub use self::conn::Connection;
pub use self::conn::Protocol;
mod builder;
#[cfg(feature = "codec")]
pub mod codec;
pub mod conn;
pub struct Server<A, P, S, R, E> {
acceptor: A,
protocol: P,
make_service: S,
executor: E,
request: PhantomData<fn(R) -> ()>,
}
impl<A, P, S, R, E> fmt::Debug for Server<A, P, S, R, E> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Server").finish()
}
}
impl Server<(), (), (), (), ()> {
pub fn builder<R>() -> Server<NeedsAcceptor, NeedsProtocol, NeedsService, R, NeedsExecutor> {
Server {
acceptor: Default::default(),
protocol: Default::default(),
make_service: Default::default(),
executor: Default::default(),
request: Default::default(),
}
}
}
impl<A, P, S, R, E> Server<A, P, S, R, E> {
pub fn new(acceptor: A, protocol: P, make_service: S, executor: E) -> Self {
Self {
acceptor,
protocol,
make_service,
executor,
request: PhantomData,
}
}
pub fn with_graceful_shutdown<F>(self, signal: F) -> GracefulShutdown<A, P, S, R, E, F>
where
S: MakeServiceRef<A::Connection, R>,
P: Protocol<S::Service, A::Connection, R>,
A: Accept + Unpin,
F: Future<Output = ()> + Send + 'static,
E: ServerExecutor<P, S, A, R>,
{
GracefulShutdown::new(self, signal)
}
}
impl<A, P, S, R, E> IntoFuture for Server<A, P, S, R, E>
where
S: MakeServiceRef<A::Connection, R>,
P: Protocol<S::Service, A::Connection, R>,
A: Accept + Unpin,
E: ServerExecutor<P, S, A, R>,
{
type IntoFuture = Serving<A, P, S, R, E>;
type Output = Result<(), ServerError>;
fn into_future(self) -> Self::IntoFuture {
Serving {
server: self,
state: State::Preparing,
span: tracing::debug_span!("accept"),
}
}
}
#[derive(Debug)]
#[pin_project::pin_project]
#[must_use = "futures do nothing unless you `.await` or poll them"]
pub struct Serving<A, P, S, R, E>
where
S: MakeServiceRef<A::Connection, R>,
A: Accept,
{
server: Server<A, P, S, R, E>,
span: tracing::Span,
#[pin]
state: State<A::Connection, S::Future>,
}
#[derive(Debug)]
#[pin_project::pin_project(project = StateProj, project_replace = StateProjOwn)]
enum State<S, F> {
Preparing,
Accepting,
Making {
#[pin]
future: F,
stream: S,
},
}
impl<A, P, S, R, E> Serving<A, P, S, R, E>
where
S: MakeServiceRef<A::Connection, R>,
P: Protocol<S::Service, A::Connection, R>,
A: Accept + Unpin,
{
#[allow(clippy::type_complexity)]
fn poll_once(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
) -> Poll<Result<Option<Instrumented<P::Connection>>, ServerError>> {
let mut me = self.as_mut().project();
let _guard = me.span.enter();
match me.state.as_mut().project() {
StateProj::Preparing => {
ready!(me.server.make_service.poll_ready_ref(cx)).map_err(ServerError::ready)?;
me.state.set(State::Accepting);
}
StateProj::Accepting => match ready!(Pin::new(&mut me.server.acceptor).poll_accept(cx))
{
Ok(stream) => {
let future = me.server.make_service.make_service_ref(&stream);
me.state.set(State::Making { future, stream });
}
Err(e) => {
return Poll::Ready(Err(ServerError::accept(e)));
}
},
StateProj::Making { future, .. } => {
let service = ready!(future.poll(cx)).map_err(ServerError::make)?;
if let StateProjOwn::Making { stream, .. } =
me.state.project_replace(State::Preparing)
{
let span = tracing::debug_span!(parent: None, "connection");
let conn = me
.server
.protocol
.serve_connection(stream, service)
.instrument(span);
return Poll::Ready(Ok(Some(conn)));
} else {
unreachable!("state must still be accepting");
}
}
};
Poll::Ready(Ok(None))
}
}
impl<A, P, S, R, E> Future for Serving<A, P, S, R, E>
where
S: MakeServiceRef<A::Connection, R>,
P: Protocol<S::Service, A::Connection, R>,
A: Accept + Unpin,
E: ServerExecutor<P, S, A, R>,
{
type Output = Result<(), ServerError>;
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
loop {
match self.as_mut().poll_once(cx) {
Poll::Ready(Ok(Some(conn))) => {
self.as_mut()
.project()
.server
.executor
.execute(ConnectionDriver::new(conn));
}
Poll::Ready(Ok(None)) => {}
Poll::Ready(Err(e)) => return Poll::Ready(Err(e)),
Poll::Pending => return Poll::Pending,
}
}
}
}
#[pin_project::pin_project]
pub struct GracefulShutdown<A, P, S, B, E, F>
where
S: MakeServiceRef<A::Connection, B>,
A: Accept,
{
#[pin]
server: Serving<A, P, S, B, E>,
#[pin]
signal: F,
channel: notify::Receiver,
shutdown: notify::Sender,
#[pin]
finished: notify::Notified,
connection: notify::Sender,
}
impl<A, P, S, R, E, F> GracefulShutdown<A, P, S, R, E, F>
where
S: MakeServiceRef<A::Connection, R>,
P: Protocol<S::Service, A::Connection, R>,
A: Accept + Unpin,
F: Future<Output = ()>,
E: ServerExecutor<P, S, A, R>,
{
fn new(server: Server<A, P, S, R, E>, signal: F) -> Self {
let (tx, rx) = notify::channel();
let (tx2, rx2) = notify::channel();
Self {
server: server.into_future(),
signal,
channel: rx,
shutdown: tx,
finished: rx2.into_future(),
connection: tx2,
}
}
}
impl<A, P, S, B, E, F> fmt::Debug for GracefulShutdown<A, P, S, B, E, F>
where
S: MakeServiceRef<A::Connection, B>,
A: Accept,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("GracefulShutdown").finish()
}
}
impl<A, P, S, Body, E, F> Future for GracefulShutdown<A, P, S, Body, E, F>
where
S: MakeServiceRef<A::Connection, Body>,
P: Protocol<S::Service, A::Connection, Body>,
A: Accept + Unpin,
F: Future<Output = ()>,
E: GracefulServerExecutor<P, S, A, Body>,
{
type Output = Result<(), ServerError>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let mut this = self.project();
loop {
match this.signal.as_mut().poll(cx) {
Poll::Ready(()) => {
debug!("received shutdown signal");
this.shutdown.send();
return Poll::Ready(Ok(()));
}
Poll::Pending => {}
}
match this.finished.as_mut().poll(cx) {
Poll::Ready(()) => {
debug!("all connections closed");
return Poll::Ready(Ok(()));
}
Poll::Pending => {}
}
match this.server.as_mut().poll_once(cx) {
Poll::Ready(Ok(Some(conn))) => {
let shutdown_rx = this.channel.clone();
let finished_tx = this.connection.clone();
let span = conn.span().clone();
this.server
.server
.executor
.execute(GracefulConnectionDriver::new(
conn,
shutdown_rx,
finished_tx,
span,
));
}
Poll::Ready(Ok(None)) => {}
Poll::Ready(Err(e)) => return Poll::Ready(Err(e)),
Poll::Pending => return Poll::Pending,
}
}
}
}
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum ServerError {
#[error("accept error: {0}")]
Accept(#[source] BoxError),
#[error(transparent)]
Io(#[from] io::Error),
#[error("make service: {0}")]
MakeService(#[source] BoxError),
}
impl ServerError {
fn accept<A>(error: A) -> Self
where
A: Into<BoxError>,
{
let boxed = error.into();
debug!("accept error: {}", boxed);
Self::Accept(boxed)
}
}
impl ServerError {
fn make<E>(error: E) -> Self
where
E: Into<BoxError>,
{
let boxed = error.into();
debug!("make service error: {}", boxed);
Self::MakeService(boxed)
}
fn ready<E>(error: E) -> Self
where
E: Into<BoxError>,
{
let boxed = error.into();
debug!("ready error: {}", boxed);
Self::MakeService(boxed)
}
}