use crate::fs::File; use crate::io::{Error, Read, self}; use crate::iter::Iterator; use crate::net::{Ipv4Addr, SocketAddr, SocketAddrV4}; use crate::str::FromStr; use crate::string::{String, ToString}; use crate::sys::syscall::EINVAL; use crate::time::{self, Duration}; use crate::vec::{IntoIter, Vec}; use crate::convert::{TryFrom, TryInto}; use self::dns::{Dns, DnsQuery}; pub use self::tcp::{TcpStream, TcpListener}; pub use self::udp::UdpSocket; pub mod netc; mod dns; mod tcp; mod udp; pub struct LookupHost(IntoIter, u16); impl LookupHost { pub fn port(&self) -> u16 { self.1 } } impl Iterator for LookupHost { type Item = SocketAddr; fn next(&mut self) -> Option { self.0.next() } } impl TryFrom<&str> for LookupHost { type Error = io::Error; fn try_from(s: &str) -> io::Result { macro_rules! try_opt { ($e:expr, $msg:expr) => ( match $e { Some(r) => r, None => return Err(io::Error::new(io::ErrorKind::InvalidInput, $msg)), } ) } // split the string by ':' and convert the second part to u16 let mut parts_iter = s.rsplitn(2, ':'); let port_str = try_opt!(parts_iter.next(), "invalid socket address"); let host = try_opt!(parts_iter.next(), "invalid socket address"); let port: u16 = try_opt!(port_str.parse().ok(), "invalid port value"); (host, port).try_into() } } impl<'a> TryFrom<(&'a str, u16)> for LookupHost { type Error = io::Error; fn try_from((host, port): (&'a str, u16)) -> io::Result { let mut ip_string = String::new(); File::open("/etc/net/ip")?.read_to_string(&mut ip_string)?; let ip: Vec = ip_string.trim().split('.').map(|part| part.parse::() .unwrap_or(0)).collect(); let mut dns_string = String::new(); File::open("/etc/net/dns")?.read_to_string(&mut dns_string)?; let dns: Vec = dns_string.trim().split('.').map(|part| part.parse::() .unwrap_or(0)).collect(); if ip.len() == 4 && dns.len() == 4 { let time = time::SystemTime::now().duration_since(time::UNIX_EPOCH).unwrap(); let tid = (time.subsec_nanos() >> 16) as u16; let packet = Dns { transaction_id: tid, flags: 0x0100, queries: vec![DnsQuery { name: host.to_string(), q_type: 0x0001, q_class: 0x0001, }], answers: vec![] }; let packet_data = packet.compile(); let my_ip = Ipv4Addr::new(ip[0], ip[1], ip[2], ip[3]); let dns_ip = Ipv4Addr::new(dns[0], dns[1], dns[2], dns[3]); let socket = UdpSocket::bind(Ok(&SocketAddr::V4(SocketAddrV4::new(my_ip, 0))))?; socket.set_read_timeout(Some(Duration::new(5, 0)))?; socket.set_write_timeout(Some(Duration::new(5, 0)))?; socket.connect(Ok(&SocketAddr::V4(SocketAddrV4::new(dns_ip, 53))))?; socket.send(&packet_data)?; let mut buf = [0; 65536]; let count = socket.recv(&mut buf)?; match Dns::parse(&buf[.. count]) { Ok(response) => { let mut addrs = vec![]; for answer in response.answers.iter() { if answer.a_type == 0x0001 && answer.a_class == 0x0001 && answer.data.len() == 4 { let answer_ip = Ipv4Addr::new(answer.data[0], answer.data[1], answer.data[2], answer.data[3]); addrs.push(SocketAddr::V4(SocketAddrV4::new(answer_ip, 0))); } } Ok(LookupHost(addrs.into_iter(), port)) }, Err(_err) => Err(Error::from_raw_os_error(EINVAL)) } } else { Err(Error::from_raw_os_error(EINVAL)) } } } fn path_to_peer_addr(path_str: &str) -> SocketAddr { let mut parts = path_str.split('/').next().unwrap_or("").split(':').skip(1); let host = Ipv4Addr::from_str(parts.next().unwrap_or("")).unwrap_or(Ipv4Addr::new(0, 0, 0, 0)); let port = parts.next().unwrap_or("").parse::().unwrap_or(0); SocketAddr::V4(SocketAddrV4::new(host, port)) } fn path_to_local_addr(path_str: &str) -> SocketAddr { let mut parts = path_str.split('/').nth(1).unwrap_or("").split(':'); let host = Ipv4Addr::from_str(parts.next().unwrap_or("")).unwrap_or(Ipv4Addr::new(0, 0, 0, 0)); let port = parts.next().unwrap_or("").parse::().unwrap_or(0); SocketAddr::V4(SocketAddrV4::new(host, port)) }