2019-07-17 02:17:51 +02:00
|
|
|
use std::collections::{vec_deque, VecDeque};
|
2019-03-13 20:40:11 +01:00
|
|
|
use std::fmt;
|
2019-07-17 02:17:51 +02:00
|
|
|
use std::iter::{FromIterator, FusedIterator};
|
2019-03-13 20:40:11 +01:00
|
|
|
use std::net::SocketAddr;
|
|
|
|
|
|
|
|
use either::Either;
|
|
|
|
|
2019-03-13 23:37:12 +01:00
|
|
|
/// Connect request
|
2019-11-18 09:30:04 +01:00
|
|
|
pub trait Address: Unpin {
|
2019-03-13 23:37:12 +01:00
|
|
|
/// Host name of the request
|
|
|
|
fn host(&self) -> &str;
|
|
|
|
|
|
|
|
/// Port of the request
|
2019-03-14 06:51:31 +01:00
|
|
|
fn port(&self) -> Option<u16>;
|
2019-03-13 23:37:12 +01:00
|
|
|
}
|
|
|
|
|
2019-03-14 06:51:31 +01:00
|
|
|
impl Address for String {
|
2019-03-13 23:37:12 +01:00
|
|
|
fn host(&self) -> &str {
|
2019-03-14 06:51:31 +01:00
|
|
|
&self
|
2019-03-13 23:37:12 +01:00
|
|
|
}
|
|
|
|
|
2019-03-14 06:51:31 +01:00
|
|
|
fn port(&self) -> Option<u16> {
|
|
|
|
None
|
2019-03-13 23:37:12 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-14 06:51:31 +01:00
|
|
|
impl Address for &'static str {
|
2019-03-13 23:37:12 +01:00
|
|
|
fn host(&self) -> &str {
|
2019-03-14 06:51:31 +01:00
|
|
|
self
|
2019-03-13 23:37:12 +01:00
|
|
|
}
|
|
|
|
|
2019-03-14 06:51:31 +01:00
|
|
|
fn port(&self) -> Option<u16> {
|
|
|
|
None
|
2019-03-13 23:37:12 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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,
|
2019-03-14 06:51:31 +01:00
|
|
|
pub(crate) port: u16,
|
2019-03-13 23:37:12 +01:00
|
|
|
pub(crate) addr: Option<Either<SocketAddr, VecDeque<SocketAddr>>>,
|
|
|
|
}
|
|
|
|
|
2019-03-14 06:51:31 +01:00
|
|
|
impl<T: Address> Connect<T> {
|
|
|
|
/// Create `Connect` instance by spliting the string by ':' and convert the second part to u16
|
|
|
|
pub fn new(req: T) -> Connect<T> {
|
|
|
|
let (_, port) = parse(req.host());
|
2019-03-13 23:37:12 +01:00
|
|
|
Connect {
|
2019-03-14 06:51:31 +01:00
|
|
|
req,
|
|
|
|
port: port.unwrap_or(0),
|
2019-03-13 23:37:12 +01:00
|
|
|
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-14 06:51:31 +01:00
|
|
|
pub fn with(req: T, addr: SocketAddr) -> Connect<T> {
|
2019-03-13 23:37:12 +01:00
|
|
|
Connect {
|
|
|
|
req,
|
2019-03-14 06:51:31 +01:00
|
|
|
port: 0,
|
2019-03-13 23:37:12 +01:00
|
|
|
addr: Some(Either::Left(addr)),
|
2019-03-13 20:40:11 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-14 19:15:32 +01:00
|
|
|
/// Use port if address does not provide one.
|
|
|
|
///
|
|
|
|
/// By default it set to 0
|
2019-03-14 06:55:01 +01:00
|
|
|
pub fn set_port(mut self, port: u16) -> Self {
|
|
|
|
self.port = port;
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2019-04-20 02:43:52 +02:00
|
|
|
/// Use address.
|
|
|
|
pub fn set_addr(mut self, addr: Option<SocketAddr>) -> Self {
|
|
|
|
if let Some(addr) = addr {
|
|
|
|
self.addr = Some(Either::Left(addr));
|
|
|
|
}
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2019-07-17 02:17:51 +02:00
|
|
|
/// Use addresses.
|
|
|
|
pub fn set_addrs<I>(mut self, addrs: I) -> Self
|
|
|
|
where
|
|
|
|
I: IntoIterator<Item = SocketAddr>,
|
|
|
|
{
|
|
|
|
let mut addrs = VecDeque::from_iter(addrs);
|
|
|
|
self.addr = if addrs.len() < 2 {
|
|
|
|
addrs.pop_front().map(Either::Left)
|
|
|
|
} else {
|
|
|
|
Some(Either::Right(addrs))
|
|
|
|
};
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
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 {
|
2019-03-14 06:51:31 +01:00
|
|
|
self.req.port().unwrap_or(self.port)
|
|
|
|
}
|
2019-07-17 02:17:51 +02:00
|
|
|
|
|
|
|
/// Preresolved addresses of the request.
|
|
|
|
pub fn addrs(&self) -> ConnectAddrsIter<'_> {
|
|
|
|
let inner = match self.addr {
|
|
|
|
None => Either::Left(None),
|
|
|
|
Some(Either::Left(addr)) => Either::Left(Some(addr)),
|
|
|
|
Some(Either::Right(ref addrs)) => Either::Right(addrs.iter()),
|
|
|
|
};
|
|
|
|
|
|
|
|
ConnectAddrsIter { inner }
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Takes preresolved addresses of the request.
|
|
|
|
pub fn take_addrs(&mut self) -> ConnectTakeAddrsIter {
|
|
|
|
let inner = match self.addr.take() {
|
|
|
|
None => Either::Left(None),
|
|
|
|
Some(Either::Left(addr)) => Either::Left(Some(addr)),
|
|
|
|
Some(Either::Right(addrs)) => Either::Right(addrs.into_iter()),
|
|
|
|
};
|
|
|
|
|
|
|
|
ConnectTakeAddrsIter { inner }
|
|
|
|
}
|
2019-03-14 06:51:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<T: Address> From<T> for Connect<T> {
|
|
|
|
fn from(addr: T) -> Self {
|
|
|
|
Connect::new(addr)
|
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-12-02 17:30:09 +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-07-17 02:17:51 +02:00
|
|
|
/// Iterator over addresses in a [`Connect`](struct.Connect.html) request.
|
|
|
|
#[derive(Clone)]
|
|
|
|
pub struct ConnectAddrsIter<'a> {
|
|
|
|
inner: Either<Option<SocketAddr>, vec_deque::Iter<'a, SocketAddr>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Iterator for ConnectAddrsIter<'_> {
|
|
|
|
type Item = SocketAddr;
|
|
|
|
|
|
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
|
|
match self.inner {
|
|
|
|
Either::Left(ref mut opt) => opt.take(),
|
|
|
|
Either::Right(ref mut iter) => iter.next().copied(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
|
|
|
match self.inner {
|
|
|
|
Either::Left(Some(_)) => (1, Some(1)),
|
|
|
|
Either::Left(None) => (0, Some(0)),
|
|
|
|
Either::Right(ref iter) => iter.size_hint(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl fmt::Debug for ConnectAddrsIter<'_> {
|
2019-12-02 17:30:09 +01:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
2019-07-17 02:17:51 +02:00
|
|
|
f.debug_list().entries(self.clone()).finish()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ExactSizeIterator for ConnectAddrsIter<'_> {}
|
|
|
|
|
|
|
|
impl FusedIterator for ConnectAddrsIter<'_> {}
|
|
|
|
|
|
|
|
/// Owned iterator over addresses in a [`Connect`](struct.Connect.html) request.
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct ConnectTakeAddrsIter {
|
|
|
|
inner: Either<Option<SocketAddr>, vec_deque::IntoIter<SocketAddr>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Iterator for ConnectTakeAddrsIter {
|
|
|
|
type Item = SocketAddr;
|
|
|
|
|
|
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
|
|
match self.inner {
|
|
|
|
Either::Left(ref mut opt) => opt.take(),
|
|
|
|
Either::Right(ref mut iter) => iter.next(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
|
|
|
match self.inner {
|
|
|
|
Either::Left(Some(_)) => (1, Some(1)),
|
|
|
|
Either::Left(None) => (0, Some(0)),
|
|
|
|
Either::Right(ref iter) => iter.size_hint(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ExactSizeIterator for ConnectTakeAddrsIter {}
|
|
|
|
|
|
|
|
impl FusedIterator for ConnectTakeAddrsIter {}
|
|
|
|
|
2019-03-14 06:51:31 +01:00
|
|
|
fn parse(host: &str) -> (&str, Option<u16>) {
|
|
|
|
let mut parts_iter = host.splitn(2, ':');
|
|
|
|
if let Some(host) = parts_iter.next() {
|
|
|
|
let port_str = parts_iter.next().unwrap_or("");
|
|
|
|
if let Ok(port) = port_str.parse::<u16>() {
|
|
|
|
(host, Some(port))
|
|
|
|
} else {
|
|
|
|
(host, None)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
(host, None)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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-12-02 17:30:09 +01:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
2019-03-13 20:40:11 +01:00
|
|
|
write!(f, "Stream {{{:?}}}", self.io)
|
|
|
|
}
|
|
|
|
}
|