From ce2ce363b02af8dbef6e23fbc9e833b1b98fdc6a Mon Sep 17 00:00:00 2001 From: Astro Date: Sat, 8 Sep 2018 01:35:26 +0200 Subject: [PATCH] happy_eyeballs: propagate actual connection error --- src/client/mod.rs | 6 ++---- src/component/mod.rs | 1 - src/happy_eyeballs.rs | 43 +++++++++++++++++++++++++++++-------------- 3 files changed, 31 insertions(+), 19 deletions(-) diff --git a/src/client/mod.rs b/src/client/mod.rs index cf4553a0..d2af19c3 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -64,10 +64,8 @@ impl Client { done(Connecter::from_lookup(&domain, Some("_xmpp-client._tcp"), 5222)) .map_err(Error::Connection) ) - .and_then(|connecter| - connecter - .map_err(Error::Connection) - ).and_then(move |tcp_stream| + .flatten() + .and_then(move |tcp_stream| xmpp_stream::XMPPStream::start(tcp_stream, jid1, NS_JABBER_CLIENT.to_owned()) ).and_then(|xmpp_stream| { if Self::can_starttls(&xmpp_stream) { diff --git a/src/component/mod.rs b/src/component/mod.rs index e34ecd4d..ce55e7ec 100644 --- a/src/component/mod.rs +++ b/src/component/mod.rs @@ -55,7 +55,6 @@ impl Component { let password = password; done(Connecter::from_lookup(server, None, port)) .flatten() - .map_err(Error::Connection) .and_then(move |tcp_stream| { xmpp_stream::XMPPStream::start(tcp_stream, jid1, NS_JABBER_COMPONENT_ACCEPT.to_owned()) }).and_then(move |xmpp_stream| { diff --git a/src/happy_eyeballs.rs b/src/happy_eyeballs.rs index 6b22cca0..4a118564 100644 --- a/src/happy_eyeballs.rs +++ b/src/happy_eyeballs.rs @@ -8,7 +8,7 @@ use tokio::net::{ConnectFuture, TcpStream}; use trust_dns_resolver::{IntoName, Name, ResolverFuture, error::ResolveError}; use trust_dns_resolver::lookup::SrvLookupFuture; use trust_dns_resolver::lookup_ip::LookupIpFuture; -use ConnecterError; +use {Error, ConnecterError}; enum State { AwaitResolver(Box + Send>), @@ -24,6 +24,7 @@ pub struct Connecter { domain: Name, state: State, targets: VecDeque<(Name, u16)>, + error: Option, } impl Connecter { @@ -38,6 +39,7 @@ impl Connecter { domain: "nohost".into_name()?, state: State::Connecting(None, vec![connect]), targets: VecDeque::new(), + error: None, }); } @@ -56,19 +58,20 @@ impl Connecter { domain: domain.into_name()?, state, targets: VecDeque::new(), + error: None, }) } } impl Future for Connecter { type Item = TcpStream; - type Error = ConnecterError; + type Error = Error; fn poll(&mut self) -> Poll { let state = mem::replace(&mut self.state, State::Invalid); match state { State::AwaitResolver(mut resolver_future) => { - match resolver_future.poll()? { + match resolver_future.poll().map_err(ConnecterError::Resolve)? { Async::NotReady => { self.state = State::AwaitResolver(resolver_future); Ok(Async::NotReady) @@ -122,14 +125,12 @@ impl Future for Connecter { } } State::Connecting(resolver, mut connects) => { - if resolver.is_some() && - connects.len() == 0 && - self.targets.len() > 0 { - let resolver = resolver.unwrap(); - let (host, port) = self.targets.pop_front().unwrap(); - let ip_lookup = resolver.lookup_ip(host); - self.state = State::ResolveTarget(resolver, ip_lookup, port); - self.poll() + if resolver.is_some() && connects.len() == 0 && self.targets.len() > 0 { + let resolver = resolver.unwrap(); + let (host, port) = self.targets.pop_front().unwrap(); + let ip_lookup = resolver.lookup_ip(host); + self.state = State::ResolveTarget(resolver, ip_lookup, port); + self.poll() } else if connects.len() > 0 { let mut success = None; connects.retain(|connect| { @@ -139,7 +140,12 @@ impl Future for Connecter { success = Some(connection); false } - Err(_) => false, + Err(e) => { + if self.error.is_none() { + self.error = Some(e.into()); + } + false + }, } }); match success { @@ -151,7 +157,13 @@ impl Future for Connecter { }, } } else { - Err(ConnecterError::AllFailed) + // All targets tried + match self.error.take() { + None => + Err(ConnecterError::AllFailed.into()), + Some(e) => + Err(e), + } } } State::ResolveTarget(resolver, mut ip_lookup, port) => { @@ -168,7 +180,10 @@ impl Future for Connecter { self.state = State::Connecting(Some(resolver), connects); self.poll() } - Err(_) => { + Err(e) => { + if self.error.is_none() { + self.error = Some(ConnecterError::Resolve(e).into()); + } // ignore, next… self.state = State::Connecting(Some(resolver), vec![]); self.poll()