aboutsummaryrefslogtreecommitdiff
path: root/ctr-std/src/sys/unix/net.rs
diff options
context:
space:
mode:
authorValentin <[email protected]>2018-06-15 18:57:24 +0200
committerFenrirWolf <[email protected]>2018-06-15 10:57:24 -0600
commitf2a90174bb36b9ad528e863ab34c02ebce002b02 (patch)
tree959e8d67883d3a89e179b3549b1f30d28e51a87c /ctr-std/src/sys/unix/net.rs
parentMerge pull request #68 from linouxis9/master (diff)
downloadctru-rs-f2a90174bb36b9ad528e863ab34c02ebce002b02.tar.xz
ctru-rs-f2a90174bb36b9ad528e863ab34c02ebce002b02.zip
Update for latest nightly 2018-06-09 (#70)
* Update for latest nightly 2018-06-09 * We now have a proper horizon os and sys modules in libstd
Diffstat (limited to 'ctr-std/src/sys/unix/net.rs')
-rw-r--r--ctr-std/src/sys/unix/net.rs73
1 files changed, 39 insertions, 34 deletions
diff --git a/ctr-std/src/sys/unix/net.rs b/ctr-std/src/sys/unix/net.rs
index 94f757d..04d9f0b 100644
--- a/ctr-std/src/sys/unix/net.rs
+++ b/ctr-std/src/sys/unix/net.rs
@@ -8,11 +8,9 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![allow(dead_code)]
-
use ffi::CStr;
use io;
-use libc::{self, c_int, c_void, size_t, sockaddr, socklen_t, EAI_NONAME as EAI_SYSTEM, MSG_PEEK};
+use libc::{self, c_int, c_void, size_t, sockaddr, socklen_t, EAI_SYSTEM, MSG_PEEK};
use mem;
use net::{SocketAddr, Shutdown};
use str;
@@ -25,7 +23,6 @@ use cmp;
pub use sys::{cvt, cvt_r};
pub extern crate libc as netc;
-#[allow(non_camel_case_types)]
pub type wrlen_t = size_t;
// See below for the usage of SOCK_CLOEXEC, but this constant is only defined on
@@ -54,12 +51,16 @@ pub fn cvt_gai(err: c_int) -> io::Result<()> {
if err == 0 {
return Ok(())
}
+
+ // We may need to trigger a glibc workaround. See on_resolver_failure() for details.
+ on_resolver_failure();
+
if err == EAI_SYSTEM {
return Err(io::Error::last_os_error())
}
let detail = unsafe {
- str::from_utf8(CStr::from_ptr(libc::gai_strerror(err) as *const _).to_bytes()).unwrap()
+ str::from_utf8(CStr::from_ptr(libc::gai_strerror(err)).to_bytes()).unwrap()
.to_owned()
};
Err(io::Error::new(io::ErrorKind::Other,
@@ -143,7 +144,7 @@ impl Socket {
let mut pollfd = libc::pollfd {
fd: self.0.raw(),
- events: 0x10, //libc::POLLOUT; value in the `libc` crate is currently incorrect
+ events: libc::POLLOUT,
revents: 0,
};
@@ -181,9 +182,7 @@ impl Socket {
_ => {
// linux returns POLLOUT|POLLERR|POLLHUP for refused connections (!), so look
// for POLLHUP rather than read readiness
- //
- // libc::POLLHUP should be 0x4. the `libc` crate incorrectly lists it as 0x10
- if pollfd.revents & 0x4 != 0 {
+ if pollfd.revents & libc::POLLHUP != 0 {
let e = self.take_error()?
.unwrap_or_else(|| {
io::Error::new(io::ErrorKind::Other, "no error set after POLLHUP")
@@ -199,6 +198,26 @@ impl Socket {
pub fn accept(&self, storage: *mut sockaddr, len: *mut socklen_t)
-> io::Result<Socket> {
+ // Unfortunately the only known way right now to accept a socket and
+ // atomically set the CLOEXEC flag is to use the `accept4` syscall on
+ // Linux. This was added in 2.6.28, however, and because we support
+ // 2.6.18 we must detect this support dynamically.
+ if cfg!(target_os = "linux") {
+ weak! {
+ fn accept4(c_int, *mut sockaddr, *mut socklen_t, c_int) -> c_int
+ }
+ if let Some(accept) = accept4.get() {
+ let res = cvt_r(|| unsafe {
+ accept(self.0.raw(), storage, len, SOCK_CLOEXEC)
+ });
+ match res {
+ Ok(fd) => return Ok(Socket(FileDesc::new(fd))),
+ Err(ref e) if e.raw_os_error() == Some(libc::ENOSYS) => {}
+ Err(e) => return Err(e),
+ }
+ }
+ }
+
let fd = cvt_r(|| unsafe {
libc::accept(self.0.raw(), storage, len)
})?;
@@ -320,7 +339,8 @@ impl Socket {
}
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
- self.0.set_nonblocking(nonblocking)
+ let mut nonblocking = nonblocking as libc::c_int;
+ cvt(unsafe { libc::ioctl(*self.as_inner(), libc::FIONBIO, &mut nonblocking) }).map(|_| ())
}
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
@@ -362,36 +382,21 @@ impl IntoInner<c_int> for Socket {
// against glibc version < 2.26. (That is, when we both know its needed and
// believe it's thread-safe).
#[cfg(target_env = "gnu")]
-pub fn res_init_if_glibc_before_2_26() -> io::Result<()> {
+fn on_resolver_failure() {
+ use sys;
+
// If the version fails to parse, we treat it the same as "not glibc".
- if let Some(Ok(version_str)) = glibc_version_cstr().map(CStr::to_str) {
- if let Some(version) = parse_glibc_version(version_str) {
- if version < (2, 26) {
- let ret = unsafe { libc::res_init() };
- if ret != 0 {
- return Err(io::Error::last_os_error());
- }
- }
+ if let Some(version) = sys::os::glibc_version() {
+ if version < (2, 26) {
+ unsafe { libc::res_init() };
}
}
- Ok(())
}
-fn glibc_version_cstr() -> Option<&'static CStr> {
- None
-}
-
-// Returns Some((major, minor)) if the string is a valid "x.y" version,
-// ignoring any extra dot-separated parts. Otherwise return None.
-fn parse_glibc_version(version: &str) -> Option<(usize, usize)> {
- let mut parsed_ints = version.split(".").map(str::parse::<usize>).fuse();
- match (parsed_ints.next(), parsed_ints.next()) {
- (Some(Ok(major)), Some(Ok(minor))) => Some((major, minor)),
- _ => None
- }
-}
+#[cfg(not(target_env = "gnu"))]
+fn on_resolver_failure() {}
-#[cfg(test)]
+#[cfg(all(test, taget_env = "gnu"))]
mod test {
use super::*;