]> git.lizzy.rs Git - rust.git/blob - src/libstd/sys/redox/net/mod.rs
Refactor net::each_addr/lookup_host to forward error from resolve
[rust.git] / src / libstd / sys / redox / net / mod.rs
1 // Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 use fs::File;
12 use io::{Error, Read, self};
13 use iter::Iterator;
14 use net::{Ipv4Addr, SocketAddr, SocketAddrV4};
15 use str::FromStr;
16 use string::{String, ToString};
17 use sys::syscall::EINVAL;
18 use time::{self, Duration};
19 use vec::{IntoIter, Vec};
20 use convert::{TryFrom, TryInto};
21
22 use self::dns::{Dns, DnsQuery};
23
24 pub use self::tcp::{TcpStream, TcpListener};
25 pub use self::udp::UdpSocket;
26
27 pub mod netc;
28
29 mod dns;
30 mod tcp;
31 mod udp;
32
33 pub struct LookupHost(IntoIter<SocketAddr>, u16);
34
35 impl LookupHost {
36     pub fn port(&self) -> u16 {
37         self.1
38     }
39 }
40
41 impl Iterator for LookupHost {
42     type Item = SocketAddr;
43     fn next(&mut self) -> Option<Self::Item> {
44         self.0.next()
45     }
46 }
47
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)),
58                 }
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))
134         }
135     }
136 }
137
138 fn path_to_peer_addr(path_str: &str) -> SocketAddr {
139     let mut parts = path_str.split('/').next().unwrap_or("").split(':').skip(1);
140     let host = Ipv4Addr::from_str(parts.next().unwrap_or("")).unwrap_or(Ipv4Addr::new(0, 0, 0, 0));
141     let port = parts.next().unwrap_or("").parse::<u16>().unwrap_or(0);
142     SocketAddr::V4(SocketAddrV4::new(host, port))
143 }
144
145 fn path_to_local_addr(path_str: &str) -> SocketAddr {
146     let mut parts = path_str.split('/').nth(1).unwrap_or("").split(':');
147     let host = Ipv4Addr::from_str(parts.next().unwrap_or("")).unwrap_or(Ipv4Addr::new(0, 0, 0, 0));
148     let port = parts.next().unwrap_or("").parse::<u16>().unwrap_or(0);
149     SocketAddr::V4(SocketAddrV4::new(host, port))
150 }