2019-03-13 20:40:11 +01:00
|
|
|
use std::collections::VecDeque;
|
|
|
|
use std::fmt;
|
|
|
|
use std::net::SocketAddr;
|
|
|
|
|
|
|
|
use either::Either;
|
|
|
|
|
|
|
|
use crate::error::ConnectError;
|
|
|
|
|
2019-03-13 23:37:12 +01:00
|
|
|
/// Connect request
|
|
|
|
pub trait Address {
|
|
|
|
/// Host name of the request
|
|
|
|
fn host(&self) -> &str;
|
|
|
|
|
|
|
|
/// Port of the request
|
|
|
|
fn port(&self) -> u16;
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Address for (String, u16) {
|
|
|
|
fn host(&self) -> &str {
|
|
|
|
&self.0
|
|
|
|
}
|
|
|
|
|
|
|
|
fn port(&self) -> u16 {
|
|
|
|
self.1
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Address for (&'static str, u16) {
|
|
|
|
fn host(&self) -> &str {
|
|
|
|
self.0
|
|
|
|
}
|
|
|
|
|
|
|
|
fn port(&self) -> u16 {
|
|
|
|
self.1
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-13 20:40:11 +01:00
|
|
|
/// Connect request
|
|
|
|
#[derive(Eq, PartialEq, Debug, Hash)]
|
2019-03-13 23:37:12 +01:00
|
|
|
pub struct Connect<T> {
|
|
|
|
pub(crate) req: T,
|
|
|
|
pub(crate) addr: Option<Either<SocketAddr, VecDeque<SocketAddr>>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Connect<(&'static str, u16)> {
|
|
|
|
/// Create new `Connect` instance.
|
|
|
|
pub fn new(host: &'static str, port: u16) -> Connect<(&'static str, u16)> {
|
|
|
|
Connect {
|
|
|
|
req: (host, port),
|
|
|
|
addr: None,
|
|
|
|
}
|
|
|
|
}
|
2019-03-13 20:40:11 +01:00
|
|
|
}
|
|
|
|
|
2019-03-13 23:55:20 +01:00
|
|
|
impl Connect<()> {
|
2019-03-13 20:40:11 +01:00
|
|
|
/// Create new `Connect` instance.
|
2019-03-13 23:55:20 +01:00
|
|
|
pub fn from_string(host: String, port: u16) -> Connect<(String, u16)> {
|
|
|
|
Connect {
|
|
|
|
req: (host, port),
|
|
|
|
addr: None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Create new `Connect` instance.
|
|
|
|
pub fn from_static(host: &'static str, port: u16) -> Connect<(&'static str, u16)> {
|
2019-03-13 23:37:12 +01:00
|
|
|
Connect {
|
2019-03-13 23:52:51 +01:00
|
|
|
req: (host, port),
|
2019-03-13 23:37:12 +01:00
|
|
|
addr: None,
|
2019-03-13 20:40:11 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Create `Connect` instance by spliting the string by ':' and convert the second part to u16
|
2019-03-13 23:55:20 +01:00
|
|
|
pub fn from_str<T: AsRef<str>>(host: T) -> Result<Connect<(String, u16)>, ConnectError> {
|
2019-03-13 20:40:11 +01:00
|
|
|
let mut parts_iter = host.as_ref().splitn(2, ':');
|
|
|
|
let host = parts_iter.next().ok_or(ConnectError::InvalidInput)?;
|
|
|
|
let port_str = parts_iter.next().unwrap_or("");
|
|
|
|
let port = port_str
|
|
|
|
.parse::<u16>()
|
|
|
|
.map_err(|_| ConnectError::InvalidInput)?;
|
2019-03-13 23:37:12 +01:00
|
|
|
Ok(Connect {
|
|
|
|
req: (host.to_owned(), port),
|
|
|
|
addr: None,
|
2019-03-13 20:40:11 +01:00
|
|
|
})
|
|
|
|
}
|
2019-03-13 23:37:12 +01:00
|
|
|
}
|
2019-03-13 20:40:11 +01:00
|
|
|
|
2019-03-13 23:37:12 +01:00
|
|
|
impl<T: Address> Connect<T> {
|
2019-03-13 23:49:31 +01:00
|
|
|
/// Create new `Connect` instance.
|
|
|
|
pub fn with_request(req: T) -> Connect<T> {
|
|
|
|
Connect { req, addr: None }
|
|
|
|
}
|
|
|
|
|
2019-03-13 20:40:11 +01:00
|
|
|
/// Create new `Connect` instance from host and address. Connector skips name resolution stage for such connect messages.
|
2019-03-13 23:37:12 +01:00
|
|
|
pub fn with_address(req: T, addr: SocketAddr) -> Connect<T> {
|
|
|
|
Connect {
|
|
|
|
req,
|
|
|
|
addr: Some(Either::Left(addr)),
|
2019-03-13 20:40:11 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Host name
|
2019-03-13 23:37:12 +01:00
|
|
|
pub fn host(&self) -> &str {
|
|
|
|
self.req.host()
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Port of the request
|
|
|
|
pub fn port(&self) -> u16 {
|
|
|
|
self.req.port()
|
2019-03-13 20:40:11 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-13 23:37:12 +01:00
|
|
|
impl<T: Address> fmt::Display for Connect<T> {
|
2019-03-13 20:40:11 +01:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
2019-03-13 23:37:12 +01:00
|
|
|
write!(f, "{}:{}", self.host(), self.port())
|
2019-03-13 20:40:11 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-13 23:37:12 +01:00
|
|
|
pub struct Connection<T, U> {
|
|
|
|
io: U,
|
|
|
|
req: T,
|
2019-03-13 20:40:11 +01:00
|
|
|
}
|
|
|
|
|
2019-03-13 23:37:12 +01:00
|
|
|
impl<T, U> Connection<T, U> {
|
|
|
|
pub fn new(io: U, req: T) -> Self {
|
|
|
|
Self { io, req }
|
2019-03-13 20:40:11 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-13 23:37:12 +01:00
|
|
|
impl<T, U> Connection<T, U> {
|
2019-03-13 20:40:11 +01:00
|
|
|
/// Reconstruct from a parts.
|
2019-03-13 23:37:12 +01:00
|
|
|
pub fn from_parts(io: U, req: T) -> Self {
|
|
|
|
Self { io, req }
|
2019-03-13 20:40:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Deconstruct into a parts.
|
2019-03-13 23:37:12 +01:00
|
|
|
pub fn into_parts(self) -> (U, T) {
|
|
|
|
(self.io, self.req)
|
2019-03-13 20:40:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Replace inclosed object, return new Stream and old object
|
2019-03-13 23:37:12 +01:00
|
|
|
pub fn replace<Y>(self, io: Y) -> (U, Connection<T, Y>) {
|
|
|
|
(self.io, Connection { io, req: self.req })
|
2019-03-13 20:40:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns a shared reference to the underlying stream.
|
2019-03-13 23:37:12 +01:00
|
|
|
pub fn get_ref(&self) -> &U {
|
2019-03-13 20:40:11 +01:00
|
|
|
&self.io
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns a mutable reference to the underlying stream.
|
2019-03-13 23:37:12 +01:00
|
|
|
pub fn get_mut(&mut self) -> &mut U {
|
2019-03-13 20:40:11 +01:00
|
|
|
&mut self.io
|
|
|
|
}
|
2019-03-13 23:37:12 +01:00
|
|
|
}
|
2019-03-13 20:40:11 +01:00
|
|
|
|
2019-03-13 23:37:12 +01:00
|
|
|
impl<T: Address, U> Connection<T, U> {
|
|
|
|
/// Get request
|
2019-03-13 20:40:11 +01:00
|
|
|
pub fn host(&self) -> &str {
|
2019-03-13 23:37:12 +01:00
|
|
|
&self.req.host()
|
2019-03-13 20:40:11 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-13 23:37:12 +01:00
|
|
|
impl<T, U> std::ops::Deref for Connection<T, U> {
|
|
|
|
type Target = U;
|
2019-03-13 20:40:11 +01:00
|
|
|
|
2019-03-13 23:37:12 +01:00
|
|
|
fn deref(&self) -> &U {
|
2019-03-13 20:40:11 +01:00
|
|
|
&self.io
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-13 23:37:12 +01:00
|
|
|
impl<T, U> std::ops::DerefMut for Connection<T, U> {
|
|
|
|
fn deref_mut(&mut self) -> &mut U {
|
2019-03-13 20:40:11 +01:00
|
|
|
&mut self.io
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-13 23:37:12 +01:00
|
|
|
impl<T, U: fmt::Debug> fmt::Debug for Connection<T, U> {
|
2019-03-13 20:40:11 +01:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
write!(f, "Stream {{{:?}}}", self.io)
|
|
|
|
}
|
|
|
|
}
|