Skip to content

Commit

Permalink
Auto merge of #38707 - redox-os:master, r=brson
Browse files Browse the repository at this point in the history
Add socket timeout and ttl support in `sys::redox`

This adds support for `read_timeout`, `write_timeout`, and `ttl` on `TcpStream`, `TcpListener`, and `UdpSocket` in the `sys::redox` module.

The DNS lookup has been set to use a 5 second timeout by default.
  • Loading branch information
bors committed Jan 4, 2017
2 parents a68622c + c6858a1 commit 01677ee
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 35 deletions.
10 changes: 1 addition & 9 deletions src/librustc_back/target/redox_base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,22 +25,14 @@ pub fn opts() -> TargetOptions {
"-Wl,--as-needed".to_string(),

// Always enable NX protection when it is available
"-Wl,-z,noexecstack".to_string(),

// Static link
"-static".to_string()
],
late_link_args: vec![
"-lc".to_string(),
"-lm".to_string()
"-Wl,-z,noexecstack".to_string()
],
executables: true,
relocation_model: "static".to_string(),
disable_redzone: true,
eliminate_frame_pointer: false,
target_family: None,
linker_is_gnu: true,
no_default_libraries: true,
lib_allocation_crate: "alloc_system".to_string(),
exe_allocation_crate: "alloc_system".to_string(),
has_elf_tls: true,
Expand Down
4 changes: 3 additions & 1 deletion src/libstd/sys/redox/net/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use net::{Ipv4Addr, SocketAddr, SocketAddrV4};
use str::FromStr;
use string::{String, ToString};
use sys::syscall::EINVAL;
use time;
use time::{self, Duration};
use vec::{IntoIter, Vec};

use self::dns::{Dns, DnsQuery};
Expand Down Expand Up @@ -69,6 +69,8 @@ pub fn lookup_host(host: &str) -> Result<LookupHost> {
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(&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(&SocketAddr::V4(SocketAddrV4::new(dns_ip, 53)))?;
socket.send(&packet_data)?;

Expand Down
75 changes: 59 additions & 16 deletions src/libstd/sys/redox/net/tcp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,13 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use cmp;
use io::{Error, ErrorKind, Result};
use mem;
use net::{SocketAddr, Shutdown};
use path::Path;
use sys::fs::{File, OpenOptions};
use sys::syscall::TimeSpec;
use sys_common::{AsInner, FromInner, IntoInner};
use time::Duration;
use vec::Vec;
Expand Down Expand Up @@ -77,15 +80,30 @@ impl TcpStream {
}

pub fn ttl(&self) -> Result<u32> {
Err(Error::new(ErrorKind::Other, "TcpStream::ttl not implemented"))
let mut ttl = [0];
let file = self.0.dup(b"ttl")?;
file.read(&mut ttl)?;
Ok(ttl[0] as u32)
}

pub fn read_timeout(&self) -> Result<Option<Duration>> {
Err(Error::new(ErrorKind::Other, "TcpStream::read_timeout not implemented"))
let mut time = TimeSpec::default();
let file = self.0.dup(b"read_timeout")?;
if file.read(&mut time)? >= mem::size_of::<TimeSpec>() {
Ok(Some(Duration::new(time.tv_sec as u64, time.tv_nsec as u32)))
} else {
Ok(None)
}
}

pub fn write_timeout(&self) -> Result<Option<Duration>> {
Err(Error::new(ErrorKind::Other, "TcpStream::write_timeout not implemented"))
let mut time = TimeSpec::default();
let file = self.0.dup(b"write_timeout")?;
if file.read(&mut time)? >= mem::size_of::<TimeSpec>() {
Ok(Some(Duration::new(time.tv_sec as u64, time.tv_nsec as u32)))
} else {
Ok(None)
}
}

pub fn set_nodelay(&self, _nodelay: bool) -> Result<()> {
Expand All @@ -100,16 +118,36 @@ impl TcpStream {
Err(Error::new(ErrorKind::Other, "TcpStream::set_only_v6 not implemented"))
}

pub fn set_ttl(&self, _ttl: u32) -> Result<()> {
Err(Error::new(ErrorKind::Other, "TcpStream::set_ttl not implemented"))
}

pub fn set_read_timeout(&self, _dur: Option<Duration>) -> Result<()> {
Err(Error::new(ErrorKind::Other, "TcpStream::set_read_timeout not implemented"))
}

pub fn set_write_timeout(&self, _dur: Option<Duration>) -> Result<()> {
Err(Error::new(ErrorKind::Other, "TcpStream::set_write_timeout not implemented"))
pub fn set_ttl(&self, ttl: u32) -> Result<()> {
let file = self.0.dup(b"ttl")?;
file.write(&[cmp::min(ttl, 255) as u8])?;
Ok(())
}

pub fn set_read_timeout(&self, duration_option: Option<Duration>) -> Result<()> {
let file = self.0.dup(b"read_timeout")?;
if let Some(duration) = duration_option {
file.write(&TimeSpec {
tv_sec: duration.as_secs() as i64,
tv_nsec: duration.subsec_nanos() as i32
})?;
} else {
file.write(&[])?;
}
Ok(())
}

pub fn set_write_timeout(&self, duration_option: Option<Duration>) -> Result<()> {
let file = self.0.dup(b"write_timeout")?;
if let Some(duration) = duration_option {
file.write(&TimeSpec {
tv_sec: duration.as_secs() as i64,
tv_nsec: duration.subsec_nanos() as i32
})?;
} else {
file.write(&[])?;
}
Ok(())
}
}

Expand Down Expand Up @@ -168,7 +206,10 @@ impl TcpListener {
}

pub fn ttl(&self) -> Result<u32> {
Err(Error::new(ErrorKind::Other, "TcpListener::ttl not implemented"))
let mut ttl = [0];
let file = self.0.dup(b"ttl")?;
file.read(&mut ttl)?;
Ok(ttl[0] as u32)
}

pub fn set_nonblocking(&self, _nonblocking: bool) -> Result<()> {
Expand All @@ -179,8 +220,10 @@ impl TcpListener {
Err(Error::new(ErrorKind::Other, "TcpListener::set_only_v6 not implemented"))
}

pub fn set_ttl(&self, _ttl: u32) -> Result<()> {
Err(Error::new(ErrorKind::Other, "TcpListener::set_ttl not implemented"))
pub fn set_ttl(&self, ttl: u32) -> Result<()> {
let file = self.0.dup(b"ttl")?;
file.write(&[cmp::min(ttl, 255) as u8])?;
Ok(())
}
}

Expand Down
56 changes: 47 additions & 9 deletions src/libstd/sys/redox/net/udp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,13 @@
// except according to those terms.

use cell::UnsafeCell;
use cmp;
use io::{Error, ErrorKind, Result};
use mem;
use net::{SocketAddr, Ipv4Addr, Ipv6Addr};
use path::Path;
use sys::fs::{File, OpenOptions};
use sys::syscall::TimeSpec;
use sys_common::{AsInner, FromInner, IntoInner};
use time::Duration;

Expand Down Expand Up @@ -109,15 +112,30 @@ impl UdpSocket {
}

pub fn ttl(&self) -> Result<u32> {
Err(Error::new(ErrorKind::Other, "UdpSocket::ttl not implemented"))
let mut ttl = [0];
let file = self.0.dup(b"ttl")?;
file.read(&mut ttl)?;
Ok(ttl[0] as u32)
}

pub fn read_timeout(&self) -> Result<Option<Duration>> {
Err(Error::new(ErrorKind::Other, "UdpSocket::read_timeout not implemented"))
let mut time = TimeSpec::default();
let file = self.0.dup(b"read_timeout")?;
if file.read(&mut time)? >= mem::size_of::<TimeSpec>() {
Ok(Some(Duration::new(time.tv_sec as u64, time.tv_nsec as u32)))
} else {
Ok(None)
}
}

pub fn write_timeout(&self) -> Result<Option<Duration>> {
Err(Error::new(ErrorKind::Other, "UdpSocket::write_timeout not implemented"))
let mut time = TimeSpec::default();
let file = self.0.dup(b"write_timeout")?;
if file.read(&mut time)? >= mem::size_of::<TimeSpec>() {
Ok(Some(Duration::new(time.tv_sec as u64, time.tv_nsec as u32)))
} else {
Ok(None)
}
}

pub fn set_broadcast(&self, _broadcast: bool) -> Result<()> {
Expand All @@ -144,16 +162,36 @@ impl UdpSocket {
Err(Error::new(ErrorKind::Other, "UdpSocket::set_only_v6 not implemented"))
}

pub fn set_ttl(&self, _ttl: u32) -> Result<()> {
Err(Error::new(ErrorKind::Other, "UdpSocket::set_ttl not implemented"))
pub fn set_ttl(&self, ttl: u32) -> Result<()> {
let file = self.0.dup(b"ttl")?;
file.write(&[cmp::min(ttl, 255) as u8])?;
Ok(())
}

pub fn set_read_timeout(&self, _dur: Option<Duration>) -> Result<()> {
Err(Error::new(ErrorKind::Other, "UdpSocket::set_read_timeout not implemented"))
pub fn set_read_timeout(&self, duration_option: Option<Duration>) -> Result<()> {
let file = self.0.dup(b"read_timeout")?;
if let Some(duration) = duration_option {
file.write(&TimeSpec {
tv_sec: duration.as_secs() as i64,
tv_nsec: duration.subsec_nanos() as i32
})?;
} else {
file.write(&[])?;
}
Ok(())
}

pub fn set_write_timeout(&self, _dur: Option<Duration>) -> Result<()> {
Err(Error::new(ErrorKind::Other, "UdpSocket::set_write_timeout not implemented"))
pub fn set_write_timeout(&self, duration_option: Option<Duration>) -> Result<()> {
let file = self.0.dup(b"write_timeout")?;
if let Some(duration) = duration_option {
file.write(&TimeSpec {
tv_sec: duration.as_secs() as i64,
tv_nsec: duration.subsec_nanos() as i32
})?;
} else {
file.write(&[])?;
}
Ok(())
}

pub fn join_multicast_v4(&self, _multiaddr: &Ipv4Addr, _interface: &Ipv4Addr) -> Result<()> {
Expand Down
19 changes: 19 additions & 0 deletions src/libstd/sys/redox/syscall/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,22 @@ pub struct TimeSpec {
pub tv_sec: i64,
pub tv_nsec: i32,
}

impl Deref for TimeSpec {
type Target = [u8];
fn deref(&self) -> &[u8] {
unsafe {
slice::from_raw_parts(self as *const TimeSpec as *const u8,
mem::size_of::<TimeSpec>()) as &[u8]
}
}
}

impl DerefMut for TimeSpec {
fn deref_mut(&mut self) -> &mut [u8] {
unsafe {
slice::from_raw_parts_mut(self as *mut TimeSpec as *mut u8,
mem::size_of::<TimeSpec>()) as &mut [u8]
}
}
}

0 comments on commit 01677ee

Please sign in to comment.