pub mod conn;
#[cfg(feature = "runtime")] mod tcp;
use std::fmt;
#[cfg(feature = "runtime")] use std::net::SocketAddr;
#[cfg(feature = "runtime")] use std::time::Duration;
use futures::{Future, Stream, Poll};
use tokio_io::{AsyncRead, AsyncWrite};
use body::{Body, Payload};
use service::{NewService, Service};
use self::conn::{Http as Http_, SpawnAll};
#[cfg(feature = "runtime")] use self::tcp::{AddrIncoming};
pub struct Server<I, S> {
spawn_all: SpawnAll<I, S>,
}
#[derive(Debug)]
pub struct Builder<I> {
incoming: I,
protocol: Http_,
}
impl<I> Server<I, ()> {
pub fn builder(incoming: I) -> Builder<I> {
Builder {
incoming,
protocol: Http_::new(),
}
}
}
#[cfg(feature = "runtime")]
impl Server<AddrIncoming, ()> {
pub fn bind(addr: &SocketAddr) -> Builder<AddrIncoming> {
let incoming = AddrIncoming::new(addr, None)
.unwrap_or_else(|e| {
panic!("error binding to {}: {}", addr, e);
});
Server::builder(incoming)
}
pub fn try_bind(addr: &SocketAddr) -> ::Result<Builder<AddrIncoming>> {
AddrIncoming::new(addr, None)
.map(Server::builder)
}
}
#[cfg(feature = "runtime")]
impl<S> Server<AddrIncoming, S> {
pub fn local_addr(&self) -> SocketAddr {
self.spawn_all.local_addr()
}
}
impl<I, S, B> Future for Server<I, S>
where
I: Stream,
I::Error: Into<Box<::std::error::Error + Send + Sync>>,
I::Item: AsyncRead + AsyncWrite + Send + 'static,
S: NewService<ReqBody=Body, ResBody=B> + Send + 'static,
S::Error: Into<Box<::std::error::Error + Send + Sync>>,
S::Service: Send,
S::Future: Send + 'static,
<S::Service as Service>::Future: Send + 'static,
B: Payload,
{
type Item = ();
type Error = ::Error;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
self.spawn_all.poll()
}
}
impl<I: fmt::Debug, S: fmt::Debug> fmt::Debug for Server<I, S> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Server")
.field("listener", &self.spawn_all.incoming_ref())
.finish()
}
}
impl<I> Builder<I> {
pub fn new(incoming: I, protocol: Http_) -> Self {
Builder {
incoming,
protocol,
}
}
pub fn http1_only(mut self, val: bool) -> Self {
self.protocol.http1_only(val);
self
}
pub fn http1_writev(mut self, val: bool) -> Self {
self.protocol.http1_writev(val);
self
}
pub fn http2_only(mut self, val: bool) -> Self {
self.protocol.http2_only(val);
self
}
pub fn serve<S, B>(self, new_service: S) -> Server<I, S>
where
I: Stream,
I::Error: Into<Box<::std::error::Error + Send + Sync>>,
I::Item: AsyncRead + AsyncWrite + Send + 'static,
S: NewService<ReqBody=Body, ResBody=B> + Send + 'static,
S::Error: Into<Box<::std::error::Error + Send + Sync>>,
S::Service: Send,
<S::Service as Service>::Future: Send + 'static,
B: Payload,
{
let serve = self.protocol.serve_incoming(self.incoming, new_service);
let spawn_all = serve.spawn_all();
Server {
spawn_all,
}
}
}
#[cfg(feature = "runtime")]
impl Builder<AddrIncoming> {
pub fn tcp_keepalive(mut self, keepalive: Option<Duration>) -> Self {
self.incoming.set_keepalive(keepalive);
self
}
pub fn tcp_nodelay(mut self, enabled: bool) -> Self {
self.incoming.set_nodelay(enabled);
self
}
}