happy_eyeballs: propagate actual connection error

This commit is contained in:
Astro 2018-09-08 01:35:26 +02:00
commit ce2ce363b0
3 changed files with 31 additions and 19 deletions

View file

@ -64,10 +64,8 @@ impl Client {
done(Connecter::from_lookup(&domain, Some("_xmpp-client._tcp"), 5222)) done(Connecter::from_lookup(&domain, Some("_xmpp-client._tcp"), 5222))
.map_err(Error::Connection) .map_err(Error::Connection)
) )
.and_then(|connecter| .flatten()
connecter .and_then(move |tcp_stream|
.map_err(Error::Connection)
).and_then(move |tcp_stream|
xmpp_stream::XMPPStream::start(tcp_stream, jid1, NS_JABBER_CLIENT.to_owned()) xmpp_stream::XMPPStream::start(tcp_stream, jid1, NS_JABBER_CLIENT.to_owned())
).and_then(|xmpp_stream| { ).and_then(|xmpp_stream| {
if Self::can_starttls(&xmpp_stream) { if Self::can_starttls(&xmpp_stream) {

View file

@ -55,7 +55,6 @@ impl Component {
let password = password; let password = password;
done(Connecter::from_lookup(server, None, port)) done(Connecter::from_lookup(server, None, port))
.flatten() .flatten()
.map_err(Error::Connection)
.and_then(move |tcp_stream| { .and_then(move |tcp_stream| {
xmpp_stream::XMPPStream::start(tcp_stream, jid1, NS_JABBER_COMPONENT_ACCEPT.to_owned()) xmpp_stream::XMPPStream::start(tcp_stream, jid1, NS_JABBER_COMPONENT_ACCEPT.to_owned())
}).and_then(move |xmpp_stream| { }).and_then(move |xmpp_stream| {

View file

@ -8,7 +8,7 @@ use tokio::net::{ConnectFuture, TcpStream};
use trust_dns_resolver::{IntoName, Name, ResolverFuture, error::ResolveError}; use trust_dns_resolver::{IntoName, Name, ResolverFuture, error::ResolveError};
use trust_dns_resolver::lookup::SrvLookupFuture; use trust_dns_resolver::lookup::SrvLookupFuture;
use trust_dns_resolver::lookup_ip::LookupIpFuture; use trust_dns_resolver::lookup_ip::LookupIpFuture;
use ConnecterError; use {Error, ConnecterError};
enum State { enum State {
AwaitResolver(Box<Future<Item = ResolverFuture, Error = ResolveError> + Send>), AwaitResolver(Box<Future<Item = ResolverFuture, Error = ResolveError> + Send>),
@ -24,6 +24,7 @@ pub struct Connecter {
domain: Name, domain: Name,
state: State, state: State,
targets: VecDeque<(Name, u16)>, targets: VecDeque<(Name, u16)>,
error: Option<Error>,
} }
impl Connecter { impl Connecter {
@ -38,6 +39,7 @@ impl Connecter {
domain: "nohost".into_name()?, domain: "nohost".into_name()?,
state: State::Connecting(None, vec![connect]), state: State::Connecting(None, vec![connect]),
targets: VecDeque::new(), targets: VecDeque::new(),
error: None,
}); });
} }
@ -56,19 +58,20 @@ impl Connecter {
domain: domain.into_name()?, domain: domain.into_name()?,
state, state,
targets: VecDeque::new(), targets: VecDeque::new(),
error: None,
}) })
} }
} }
impl Future for Connecter { impl Future for Connecter {
type Item = TcpStream; type Item = TcpStream;
type Error = ConnecterError; type Error = Error;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> { fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
let state = mem::replace(&mut self.state, State::Invalid); let state = mem::replace(&mut self.state, State::Invalid);
match state { match state {
State::AwaitResolver(mut resolver_future) => { State::AwaitResolver(mut resolver_future) => {
match resolver_future.poll()? { match resolver_future.poll().map_err(ConnecterError::Resolve)? {
Async::NotReady => { Async::NotReady => {
self.state = State::AwaitResolver(resolver_future); self.state = State::AwaitResolver(resolver_future);
Ok(Async::NotReady) Ok(Async::NotReady)
@ -122,14 +125,12 @@ impl Future for Connecter {
} }
} }
State::Connecting(resolver, mut connects) => { State::Connecting(resolver, mut connects) => {
if resolver.is_some() && if resolver.is_some() && connects.len() == 0 && self.targets.len() > 0 {
connects.len() == 0 && let resolver = resolver.unwrap();
self.targets.len() > 0 { let (host, port) = self.targets.pop_front().unwrap();
let resolver = resolver.unwrap(); let ip_lookup = resolver.lookup_ip(host);
let (host, port) = self.targets.pop_front().unwrap(); self.state = State::ResolveTarget(resolver, ip_lookup, port);
let ip_lookup = resolver.lookup_ip(host); self.poll()
self.state = State::ResolveTarget(resolver, ip_lookup, port);
self.poll()
} else if connects.len() > 0 { } else if connects.len() > 0 {
let mut success = None; let mut success = None;
connects.retain(|connect| { connects.retain(|connect| {
@ -139,7 +140,12 @@ impl Future for Connecter {
success = Some(connection); success = Some(connection);
false false
} }
Err(_) => false, Err(e) => {
if self.error.is_none() {
self.error = Some(e.into());
}
false
},
} }
}); });
match success { match success {
@ -151,7 +157,13 @@ impl Future for Connecter {
}, },
} }
} else { } 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) => { State::ResolveTarget(resolver, mut ip_lookup, port) => {
@ -168,7 +180,10 @@ impl Future for Connecter {
self.state = State::Connecting(Some(resolver), connects); self.state = State::Connecting(Some(resolver), connects);
self.poll() self.poll()
} }
Err(_) => { Err(e) => {
if self.error.is_none() {
self.error = Some(ConnecterError::Resolve(e).into());
}
// ignore, next… // ignore, next…
self.state = State::Connecting(Some(resolver), vec![]); self.state = State::Connecting(Some(resolver), vec![]);
self.poll() self.poll()