use std::fmt::{self, Display, Formatter};
use std::future::Future;
use std::io::Result as IoResult;
use http::uri::Scheme;
use tokio::io::{AsyncRead, AsyncWrite};
use crate::fuse::ArcFuseFactory;
use crate::http::{HttpConnection, Version};
mod proto;
pub use proto::HttpBuilder;
mod stream;
pub use stream::*;
cfg_feature! {
#![feature = "acme"]
pub mod acme;
pub use acme::AcmeListener;
}
cfg_feature! {
#![feature = "native-tls"]
pub mod native_tls;
pub use self::native_tls::NativeTlsListener;
}
cfg_feature! {
#![feature = "rustls"]
pub mod rustls;
pub use rustls::RustlsListener;
}
cfg_feature! {
#![feature = "openssl"]
pub mod openssl;
pub use self::openssl::OpensslListener;
}
cfg_feature! {
#![feature = "http1"]
pub use hyper::server::conn::http1;
}
cfg_feature! {
#![feature = "http2"]
pub use hyper::server::conn::http2;
}
cfg_feature! {
#![feature = "quinn"]
pub mod quinn;
pub(crate) mod rustls_old;
pub use self::quinn::{QuinnListener, H3Connection};
}
cfg_feature! {
#![unix]
pub mod unix;
}
pub mod addr;
pub use addr::SocketAddr;
pub mod tcp;
pub use tcp::TcpListener;
mod joined;
pub use joined::JoinedListener;
cfg_feature! {
#![unix]
pub use unix::UnixListener;
}
#[cfg(any(feature = "rustls", feature = "native-tls", feature = "openssl"))]
pub trait IntoConfigStream<C> {
type Stream: futures_util::Stream<Item = C> + Send + 'static;
fn into_stream(self) -> Self::Stream;
}
#[non_exhaustive]
pub struct Accepted<C>
where
C: HttpConnection,
{
pub conn: C,
pub local_addr: SocketAddr,
pub remote_addr: SocketAddr,
pub http_scheme: Scheme,
pub http_version: Version,
}
impl<C> Accepted<C>
where
C: HttpConnection + AsyncRead + AsyncWrite + Unpin + Send + 'static,
{
#[inline]
pub fn map_conn<T>(self, wrap_fn: impl FnOnce(C) -> T) -> Accepted<T>
where
T: HttpConnection,
{
let Accepted {
conn,
local_addr,
remote_addr,
http_version,
http_scheme,
} = self;
Accepted {
conn: wrap_fn(conn),
local_addr,
remote_addr,
http_version,
http_scheme,
}
}
}
pub trait Acceptor {
type Conn: HttpConnection + AsyncRead + AsyncWrite + Send + Unpin + 'static;
fn holdings(&self) -> &[Holding];
fn accept(
&mut self,
fuse_factory: Option<ArcFuseFactory>,
) -> impl Future<Output = IoResult<Accepted<Self::Conn>>> + Send;
}
#[derive(Clone, Debug)]
#[non_exhaustive]
pub struct Holding {
pub local_addr: SocketAddr,
pub http_versions: Vec<Version>,
pub http_scheme: Scheme,
}
impl Display for Holding {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(
f,
"{:?} on {}://{}",
self.http_versions,
self.http_scheme,
self.local_addr.to_string().trim_start_matches("socket://")
)
}
}
pub trait Listener {
type Acceptor: Acceptor;
fn bind(self) -> impl Future<Output = Self::Acceptor> + Send
where
Self: Sized + Send,
{
async move { self.try_bind().await.expect("bind failed") }
}
fn try_bind(self) -> impl Future<Output = crate::Result<Self::Acceptor>> + Send;
#[inline]
fn join<T>(self, other: T) -> JoinedListener<Self, T>
where
Self: Sized + Send,
{
JoinedListener::new(self, other)
}
}