1
0
mirror of https://github.com/fafhrd91/actix-net synced 2025-01-19 22:14:40 +01:00

383 lines
10 KiB
Rust
Raw Normal View History

2018-08-23 20:47:41 -07:00
use std::collections::VecDeque;
use std::marker::PhantomData;
use std::net::{IpAddr, SocketAddr};
2018-10-23 22:14:02 -07:00
use std::time::Duration;
2018-10-29 14:04:53 -07:00
use std::{fmt, io};
2018-08-23 20:47:41 -07:00
2018-12-09 10:15:49 -08:00
use actix_service::{NewService, Service};
2018-11-21 08:07:04 -10:00
use futures::future::{ok, Either, FutureResult};
2018-12-06 14:04:42 -08:00
use futures::{try_ready, Async, Future, Poll};
2018-08-23 20:47:41 -07:00
use tokio_tcp::{ConnectFuture, TcpStream};
use trust_dns_resolver::config::{ResolverConfig, ResolverOpts};
2018-08-28 16:24:36 -07:00
use trust_dns_resolver::system_conf::read_system_conf;
2018-08-23 20:47:41 -07:00
use super::resolver::{RequestHost, ResolveError, Resolver, ResolverFuture};
2018-08-28 16:24:36 -07:00
/// Port of the request
pub trait RequestPort {
fn port(&self) -> u16;
}
2018-09-10 19:39:55 -07:00
// #[derive(Fail, Debug)]
#[derive(Debug)]
2018-08-23 20:47:41 -07:00
pub enum ConnectorError {
/// Failed to resolve the hostname
2018-09-10 19:39:55 -07:00
// #[fail(display = "Failed resolving hostname: {}", _0)]
2018-10-29 20:29:47 -07:00
Resolver(ResolveError),
2018-08-23 20:47:41 -07:00
2018-10-29 20:29:47 -07:00
/// No dns records
// #[fail(display = "No dns records found for the input")]
2018-09-10 19:39:55 -07:00
NoRecords,
2018-08-23 20:47:41 -07:00
2018-10-23 22:14:02 -07:00
/// Connecting took too long
// #[fail(display = "Timeout out while establishing connection")]
Timeout,
2018-10-29 20:29:47 -07:00
/// Invalid input
InvalidInput,
2018-08-23 20:47:41 -07:00
/// Connection io error
2018-09-10 19:39:55 -07:00
// #[fail(display = "{}", _0)]
2018-08-23 20:47:41 -07:00
IoError(io::Error),
}
2018-10-29 20:29:47 -07:00
impl From<ResolveError> for ConnectorError {
fn from(err: ResolveError) -> Self {
2018-09-10 19:39:55 -07:00
ConnectorError::Resolver(err)
}
}
impl From<io::Error> for ConnectorError {
fn from(err: io::Error) -> Self {
ConnectorError::IoError(err)
}
}
2018-10-29 20:29:47 -07:00
/// Connect request
2018-10-29 13:27:00 -07:00
#[derive(Eq, PartialEq, Debug, Hash)]
2018-10-23 22:14:02 -07:00
pub struct Connect {
2018-11-21 08:07:04 -10:00
pub kind: ConnectKind,
2018-10-23 22:14:02 -07:00
pub timeout: Duration,
}
2018-11-21 08:07:04 -10:00
#[derive(Eq, PartialEq, Debug, Hash)]
pub enum ConnectKind {
Host { host: String, port: u16 },
Addr { host: String, addr: SocketAddr },
}
2018-10-23 22:14:02 -07:00
impl Connect {
2018-10-29 20:29:47 -07:00
/// Create new `Connect` instance.
2018-10-23 22:40:56 -07:00
pub fn new<T: AsRef<str>>(host: T, port: u16) -> Connect {
2018-10-23 22:14:02 -07:00
Connect {
2018-11-21 08:07:04 -10:00
kind: ConnectKind::Host {
host: host.as_ref().to_owned(),
port,
},
2018-10-23 22:14:02 -07:00
timeout: Duration::from_secs(1),
}
}
2018-10-29 20:29:47 -07:00
/// Create `Connect` instance by spliting the string by ':' and convert the second part to u16
pub fn with<T: AsRef<str>>(host: T) -> Result<Connect, ConnectorError> {
2018-10-29 13:41:54 -07:00
let mut parts_iter = host.as_ref().splitn(2, ':');
2018-10-29 20:29:47 -07:00
let host = parts_iter.next().ok_or(ConnectorError::InvalidInput)?;
let port_str = parts_iter.next().unwrap_or("");
let port = port_str
.parse::<u16>()
.map_err(|_| ConnectorError::InvalidInput)?;
Ok(Connect {
2018-11-21 08:07:04 -10:00
kind: ConnectKind::Host {
host: host.to_owned(),
port,
},
2018-10-29 20:29:47 -07:00
timeout: Duration::from_secs(1),
})
2018-10-29 13:41:54 -07:00
}
2018-11-21 08:07:04 -10:00
/// Create new `Connect` instance from host and address. Connector skips name resolution stage for such connect messages.
pub fn with_address<T: Into<String>>(host: T, addr: SocketAddr) -> Connect {
Connect {
kind: ConnectKind::Addr {
addr,
host: host.into(),
},
timeout: Duration::from_secs(1),
}
}
2018-10-23 22:14:02 -07:00
/// Set connect timeout
///
/// By default timeout is set to a 1 second.
pub fn timeout(mut self, timeout: Duration) -> Connect {
self.timeout = timeout;
self
}
}
impl RequestHost for Connect {
2018-10-23 22:14:02 -07:00
fn host(&self) -> &str {
2018-11-21 08:07:04 -10:00
match self.kind {
2018-12-06 14:04:42 -08:00
ConnectKind::Host { ref host, .. } => host,
ConnectKind::Addr { ref host, .. } => host,
2018-11-21 08:07:04 -10:00
}
2018-10-23 22:14:02 -07:00
}
2018-08-28 16:24:36 -07:00
}
impl RequestPort for Connect {
fn port(&self) -> u16 {
2018-11-21 08:07:04 -10:00
match self.kind {
2018-12-06 14:04:42 -08:00
ConnectKind::Host { port, .. } => port,
ConnectKind::Addr { addr, .. } => addr.port(),
2018-11-21 08:07:04 -10:00
}
}
}
2018-10-29 14:04:53 -07:00
impl fmt::Display for Connect {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2018-11-21 08:07:04 -10:00
write!(f, "{}:{}", self.host(), self.port())
2018-10-29 14:04:53 -07:00
}
}
2018-10-29 20:29:47 -07:00
/// Tcp connector
2018-10-23 22:14:02 -07:00
pub struct Connector {
resolver: Resolver<Connect>,
2018-08-23 20:47:41 -07:00
}
2018-10-23 22:14:02 -07:00
impl Default for Connector {
2018-08-28 16:24:36 -07:00
fn default() -> Self {
let (cfg, opts) = if let Ok((cfg, opts)) = read_system_conf() {
(cfg, opts)
} else {
(ResolverConfig::default(), ResolverOpts::default())
2018-08-23 20:47:41 -07:00
};
2018-08-28 16:24:36 -07:00
Connector::new(cfg, opts)
}
}
2018-10-23 22:14:02 -07:00
impl Connector {
2018-10-29 20:29:47 -07:00
/// Create new connector with resolver configuration
2018-08-28 16:24:36 -07:00
pub fn new(cfg: ResolverConfig, opts: ResolverOpts) -> Self {
2018-08-29 15:15:24 -07:00
Connector {
2018-09-10 19:39:55 -07:00
resolver: Resolver::new(cfg, opts),
2018-08-29 15:15:24 -07:00
}
2018-08-23 20:47:41 -07:00
}
2018-08-27 20:32:49 -07:00
2018-10-29 20:29:47 -07:00
/// Create new connector with custom resolver
2018-09-10 19:42:51 -07:00
pub fn with_resolver(
2018-10-23 22:14:02 -07:00
resolver: Resolver<Connect>,
2018-11-29 16:56:15 -10:00
) -> impl Service<Connect, Response = (Connect, TcpStream), Error = ConnectorError> + Clone
{
2018-09-10 19:42:51 -07:00
Connector { resolver }
}
2018-11-29 17:17:02 -10:00
/// Create new default connector service
pub fn new_service_with_config<E>(
cfg: ResolverConfig,
opts: ResolverOpts,
) -> impl NewService<
Connect,
Response = (Connect, TcpStream),
Error = ConnectorError,
InitError = E,
> + Clone {
move || -> FutureResult<Connector, E> { ok(Connector::new(cfg.clone(), opts)) }
}
2018-08-27 20:32:49 -07:00
}
2018-10-23 22:14:02 -07:00
impl Clone for Connector {
2018-08-27 20:32:49 -07:00
fn clone(&self) -> Self {
Connector {
resolver: self.resolver.clone(),
}
}
2018-08-23 20:47:41 -07:00
}
2018-11-29 16:56:15 -10:00
impl Service<Connect> for Connector {
2018-10-23 22:14:02 -07:00
type Response = (Connect, TcpStream);
2018-08-23 20:47:41 -07:00
type Error = ConnectorError;
2018-11-21 08:07:04 -10:00
type Future = Either<ConnectorFuture, ConnectorTcpFuture>;
2018-08-23 20:47:41 -07:00
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
Ok(Async::Ready(()))
}
2018-11-29 16:56:15 -10:00
fn call(&mut self, req: Connect) -> Self::Future {
2018-11-21 08:07:04 -10:00
match req.kind {
2018-12-06 14:04:42 -08:00
ConnectKind::Host { .. } => Either::A(ConnectorFuture {
2018-11-21 08:07:04 -10:00
fut: self.resolver.call(req),
fut2: None,
}),
2018-12-06 14:04:42 -08:00
ConnectKind::Addr { addr, .. } => {
2018-11-21 08:07:04 -10:00
let mut addrs = VecDeque::new();
addrs.push_back(addr.ip());
Either::B(ConnectorTcpFuture {
fut: TcpConnectorResponse::new(req, addrs),
})
}
2018-09-10 19:39:55 -07:00
}
2018-08-23 20:47:41 -07:00
}
}
2018-09-11 14:01:51 -07:00
#[doc(hidden)]
2018-10-23 22:14:02 -07:00
pub struct ConnectorFuture {
fut: ResolverFuture<Connect>,
fut2: Option<TcpConnectorResponse<Connect>>,
2018-08-23 20:47:41 -07:00
}
2018-10-23 22:14:02 -07:00
impl Future for ConnectorFuture {
type Item = (Connect, TcpStream);
2018-08-23 20:47:41 -07:00
type Error = ConnectorError;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
if let Some(ref mut fut) = self.fut2 {
return fut.poll().map_err(ConnectorError::from);
2018-08-23 20:47:41 -07:00
}
2018-09-10 19:39:55 -07:00
match self.fut.poll().map_err(ConnectorError::from)? {
Async::Ready((req, addrs)) => {
2018-09-10 19:39:55 -07:00
if addrs.is_empty() {
Err(ConnectorError::NoRecords)
} else {
self.fut2 = Some(TcpConnectorResponse::new(req, addrs));
2018-09-10 19:39:55 -07:00
self.poll()
}
2018-08-23 22:12:10 -07:00
}
Async::NotReady => Ok(Async::NotReady),
2018-08-23 20:47:41 -07:00
}
}
}
2018-11-21 08:07:04 -10:00
#[doc(hidden)]
pub struct ConnectorTcpFuture {
fut: TcpConnectorResponse<Connect>,
}
impl Future for ConnectorTcpFuture {
type Item = (Connect, TcpStream);
type Error = ConnectorError;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
self.fut.poll().map_err(ConnectorError::IoError)
}
}
/// Tcp stream connector service
pub struct TcpConnector<T: RequestPort>(PhantomData<T>);
impl<T: RequestPort> Default for TcpConnector<T> {
fn default() -> TcpConnector<T> {
TcpConnector(PhantomData)
}
}
2018-11-29 16:56:15 -10:00
impl<T: RequestPort> Service<(T, VecDeque<IpAddr>)> for TcpConnector<T> {
type Response = (T, TcpStream);
type Error = io::Error;
type Future = TcpConnectorResponse<T>;
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
Ok(Async::Ready(()))
}
2018-11-29 16:56:15 -10:00
fn call(&mut self, (req, addrs): (T, VecDeque<IpAddr>)) -> Self::Future {
TcpConnectorResponse::new(req, addrs)
}
}
2018-09-11 14:01:51 -07:00
#[doc(hidden)]
/// Tcp stream connector response future
pub struct TcpConnectorResponse<T: RequestPort> {
port: u16,
req: Option<T>,
2018-08-28 16:24:36 -07:00
addr: Option<SocketAddr>,
addrs: VecDeque<IpAddr>,
2018-08-23 20:47:41 -07:00
stream: Option<ConnectFuture>,
}
impl<T: RequestPort> TcpConnectorResponse<T> {
pub fn new(req: T, addrs: VecDeque<IpAddr>) -> TcpConnectorResponse<T> {
TcpConnectorResponse {
2018-08-23 20:47:41 -07:00
addrs,
port: req.port(),
2018-08-29 15:15:24 -07:00
req: Some(req),
2018-08-28 16:24:36 -07:00
addr: None,
2018-08-23 20:47:41 -07:00
stream: None,
}
}
}
impl<T: RequestPort> Future for TcpConnectorResponse<T> {
type Item = (T, TcpStream);
type Error = io::Error;
2018-08-23 20:47:41 -07:00
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
// connect
loop {
if let Some(new) = self.stream.as_mut() {
match new.poll() {
2018-08-28 16:24:36 -07:00
Ok(Async::Ready(sock)) => {
2018-10-23 22:14:02 -07:00
return Ok(Async::Ready((self.req.take().unwrap(), sock)))
2018-08-28 16:24:36 -07:00
}
2018-08-23 20:47:41 -07:00
Ok(Async::NotReady) => return Ok(Async::NotReady),
Err(err) => {
if self.addrs.is_empty() {
return Err(err);
2018-08-23 20:47:41 -07:00
}
}
}
}
// try to connect
let addr = SocketAddr::new(self.addrs.pop_front().unwrap(), self.port);
2018-08-23 20:47:41 -07:00
self.stream = Some(TcpStream::connect(&addr));
2018-08-28 16:24:36 -07:00
self.addr = Some(addr)
2018-08-23 20:47:41 -07:00
}
}
}
2018-10-23 22:26:16 -07:00
#[derive(Clone)]
pub struct DefaultConnector(Connector);
impl Default for DefaultConnector {
fn default() -> Self {
DefaultConnector(Connector::default())
}
}
impl DefaultConnector {
pub fn new(cfg: ResolverConfig, opts: ResolverOpts) -> Self {
DefaultConnector(Connector::new(cfg, opts))
}
}
2018-11-29 16:56:15 -10:00
impl Service<Connect> for DefaultConnector {
2018-10-23 22:26:16 -07:00
type Response = TcpStream;
type Error = ConnectorError;
type Future = DefaultConnectorFuture;
fn poll_ready(&mut self) -> Poll<(), Self::Error> {
self.0.poll_ready()
}
2018-11-29 16:56:15 -10:00
fn call(&mut self, req: Connect) -> Self::Future {
2018-10-23 22:26:16 -07:00
DefaultConnectorFuture {
fut: self.0.call(req),
}
}
}
#[doc(hidden)]
pub struct DefaultConnectorFuture {
2018-11-21 08:07:04 -10:00
fut: Either<ConnectorFuture, ConnectorTcpFuture>,
2018-10-23 22:26:16 -07:00
}
impl Future for DefaultConnectorFuture {
type Item = TcpStream;
type Error = ConnectorError;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
Ok(Async::Ready(try_ready!(self.fut.poll()).1))
}
}