happy_eyeballs: improvements

This commit is contained in:
Astro 2017-07-13 22:17:29 +02:00
parent 7e18db0717
commit 2335bab844

View file

@ -1,4 +1,6 @@
use std::str::FromStr; use std::str::FromStr;
use std::collections::HashMap;
use std::net::SocketAddr;
use futures::*; use futures::*;
use tokio_core::reactor::Handle; use tokio_core::reactor::Handle;
use tokio_core::net::{TcpStream, TcpStreamNew}; use tokio_core::net::{TcpStream, TcpStreamNew};
@ -11,7 +13,7 @@ pub struct Connecter {
resolver: Resolver, resolver: Resolver,
lookup: Option<LookupSrv>, lookup: Option<LookupSrv>,
srvs: Option<LookupSrvStream>, srvs: Option<LookupSrvStream>,
connects: Vec<TcpStreamNew>, connects: HashMap<SocketAddr, TcpStreamNew>,
} }
impl Connecter { impl Connecter {
@ -33,7 +35,7 @@ impl Connecter {
resolver, resolver,
lookup: Some(lookup), lookup: Some(lookup),
srvs: None, srvs: None,
connects: vec![], connects: HashMap::new(),
}) })
} }
} }
@ -65,27 +67,37 @@ impl Future for Connecter {
Some(Ok(Async::Ready(None))) => Some(Ok(Async::Ready(None))) =>
self.srvs = None, self.srvs = None,
Some(Ok(Async::Ready(Some(srv_item)))) => { Some(Ok(Async::Ready(Some(srv_item)))) => {
let handle = &self.handle;
for addr in srv_item.to_socket_addrs() { for addr in srv_item.to_socket_addrs() {
self.connects.entry(addr)
.or_insert_with(|| {
println!("Connect to {}", addr); println!("Connect to {}", addr);
let connect = TcpStream::connect(&addr, &self.handle); TcpStream::connect(&addr, handle)
self.connects.push(connect); });
} }
}, },
Some(Err(e)) => Some(Err(e)) =>
return Err(format!("{}", e)), return Err(format!("{}", e)),
} }
for mut connect in &mut self.connects { for mut connect in self.connects.values_mut() {
match connect.poll() { match connect.poll() {
Ok(Async::NotReady) => (), Ok(Async::NotReady) => (),
Ok(Async::Ready(tcp_stream)) => Ok(Async::Ready(tcp_stream)) =>
// Success! // Success!
return Ok(Async::Ready(tcp_stream)), return Ok(Async::Ready(tcp_stream)),
Err(e) => Err(e) =>
return Err(format!("{}", e)), println!("{}", e),
} }
} }
if self.lookup.is_none() &&
self.srvs.is_none() &&
self.connects.is_empty()
{
return Err("All connection attempts failed".to_owned());
}
Ok(Async::NotReady) Ok(Async::NotReady)
} }
} }