update ServiceFactory api

This commit is contained in:
Nikolay Kim 2021-12-24 03:53:39 +06:00
parent 359d94fd5a
commit f0f899a36e
12 changed files with 71 additions and 123 deletions

View file

@ -86,8 +86,7 @@ impl Filter for Base {
Poll::Ready(WriteStatus::Terminate) Poll::Ready(WriteStatus::Terminate)
} else if flags.intersects(Flags::IO_SHUTDOWN) { } else if flags.intersects(Flags::IO_SHUTDOWN) {
Poll::Ready(WriteStatus::Shutdown(self.0 .0.disconnect_timeout.get())) Poll::Ready(WriteStatus::Shutdown(self.0 .0.disconnect_timeout.get()))
} else if flags.contains(Flags::IO_FILTERS) } else if flags.contains(Flags::IO_FILTERS) && !flags.contains(Flags::IO_FILTERS_TO)
&& !flags.contains(Flags::IO_FILTERS_TO)
{ {
flags.insert(Flags::IO_FILTERS_TO); flags.insert(Flags::IO_FILTERS_TO);
self.0.set_flags(flags); self.0.set_flags(flags);

View file

@ -559,9 +559,12 @@ impl<F> Io<F> {
pub fn poll_flush(&self, cx: &mut Context<'_>, full: bool) -> Poll<io::Result<()>> { pub fn poll_flush(&self, cx: &mut Context<'_>, full: bool) -> Poll<io::Result<()>> {
// check io error // check io error
if !self.0 .0.is_io_open() { if !self.0 .0.is_io_open() {
return Poll::Ready(Err(self.0 .0.error.take().unwrap_or_else(|| { return Poll::Ready(Err(self
io::Error::new(io::ErrorKind::Other, "disconnected") .0
}))); .0
.error
.take()
.unwrap_or_else(|| io::Error::new(io::ErrorKind::Other, "disconnected"))));
} }
if let Some(buf) = self.0 .0.write_buf.take() { if let Some(buf) = self.0 .0.write_buf.take() {

View file

@ -185,11 +185,7 @@ impl IoRef {
/// Encode and write item to a buffer and wake up write task /// Encode and write item to a buffer and wake up write task
/// ///
/// Returns write buffer state, false is returned if write buffer if full. /// Returns write buffer state, false is returned if write buffer if full.
pub fn encode<U>( pub fn encode<U>(&self, item: U::Item, codec: &U) -> Result<bool, <U as Encoder>::Error>
&self,
item: U::Item,
codec: &U,
) -> Result<bool, <U as Encoder>::Error>
where where
U: Encoder, U: Encoder,
{ {

View file

@ -29,9 +29,7 @@ pub use self::io::{Io, IoRef, OnDisconnect};
pub use self::tasks::{ReadContext, WriteContext}; pub use self::tasks::{ReadContext, WriteContext};
pub use self::time::Timer; pub use self::time::Timer;
pub use self::utils::{ pub use self::utils::{filter_factory, seal, sealed_service, SealedFactory, SealedService};
filter_factory, seal, sealed_service, SealedFactory, SealedService,
};
pub type IoBoxed = Io<Sealed>; pub type IoBoxed = Io<Sealed>;
@ -148,24 +146,6 @@ pub mod rt {
pub use crate::tokio_rt::*; pub use crate::tokio_rt::*;
} }
#[deprecated]
#[doc(hidden)]
pub fn into_boxed<F, S>(
srv: S,
) -> impl ntex_service::ServiceFactory<
Io<F>,
Config = S::Config,
Response = S::Response,
Error = S::Error,
InitError = S::InitError,
>
where
F: Filter + 'static,
S: ntex_service::ServiceFactory<IoBoxed>,
{
seal(srv)
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
@ -187,7 +167,8 @@ mod tests {
.contains("DispatchItem::WBackPressureEnabled")); .contains("DispatchItem::WBackPressureEnabled"));
assert!(format!("{:?}", T::WBackPressureDisabled) assert!(format!("{:?}", T::WBackPressureDisabled)
.contains("DispatchItem::WBackPressureDisabled")); .contains("DispatchItem::WBackPressureDisabled"));
assert!(format!("{:?}", T::KeepAliveTimeout) assert!(
.contains("DispatchItem::KeepAliveTimeout")); format!("{:?}", T::KeepAliveTimeout).contains("DispatchItem::KeepAliveTimeout")
);
} }
} }

View file

@ -7,9 +7,7 @@ use ntex_bytes::{Buf, BufMut, BytesMut};
use ntex_util::future::poll_fn; use ntex_util::future::poll_fn;
use ntex_util::time::{sleep, Millis, Sleep}; use ntex_util::time::{sleep, Millis, Sleep};
use crate::{ use crate::{types, Handle, IoStream, ReadContext, ReadStatus, WriteContext, WriteStatus};
types, Handle, IoStream, ReadContext, ReadStatus, WriteContext, WriteStatus,
};
#[derive(Default)] #[derive(Default)]
struct AtomicWaker(Arc<Mutex<RefCell<Option<Waker>>>>); struct AtomicWaker(Arc<Mutex<RefCell<Option<Waker>>>>);
@ -411,10 +409,7 @@ impl Future for ReadTask {
match io.poll_read_buf(cx, &mut buf) { match io.poll_read_buf(cx, &mut buf) {
Poll::Pending => { Poll::Pending => {
log::trace!( log::trace!("no more data in io stream, read: {:?}", new_bytes);
"no more data in io stream, read: {:?}",
new_bytes
);
break; break;
} }
Poll::Ready(Ok(n)) => { Poll::Ready(Ok(n)) => {
@ -732,10 +727,7 @@ mod tokio_impl {
} }
} }
fn poll_flush( fn poll_flush(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<()>> {
self: Pin<&mut Self>,
_: &mut Context<'_>,
) -> Poll<io::Result<()>> {
Poll::Ready(Ok(())) Poll::Ready(Ok(()))
} }

View file

@ -72,8 +72,7 @@ impl Future for ReadTask {
Poll::Ready(Ok(n)) => { Poll::Ready(Ok(n)) => {
if n == 0 { if n == 0 {
log::trace!("io stream is disconnected"); log::trace!("io stream is disconnected");
if let Err(e) = if let Err(e) = this.state.release_read_buf(buf, new_bytes)
this.state.release_read_buf(buf, new_bytes)
{ {
this.state.close(Some(e)); this.state.close(Some(e));
} else { } else {
@ -221,8 +220,7 @@ impl Future for WriteTask {
} }
Shutdown::Flushed => { Shutdown::Flushed => {
// shutdown WRITE side // shutdown WRITE side
match Pin::new(&mut *this.io.borrow_mut()).poll_shutdown(cx) match Pin::new(&mut *this.io.borrow_mut()).poll_shutdown(cx) {
{
Poll::Ready(Ok(_)) => { Poll::Ready(Ok(_)) => {
*st = Shutdown::Stopping; *st = Shutdown::Stopping;
continue; continue;
@ -386,10 +384,7 @@ impl<F: Filter> AsyncWrite for Io<F> {
Io::poll_flush(&*self, cx, false) Io::poll_flush(&*self, cx, false)
} }
fn poll_shutdown( fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
self: Pin<&mut Self>,
cx: &mut Context<'_>,
) -> Poll<io::Result<()>> {
Io::poll_shutdown(&*self, cx) Io::poll_shutdown(&*self, cx)
} }
} }
@ -431,10 +426,7 @@ impl AsyncWrite for IoBoxed {
Self::poll_flush(&*self, cx, false) Self::poll_flush(&*self, cx, false)
} }
fn poll_shutdown( fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
self: Pin<&mut Self>,
cx: &mut Context<'_>,
) -> Poll<io::Result<()>> {
Self::poll_shutdown(&*self, cx) Self::poll_shutdown(&*self, cx)
} }
} }
@ -446,11 +438,7 @@ mod unixstream {
use super::*; use super::*;
impl IoStream for UnixStream { impl IoStream for UnixStream {
fn start( fn start(self, read: ReadContext, write: WriteContext) -> Option<Box<dyn Handle>> {
self,
read: ReadContext,
write: WriteContext,
) -> Option<Box<dyn Handle>> {
let io = Rc::new(RefCell::new(self)); let io = Rc::new(RefCell::new(self));
tok_io::task::spawn_local(ReadTask::new(io.clone(), read)); tok_io::task::spawn_local(ReadTask::new(io.clone(), read));
@ -604,8 +592,7 @@ mod unixstream {
Poll::Ready(WriteStatus::Terminate) => { Poll::Ready(WriteStatus::Terminate) => {
log::trace!("write task is instructed to terminate"); log::trace!("write task is instructed to terminate");
let _ = let _ = Pin::new(&mut *this.io.borrow_mut()).poll_shutdown(cx);
Pin::new(&mut *this.io.borrow_mut()).poll_shutdown(cx);
this.state.close(None); this.state.close(None);
Poll::Ready(()) Poll::Ready(())
} }
@ -619,11 +606,8 @@ mod unixstream {
match st { match st {
Shutdown::None => { Shutdown::None => {
// flush write buffer // flush write buffer
match flush_io( match flush_io(&mut *this.io.borrow_mut(), &this.state, cx)
&mut *this.io.borrow_mut(), {
&this.state,
cx,
) {
Poll::Ready(true) => { Poll::Ready(true) => {
*st = Shutdown::Flushed; *st = Shutdown::Flushed;
continue; continue;
@ -639,15 +623,16 @@ mod unixstream {
} }
Shutdown::Flushed => { Shutdown::Flushed => {
// shutdown WRITE side // shutdown WRITE side
match Pin::new(&mut *this.io.borrow_mut()) match Pin::new(&mut *this.io.borrow_mut()).poll_shutdown(cx)
.poll_shutdown(cx)
{ {
Poll::Ready(Ok(_)) => { Poll::Ready(Ok(_)) => {
*st = Shutdown::Stopping; *st = Shutdown::Stopping;
continue; continue;
} }
Poll::Ready(Err(e)) => { Poll::Ready(Err(e)) => {
log::trace!("write task is closed with err during shutdown"); log::trace!(
"write task is closed with err during shutdown"
);
this.state.close(Some(e)); this.state.close(Some(e));
return Poll::Ready(()); return Poll::Ready(());
} }
@ -660,8 +645,7 @@ mod unixstream {
let mut io = this.io.borrow_mut(); let mut io = this.io.borrow_mut();
loop { loop {
let mut read_buf = ReadBuf::new(&mut buf); let mut read_buf = ReadBuf::new(&mut buf);
match Pin::new(&mut *io).poll_read(cx, &mut read_buf) match Pin::new(&mut *io).poll_read(cx, &mut read_buf) {
{
Poll::Ready(Err(_)) | Poll::Ready(Ok(_)) Poll::Ready(Err(_)) | Poll::Ready(Ok(_))
if read_buf.filled().is_empty() => if read_buf.filled().is_empty() =>
{ {

View file

@ -6,20 +6,20 @@ use ntex_util::{future::Ready, ready};
use super::{Filter, FilterFactory, Io, IoBoxed}; use super::{Filter, FilterFactory, Io, IoBoxed};
/// Service that converts any Io<F> stream to IoBoxed stream /// Service that converts any Io<F> stream to IoBoxed stream
pub fn seal<F, S>( pub fn seal<F, S, C>(
srv: S, srv: S,
) -> impl ServiceFactory< ) -> impl ServiceFactory<
Io<F>, Io<F>,
Config = S::Config, C,
Response = S::Response, Response = S::Response,
Error = S::Error, Error = S::Error,
InitError = S::InitError, InitError = S::InitError,
> >
where where
F: Filter + 'static, F: Filter + 'static,
S: ServiceFactory<IoBoxed>, S: ServiceFactory<IoBoxed, C>,
{ {
fn_factory_with_config(move |cfg: S::Config| { fn_factory_with_config(move |cfg: C| {
let fut = srv.new_service(cfg); let fut = srv.new_service(cfg);
async move { async move {
let srv = fut.await?; let srv = fut.await?;
@ -72,19 +72,18 @@ impl<S: Clone, R> Clone for SealedFactory<S, R> {
} }
} }
impl<S, R, F> ServiceFactory<R> for SealedFactory<S, R> impl<S, R, C, F> ServiceFactory<R, C> for SealedFactory<S, R>
where where
F: Filter, F: Filter,
S: ServiceFactory<R, Response = Io<F>>, S: ServiceFactory<R, C, Response = Io<F>>,
{ {
type Config = S::Config;
type Response = IoBoxed; type Response = IoBoxed;
type Error = S::Error; type Error = S::Error;
type Service = SealedService<S::Service, R>; type Service = SealedService<S::Service, R>;
type InitError = S::InitError; type InitError = S::InitError;
type Future = SealedFactoryResponse<S, R>; type Future = SealedFactoryResponse<S, R, C>;
fn new_service(&self, cfg: S::Config) -> Self::Future { fn new_service(&self, cfg: C) -> Self::Future {
SealedFactoryResponse { SealedFactoryResponse {
fut: self.inner.new_service(cfg), fut: self.inner.new_service(cfg),
_t: PhantomData, _t: PhantomData,
@ -138,14 +137,14 @@ where
} }
pin_project_lite::pin_project! { pin_project_lite::pin_project! {
pub struct SealedFactoryResponse<S: ServiceFactory<R>, R> { pub struct SealedFactoryResponse<S: ServiceFactory<R, C>, R, C> {
#[pin] #[pin]
fut: S::Future, fut: S::Future,
_t: PhantomData<R> _t: PhantomData<(R, C)>
} }
} }
impl<S: ServiceFactory<R>, R> Future for SealedFactoryResponse<S, R> { impl<S: ServiceFactory<R, C>, R, C> Future for SealedFactoryResponse<S, R, C> {
type Output = Result<SealedService<S::Service, R>, S::InitError>; type Output = Result<SealedService<S::Service, R>, S::InitError>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
@ -165,9 +164,7 @@ pin_project_lite::pin_project! {
} }
} }
impl<S: Service<R, Response = Io<F>>, R, F: Filter> Future impl<S: Service<R, Response = Io<F>>, R, F: Filter> Future for SealedServiceResponse<S, R> {
for SealedServiceResponse<S, R>
{
type Output = Result<IoBoxed, S::Error>; type Output = Result<IoBoxed, S::Error>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
@ -180,12 +177,11 @@ pub struct FilterServiceFactory<T, F> {
_t: PhantomData<F>, _t: PhantomData<F>,
} }
impl<T, F> ServiceFactory<Io<F>> for FilterServiceFactory<T, F> impl<T, F> ServiceFactory<Io<F>, ()> for FilterServiceFactory<T, F>
where where
T: FilterFactory<F> + Clone, T: FilterFactory<F> + Clone,
F: Filter, F: Filter,
{ {
type Config = ();
type Response = Io<T::Filter>; type Response = Io<T::Filter>;
type Error = T::Error; type Error = T::Error;
type Service = FilterService<T, F>; type Service = FilterService<T, F>;

View file

@ -17,8 +17,7 @@ async fn main() -> io::Result<()> {
// load ssl keys // load ssl keys
let cert_file = let cert_file =
&mut BufReader::new(File::open("../ntex-tls/examples/cert.pem").unwrap()); &mut BufReader::new(File::open("../ntex-tls/examples/cert.pem").unwrap());
let key_file = let key_file = &mut BufReader::new(File::open("../ntex-tls/examples/key.pem").unwrap());
&mut BufReader::new(File::open("../ntex-tls/examples/key.pem").unwrap());
let keys = PrivateKey(rsa_private_keys(key_file).unwrap().remove(0)); let keys = PrivateKey(rsa_private_keys(key_file).unwrap().remove(0));
let cert_chain = certs(cert_file) let cert_chain = certs(cert_file)
.unwrap() .unwrap()
@ -36,8 +35,8 @@ async fn main() -> io::Result<()> {
// start server // start server
server::ServerBuilder::new() server::ServerBuilder::new()
.bind("basic", "127.0.0.1:8443", move |_| { .bind("basic", "127.0.0.1:8443", move |_| {
pipeline_factory(filter_factory(TlsAcceptor::new(tls_config.clone()))) pipeline_factory(filter_factory(TlsAcceptor::new(tls_config.clone()))).and_then(
.and_then(fn_service(|io: Io<_>| async move { fn_service(|io: Io<_>| async move {
println!("New client is connected"); println!("New client is connected");
io.send( io.send(
@ -64,7 +63,8 @@ async fn main() -> io::Result<()> {
} }
println!("Client is disconnected"); println!("Client is disconnected");
Ok(()) Ok(())
})) }),
)
})? })?
.workers(1) .workers(1)
.run() .run()

View file

@ -25,8 +25,8 @@ async fn main() -> io::Result<()> {
// start server // start server
server::ServerBuilder::new() server::ServerBuilder::new()
.bind("basic", "127.0.0.1:8443", move |_| { .bind("basic", "127.0.0.1:8443", move |_| {
pipeline_factory(filter_factory(SslAcceptor::new(acceptor.clone()))) pipeline_factory(filter_factory(SslAcceptor::new(acceptor.clone()))).and_then(
.and_then(fn_service(|io: Io<_>| async move { fn_service(|io: Io<_>| async move {
println!("New client is connected"); println!("New client is connected");
loop { loop {
match io.recv(&codec::BytesCodec).await { match io.recv(&codec::BytesCodec).await {
@ -45,7 +45,8 @@ async fn main() -> io::Result<()> {
} }
println!("Client is disconnected"); println!("Client is disconnected");
Ok(()) Ok(())
})) }),
)
})? })?
.workers(1) .workers(1)
.run() .run()

View file

@ -56,15 +56,15 @@ impl<F> Clone for Acceptor<F> {
} }
} }
impl<F: Filter> ServiceFactory<Io<F>> for Acceptor<F> { impl<F: Filter, C> ServiceFactory<Io<F>, C> for Acceptor<F> {
type Response = Io<SslFilter<F>>; type Response = Io<SslFilter<F>>;
type Error = Box<dyn Error>; type Error = Box<dyn Error>;
type Config = ();
type Service = AcceptorService<F>; type Service = AcceptorService<F>;
type InitError = (); type InitError = ();
type Future = Ready<Self::Service, Self::InitError>; type Future = Ready<Self::Service, Self::InitError>;
fn new_service(&self, _: ()) -> Self::Future { #[inline]
fn new_service(&self, _: C) -> Self::Future {
MAX_SSL_ACCEPT_COUNTER.with(|conns| { MAX_SSL_ACCEPT_COUNTER.with(|conns| {
Ready::Ok(AcceptorService { Ready::Ok(AcceptorService {
acceptor: self.acceptor.clone(), acceptor: self.acceptor.clone(),

View file

@ -65,9 +65,8 @@ impl<F: Filter> io::Write for IoInner<F> {
impl<F: Filter> Filter for SslFilter<F> { impl<F: Filter> Filter for SslFilter<F> {
fn query(&self, id: any::TypeId) -> Option<Box<dyn any::Any>> { fn query(&self, id: any::TypeId) -> Option<Box<dyn any::Any>> {
if id == any::TypeId::of::<types::HttpProtocol>() { if id == any::TypeId::of::<types::HttpProtocol>() {
let proto = if let Some(protos) = let proto =
self.inner.borrow().ssl().selected_alpn_protocol() if let Some(protos) = self.inner.borrow().ssl().selected_alpn_protocol() {
{
if protos.windows(2).any(|window| window == b"h2") { if protos.windows(2).any(|window| window == b"h2") {
types::HttpProtocol::Http2 types::HttpProtocol::Http2
} else { } else {
@ -160,8 +159,8 @@ impl<F: Filter> Filter for SslFilter<F> {
let (hw, lw) = pool.read_params().unpack(); let (hw, lw) = pool.read_params().unpack();
// get inner filter buffer // get inner filter buffer
let mut buf = let mut buf = if let Some(buf) = self.inner.borrow().get_ref().inner.get_read_buf()
if let Some(buf) = self.inner.borrow().get_ref().inner.get_read_buf() { {
buf buf
} else { } else {
BytesMut::with_capacity_in(lw, pool) BytesMut::with_capacity_in(lw, pool)
@ -330,9 +329,7 @@ impl<F: Filter> FilterFactory<F> for SslConnector {
}) })
})?; })?;
poll_fn(|cx| { poll_fn(|cx| handle_result(st.filter().inner.borrow_mut().connect(), &st, cx))
handle_result(st.filter().inner.borrow_mut().connect(), &st, cx)
})
.await?; .await?;
Ok(st) Ok(st)

View file

@ -51,16 +51,15 @@ impl<F> Clone for Acceptor<F> {
} }
} }
impl<F: Filter> ServiceFactory<Io<F>> for Acceptor<F> { impl<F: Filter, C> ServiceFactory<Io<F>, C> for Acceptor<F> {
type Response = Io<TlsFilter<F>>; type Response = Io<TlsFilter<F>>;
type Error = io::Error; type Error = io::Error;
type Service = AcceptorService<F>; type Service = AcceptorService<F>;
type Config = ();
type InitError = (); type InitError = ();
type Future = Ready<Self::Service, Self::InitError>; type Future = Ready<Self::Service, Self::InitError>;
fn new_service(&self, _: ()) -> Self::Future { fn new_service(&self, _: C) -> Self::Future {
MAX_SSL_ACCEPT_COUNTER.with(|conns| { MAX_SSL_ACCEPT_COUNTER.with(|conns| {
Ready::Ok(AcceptorService { Ready::Ok(AcceptorService {
acceptor: self.inner.clone(), acceptor: self.inner.clone(),