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)
} else if flags.intersects(Flags::IO_SHUTDOWN) {
Poll::Ready(WriteStatus::Shutdown(self.0 .0.disconnect_timeout.get()))
} else if flags.contains(Flags::IO_FILTERS)
&& !flags.contains(Flags::IO_FILTERS_TO)
} else if flags.contains(Flags::IO_FILTERS) && !flags.contains(Flags::IO_FILTERS_TO)
{
flags.insert(Flags::IO_FILTERS_TO);
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<()>> {
// check io error
if !self.0 .0.is_io_open() {
return Poll::Ready(Err(self.0 .0.error.take().unwrap_or_else(|| {
io::Error::new(io::ErrorKind::Other, "disconnected")
})));
return Poll::Ready(Err(self
.0
.0
.error
.take()
.unwrap_or_else(|| io::Error::new(io::ErrorKind::Other, "disconnected"))));
}
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
///
/// Returns write buffer state, false is returned if write buffer if full.
pub fn encode<U>(
&self,
item: U::Item,
codec: &U,
) -> Result<bool, <U as Encoder>::Error>
pub fn encode<U>(&self, item: U::Item, codec: &U) -> Result<bool, <U as Encoder>::Error>
where
U: Encoder,
{

View file

@ -29,9 +29,7 @@ pub use self::io::{Io, IoRef, OnDisconnect};
pub use self::tasks::{ReadContext, WriteContext};
pub use self::time::Timer;
pub use self::utils::{
filter_factory, seal, sealed_service, SealedFactory, SealedService,
};
pub use self::utils::{filter_factory, seal, sealed_service, SealedFactory, SealedService};
pub type IoBoxed = Io<Sealed>;
@ -148,24 +146,6 @@ pub mod 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)]
mod tests {
use super::*;
@ -187,7 +167,8 @@ mod tests {
.contains("DispatchItem::WBackPressureEnabled"));
assert!(format!("{:?}", T::WBackPressureDisabled)
.contains("DispatchItem::WBackPressureDisabled"));
assert!(format!("{:?}", T::KeepAliveTimeout)
.contains("DispatchItem::KeepAliveTimeout"));
assert!(
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::time::{sleep, Millis, Sleep};
use crate::{
types, Handle, IoStream, ReadContext, ReadStatus, WriteContext, WriteStatus,
};
use crate::{types, Handle, IoStream, ReadContext, ReadStatus, WriteContext, WriteStatus};
#[derive(Default)]
struct AtomicWaker(Arc<Mutex<RefCell<Option<Waker>>>>);
@ -411,10 +409,7 @@ impl Future for ReadTask {
match io.poll_read_buf(cx, &mut buf) {
Poll::Pending => {
log::trace!(
"no more data in io stream, read: {:?}",
new_bytes
);
log::trace!("no more data in io stream, read: {:?}", new_bytes);
break;
}
Poll::Ready(Ok(n)) => {
@ -732,10 +727,7 @@ mod tokio_impl {
}
}
fn poll_flush(
self: Pin<&mut Self>,
_: &mut Context<'_>,
) -> Poll<io::Result<()>> {
fn poll_flush(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<()>> {
Poll::Ready(Ok(()))
}

View file

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

View file

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

View file

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

View file

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

View file

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