Skip to content

Commit 22c4368

Browse files
author
Jethro Beekman
committed
Refactor net::each_addr/lookup_host to forward error from resolve
1 parent 030b1ed commit 22c4368

File tree

9 files changed

+250
-126
lines changed

9 files changed

+250
-126
lines changed

src/libstd/net/addr.rs

+7-21
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,11 @@ use net::{ntoh, hton, IpAddr, Ipv4Addr, Ipv6Addr};
1616
use option;
1717
use sys::net::netc as c;
1818
use sys_common::{FromInner, AsInner, IntoInner};
19-
use sys_common::net::lookup_host;
19+
use sys_common::net::LookupHost;
2020
use vec;
2121
use iter;
2222
use slice;
23+
use convert::TryInto;
2324

2425
/// An internet socket address, either IPv4 or IPv6.
2526
///
@@ -863,9 +864,9 @@ impl ToSocketAddrs for (Ipv6Addr, u16) {
863864
}
864865
}
865866

866-
fn resolve_socket_addr(s: &str, p: u16) -> io::Result<vec::IntoIter<SocketAddr>> {
867-
let ips = lookup_host(s)?;
868-
let v: Vec<_> = ips.map(|mut a| { a.set_port(p); a }).collect();
867+
fn resolve_socket_addr(lh: LookupHost) -> io::Result<vec::IntoIter<SocketAddr>> {
868+
let p = lh.port();
869+
let v: Vec<_> = lh.map(|mut a| { a.set_port(p); a }).collect();
869870
Ok(v.into_iter())
870871
}
871872

@@ -885,7 +886,7 @@ impl<'a> ToSocketAddrs for (&'a str, u16) {
885886
return Ok(vec![SocketAddr::V6(addr)].into_iter())
886887
}
887888

888-
resolve_socket_addr(host, port)
889+
resolve_socket_addr((host, port).try_into()?)
889890
}
890891
}
891892

@@ -899,22 +900,7 @@ impl ToSocketAddrs for str {
899900
return Ok(vec![addr].into_iter());
900901
}
901902

902-
macro_rules! try_opt {
903-
($e:expr, $msg:expr) => (
904-
match $e {
905-
Some(r) => r,
906-
None => return Err(io::Error::new(io::ErrorKind::InvalidInput,
907-
$msg)),
908-
}
909-
)
910-
}
911-
912-
// split the string by ':' and convert the second part to u16
913-
let mut parts_iter = self.rsplitn(2, ':');
914-
let port_str = try_opt!(parts_iter.next(), "invalid socket address");
915-
let host = try_opt!(parts_iter.next(), "invalid socket address");
916-
let port: u16 = try_opt!(port_str.parse().ok(), "invalid port value");
917-
resolve_socket_addr(host, port)
903+
resolve_socket_addr(self.try_into()?)
918904
}
919905
}
920906

src/libstd/net/mod.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -112,11 +112,15 @@ fn hton<I: NetInt>(i: I) -> I { i.to_be() }
112112
fn ntoh<I: NetInt>(i: I) -> I { I::from_be(i) }
113113

114114
fn each_addr<A: ToSocketAddrs, F, T>(addr: A, mut f: F) -> io::Result<T>
115-
where F: FnMut(&SocketAddr) -> io::Result<T>
115+
where F: FnMut(io::Result<&SocketAddr>) -> io::Result<T>
116116
{
117+
let addrs = match addr.to_socket_addrs() {
118+
Ok(addrs) => addrs,
119+
Err(e) => return f(Err(e))
120+
};
117121
let mut last_err = None;
118-
for addr in addr.to_socket_addrs()? {
119-
match f(&addr) {
122+
for addr in addrs {
123+
match f(Ok(&addr)) {
120124
Ok(l) => return Ok(l),
121125
Err(e) => last_err = Some(e),
122126
}

src/libstd/sys/cloudabi/shims/net.rs

+25-6
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,14 @@ use io;
1313
use net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr};
1414
use time::Duration;
1515
use sys::{unsupported, Void};
16+
use convert::TryFrom;
1617

1718
pub extern crate libc as netc;
1819

1920
pub struct TcpStream(Void);
2021

2122
impl TcpStream {
22-
pub fn connect(_: &SocketAddr) -> io::Result<TcpStream> {
23+
pub fn connect(_: io::Result<&SocketAddr>) -> io::Result<TcpStream> {
2324
unsupported()
2425
}
2526

@@ -105,7 +106,7 @@ impl fmt::Debug for TcpStream {
105106
pub struct TcpListener(Void);
106107

107108
impl TcpListener {
108-
pub fn bind(_: &SocketAddr) -> io::Result<TcpListener> {
109+
pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<TcpListener> {
109110
unsupported()
110111
}
111112

@@ -155,7 +156,7 @@ impl fmt::Debug for TcpListener {
155156
pub struct UdpSocket(Void);
156157

157158
impl UdpSocket {
158-
pub fn bind(_: &SocketAddr) -> io::Result<UdpSocket> {
159+
pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<UdpSocket> {
159160
unsupported()
160161
}
161162

@@ -271,7 +272,7 @@ impl UdpSocket {
271272
match self.0 {}
272273
}
273274

274-
pub fn connect(&self, _: &SocketAddr) -> io::Result<()> {
275+
pub fn connect(&self, _: io::Result<&SocketAddr>) -> io::Result<()> {
275276
match self.0 {}
276277
}
277278
}
@@ -284,13 +285,31 @@ impl fmt::Debug for UdpSocket {
284285

285286
pub struct LookupHost(Void);
286287

288+
impl LookupHost {
289+
pub fn port(&self) -> u16 {
290+
match self.0 {}
291+
}
292+
}
293+
287294
impl Iterator for LookupHost {
288295
type Item = SocketAddr;
289296
fn next(&mut self) -> Option<SocketAddr> {
290297
match self.0 {}
291298
}
292299
}
293300

294-
pub fn lookup_host(_: &str) -> io::Result<LookupHost> {
295-
unsupported()
301+
impl<'a> TryFrom<&'a str> for LookupHost {
302+
type Error = io::Error;
303+
304+
fn try_from(_v: &'a str) -> io::Result<LookupHost> {
305+
unsupported()
306+
}
307+
}
308+
309+
impl<'a> TryFrom<(&'a str, u16)> for LookupHost {
310+
type Error = io::Error;
311+
312+
fn try_from(_v: (&'a str, u16)) -> io::Result<LookupHost> {
313+
unsupported()
314+
}
296315
}

src/libstd/sys/redox/net/mod.rs

+94-59
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,15 @@
99
// except according to those terms.
1010

1111
use fs::File;
12-
use io::{Error, Result, Read};
12+
use io::{Error, Read, self};
1313
use iter::Iterator;
1414
use net::{Ipv4Addr, SocketAddr, SocketAddrV4};
1515
use str::FromStr;
1616
use string::{String, ToString};
1717
use sys::syscall::EINVAL;
1818
use time::{self, Duration};
1919
use vec::{IntoIter, Vec};
20+
use convert::{TryFrom, TryInto};
2021

2122
use self::dns::{Dns, DnsQuery};
2223

@@ -29,7 +30,13 @@ mod dns;
2930
mod tcp;
3031
mod udp;
3132

32-
pub struct LookupHost(IntoIter<SocketAddr>);
33+
pub struct LookupHost(IntoIter<SocketAddr>, u16);
34+
35+
impl LookupHost {
36+
pub fn port(&self) -> u16 {
37+
self.1
38+
}
39+
}
3340

3441
impl Iterator for LookupHost {
3542
type Item = SocketAddr;
@@ -38,65 +45,93 @@ impl Iterator for LookupHost {
3845
}
3946
}
4047

41-
pub fn lookup_host(host: &str) -> Result<LookupHost> {
42-
let mut ip_string = String::new();
43-
File::open("/etc/net/ip")?.read_to_string(&mut ip_string)?;
44-
let ip: Vec<u8> = ip_string.trim().split('.').map(|part| part.parse::<u8>()
45-
.unwrap_or(0)).collect();
46-
47-
let mut dns_string = String::new();
48-
File::open("/etc/net/dns")?.read_to_string(&mut dns_string)?;
49-
let dns: Vec<u8> = dns_string.trim().split('.').map(|part| part.parse::<u8>()
50-
.unwrap_or(0)).collect();
51-
52-
if ip.len() == 4 && dns.len() == 4 {
53-
let time = time::SystemTime::now().duration_since(time::UNIX_EPOCH).unwrap();
54-
let tid = (time.subsec_nanos() >> 16) as u16;
55-
56-
let packet = Dns {
57-
transaction_id: tid,
58-
flags: 0x0100,
59-
queries: vec![DnsQuery {
60-
name: host.to_string(),
61-
q_type: 0x0001,
62-
q_class: 0x0001,
63-
}],
64-
answers: vec![]
65-
};
66-
67-
let packet_data = packet.compile();
68-
69-
let my_ip = Ipv4Addr::new(ip[0], ip[1], ip[2], ip[3]);
70-
let dns_ip = Ipv4Addr::new(dns[0], dns[1], dns[2], dns[3]);
71-
let socket = UdpSocket::bind(&SocketAddr::V4(SocketAddrV4::new(my_ip, 0)))?;
72-
socket.set_read_timeout(Some(Duration::new(5, 0)))?;
73-
socket.set_write_timeout(Some(Duration::new(5, 0)))?;
74-
socket.connect(&SocketAddr::V4(SocketAddrV4::new(dns_ip, 53)))?;
75-
socket.send(&packet_data)?;
76-
77-
let mut buf = [0; 65536];
78-
let count = socket.recv(&mut buf)?;
79-
80-
match Dns::parse(&buf[.. count]) {
81-
Ok(response) => {
82-
let mut addrs = vec![];
83-
for answer in response.answers.iter() {
84-
if answer.a_type == 0x0001 && answer.a_class == 0x0001
85-
&& answer.data.len() == 4
86-
{
87-
let answer_ip = Ipv4Addr::new(answer.data[0],
88-
answer.data[1],
89-
answer.data[2],
90-
answer.data[3]);
91-
addrs.push(SocketAddr::V4(SocketAddrV4::new(answer_ip, 0)));
92-
}
48+
impl<'a> TryFrom<&'a str> for LookupHost {
49+
type Error = io::Error;
50+
51+
fn try_from(s: &str) -> io::Result<LookupHost> {
52+
macro_rules! try_opt {
53+
($e:expr, $msg:expr) => (
54+
match $e {
55+
Some(r) => r,
56+
None => return Err(io::Error::new(io::ErrorKind::InvalidInput,
57+
$msg)),
9358
}
94-
Ok(LookupHost(addrs.into_iter()))
95-
},
96-
Err(_err) => Err(Error::from_raw_os_error(EINVAL))
59+
)
60+
}
61+
62+
// split the string by ':' and convert the second part to u16
63+
let mut parts_iter = s.rsplitn(2, ':');
64+
let port_str = try_opt!(parts_iter.next(), "invalid socket address");
65+
let host = try_opt!(parts_iter.next(), "invalid socket address");
66+
let port: u16 = try_opt!(port_str.parse().ok(), "invalid port value");
67+
68+
(host, port).try_into()
69+
}
70+
}
71+
72+
impl<'a> TryFrom<(&'a str, u16)> for LookupHost {
73+
type Error = io::Error;
74+
75+
fn try_from((host, port): (&'a str, u16)) -> io::Result<LookupHost> {
76+
let mut ip_string = String::new();
77+
File::open("/etc/net/ip")?.read_to_string(&mut ip_string)?;
78+
let ip: Vec<u8> = ip_string.trim().split('.').map(|part| part.parse::<u8>()
79+
.unwrap_or(0)).collect();
80+
81+
let mut dns_string = String::new();
82+
File::open("/etc/net/dns")?.read_to_string(&mut dns_string)?;
83+
let dns: Vec<u8> = dns_string.trim().split('.').map(|part| part.parse::<u8>()
84+
.unwrap_or(0)).collect();
85+
86+
if ip.len() == 4 && dns.len() == 4 {
87+
let time = time::SystemTime::now().duration_since(time::UNIX_EPOCH).unwrap();
88+
let tid = (time.subsec_nanos() >> 16) as u16;
89+
90+
let packet = Dns {
91+
transaction_id: tid,
92+
flags: 0x0100,
93+
queries: vec![DnsQuery {
94+
name: host.to_string(),
95+
q_type: 0x0001,
96+
q_class: 0x0001,
97+
}],
98+
answers: vec![]
99+
};
100+
101+
let packet_data = packet.compile();
102+
103+
let my_ip = Ipv4Addr::new(ip[0], ip[1], ip[2], ip[3]);
104+
let dns_ip = Ipv4Addr::new(dns[0], dns[1], dns[2], dns[3]);
105+
let socket = UdpSocket::bind(Ok(&SocketAddr::V4(SocketAddrV4::new(my_ip, 0))))?;
106+
socket.set_read_timeout(Some(Duration::new(5, 0)))?;
107+
socket.set_write_timeout(Some(Duration::new(5, 0)))?;
108+
socket.connect(Ok(&SocketAddr::V4(SocketAddrV4::new(dns_ip, 53))))?;
109+
socket.send(&packet_data)?;
110+
111+
let mut buf = [0; 65536];
112+
let count = socket.recv(&mut buf)?;
113+
114+
match Dns::parse(&buf[.. count]) {
115+
Ok(response) => {
116+
let mut addrs = vec![];
117+
for answer in response.answers.iter() {
118+
if answer.a_type == 0x0001 && answer.a_class == 0x0001
119+
&& answer.data.len() == 4
120+
{
121+
let answer_ip = Ipv4Addr::new(answer.data[0],
122+
answer.data[1],
123+
answer.data[2],
124+
answer.data[3]);
125+
addrs.push(SocketAddr::V4(SocketAddrV4::new(answer_ip, 0)));
126+
}
127+
}
128+
Ok(LookupHost(addrs.into_iter(), port))
129+
},
130+
Err(_err) => Err(Error::from_raw_os_error(EINVAL))
131+
}
132+
} else {
133+
Err(Error::from_raw_os_error(EINVAL))
97134
}
98-
} else {
99-
Err(Error::from_raw_os_error(EINVAL))
100135
}
101136
}
102137

src/libstd/sys/redox/net/tcp.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ use super::{path_to_peer_addr, path_to_local_addr};
2424
pub struct TcpStream(File);
2525

2626
impl TcpStream {
27-
pub fn connect(addr: &SocketAddr) -> Result<TcpStream> {
28-
let path = format!("tcp:{}", addr);
27+
pub fn connect(addr: Result<&SocketAddr>) -> Result<TcpStream> {
28+
let path = format!("tcp:{}", addr?);
2929
let mut options = OpenOptions::new();
3030
options.read(true);
3131
options.write(true);
@@ -180,8 +180,8 @@ impl IntoInner<File> for TcpStream {
180180
pub struct TcpListener(File);
181181

182182
impl TcpListener {
183-
pub fn bind(addr: &SocketAddr) -> Result<TcpListener> {
184-
let path = format!("tcp:/{}", addr);
183+
pub fn bind(addr: Result<&SocketAddr>) -> Result<TcpListener> {
184+
let path = format!("tcp:/{}", addr?);
185185
let mut options = OpenOptions::new();
186186
options.read(true);
187187
options.write(true);

src/libstd/sys/redox/net/udp.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ use super::{path_to_peer_addr, path_to_local_addr};
2525
pub struct UdpSocket(File, UnsafeCell<Option<SocketAddr>>);
2626

2727
impl UdpSocket {
28-
pub fn bind(addr: &SocketAddr) -> Result<UdpSocket> {
29-
let path = format!("udp:/{}", addr);
28+
pub fn bind(addr: Result<&SocketAddr>) -> Result<UdpSocket> {
29+
let path = format!("udp:/{}", addr?);
3030
let mut options = OpenOptions::new();
3131
options.read(true);
3232
options.write(true);
@@ -37,8 +37,8 @@ impl UdpSocket {
3737
unsafe { &mut *(self.1.get()) }
3838
}
3939

40-
pub fn connect(&self, addr: &SocketAddr) -> Result<()> {
41-
unsafe { *self.1.get() = Some(*addr) };
40+
pub fn connect(&self, addr: Result<&SocketAddr>) -> Result<()> {
41+
unsafe { *self.1.get() = Some(*addr?) };
4242
Ok(())
4343
}
4444

0 commit comments

Comments
 (0)