2019-11-14 13:38:24 +01:00
|
|
|
use std::future::Future;
|
|
|
|
use std::pin::Pin;
|
|
|
|
use std::task::{Context, Poll};
|
|
|
|
|
|
|
|
use actix_service::{Service, ServiceFactory};
|
|
|
|
use either::Either;
|
|
|
|
use futures::future::{ok, Ready};
|
|
|
|
use tokio_net::tcp::TcpStream;
|
2019-08-05 18:52:50 +02:00
|
|
|
use trust_dns_resolver::AsyncResolver;
|
|
|
|
|
|
|
|
use crate::connect::{Address, Connect, Connection};
|
|
|
|
use crate::connector::{TcpConnector, TcpConnectorFactory};
|
|
|
|
use crate::error::ConnectError;
|
|
|
|
use crate::resolver::{Resolver, ResolverFactory};
|
|
|
|
|
|
|
|
pub struct ConnectServiceFactory<T> {
|
|
|
|
tcp: TcpConnectorFactory<T>,
|
|
|
|
resolver: ResolverFactory<T>,
|
|
|
|
}
|
|
|
|
|
2019-11-14 13:38:24 +01:00
|
|
|
impl<T: Unpin> ConnectServiceFactory<T> {
|
2019-08-05 18:52:50 +02:00
|
|
|
/// Construct new ConnectService factory
|
|
|
|
pub fn new() -> Self {
|
|
|
|
ConnectServiceFactory {
|
|
|
|
tcp: TcpConnectorFactory::default(),
|
|
|
|
resolver: ResolverFactory::default(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Construct new connect service with custom dns resolver
|
|
|
|
pub fn with_resolver(resolver: AsyncResolver) -> Self {
|
|
|
|
ConnectServiceFactory {
|
|
|
|
tcp: TcpConnectorFactory::default(),
|
|
|
|
resolver: ResolverFactory::new(resolver),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Construct new service
|
|
|
|
pub fn service(&self) -> ConnectService<T> {
|
|
|
|
ConnectService {
|
|
|
|
tcp: self.tcp.service(),
|
|
|
|
resolver: self.resolver.service(),
|
|
|
|
}
|
|
|
|
}
|
2019-09-06 01:34:48 +02:00
|
|
|
|
|
|
|
/// Construct new tcp stream service
|
|
|
|
pub fn tcp_service(&self) -> TcpConnectService<T> {
|
|
|
|
TcpConnectService {
|
|
|
|
tcp: self.tcp.service(),
|
|
|
|
resolver: self.resolver.service(),
|
|
|
|
}
|
|
|
|
}
|
2019-08-05 18:52:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> Default for ConnectServiceFactory<T> {
|
|
|
|
fn default() -> Self {
|
|
|
|
ConnectServiceFactory {
|
|
|
|
tcp: TcpConnectorFactory::default(),
|
|
|
|
resolver: ResolverFactory::default(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> Clone for ConnectServiceFactory<T> {
|
|
|
|
fn clone(&self) -> Self {
|
|
|
|
ConnectServiceFactory {
|
|
|
|
tcp: self.tcp.clone(),
|
|
|
|
resolver: self.resolver.clone(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-14 13:38:24 +01:00
|
|
|
impl<T: Address + Unpin> ServiceFactory for ConnectServiceFactory<T> {
|
2019-08-05 18:52:50 +02:00
|
|
|
type Request = Connect<T>;
|
|
|
|
type Response = Connection<T, TcpStream>;
|
|
|
|
type Error = ConnectError;
|
|
|
|
type Config = ();
|
|
|
|
type Service = ConnectService<T>;
|
|
|
|
type InitError = ();
|
2019-11-14 13:38:24 +01:00
|
|
|
type Future = Ready<Result<Self::Service, Self::InitError>>;
|
2019-08-05 18:52:50 +02:00
|
|
|
|
|
|
|
fn new_service(&self, _: &()) -> Self::Future {
|
|
|
|
ok(self.service())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone)]
|
|
|
|
pub struct ConnectService<T> {
|
|
|
|
tcp: TcpConnector<T>,
|
|
|
|
resolver: Resolver<T>,
|
|
|
|
}
|
|
|
|
|
2019-11-14 13:38:24 +01:00
|
|
|
impl<T: Address + Unpin> Service for ConnectService<T> {
|
2019-08-05 18:52:50 +02:00
|
|
|
type Request = Connect<T>;
|
|
|
|
type Response = Connection<T, TcpStream>;
|
|
|
|
type Error = ConnectError;
|
|
|
|
type Future = ConnectServiceResponse<T>;
|
|
|
|
|
2019-11-14 13:38:24 +01:00
|
|
|
fn poll_ready(&mut self, _: &mut Context) -> Poll<Result<(), Self::Error>> {
|
|
|
|
Poll::Ready(Ok(()))
|
2019-08-05 18:52:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
fn call(&mut self, req: Connect<T>) -> Self::Future {
|
|
|
|
ConnectServiceResponse {
|
2019-11-14 13:38:24 +01:00
|
|
|
state: ConnectState::Resolve(self.resolver.call(req)),
|
2019-08-05 18:52:50 +02:00
|
|
|
tcp: self.tcp.clone(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-14 13:38:24 +01:00
|
|
|
enum ConnectState<T: Address + Unpin> {
|
|
|
|
Resolve(<Resolver<T> as Service>::Future),
|
|
|
|
Connect(<TcpConnector<T> as Service>::Future),
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T: Address + Unpin> ConnectState<T> {
|
|
|
|
fn poll(
|
|
|
|
&mut self,
|
|
|
|
cx: &mut Context,
|
|
|
|
) -> Either<Poll<Result<Connection<T, TcpStream>, ConnectError>>, Connect<T>> {
|
|
|
|
match self {
|
|
|
|
ConnectState::Resolve(ref mut fut) => match Pin::new(fut).poll(cx) {
|
|
|
|
Poll::Pending => Either::Left(Poll::Pending),
|
|
|
|
Poll::Ready(Ok(res)) => Either::Right(res),
|
|
|
|
Poll::Ready(Err(err)) => Either::Left(Poll::Ready(Err(err))),
|
|
|
|
},
|
|
|
|
ConnectState::Connect(ref mut fut) => Either::Left(Pin::new(fut).poll(cx)),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct ConnectServiceResponse<T: Address + Unpin> {
|
|
|
|
state: ConnectState<T>,
|
2019-08-05 18:52:50 +02:00
|
|
|
tcp: TcpConnector<T>,
|
|
|
|
}
|
|
|
|
|
2019-11-14 13:38:24 +01:00
|
|
|
impl<T: Address + Unpin> Future for ConnectServiceResponse<T> {
|
|
|
|
type Output = Result<Connection<T, TcpStream>, ConnectError>;
|
2019-08-05 18:52:50 +02:00
|
|
|
|
2019-11-14 13:38:24 +01:00
|
|
|
fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
|
|
|
let res = match self.state.poll(cx) {
|
|
|
|
Either::Right(res) => {
|
|
|
|
self.state = ConnectState::Connect(self.tcp.call(res));
|
|
|
|
self.state.poll(cx)
|
|
|
|
}
|
|
|
|
Either::Left(res) => return res,
|
|
|
|
};
|
2019-08-05 18:52:50 +02:00
|
|
|
|
2019-11-14 13:38:24 +01:00
|
|
|
match res {
|
|
|
|
Either::Left(res) => res,
|
|
|
|
Either::Right(_) => panic!(),
|
2019-08-05 18:52:50 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-09-06 01:34:48 +02:00
|
|
|
|
|
|
|
#[derive(Clone)]
|
|
|
|
pub struct TcpConnectService<T> {
|
|
|
|
tcp: TcpConnector<T>,
|
|
|
|
resolver: Resolver<T>,
|
|
|
|
}
|
|
|
|
|
2019-11-14 13:38:24 +01:00
|
|
|
impl<T: Address + Unpin + 'static> Service for TcpConnectService<T> {
|
2019-09-06 01:34:48 +02:00
|
|
|
type Request = Connect<T>;
|
|
|
|
type Response = TcpStream;
|
|
|
|
type Error = ConnectError;
|
|
|
|
type Future = TcpConnectServiceResponse<T>;
|
|
|
|
|
2019-11-14 13:38:24 +01:00
|
|
|
fn poll_ready(&mut self, _: &mut Context) -> Poll<Result<(), Self::Error>> {
|
|
|
|
Poll::Ready(Ok(()))
|
2019-09-06 01:34:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
fn call(&mut self, req: Connect<T>) -> Self::Future {
|
|
|
|
TcpConnectServiceResponse {
|
2019-11-14 13:38:24 +01:00
|
|
|
state: TcpConnectState::Resolve(self.resolver.call(req)),
|
2019-09-06 01:34:48 +02:00
|
|
|
tcp: self.tcp.clone(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-14 13:38:24 +01:00
|
|
|
enum TcpConnectState<T: Address + Unpin> {
|
|
|
|
Resolve(<Resolver<T> as Service>::Future),
|
|
|
|
Connect(<TcpConnector<T> as Service>::Future),
|
2019-09-06 01:34:48 +02:00
|
|
|
}
|
|
|
|
|
2019-11-14 13:38:24 +01:00
|
|
|
impl<T: Address + Unpin> TcpConnectState<T> {
|
|
|
|
fn poll(
|
|
|
|
&mut self,
|
|
|
|
cx: &mut Context,
|
|
|
|
) -> Either<Poll<Result<TcpStream, ConnectError>>, Connect<T>> {
|
|
|
|
match self {
|
|
|
|
TcpConnectState::Resolve(ref mut fut) => match Pin::new(fut).poll(cx) {
|
|
|
|
Poll::Pending => (),
|
|
|
|
Poll::Ready(Ok(res)) => return Either::Right(res),
|
|
|
|
Poll::Ready(Err(err)) => return Either::Left(Poll::Ready(Err(err))),
|
|
|
|
},
|
|
|
|
TcpConnectState::Connect(ref mut fut) => {
|
|
|
|
if let Poll::Ready(res) = Pin::new(fut).poll(cx) {
|
|
|
|
return match res {
|
|
|
|
Ok(conn) => Either::Left(Poll::Ready(Ok(conn.into_parts().0))),
|
|
|
|
Err(err) => Either::Left(Poll::Ready(Err(err))),
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
2019-09-06 01:34:48 +02:00
|
|
|
}
|
2019-11-14 13:38:24 +01:00
|
|
|
Either::Left(Poll::Pending)
|
|
|
|
}
|
|
|
|
}
|
2019-09-06 01:34:48 +02:00
|
|
|
|
2019-11-14 13:38:24 +01:00
|
|
|
pub struct TcpConnectServiceResponse<T: Address + Unpin> {
|
|
|
|
state: TcpConnectState<T>,
|
|
|
|
tcp: TcpConnector<T>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T: Address + Unpin> Future for TcpConnectServiceResponse<T> {
|
|
|
|
type Output = Result<TcpStream, ConnectError>;
|
|
|
|
|
|
|
|
fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
|
|
|
let res = match self.state.poll(cx) {
|
|
|
|
Either::Right(res) => {
|
|
|
|
self.state = TcpConnectState::Connect(self.tcp.call(res));
|
|
|
|
self.state.poll(cx)
|
2019-09-06 01:34:48 +02:00
|
|
|
}
|
2019-11-14 13:38:24 +01:00
|
|
|
Either::Left(res) => return res,
|
|
|
|
};
|
2019-09-06 01:34:48 +02:00
|
|
|
|
2019-11-14 13:38:24 +01:00
|
|
|
match res {
|
|
|
|
Either::Left(res) => res,
|
|
|
|
Either::Right(_) => panic!(),
|
|
|
|
}
|
2019-09-06 01:34:48 +02:00
|
|
|
}
|
|
|
|
}
|