| @@ -0,0 +1,3 @@ | |||
| pub use sys::imp::backtrace::{ | |||
| Backtrace, | |||
| }; | |||
| @@ -0,0 +1,5 @@ | |||
| pub use sys::imp::c::{ | |||
| EINVAL, EIO, | |||
| EBADF, | |||
| strlen | |||
| }; | |||
| @@ -0,0 +1,4 @@ | |||
| pub use libc::{ | |||
| EINVAL, EIO, | |||
| strlen | |||
| }; | |||
| @@ -0,0 +1,134 @@ | |||
| // Copyright 2015 The Rust Project Developers. See the COPYRIGHT | |||
| // file at the top-level directory of this distribution and at | |||
| // http://rust-lang.org/COPYRIGHT. | |||
| // | |||
| // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |||
| // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |||
| // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |||
| // option. This file may not be copied, modified, or distributed | |||
| // except according to those terms. | |||
|
|
|||
| use sys::inner::*; | |||
|
|
|||
| use hash; | |||
| use libc::{self, socklen_t, sa_family_t}; | |||
| use mem; | |||
| use super::{ntoh, hton}; | |||
| use sys::net::{self as sys, IpAddr, SocketAddr}; | |||
| use super::ip::{IpAddrV4, IpAddrV6}; | |||
|
|
|||
| #[derive(Copy)] | |||
| pub struct SocketAddrV4(libc::sockaddr_in); | |||
|
|
|||
| #[derive(Copy)] | |||
| pub struct SocketAddrV6(libc::sockaddr_in6); | |||
|
|
|||
| impl SocketAddrV4 { | |||
| pub fn new(ip: IpAddrV4, port: u16) -> SocketAddrV4 { | |||
| SocketAddrV4( | |||
| libc::sockaddr_in { | |||
| sin_family: libc::AF_INET as sa_family_t, | |||
| sin_port: hton(port), | |||
| sin_addr: *ip.as_inner(), | |||
| .. unsafe { mem::zeroed() } | |||
| } | |||
| ) | |||
| } | |||
|
|
|||
| pub fn addr(&self) -> &IpAddrV4 { | |||
| unsafe { | |||
| &*(&self.0.sin_addr as *const libc::in_addr as *const IpAddrV4) | |||
| } | |||
| } | |||
|
|
|||
| pub fn port(&self) -> u16 { ntoh(self.0.sin_port) } | |||
| } | |||
|
|
|||
| impl SocketAddrV6 { | |||
| pub fn new(ip: IpAddrV6, port: u16, flowinfo: u32, scope_id: u32) | |||
| -> SocketAddrV6 { | |||
| SocketAddrV6( | |||
| libc::sockaddr_in6 { | |||
| sin6_family: libc::AF_INET6 as sa_family_t, | |||
| sin6_port: hton(port), | |||
| sin6_addr: *ip.as_inner(), | |||
| sin6_flowinfo: hton(flowinfo), | |||
| sin6_scope_id: hton(scope_id), | |||
| .. unsafe { mem::zeroed() } | |||
| } | |||
| ) | |||
| } | |||
|
|
|||
| pub fn addr(&self) -> &IpAddrV6 { | |||
| unsafe { | |||
| &*(&self.0.sin6_addr as *const libc::in6_addr as *const IpAddrV6) | |||
| } | |||
| } | |||
|
|
|||
| pub fn port(&self) -> u16 { ntoh(self.0.sin6_port) } | |||
|
|
|||
| pub fn flowinfo(&self) -> u32 { ntoh(self.0.sin6_flowinfo) } | |||
|
|
|||
| pub fn scope_id(&self) -> u32 { ntoh(self.0.sin6_scope_id) } | |||
| } | |||
|
|
|||
| impl Clone for SocketAddrV4 { | |||
| fn clone(&self) -> SocketAddrV4 { *self } | |||
| } | |||
|
|
|||
| impl Clone for SocketAddrV6 { | |||
| fn clone(&self) -> SocketAddrV6 { *self } | |||
| } | |||
|
|
|||
| impl PartialEq for SocketAddrV4 { | |||
| fn eq(&self, other: &SocketAddrV4) -> bool { | |||
| self.0.sin_port == other.0.sin_port && | |||
| self.0.sin_addr.s_addr == other.0.sin_addr.s_addr | |||
| } | |||
| } | |||
|
|
|||
| impl PartialEq for SocketAddrV6 { | |||
| fn eq(&self, other: &SocketAddrV6) -> bool { | |||
| self.0.sin6_port == other.0.sin6_port && | |||
| self.0.sin6_addr.s6_addr == other.0.sin6_addr.s6_addr && | |||
| self.0.sin6_flowinfo == other.0.sin6_flowinfo && | |||
| self.0.sin6_scope_id == other.0.sin6_scope_id | |||
| } | |||
| } | |||
|
|
|||
| impl Eq for SocketAddrV4 {} | |||
| impl Eq for SocketAddrV6 {} | |||
|
|
|||
| impl hash::Hash for SocketAddrV4 { | |||
| fn hash<H: hash::Hasher>(&self, s: &mut H) { | |||
| (self.0.sin_port, self.0.sin_addr.s_addr).hash(s) | |||
| } | |||
| } | |||
|
|
|||
| impl hash::Hash for SocketAddrV6 { | |||
| fn hash<H: hash::Hasher>(&self, s: &mut H) { | |||
| (self.0.sin6_port, &self.0.sin6_addr.s6_addr, | |||
| self.0.sin6_flowinfo, self.0.sin6_scope_id).hash(s) | |||
| } | |||
| } | |||
|
|
|||
| impl_inner!(SocketAddrV4(libc::sockaddr_in)); | |||
| impl_inner!(SocketAddrV6(libc::sockaddr_in6)); | |||
|
|
|||
| pub fn sockaddr(addr: &SocketAddr) -> (*const libc::sockaddr, socklen_t) { | |||
| match *addr { | |||
| SocketAddr::V4(ref a) => { | |||
| (&a.0 as *const _ as *const _, mem::size_of_val(&a.0) as socklen_t) | |||
| } | |||
| SocketAddr::V6(ref a) => { | |||
| (&a.0 as *const _ as *const _, mem::size_of_val(&a.0) as socklen_t) | |||
| } | |||
| } | |||
| } | |||
|
|
|||
| pub fn new_sockaddr(addr: IpAddr, port: u16) -> SocketAddr { | |||
| match addr { | |||
| IpAddr::V4(a) => SocketAddr::V4(sys::SocketAddrV4::new(a, port)), | |||
| IpAddr::V6(a) => SocketAddr::V6(sys::SocketAddrV6::new(a, port, 0, 0)), | |||
| } | |||
| } | |||
| @@ -0,0 +1,125 @@ | |||
| // Copyright 2015 The Rust Project Developers. See the COPYRIGHT | |||
| // file at the top-level directory of this distribution and at | |||
| // http://rust-lang.org/COPYRIGHT. | |||
| // | |||
| // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |||
| // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |||
| // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |||
| // option. This file may not be copied, modified, or distributed | |||
| // except according to those terms. | |||
|
|
|||
| use cmp::Ordering; | |||
| use hash; | |||
| use libc; | |||
| use super::{hton, ntoh}; | |||
|
|
|||
| #[derive(Copy)] | |||
| pub struct IpAddrV4(libc::in_addr); | |||
|
|
|||
| #[derive(Copy)] | |||
| pub struct IpAddrV6(libc::in6_addr); | |||
|
|
|||
| impl_inner!(IpAddrV4(libc::in_addr)); | |||
| impl_inner!(IpAddrV6(libc::in6_addr)); | |||
|
|
|||
| impl IpAddrV4 { | |||
| pub fn new(a: u8, b: u8, c: u8, d: u8) -> IpAddrV4 { | |||
| IpAddrV4( | |||
| libc::in_addr { | |||
| s_addr: hton(((a as u32) << 24) | | |||
| ((b as u32) << 16) | | |||
| ((c as u32) << 8) | | |||
| (d as u32)), | |||
| } | |||
| ) | |||
| } | |||
|
|
|||
| pub fn octets(&self) -> [u8; 4] { | |||
| let bits = ntoh(self.0.s_addr); | |||
| [(bits >> 24) as u8, (bits >> 16) as u8, (bits >> 8) as u8, bits as u8] | |||
| } | |||
| } | |||
|
|
|||
| impl Clone for IpAddrV4 { | |||
| fn clone(&self) -> IpAddrV4 { *self } | |||
| } | |||
|
|
|||
| impl PartialEq for IpAddrV4 { | |||
| fn eq(&self, other: &IpAddrV4) -> bool { | |||
| self.0.s_addr == other.0.s_addr | |||
| } | |||
| } | |||
|
|
|||
| impl Eq for IpAddrV4 {} | |||
|
|
|||
| impl hash::Hash for IpAddrV4 { | |||
| fn hash<H: hash::Hasher>(&self, s: &mut H) { | |||
| self.0.s_addr.hash(s) | |||
| } | |||
| } | |||
|
|
|||
| impl PartialOrd for IpAddrV4 { | |||
| fn partial_cmp(&self, other: &IpAddrV4) -> Option<Ordering> { | |||
| Some(self.cmp(other)) | |||
| } | |||
| } | |||
|
|
|||
| impl Ord for IpAddrV4 { | |||
| fn cmp(&self, other: &IpAddrV4) -> Ordering { | |||
| self.0.s_addr.cmp(&other.0.s_addr) | |||
| } | |||
| } | |||
|
|
|||
| impl IpAddrV6 { | |||
| pub fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, | |||
| h: u16) -> IpAddrV6 { | |||
| IpAddrV6( | |||
| libc::in6_addr { | |||
| s6_addr: [hton(a), hton(b), hton(c), hton(d), | |||
| hton(e), hton(f), hton(g), hton(h)] | |||
| } | |||
| ) | |||
| } | |||
|
|
|||
| /// Returns the eight 16-bit segments that make up this address. | |||
| pub fn segments(&self) -> [u16; 8] { | |||
| [ntoh(self.0.s6_addr[0]), | |||
| ntoh(self.0.s6_addr[1]), | |||
| ntoh(self.0.s6_addr[2]), | |||
| ntoh(self.0.s6_addr[3]), | |||
| ntoh(self.0.s6_addr[4]), | |||
| ntoh(self.0.s6_addr[5]), | |||
| ntoh(self.0.s6_addr[6]), | |||
| ntoh(self.0.s6_addr[7])] | |||
| } | |||
| } | |||
|
|
|||
| impl Clone for IpAddrV6 { | |||
| fn clone(&self) -> IpAddrV6 { *self } | |||
| } | |||
|
|
|||
| impl PartialEq for IpAddrV6 { | |||
| fn eq(&self, other: &IpAddrV6) -> bool { | |||
| self.0.s6_addr == other.0.s6_addr | |||
| } | |||
| } | |||
|
|
|||
| impl Eq for IpAddrV6 {} | |||
|
|
|||
| impl hash::Hash for IpAddrV6 { | |||
| fn hash<H: hash::Hasher>(&self, s: &mut H) { | |||
| self.0.s6_addr.hash(s) | |||
| } | |||
| } | |||
|
|
|||
| impl PartialOrd for IpAddrV6 { | |||
| fn partial_cmp(&self, other: &IpAddrV6) -> Option<Ordering> { | |||
| Some(self.cmp(other)) | |||
| } | |||
| } | |||
|
|
|||
| impl Ord for IpAddrV6 { | |||
| fn cmp(&self, other: &IpAddrV6) -> Ordering { | |||
| self.0.s6_addr.cmp(&other.0.s6_addr) | |||
| } | |||
| } | |||
| @@ -0,0 +1,313 @@ | |||
| // Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT | |||
| // file at the top-level directory of this distribution and at | |||
| // http://rust-lang.org/COPYRIGHT. | |||
| // | |||
| // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |||
| // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |||
| // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |||
| // option. This file may not be copied, modified, or distributed | |||
| // except according to those terms. | |||
|
|
|||
| use io::prelude::*; | |||
| use sys::error::{Error, Result}; | |||
| use sys::inner::*; | |||
|
|
|||
| use ffi::{CStr, CString}; | |||
| use libc::{self, c_int, c_char, c_void, socklen_t}; | |||
| use mem; | |||
| use ptr; | |||
| use io; | |||
| use sys::target::{c, cvt, cvt_r}; | |||
| use sys::target::net::{cvt_gai, Socket as SocketImp, init, wrlen_t}; | |||
| use sys::net::{self as sys, SocketAddr, IpAddr}; | |||
| use net::Shutdown; | |||
| use time::Duration; | |||
|
|
|||
| mod ip; | |||
| mod addr; | |||
|
|
|||
| use self::addr::{new_sockaddr, sockaddr}; | |||
|
|
|||
| pub use self::ip::{IpAddrV4, IpAddrV6}; | |||
| pub use self::addr::{SocketAddrV4, SocketAddrV6}; | |||
|
|
|||
| pub type TcpStream = Socket; | |||
| pub type TcpListener = Socket; | |||
| pub type UdpSocket = Socket; | |||
|
|
|||
| pub fn setsockopt<T>(sock: &SocketImp, opt: c_int, val: c_int, | |||
| payload: T) -> Result<()> { | |||
| unsafe { | |||
| let payload = &payload as *const T as *const c_void; | |||
| cvt(libc::setsockopt(*sock.as_inner(), opt, val, payload, mem::size_of::<T>() as socklen_t)).map(drop) | |||
| } | |||
| } | |||
|
|
|||
| pub fn getsockopt<T: Copy>(sock: &SocketImp, opt: c_int, | |||
| val: c_int) -> Result<T> { | |||
| unsafe { | |||
| let mut slot: T = mem::zeroed(); | |||
| let mut len = mem::size_of::<T>() as socklen_t; | |||
| try!(cvt(c::getsockopt(*sock.as_inner(), opt, val, &mut slot as *mut _ as *mut _, &mut len))); | |||
| if len as usize != mem::size_of::<T>() { | |||
| Err(Error::from_code(libc::EINVAL)) | |||
| } else { | |||
| Ok(slot) | |||
| } | |||
| } | |||
| } | |||
|
|
|||
| fn sockname<F>(f: F) -> Result<SocketAddr> | |||
| where F: FnOnce(*mut libc::sockaddr, *mut socklen_t) -> c_int | |||
| { | |||
| unsafe { | |||
| let mut storage: libc::sockaddr_storage = mem::zeroed(); | |||
| let mut len = mem::size_of_val(&storage) as socklen_t; | |||
| try!(cvt(f(&mut storage as *mut _ as *mut _, &mut len))); | |||
| sockaddr_to_addr(&storage, len as usize) | |||
| } | |||
| } | |||
|
|
|||
| fn sockaddr_to_addr(storage: &libc::sockaddr_storage, | |||
| len: usize) -> Result<SocketAddr> { | |||
| match storage.ss_family as libc::c_int { | |||
| libc::AF_INET => { | |||
| assert!(len as usize >= mem::size_of::<libc::sockaddr_in>()); | |||
| Ok(SocketAddr::V4(FromInner::from_inner(unsafe { | |||
| *(storage as *const _ as *const libc::sockaddr_in) | |||
| }))) | |||
| } | |||
| libc::AF_INET6 => { | |||
| assert!(len as usize >= mem::size_of::<libc::sockaddr_in6>()); | |||
| Ok(SocketAddr::V6(FromInner::from_inner(unsafe { | |||
| *(storage as *const _ as *const libc::sockaddr_in6) | |||
| }))) | |||
| } | |||
| _ => Err(Error::from_code(libc::EINVAL)) | |||
| } | |||
| } | |||
|
|
|||
| trait NetInt { | |||
| fn from_be(i: Self) -> Self; | |||
| fn to_be(&self) -> Self; | |||
| } | |||
| macro_rules! doit { | |||
| ($($t:ident)*) => ($(impl NetInt for $t { | |||
| fn from_be(i: Self) -> Self { <$t>::from_be(i) } | |||
| fn to_be(&self) -> Self { <$t>::to_be(*self) } | |||
| })*) | |||
| } | |||
| doit! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize } | |||
|
|
|||
| fn hton<I: NetInt>(i: I) -> I { i.to_be() } | |||
| fn ntoh<I: NetInt>(i: I) -> I { I::from_be(i) } | |||
|
|
|||
| extern "system" { | |||
| fn getaddrinfo(node: *const c_char, service: *const c_char, | |||
| hints: *const libc::addrinfo, | |||
| res: *mut *mut libc::addrinfo) -> c_int; | |||
| fn freeaddrinfo(res: *mut libc::addrinfo); | |||
| } | |||
|
|
|||
| pub struct LookupHost { | |||
| original: *mut libc::addrinfo, | |||
| cur: *mut libc::addrinfo, | |||
| } | |||
|
|
|||
| impl Iterator for LookupHost { | |||
| type Item = Result<SocketAddr>; | |||
| fn next(&mut self) -> Option<Result<SocketAddr>> { | |||
| unsafe { | |||
| if self.cur.is_null() { return None } | |||
| let ret = sockaddr_to_addr(mem::transmute((*self.cur).ai_addr), | |||
| (*self.cur).ai_addrlen as usize); | |||
| self.cur = (*self.cur).ai_next as *mut libc::addrinfo; | |||
| Some(ret) | |||
| } | |||
| } | |||
| } | |||
|
|
|||
| unsafe impl Sync for LookupHost {} | |||
| unsafe impl Send for LookupHost {} | |||
|
|
|||
| impl Drop for LookupHost { | |||
| fn drop(&mut self) { | |||
| unsafe { freeaddrinfo(self.original) } | |||
| } | |||
| } | |||
|
|
|||
| extern "system" { | |||
| fn getnameinfo(sa: *const libc::sockaddr, salen: socklen_t, | |||
| host: *mut c_char, hostlen: libc::size_t, | |||
| serv: *mut c_char, servlen: libc::size_t, | |||
| flags: c_int) -> c_int; | |||
| } | |||
|
|
|||
| const NI_MAXHOST: usize = 1025; | |||
|
|
|||
| pub struct LookupAddr([c_char; NI_MAXHOST]); | |||
|
|
|||
| impl LookupAddr { | |||
| pub fn as_bytes(&self) -> &[u8] { | |||
| unsafe { CStr::from_ptr(self.0.as_ptr()).to_bytes() } | |||
| } | |||
| } | |||
|
|
|||
| pub struct Socket(SocketImp); | |||
| impl_inner!(Socket(SocketImp)); | |||
| impl_inner!(for<T> Socket(SocketImp(T))); | |||
|
|
|||
| impl Socket { | |||
| pub fn set_read_timeout(&self, dur: Option<Duration>) -> Result<()> { | |||
| self.0.set_timeout(dur, libc::SO_RCVTIMEO) | |||
| } | |||
|
|
|||
| pub fn set_write_timeout(&self, dur: Option<Duration>) -> Result<()> { | |||
| self.0.set_timeout(dur, libc::SO_SNDTIMEO) | |||
| } | |||
|
|
|||
| pub fn read_timeout(&self) -> Result<Option<Duration>> { | |||
| self.0.timeout(libc::SO_RCVTIMEO) | |||
| } | |||
|
|
|||
| pub fn write_timeout(&self) -> Result<Option<Duration>> { | |||
| self.0.timeout(libc::SO_SNDTIMEO) | |||
| } | |||
|
|
|||
| pub fn duplicate(&self) -> Result<Self> { | |||
| self.0.duplicate().map(Socket) | |||
| } | |||
|
|
|||
| pub fn socket_addr(&self) -> Result<SocketAddr> { | |||
| sockname(|buf, len| unsafe { | |||
| libc::getsockname(*self.0.as_inner(), buf, len) | |||
| }) | |||
| } | |||
|
|
|||
| pub fn read(&self, buf: &mut [u8]) -> Result<usize> { | |||
| self.0.read(buf) | |||
| } | |||
|
|
|||
| pub fn write(&self, buf: &[u8]) -> Result<usize> { | |||
| self.0.write(buf) | |||
| } | |||
|
|
|||
| pub fn flush(&self) -> io::Result<()> { Ok(()) } | |||
| } | |||
|
|
|||
| impl Socket { | |||
| pub fn peer_addr(&self) -> Result<SocketAddr> { | |||
| sockname(|buf, len| unsafe { | |||
| libc::getpeername(*self.0.as_inner(), buf, len) | |||
| }) | |||
| } | |||
|
|
|||
| pub fn shutdown(&self, how: Shutdown) -> Result<()> { | |||
| use libc::consts::os::bsd44::SHUT_RDWR; | |||
|
|
|||
| let how = match how { | |||
| Shutdown::Write => libc::SHUT_WR, | |||
| Shutdown::Read => libc::SHUT_RD, | |||
| Shutdown::Both => SHUT_RDWR, | |||
| }; | |||
| cvt(unsafe { libc::shutdown(*self.0.as_inner(), how) }) | |||
| .map_err(From::from).map(drop) | |||
| } | |||
| } | |||
|
|
|||
| impl Socket { | |||
| pub fn accept(&self) -> Result<(Socket, SocketAddr)> { | |||
| let mut storage: libc::sockaddr_storage = unsafe { mem::zeroed() }; | |||
| let mut len = mem::size_of_val(&storage) as socklen_t; | |||
| let sock = try!(self.0.accept(&mut storage as *mut _ as *mut _, | |||
| &mut len)); | |||
| let addr = try!(sockaddr_to_addr(&storage, len as usize)); | |||
| Ok((Socket(sock), addr)) | |||
| } | |||
| } | |||
|
|
|||
| impl Socket { | |||
| pub fn recv_from(&self, buf: &mut [u8]) -> Result<(usize, SocketAddr)> { | |||
| let mut storage: libc::sockaddr_storage = unsafe { mem::zeroed() }; | |||
| let mut addrlen = mem::size_of_val(&storage) as socklen_t; | |||
|
|
|||
| let n = try!(cvt(unsafe { libc::recvfrom(*self.0.as_inner(), | |||
| buf.as_mut_ptr() as *mut c_void, buf.len() as wrlen_t, 0, &mut storage as *mut _ as *mut _, &mut addrlen) })); | |||
| Ok((n as usize, try!(sockaddr_to_addr(&storage, addrlen as usize)))) | |||
| } | |||
|
|
|||
| pub fn send_to(&self, buf: &[u8], dst: &SocketAddr) -> Result<usize> { | |||
| let (dstp, dstlen) = sockaddr(dst); | |||
| cvt(unsafe { libc::sendto(*self.0.as_inner(), buf.as_ptr() as *const c_void, buf.len() as wrlen_t, 0, dstp, dstlen) }) | |||
| .map_err(From::from).map(|v| v as usize) | |||
| } | |||
| } | |||
|
|
|||
| pub fn lookup_host(host: &str) -> Result<LookupHost> { | |||
| init(); | |||
|
|
|||
| let c_host = try!(CString::new(host)); | |||
| let mut res = ptr::null_mut(); | |||
| unsafe { | |||
| try!(cvt_gai(getaddrinfo(c_host.as_ptr(), ptr::null(), ptr::null(), | |||
| &mut res))); | |||
| Ok(LookupHost { original: res, cur: res }) | |||
| } | |||
| } | |||
|
|
|||
| pub fn lookup_addr(addr: &sys::IpAddr) -> Result<LookupAddr> { | |||
| init(); | |||
|
|
|||
| let saddr = new_sockaddr(addr.clone(), 0); | |||
| let (inner, len) = sockaddr(&saddr); | |||
| let mut hostbuf = [0 as c_char; NI_MAXHOST]; | |||
|
|
|||
| unsafe { | |||
| try!(cvt_gai(getnameinfo(inner, len, | |||
| hostbuf.as_mut_ptr(), NI_MAXHOST as libc::size_t, | |||
| ptr::null_mut(), 0, 0))); | |||
| } | |||
|
|
|||
| Ok(LookupAddr(hostbuf)) | |||
| } | |||
|
|
|||
| pub fn connect_tcp(addr: &SocketAddr) -> Result<Socket> { | |||
| init(); | |||
|
|
|||
| let sock = try!(SocketImp::new(addr, libc::SOCK_STREAM)); | |||
|
|
|||
| let (addrp, len) = sockaddr(addr); | |||
| try!(cvt_r(|| unsafe { libc::connect(*sock.as_inner(), addrp, len) })); | |||
| Ok(Socket(sock)) | |||
| } | |||
|
|
|||
| pub fn bind_tcp(addr: &SocketAddr) -> Result<Socket> { | |||
| init(); | |||
|
|
|||
| let sock = try!(SocketImp::new(addr, libc::SOCK_STREAM)); | |||
|
|
|||
| // On platforms with Berkeley-derived sockets, this allows | |||
| // to quickly rebind a socket, without needing to wait for | |||
| // the OS to clean up the previous one. | |||
| if !cfg!(windows) { | |||
| try!(setsockopt(&sock, libc::SOL_SOCKET, libc::SO_REUSEADDR, | |||
| 1 as c_int)); | |||
| } | |||
|
|
|||
| // Bind our new socket | |||
| let (addrp, len) = sockaddr(addr); | |||
| try!(cvt(unsafe { libc::bind(*sock.as_inner(), addrp, len) })); | |||
|
|
|||
| // Start listening | |||
| try!(cvt(unsafe { libc::listen(*sock.as_inner(), 128) })); | |||
| Ok(Socket(sock)) | |||
| } | |||
|
|
|||
| pub fn bind_udp(addr: &SocketAddr) -> Result<Socket> { | |||
| init(); | |||
|
|
|||
| let sock = try!(SocketImp::new(addr, libc::SOCK_DGRAM)); | |||
| let (addrp, len) = sockaddr(addr); | |||
| try!(cvt(unsafe { libc::bind(*sock.as_inner(), addrp, len) })); | |||
| Ok(Socket(sock)) | |||
| } | |||
| @@ -0,0 +1,31 @@ | |||
| pub fn min_stack() -> usize { | |||
| use env; | |||
| use sync::atomic::{AtomicUsize, Ordering}; | |||
|
|
|||
| static MIN: AtomicUsize = AtomicUsize::new(0); | |||
| match MIN.load(Ordering::Relaxed) { | |||
| 0 => {} | |||
| n => return n - 1, | |||
| } | |||
| let amt = env::var("RUST_MIN_STACK").ok() | |||
| .and_then(|s| s.parse().ok()); | |||
| let amt = amt.unwrap_or(2 * 1024 * 1024); | |||
| // 0 is our sentinel value, so ensure that we'll never see 0 after | |||
| // initialization has run | |||
| MIN.store(amt + 1, Ordering::Relaxed); | |||
| amt | |||
| } | |||
|
|
|||
| #[macro_export] | |||
| macro_rules! rtabort { | |||
| ($($t:tt)*) => ($crate::panicking::abort(format_args!($($t)*))) | |||
| } | |||
|
|
|||
| #[macro_export] | |||
| macro_rules! rtassert { | |||
| ($e:expr) => ({ | |||
| if !$e { | |||
| rtabort!(concat!("assertion failed: ", stringify!($e))) | |||
| } | |||
| }) | |||
| } | |||
| @@ -0,0 +1,56 @@ | |||
| // Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT | |||
| // file at the top-level directory of this distribution and at | |||
| // http://rust-lang.org/COPYRIGHT. | |||
| // | |||
| // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |||
| // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |||
| // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |||
| // option. This file may not be copied, modified, or distributed | |||
| // except according to those terms. | |||
|
|
|||
| //! This module contains the linkage attributes to all runtime dependencies of | |||
| //! the standard library This varies per-platform, but these libraries are | |||
| //! necessary for running libstd. | |||
|
|
|||
| // A few small shims in C that haven't been translated to Rust yet | |||
| #[cfg(all(not(test), unix))] | |||
| #[link(name = "rust_builtin", kind = "static")] | |||
| extern {} | |||
|
|
|||
| // On Linux, librt and libdl are indirect dependencies via std, | |||
| // and binutils 2.22+ won't add them automatically | |||
| #[cfg(all(target_os = "linux", not(target_env = "musl")))] | |||
| #[link(name = "dl")] | |||
| #[link(name = "pthread")] | |||
| extern {} | |||
|
|
|||
| #[cfg(all(not(test), | |||
| any(all(unix, not(any(target_os = "macos", target_os = "ios"))), | |||
| all(windows, target_env = "gnu"))))] | |||
| #[link(name = "backtrace", kind = "static")] | |||
| extern {} | |||
|
|
|||
| #[cfg(target_os = "android")] | |||
| #[link(name = "dl")] | |||
| #[link(name = "log")] | |||
| extern {} | |||
|
|
|||
| #[cfg(target_os = "freebsd")] | |||
| #[link(name = "execinfo")] | |||
| #[link(name = "pthread")] | |||
| extern {} | |||
|
|
|||
| #[cfg(any(target_os = "dragonfly", | |||
| target_os = "bitrig", | |||
| target_os = "netbsd", | |||
| target_os = "openbsd"))] | |||
| #[link(name = "pthread")] | |||
| extern {} | |||
|
|
|||
| #[cfg(target_os = "macos")] | |||
| #[link(name = "System")] | |||
| extern {} | |||
|
|
|||
| #[cfg(target_os = "ios")] | |||
| #[link(name = "System")] | |||
| extern {} | |||
| @@ -0,0 +1,5 @@ | |||
| pub use sys::imp::dynamic_lib::{ | |||
| ENVVAR, SEPARATOR, | |||
| DynamicLibrary, Error, | |||
| open, | |||
| }; | |||
| @@ -0,0 +1,53 @@ | |||
| pub use sys::imp::env::{ | |||
| Args, Vars, SplitPaths, | |||
| getcwd, chdir, | |||
| getenv, setenv, unsetenv, | |||
| home_dir, temp_dir, current_exe, | |||
| vars, args, | |||
| join_paths, join_paths_error, | |||
| split_paths, | |||
| FAMILY, OS, | |||
| DLL_PREFIX, DLL_SUFFIX, DLL_EXTENSION, | |||
| EXE_SUFFIX, EXE_EXTENSION, | |||
| }; | |||
|
|
|||
| use fmt; | |||
|
|
|||
| pub struct JoinPathsError(()); | |||
|
|
|||
| impl fmt::Display for JoinPathsError { | |||
| fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |||
| join_paths_error().fmt(f) | |||
| } | |||
| } | |||
|
|
|||
| impl fmt::Debug for JoinPathsError { | |||
| fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |||
| join_paths_error().fmt(f) | |||
| } | |||
| } | |||
|
|
|||
| impl JoinPathsError { | |||
| pub const fn new() -> Self { JoinPathsError(()) } | |||
| } | |||
|
|
|||
| #[cfg(target_arch = "x86")] | |||
| pub const ARCH: &'static str = "x86"; | |||
|
|
|||
| #[cfg(target_arch = "x86_64")] | |||
| pub const ARCH: &'static str = "x86_64"; | |||
|
|
|||
| #[cfg(target_arch = "arm")] | |||
| pub const ARCH: &'static str = "arm"; | |||
|
|
|||
| #[cfg(target_arch = "aarch64")] | |||
| pub const ARCH: &'static str = "aarch64"; | |||
|
|
|||
| #[cfg(target_arch = "mips")] | |||
| pub const ARCH: &'static str = "mips"; | |||
|
|
|||
| #[cfg(target_arch = "mipsel")] | |||
| pub const ARCH: &'static str = "mipsel"; | |||
|
|
|||
| #[cfg(target_arch = "powerpc")] | |||
| pub const ARCH: &'static str = "powerpc"; | |||
| @@ -0,0 +1,28 @@ | |||
| pub use sys::imp::error::{ | |||
| Error, | |||
| ErrorString, | |||
| }; | |||
|
|
|||
| use str; | |||
| use borrow::Cow; | |||
| use string::String; | |||
|
|
|||
| pub type Result<T> = ::result::Result<T, Error>; | |||
|
|
|||
| pub fn expect_last_result<T>() -> Result<T> { | |||
| Err(expect_last_error()) | |||
| } | |||
|
|
|||
| pub fn expect_last_error() -> Error { | |||
| Error::last_error().unwrap_or_else(|| Error::from_code(0)) | |||
| } | |||
|
|
|||
| impl ErrorString { | |||
| pub fn to_str(&self) -> ::result::Result<&str, str::Utf8Error> { | |||
| str::from_utf8(self.as_bytes()) | |||
| } | |||
|
|
|||
| pub fn to_string_lossy(&self) -> Cow<str> { | |||
| String::from_utf8_lossy(self.as_bytes()) | |||
| } | |||
| } | |||
| @@ -0,0 +1,8 @@ | |||
| pub use sys::imp::fs::{ | |||
| ReadDir, DirEntry, | |||
| File, OpenOptions, | |||
| FileAttr, FileType, FilePermissions, FileHandle, | |||
| DirBuilder, | |||
| COPY_IMP, copy, | |||
| unlink, stat, lstat, rename, link, symlink, readlink, canonicalize, rmdir, readdir, set_perm, | |||
| }; | |||
| @@ -0,0 +1,131 @@ | |||
| /// A trait for viewing representations from std types | |||
| pub trait AsInner<Inner: ?Sized> { | |||
| fn as_inner(&self) -> &Inner; | |||
| } | |||
|
|
|||
| /// A trait for viewing representations from std types | |||
| pub trait AsInnerMut<Inner: ?Sized> { | |||
| fn as_inner_mut(&mut self) -> &mut Inner; | |||
| } | |||
|
|
|||
| /// A trait for extracting representations from std types | |||
| pub trait IntoInner<Inner> { | |||
| fn into_inner(self) -> Inner; | |||
| } | |||
|
|
|||
| /// A trait for creating std types from internal representations | |||
| pub trait FromInner<Inner> { | |||
| fn from_inner(inner: Inner) -> Self; | |||
| } | |||
|
|
|||
| #[macro_export] | |||
| macro_rules! impl_inner { | |||
| (for<$T:ident> $t:ident($t0:ident($TT:ident)): AsInner) => { | |||
| impl<$T> $crate::sys::inner::AsInner<$T> for $t where $t0: $crate::sys::inner::AsInner<$T> { | |||
| fn as_inner(&self) -> &$T { $crate::sys::inner::AsInner::<$T>::as_inner(&self.0) } | |||
| } | |||
| }; | |||
|
|
|||
| (for<$T:ident> $t:ident($t0:ident($TT:ident)): IntoInner) => { | |||
| impl<$T> $crate::sys::inner::IntoInner<$T> for $t where $t0: $crate::sys::inner::IntoInner<$T> { | |||
| fn into_inner(self) -> $T { $crate::sys::inner::IntoInner::<$T>::into_inner(self.0) } | |||
| } | |||
| }; | |||
|
|
|||
| (for<$T:ident> $t:ident($t0:ident($TT:ident)): IntoInnerForget) => { | |||
| impl<$T> $crate::sys::inner::IntoInner<$T> for $t where $t0: $crate::sys::inner::IntoInner<$T> { | |||
| fn into_inner(self) -> $T { | |||
| let inner = $crate::sys::inner::IntoInner::<$T>::into_inner(self.0); | |||
| ::core::mem::forget(self); | |||
| inner | |||
| } | |||
| } | |||
| }; | |||
|
|
|||
| (for<$T:ident> $t:ident($t0:ident($TT:ident)): FromInner) => { | |||
| impl<$T> $crate::sys::inner::FromInner<$T> for $t where $t0: $crate::sys::inner::FromInner<$T> { | |||
| fn from_inner(inner: $T) -> $t { $t($crate::sys::inner::FromInner::<$T>::from_inner(inner)) } | |||
| } | |||
| }; | |||
|
|
|||
| (1 => $t:ident($t0:ident($inner:ty)): AsInner) => { | |||
| impl $crate::sys::inner::AsInner<$inner> for $t { | |||
| fn as_inner(&self) -> &$inner { $crate::sys::inner::AsInner::<$inner>::as_inner($crate::sys::inner::AsInner::<$t0>::as_inner(self)) } | |||
| } | |||
| }; | |||
|
|
|||
| (1 => $t:ident($t0:ident($inner:ty)): IntoInner) => { | |||
| impl $crate::sys::inner::IntoInner<$inner> for $t { | |||
| fn into_inner(self) -> $inner { $crate::sys::inner::IntoInner::<$inner>::into_inner($crate::sys::inner::IntoInner::<$t0>::into_inner(self)) } | |||
| } | |||
| }; | |||
|
|
|||
| (1 => $t:ident($t0:ident($inner:ty)): FromInner) => { | |||
| impl $crate::sys::inner::FromInner<$inner> for $t { | |||
| fn from_inner(inner: $inner) -> Self { $crate::sys::inner::FromInner::<$t0>::from_inner($crate::sys::inner::FromInner::<$inner>::from_inner(inner)) } | |||
| } | |||
| }; | |||
|
|
|||
| (0 => $t:ident($inner:ty): AsInner) => { | |||
| impl $crate::sys::inner::AsInner<$inner> for $t { | |||
| fn as_inner(&self) -> &$inner { &self.0 } | |||
| } | |||
| }; | |||
|
|
|||
| (0 => $t:ident($inner:ty): IntoInnerForget) => { | |||
| impl $crate::sys::inner::IntoInner<$inner> for $t { | |||
| fn into_inner(self) -> $inner { | |||
| let inner = self.0; | |||
| ::core::mem::forget(self); | |||
| inner | |||
| } | |||
| } | |||
| }; | |||
|
|
|||
| (0 => $t:ident($inner:ty): IntoInner) => { | |||
| impl $crate::sys::inner::IntoInner<$inner> for $t { | |||
| fn into_inner(self) -> $inner { self.0 } | |||
| } | |||
| }; | |||
|
|
|||
| (0 => $t:ident($inner:ty): FromInner) => { | |||
| impl $crate::sys::inner::FromInner<$inner> for $t { | |||
| fn from_inner(inner: $inner) -> Self { $t(inner) } | |||
| } | |||
| }; | |||
|
|
|||
| ($t:ident($t0:ident($inner:ty)): $im:ident) => { impl_inner!(1 => $t($t0($inner)): $im); }; | |||
| ($t:ident($inner:ty): $im:ident) => { impl_inner!(0 => $t($inner): $im); }; | |||
|
|
|||
| ($t:ident($t0:ident($inner:ty)): $im0:ident $(+ $im:ident)+) => { | |||
| $( | |||
| impl_inner!(1 =>$t($t0($inner)): $im); | |||
| )+ | |||
|
|
|||
| impl_inner!(1 => $t($t0($inner)): $im0); | |||
| }; | |||
|
|
|||
| ($t:ident($inner:ty): $im0:ident $(+ $im:ident)+) => { | |||
| $( | |||
| impl_inner!(0 => $t($inner): $im); | |||
| )+ | |||
|
|
|||
| impl_inner!(0 => $t($inner): $im0); | |||
| }; | |||
|
|
|||
| (for<$T:ident> $t:ident($t0:ident($TT:ident)): $im0:ident $(+ $im:ident)+) => { | |||
| $( | |||
| impl_inner!(for<$T> $t($t0($TT)): $im); | |||
| )+ | |||
|
|
|||
| impl_inner!(for<$T> $t($t0($TT)): $im0); | |||
| }; | |||
|
|
|||
| ($t:ident($($tt:tt)*)) => { | |||
| impl_inner!($t($($tt)*): AsInner + IntoInner + FromInner); | |||
| }; | |||
|
|
|||
| (for<$T:ident> $t:ident($($tt:tt)*)) => { | |||
| impl_inner!(for<$T> $t($($tt)*): AsInner + IntoInner + FromInner); | |||
| }; | |||
| } | |||
| @@ -0,0 +1,104 @@ | |||
| #![allow(missing_docs)] | |||
| #![doc(hidden)] | |||
|
|
|||
| #[macro_use] | |||
| pub mod inner; | |||
| mod wtf8; | |||
| mod deps; | |||
|
|
|||
| #[macro_use] | |||
| #[cfg(any(target_family = "unix", target_family = "windows"))] | |||
| pub mod common; | |||
|
|
|||
| #[cfg(target_family = "unix")] | |||
| pub mod unix; | |||
|
|
|||
| #[cfg(target_family = "windows")] | |||
| pub mod windows; | |||
|
|
|||
| #[cfg(target_family = "unix")] | |||
| pub use self::unix as target; | |||
|
|
|||
| #[cfg(target_family = "windows")] | |||
| pub use self::windows as target; | |||
|
|
|||
| pub mod thread_local; | |||
| pub mod unwind; | |||
| pub mod error; | |||
| pub mod time; | |||
| pub mod sync; | |||
| pub mod thread; | |||
| pub mod backtrace; | |||
| pub mod env; | |||
| pub mod stdio; | |||
| pub mod path; | |||
| pub mod stack_overflow; | |||
| pub mod rand; | |||
| pub mod fs; | |||
| pub mod dynamic_lib; | |||
| pub mod net; | |||
| pub mod os_str; | |||
| pub mod process; | |||
| pub mod rt; | |||
| pub mod c; | |||
|
|
|||
| pub mod os; | |||
|
|
|||
| #[cfg(target_family = "unix")] | |||
| pub mod imp { | |||
| pub use sys::unix::{ | |||
| error, | |||
| env, | |||
| stdio, | |||
| path, | |||
| time, | |||
| thread, | |||
| stack_overflow, | |||
| rand, | |||
| dynamic_lib, | |||
| fs, | |||
| process, | |||
| backtrace, | |||
| }; | |||
|
|
|||
| pub use sys::common::{ | |||
| thread_local, | |||
| unwind, | |||
| }; | |||
|
|
|||
| pub mod rt { | |||
| pub use sys::unix::rt::{ | |||
| run_main, run_thread, | |||
| cleanup, thread_cleanup, | |||
| }; | |||
| pub use sys::common::rt::min_stack; | |||
| } | |||
|
|
|||
| pub mod sync { | |||
| pub use sys::unix::mutex::{Mutex, ReentrantMutex}; | |||
| pub use sys::unix::condvar::Condvar; | |||
| pub use sys::unix::rwlock::RwLock; | |||
| } | |||
|
|
|||
| pub mod net { | |||
| pub use sys::unix::net::Socket; | |||
| pub use sys::common::net::{ | |||
| TcpListener, TcpStream, UdpSocket, | |||
| IpAddrV4, IpAddrV6, | |||
| SocketAddrV4, SocketAddrV6, | |||
| LookupHost, LookupAddr, | |||
| connect_tcp, bind_tcp, bind_udp, | |||
| lookup_host, lookup_addr, | |||
| }; | |||
| } | |||
|
|
|||
| pub mod c { | |||
| pub use libc::{ | |||
| EINVAL, EIO, | |||
| EBADF, | |||
| strlen, | |||
| }; | |||
| } | |||
|
|
|||
| pub use sys::os_str::u8 as os_str; | |||
| } | |||
| @@ -0,0 +1,23 @@ | |||
| pub use sys::imp::net::{ | |||
| LookupAddr, LookupHost, | |||
| SocketAddrV4, SocketAddrV6, | |||
| IpAddrV4, IpAddrV6, | |||
| Socket, TcpStream, TcpListener, UdpSocket, | |||
| lookup_host, lookup_addr, | |||
| connect_tcp, bind_tcp, bind_udp, | |||
| }; | |||
|
|
|||
| pub enum SocketAddr { | |||
| V4(SocketAddrV4), | |||
| V6(SocketAddrV6), | |||
| } | |||
|
|
|||
| pub enum IpAddr { | |||
| V4(IpAddrV4), | |||
| V6(IpAddrV6), | |||
| } | |||
|
|
|||
| impl Copy for IpAddr { } | |||
| impl Copy for SocketAddr { } | |||
| impl Clone for IpAddr { fn clone(&self) -> Self { *self } } | |||
| impl Clone for SocketAddr { fn clone(&self) -> Self { *self } } | |||