2019-11-14 13:38:24 +01:00
|
|
|
use std::future::Future;
|
2019-06-26 11:19:40 +02:00
|
|
|
use std::marker::PhantomData;
|
2019-11-14 13:38:24 +01:00
|
|
|
use std::pin::Pin;
|
2019-06-26 11:19:40 +02:00
|
|
|
use std::rc::Rc;
|
2019-11-14 13:38:24 +01:00
|
|
|
use std::task::{Context, Poll};
|
2019-06-26 11:19:40 +02:00
|
|
|
|
|
|
|
use actix_codec::{AsyncRead, AsyncWrite, Decoder, Encoder};
|
2019-11-14 13:38:24 +01:00
|
|
|
use actix_service::{IntoService, IntoServiceFactory, Service, ServiceFactory};
|
|
|
|
use either::Either;
|
|
|
|
use futures::future::{FutureExt, LocalBoxFuture};
|
2019-11-19 09:51:40 +01:00
|
|
|
use pin_project::project;
|
2019-06-26 11:19:40 +02:00
|
|
|
|
|
|
|
use crate::connect::{Connect, ConnectResult};
|
|
|
|
use crate::dispatcher::FramedDispatcher;
|
|
|
|
use crate::error::ServiceError;
|
|
|
|
use crate::item::Item;
|
|
|
|
|
|
|
|
type RequestItem<S, U> = Item<S, U>;
|
|
|
|
type ResponseItem<U> = Option<<U as Encoder>::Item>;
|
|
|
|
|
|
|
|
/// Service builder - structure that follows the builder pattern
|
|
|
|
/// for building instances for framed services.
|
|
|
|
pub struct Builder<St, Codec>(PhantomData<(St, Codec)>);
|
|
|
|
|
2019-12-02 17:30:09 +01:00
|
|
|
impl<St: Clone, Codec> Default for Builder<St, Codec> {
|
|
|
|
fn default() -> Builder<St, Codec> {
|
|
|
|
Builder::new()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-02 16:27:48 +01:00
|
|
|
impl<St: Clone, Codec> Builder<St, Codec> {
|
2019-06-26 11:19:40 +02:00
|
|
|
pub fn new() -> Builder<St, Codec> {
|
|
|
|
Builder(PhantomData)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Construct framed handler service with specified connect service
|
|
|
|
pub fn service<Io, C, F>(self, connect: F) -> ServiceBuilder<St, C, Io, Codec>
|
|
|
|
where
|
|
|
|
F: IntoService<C>,
|
2019-11-19 09:51:40 +01:00
|
|
|
Io: AsyncRead + AsyncWrite,
|
2019-06-26 11:19:40 +02:00
|
|
|
C: Service<Request = Connect<Io>, Response = ConnectResult<Io, St, Codec>>,
|
2019-11-19 09:51:40 +01:00
|
|
|
Codec: Decoder + Encoder,
|
2019-06-26 11:19:40 +02:00
|
|
|
{
|
|
|
|
ServiceBuilder {
|
|
|
|
connect: connect.into_service(),
|
2019-07-02 08:10:05 +02:00
|
|
|
disconnect: None,
|
2019-06-26 11:19:40 +02:00
|
|
|
_t: PhantomData,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Construct framed handler new service with specified connect service
|
|
|
|
pub fn factory<Io, C, F>(self, connect: F) -> NewServiceBuilder<St, C, Io, Codec>
|
|
|
|
where
|
2019-11-14 13:38:24 +01:00
|
|
|
F: IntoServiceFactory<C>,
|
2019-11-19 09:51:40 +01:00
|
|
|
Io: AsyncRead + AsyncWrite,
|
2019-11-14 13:38:24 +01:00
|
|
|
C: ServiceFactory<
|
2019-06-26 11:19:40 +02:00
|
|
|
Config = (),
|
|
|
|
Request = Connect<Io>,
|
|
|
|
Response = ConnectResult<Io, St, Codec>,
|
|
|
|
>,
|
|
|
|
C::Error: 'static,
|
|
|
|
C::Future: 'static,
|
2019-11-19 09:51:40 +01:00
|
|
|
Codec: Decoder + Encoder,
|
2019-06-26 11:19:40 +02:00
|
|
|
{
|
|
|
|
NewServiceBuilder {
|
2019-11-14 13:38:24 +01:00
|
|
|
connect: connect.into_factory(),
|
2019-07-02 08:10:05 +02:00
|
|
|
disconnect: None,
|
2019-06-26 11:19:40 +02:00
|
|
|
_t: PhantomData,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct ServiceBuilder<St, C, Io, Codec> {
|
|
|
|
connect: C,
|
2019-08-16 22:15:51 +02:00
|
|
|
disconnect: Option<Rc<dyn Fn(&mut St, bool)>>,
|
2019-06-26 11:19:40 +02:00
|
|
|
_t: PhantomData<(St, Io, Codec)>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<St, C, Io, Codec> ServiceBuilder<St, C, Io, Codec>
|
|
|
|
where
|
2019-12-02 16:27:48 +01:00
|
|
|
St: Clone,
|
2019-06-26 11:19:40 +02:00
|
|
|
C: Service<Request = Connect<Io>, Response = ConnectResult<Io, St, Codec>>,
|
|
|
|
C::Error: 'static,
|
2019-11-19 09:51:40 +01:00
|
|
|
Io: AsyncRead + AsyncWrite,
|
|
|
|
Codec: Decoder + Encoder,
|
2019-06-26 11:19:40 +02:00
|
|
|
<Codec as Encoder>::Item: 'static,
|
|
|
|
<Codec as Encoder>::Error: std::fmt::Debug,
|
|
|
|
{
|
2019-07-02 08:10:05 +02:00
|
|
|
/// Callback to execute on disconnect
|
|
|
|
///
|
|
|
|
/// Second parameter indicates error occured during disconnect.
|
|
|
|
pub fn disconnect<F, Out>(mut self, disconnect: F) -> Self
|
|
|
|
where
|
2019-07-02 08:35:27 +02:00
|
|
|
F: Fn(&mut St, bool) + 'static,
|
2019-07-02 08:10:05 +02:00
|
|
|
{
|
2019-07-02 08:35:27 +02:00
|
|
|
self.disconnect = Some(Rc::new(disconnect));
|
2019-07-02 08:10:05 +02:00
|
|
|
self
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Provide stream items handler service and construct service factory.
|
2019-11-18 13:28:54 +01:00
|
|
|
pub fn finish<F, T>(self, service: F) -> FramedServiceImpl<St, C, T, Io, Codec>
|
2019-06-26 11:19:40 +02:00
|
|
|
where
|
2019-11-14 13:38:24 +01:00
|
|
|
F: IntoServiceFactory<T>,
|
|
|
|
T: ServiceFactory<
|
2019-06-26 11:19:40 +02:00
|
|
|
Config = St,
|
|
|
|
Request = RequestItem<St, Codec>,
|
|
|
|
Response = ResponseItem<Codec>,
|
|
|
|
Error = C::Error,
|
|
|
|
InitError = C::Error,
|
|
|
|
> + 'static,
|
|
|
|
{
|
|
|
|
FramedServiceImpl {
|
|
|
|
connect: self.connect,
|
2019-11-14 13:38:24 +01:00
|
|
|
handler: Rc::new(service.into_factory()),
|
2019-07-02 08:10:05 +02:00
|
|
|
disconnect: self.disconnect.clone(),
|
2019-06-26 11:19:40 +02:00
|
|
|
_t: PhantomData,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct NewServiceBuilder<St, C, Io, Codec> {
|
|
|
|
connect: C,
|
2019-08-16 22:15:51 +02:00
|
|
|
disconnect: Option<Rc<dyn Fn(&mut St, bool)>>,
|
2019-06-26 11:19:40 +02:00
|
|
|
_t: PhantomData<(St, Io, Codec)>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<St, C, Io, Codec> NewServiceBuilder<St, C, Io, Codec>
|
|
|
|
where
|
2019-12-02 16:27:48 +01:00
|
|
|
St: Clone,
|
2019-11-19 09:51:40 +01:00
|
|
|
Io: AsyncRead + AsyncWrite,
|
2019-11-14 13:38:24 +01:00
|
|
|
C: ServiceFactory<
|
|
|
|
Config = (),
|
|
|
|
Request = Connect<Io>,
|
|
|
|
Response = ConnectResult<Io, St, Codec>,
|
|
|
|
>,
|
2019-06-26 11:19:40 +02:00
|
|
|
C::Error: 'static,
|
2019-11-19 09:51:40 +01:00
|
|
|
C::Future: 'static,
|
|
|
|
Codec: Decoder + Encoder,
|
2019-06-26 11:19:40 +02:00
|
|
|
<Codec as Encoder>::Item: 'static,
|
|
|
|
<Codec as Encoder>::Error: std::fmt::Debug,
|
|
|
|
{
|
2019-07-02 08:10:05 +02:00
|
|
|
/// Callback to execute on disconnect
|
|
|
|
///
|
|
|
|
/// Second parameter indicates error occured during disconnect.
|
2019-07-02 08:35:27 +02:00
|
|
|
pub fn disconnect<F>(mut self, disconnect: F) -> Self
|
2019-07-02 08:10:05 +02:00
|
|
|
where
|
2019-07-02 08:35:27 +02:00
|
|
|
F: Fn(&mut St, bool) + 'static,
|
2019-07-02 08:10:05 +02:00
|
|
|
{
|
2019-07-02 08:35:27 +02:00
|
|
|
self.disconnect = Some(Rc::new(disconnect));
|
2019-07-02 08:10:05 +02:00
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2019-11-18 13:28:54 +01:00
|
|
|
pub fn finish<F, T, Cfg>(self, service: F) -> FramedService<St, C, T, Io, Codec, Cfg>
|
2019-06-26 11:19:40 +02:00
|
|
|
where
|
2019-11-14 13:38:24 +01:00
|
|
|
F: IntoServiceFactory<T>,
|
|
|
|
T: ServiceFactory<
|
2019-06-26 11:19:40 +02:00
|
|
|
Config = St,
|
|
|
|
Request = RequestItem<St, Codec>,
|
|
|
|
Response = ResponseItem<Codec>,
|
|
|
|
Error = C::Error,
|
|
|
|
InitError = C::Error,
|
|
|
|
> + 'static,
|
|
|
|
{
|
|
|
|
FramedService {
|
|
|
|
connect: self.connect,
|
2019-11-14 13:38:24 +01:00
|
|
|
handler: Rc::new(service.into_factory()),
|
2019-07-02 08:10:05 +02:00
|
|
|
disconnect: self.disconnect,
|
2019-06-26 11:19:40 +02:00
|
|
|
_t: PhantomData,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-18 13:28:54 +01:00
|
|
|
pub struct FramedService<St, C, T, Io, Codec, Cfg> {
|
2019-06-26 11:19:40 +02:00
|
|
|
connect: C,
|
|
|
|
handler: Rc<T>,
|
2019-08-16 22:15:51 +02:00
|
|
|
disconnect: Option<Rc<dyn Fn(&mut St, bool)>>,
|
2019-07-03 09:02:03 +02:00
|
|
|
_t: PhantomData<(St, Io, Codec, Cfg)>,
|
2019-06-26 11:19:40 +02:00
|
|
|
}
|
|
|
|
|
2019-11-14 13:38:24 +01:00
|
|
|
impl<St, C, T, Io, Codec, Cfg> ServiceFactory for FramedService<St, C, T, Io, Codec, Cfg>
|
2019-06-26 11:19:40 +02:00
|
|
|
where
|
2019-12-02 16:27:48 +01:00
|
|
|
St: Clone + 'static,
|
2019-11-19 09:51:40 +01:00
|
|
|
Io: AsyncRead + AsyncWrite,
|
2019-11-14 13:38:24 +01:00
|
|
|
C: ServiceFactory<
|
|
|
|
Config = (),
|
|
|
|
Request = Connect<Io>,
|
|
|
|
Response = ConnectResult<Io, St, Codec>,
|
|
|
|
>,
|
2019-06-26 11:19:40 +02:00
|
|
|
C::Error: 'static,
|
2019-11-19 09:51:40 +01:00
|
|
|
C::Future: 'static,
|
2019-11-14 13:38:24 +01:00
|
|
|
T: ServiceFactory<
|
2019-06-26 11:19:40 +02:00
|
|
|
Config = St,
|
|
|
|
Request = RequestItem<St, Codec>,
|
|
|
|
Response = ResponseItem<Codec>,
|
|
|
|
Error = C::Error,
|
|
|
|
InitError = C::Error,
|
|
|
|
> + 'static,
|
2019-11-19 09:51:40 +01:00
|
|
|
<T::Service as Service>::Future: 'static,
|
|
|
|
Codec: Decoder + Encoder,
|
2019-06-26 11:19:40 +02:00
|
|
|
<Codec as Encoder>::Item: 'static,
|
|
|
|
<Codec as Encoder>::Error: std::fmt::Debug,
|
|
|
|
{
|
2019-07-03 09:02:03 +02:00
|
|
|
type Config = Cfg;
|
2019-06-26 11:19:40 +02:00
|
|
|
type Request = Io;
|
|
|
|
type Response = ();
|
|
|
|
type Error = ServiceError<C::Error, Codec>;
|
|
|
|
type InitError = C::InitError;
|
|
|
|
type Service = FramedServiceImpl<St, C::Service, T, Io, Codec>;
|
2019-11-14 13:38:24 +01:00
|
|
|
type Future = LocalBoxFuture<'static, Result<Self::Service, Self::InitError>>;
|
2019-06-26 11:19:40 +02:00
|
|
|
|
2019-12-02 16:27:48 +01:00
|
|
|
fn new_service(&self, _: Cfg) -> Self::Future {
|
2019-06-26 11:19:40 +02:00
|
|
|
let handler = self.handler.clone();
|
2019-07-02 08:10:05 +02:00
|
|
|
let disconnect = self.disconnect.clone();
|
2019-06-26 11:19:40 +02:00
|
|
|
|
|
|
|
// create connect service and then create service impl
|
2019-11-14 13:38:24 +01:00
|
|
|
self.connect
|
2019-12-02 16:27:48 +01:00
|
|
|
.new_service(())
|
2019-11-14 13:38:24 +01:00
|
|
|
.map(move |result| {
|
|
|
|
result.map(move |connect| FramedServiceImpl {
|
2019-06-26 11:19:40 +02:00
|
|
|
connect,
|
|
|
|
handler,
|
2019-07-02 08:10:05 +02:00
|
|
|
disconnect,
|
2019-06-26 11:19:40 +02:00
|
|
|
_t: PhantomData,
|
2019-11-14 13:38:24 +01:00
|
|
|
})
|
|
|
|
})
|
|
|
|
.boxed_local()
|
2019-06-26 11:19:40 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct FramedServiceImpl<St, C, T, Io, Codec> {
|
|
|
|
connect: C,
|
|
|
|
handler: Rc<T>,
|
2019-08-16 22:15:51 +02:00
|
|
|
disconnect: Option<Rc<dyn Fn(&mut St, bool)>>,
|
2019-06-26 11:19:40 +02:00
|
|
|
_t: PhantomData<(St, Io, Codec)>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<St, C, T, Io, Codec> Service for FramedServiceImpl<St, C, T, Io, Codec>
|
|
|
|
where
|
2019-12-02 16:27:48 +01:00
|
|
|
St: Clone,
|
2019-11-19 09:51:40 +01:00
|
|
|
Io: AsyncRead + AsyncWrite,
|
2019-06-26 11:19:40 +02:00
|
|
|
C: Service<Request = Connect<Io>, Response = ConnectResult<Io, St, Codec>>,
|
|
|
|
C::Error: 'static,
|
2019-11-14 13:38:24 +01:00
|
|
|
T: ServiceFactory<
|
2019-06-26 11:19:40 +02:00
|
|
|
Config = St,
|
|
|
|
Request = RequestItem<St, Codec>,
|
|
|
|
Response = ResponseItem<Codec>,
|
|
|
|
Error = C::Error,
|
|
|
|
InitError = C::Error,
|
|
|
|
>,
|
2019-11-19 09:51:40 +01:00
|
|
|
<T::Service as Service>::Future: 'static,
|
|
|
|
Codec: Decoder + Encoder,
|
2019-06-26 11:19:40 +02:00
|
|
|
<Codec as Encoder>::Item: 'static,
|
|
|
|
<Codec as Encoder>::Error: std::fmt::Debug,
|
|
|
|
{
|
|
|
|
type Request = Io;
|
|
|
|
type Response = ();
|
|
|
|
type Error = ServiceError<C::Error, Codec>;
|
|
|
|
type Future = FramedServiceImplResponse<St, Io, Codec, C, T>;
|
|
|
|
|
2019-12-02 17:30:09 +01:00
|
|
|
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
2019-11-14 13:38:24 +01:00
|
|
|
self.connect.poll_ready(cx).map_err(|e| e.into())
|
2019-06-26 11:19:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
fn call(&mut self, req: Io) -> Self::Future {
|
|
|
|
FramedServiceImplResponse {
|
|
|
|
inner: FramedServiceImplResponseInner::Connect(
|
|
|
|
self.connect.call(Connect::new(req)),
|
|
|
|
self.handler.clone(),
|
2019-11-14 13:38:24 +01:00
|
|
|
self.disconnect.clone(),
|
2019-06-26 11:19:40 +02:00
|
|
|
),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-19 09:51:40 +01:00
|
|
|
#[pin_project::pin_project]
|
2019-06-26 11:19:40 +02:00
|
|
|
pub struct FramedServiceImplResponse<St, Io, Codec, C, T>
|
|
|
|
where
|
2019-12-02 16:27:48 +01:00
|
|
|
St: Clone,
|
2019-06-26 11:19:40 +02:00
|
|
|
C: Service<Request = Connect<Io>, Response = ConnectResult<Io, St, Codec>>,
|
|
|
|
C::Error: 'static,
|
2019-11-14 13:38:24 +01:00
|
|
|
T: ServiceFactory<
|
2019-06-26 11:19:40 +02:00
|
|
|
Config = St,
|
|
|
|
Request = RequestItem<St, Codec>,
|
|
|
|
Response = ResponseItem<Codec>,
|
|
|
|
Error = C::Error,
|
|
|
|
InitError = C::Error,
|
|
|
|
>,
|
2019-11-19 09:51:40 +01:00
|
|
|
<T::Service as Service>::Future: 'static,
|
|
|
|
Io: AsyncRead + AsyncWrite,
|
|
|
|
Codec: Encoder + Decoder,
|
2019-06-26 11:19:40 +02:00
|
|
|
<Codec as Encoder>::Item: 'static,
|
|
|
|
<Codec as Encoder>::Error: std::fmt::Debug,
|
|
|
|
{
|
2019-11-19 09:51:40 +01:00
|
|
|
#[pin]
|
2019-06-26 11:19:40 +02:00
|
|
|
inner: FramedServiceImplResponseInner<St, Io, Codec, C, T>,
|
|
|
|
}
|
|
|
|
|
2019-11-14 13:38:24 +01:00
|
|
|
impl<St, Io, Codec, C, T> Future for FramedServiceImplResponse<St, Io, Codec, C, T>
|
|
|
|
where
|
2019-12-02 16:27:48 +01:00
|
|
|
St: Clone,
|
2019-11-14 13:38:24 +01:00
|
|
|
C: Service<Request = Connect<Io>, Response = ConnectResult<Io, St, Codec>>,
|
|
|
|
C::Error: 'static,
|
|
|
|
T: ServiceFactory<
|
|
|
|
Config = St,
|
|
|
|
Request = RequestItem<St, Codec>,
|
|
|
|
Response = ResponseItem<Codec>,
|
|
|
|
Error = C::Error,
|
|
|
|
InitError = C::Error,
|
|
|
|
>,
|
2019-11-19 09:51:40 +01:00
|
|
|
<T::Service as Service>::Future: 'static,
|
|
|
|
Io: AsyncRead + AsyncWrite,
|
|
|
|
Codec: Encoder + Decoder,
|
2019-11-14 13:38:24 +01:00
|
|
|
<Codec as Encoder>::Item: 'static,
|
|
|
|
<Codec as Encoder>::Error: std::fmt::Debug,
|
|
|
|
{
|
|
|
|
type Output = Result<(), ServiceError<C::Error, Codec>>;
|
|
|
|
|
2019-12-02 17:30:09 +01:00
|
|
|
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
2019-11-19 09:51:40 +01:00
|
|
|
let mut this = self.as_mut().project();
|
2019-11-14 13:38:24 +01:00
|
|
|
|
|
|
|
loop {
|
2019-11-18 13:28:54 +01:00
|
|
|
match this.inner.poll(cx) {
|
2019-11-19 09:51:40 +01:00
|
|
|
Either::Left(new) => {
|
|
|
|
this = self.as_mut().project();
|
|
|
|
this.inner.set(new)
|
|
|
|
}
|
2019-11-14 13:38:24 +01:00
|
|
|
Either::Right(poll) => return poll,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-19 09:51:40 +01:00
|
|
|
#[pin_project::pin_project]
|
2019-06-26 11:19:40 +02:00
|
|
|
enum FramedServiceImplResponseInner<St, Io, Codec, C, T>
|
|
|
|
where
|
2019-12-02 16:27:48 +01:00
|
|
|
St: Clone,
|
2019-06-26 11:19:40 +02:00
|
|
|
C: Service<Request = Connect<Io>, Response = ConnectResult<Io, St, Codec>>,
|
|
|
|
C::Error: 'static,
|
2019-11-14 13:38:24 +01:00
|
|
|
T: ServiceFactory<
|
2019-06-26 11:19:40 +02:00
|
|
|
Config = St,
|
|
|
|
Request = RequestItem<St, Codec>,
|
|
|
|
Response = ResponseItem<Codec>,
|
|
|
|
Error = C::Error,
|
|
|
|
InitError = C::Error,
|
|
|
|
>,
|
2019-11-19 09:51:40 +01:00
|
|
|
<T::Service as Service>::Future: 'static,
|
|
|
|
Io: AsyncRead + AsyncWrite,
|
|
|
|
Codec: Encoder + Decoder,
|
2019-06-26 11:19:40 +02:00
|
|
|
<Codec as Encoder>::Item: 'static,
|
|
|
|
<Codec as Encoder>::Error: std::fmt::Debug,
|
|
|
|
{
|
2019-11-19 09:51:40 +01:00
|
|
|
Connect(#[pin] C::Future, Rc<T>, Option<Rc<dyn Fn(&mut St, bool)>>),
|
2019-11-14 13:38:24 +01:00
|
|
|
Handler(
|
2019-11-19 09:51:40 +01:00
|
|
|
#[pin] T::Future,
|
2019-11-14 13:38:24 +01:00
|
|
|
Option<ConnectResult<Io, St, Codec>>,
|
|
|
|
Option<Rc<dyn Fn(&mut St, bool)>>,
|
|
|
|
),
|
2019-11-19 09:51:40 +01:00
|
|
|
Dispatcher(#[pin] FramedDispatcher<St, T::Service, Io, Codec>),
|
2019-06-26 11:19:40 +02:00
|
|
|
}
|
|
|
|
|
2019-11-14 13:38:24 +01:00
|
|
|
impl<St, Io, Codec, C, T> FramedServiceImplResponseInner<St, Io, Codec, C, T>
|
2019-06-26 11:19:40 +02:00
|
|
|
where
|
2019-12-02 16:27:48 +01:00
|
|
|
St: Clone,
|
2019-06-26 11:19:40 +02:00
|
|
|
C: Service<Request = Connect<Io>, Response = ConnectResult<Io, St, Codec>>,
|
|
|
|
C::Error: 'static,
|
2019-11-14 13:38:24 +01:00
|
|
|
T: ServiceFactory<
|
2019-06-26 11:19:40 +02:00
|
|
|
Config = St,
|
|
|
|
Request = RequestItem<St, Codec>,
|
|
|
|
Response = ResponseItem<Codec>,
|
|
|
|
Error = C::Error,
|
|
|
|
InitError = C::Error,
|
|
|
|
>,
|
2019-11-19 09:51:40 +01:00
|
|
|
<T::Service as Service>::Future: 'static,
|
|
|
|
Io: AsyncRead + AsyncWrite,
|
|
|
|
Codec: Encoder + Decoder,
|
2019-06-26 11:19:40 +02:00
|
|
|
<Codec as Encoder>::Item: 'static,
|
|
|
|
<Codec as Encoder>::Error: std::fmt::Debug,
|
|
|
|
{
|
2019-11-19 09:51:40 +01:00
|
|
|
#[project]
|
2019-11-14 13:38:24 +01:00
|
|
|
fn poll(
|
2019-11-19 09:51:40 +01:00
|
|
|
self: Pin<&mut Self>,
|
2019-12-02 17:30:09 +01:00
|
|
|
cx: &mut Context<'_>,
|
2019-11-14 13:38:24 +01:00
|
|
|
) -> Either<
|
|
|
|
FramedServiceImplResponseInner<St, Io, Codec, C, T>,
|
|
|
|
Poll<Result<(), ServiceError<C::Error, Codec>>>,
|
|
|
|
> {
|
2019-11-19 09:51:40 +01:00
|
|
|
#[project]
|
|
|
|
match self.project() {
|
|
|
|
FramedServiceImplResponseInner::Connect(fut, handler, disconnect) => {
|
|
|
|
match fut.poll(cx) {
|
|
|
|
Poll::Ready(Ok(res)) => {
|
|
|
|
Either::Left(FramedServiceImplResponseInner::Handler(
|
2019-12-02 16:27:48 +01:00
|
|
|
handler.new_service(res.state.clone()),
|
2019-11-19 09:51:40 +01:00
|
|
|
Some(res),
|
|
|
|
disconnect.take(),
|
|
|
|
))
|
|
|
|
}
|
|
|
|
Poll::Pending => Either::Right(Poll::Pending),
|
|
|
|
Poll::Ready(Err(e)) => Either::Right(Poll::Ready(Err(e.into()))),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
FramedServiceImplResponseInner::Handler(fut, res, disconnect) => match fut.poll(cx)
|
|
|
|
{
|
2019-11-14 13:38:24 +01:00
|
|
|
Poll::Ready(Ok(handler)) => {
|
|
|
|
let res = res.take().unwrap();
|
|
|
|
Either::Left(FramedServiceImplResponseInner::Dispatcher(
|
|
|
|
FramedDispatcher::new(
|
|
|
|
res.framed,
|
2019-12-02 16:27:48 +01:00
|
|
|
res.state,
|
2019-11-14 13:38:24 +01:00
|
|
|
handler,
|
|
|
|
res.rx,
|
|
|
|
res.sink,
|
|
|
|
disconnect.take(),
|
|
|
|
),
|
|
|
|
))
|
2019-06-26 11:19:40 +02:00
|
|
|
}
|
2019-11-14 13:38:24 +01:00
|
|
|
Poll::Pending => Either::Right(Poll::Pending),
|
|
|
|
Poll::Ready(Err(e)) => Either::Right(Poll::Ready(Err(e.into()))),
|
|
|
|
},
|
|
|
|
FramedServiceImplResponseInner::Dispatcher(ref mut fut) => {
|
2019-11-18 13:28:54 +01:00
|
|
|
Either::Right(fut.poll(cx))
|
2019-06-26 11:19:40 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|