Skip to content

Implement missing new rt tcp/udp methods. #8040

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions src/libstd/rt/io/net/ip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,52 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use num::FromStrRadix;
use to_str::ToStr;

type Port = u16;

#[deriving(Eq, TotalEq)]
pub enum IpAddr {
Ipv4(u8, u8, u8, u8, Port),
Ipv6(u16, u16, u16, u16, u16, u16, u16, u16, Port)
}

impl ToStr for IpAddr {
fn to_str(&self) -> ~str {
match *self {
Ipv4(a, b, c, d, p) =>
fmt!("%u.%u.%u.%u:%u",
a as uint, b as uint, c as uint, d as uint, p as uint),

// Ipv4 Compatible address
Ipv6(0, 0, 0, 0, 0, 0, g, h, p) => {
let a = fmt!("%04x", g as uint);
let b = FromStrRadix::from_str_radix(a.slice(2, 4), 16).unwrap();
let a = FromStrRadix::from_str_radix(a.slice(0, 2), 16).unwrap();
let c = fmt!("%04x", h as uint);
let d = FromStrRadix::from_str_radix(c.slice(2, 4), 16).unwrap();
let c = FromStrRadix::from_str_radix(c.slice(0, 2), 16).unwrap();

fmt!("[::%u.%u.%u.%u]:%u", a, b, c, d, p as uint)
}

// Ipv4-Mapped address
Ipv6(0, 0, 0, 0, 0, 1, g, h, p) => {
let a = fmt!("%04x", g as uint);
let b = FromStrRadix::from_str_radix(a.slice(2, 4), 16).unwrap();
let a = FromStrRadix::from_str_radix(a.slice(0, 2), 16).unwrap();
let c = fmt!("%04x", h as uint);
let d = FromStrRadix::from_str_radix(c.slice(2, 4), 16).unwrap();
let c = FromStrRadix::from_str_radix(c.slice(0, 2), 16).unwrap();

fmt!("[::FFFF:%u.%u.%u.%u]:%u", a, b, c, d, p as uint)
}

Ipv6(a, b, c, d, e, f, g, h, p) =>
fmt!("[%x:%x:%x:%x:%x:%x:%x:%x]:%u",
a as uint, b as uint, c as uint, d as uint,
e as uint, f as uint, g as uint, h as uint, p as uint)
}
}
}
95 changes: 93 additions & 2 deletions src/libstd/rt/io/net/tcp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ use rt::io::net::ip::IpAddr;
use rt::io::{Reader, Writer, Listener};
use rt::io::{io_error, read_error, EndOfFile};
use rt::rtio::{IoFactory, IoFactoryObject,
RtioTcpListener, RtioTcpListenerObject,
RtioTcpStream, RtioTcpStreamObject};
RtioSocket, RtioTcpListener,
RtioTcpListenerObject, RtioTcpStream,
RtioTcpStreamObject};
use rt::local::Local;

pub struct TcpStream(~RtioTcpStreamObject);
Expand All @@ -42,6 +43,28 @@ impl TcpStream {
}
}
}

pub fn peer_name(&mut self) -> Option<IpAddr> {
match (**self).peer_name() {
Ok(pn) => Some(pn),
Err(ioerr) => {
rtdebug!("failed to get peer name: %?", ioerr);
io_error::cond.raise(ioerr);
None
}
}
}

pub fn socket_name(&mut self) -> Option<IpAddr> {
match (**self).socket_name() {
Ok(sn) => Some(sn),
Err(ioerr) => {
rtdebug!("failed to get socket name: %?", ioerr);
io_error::cond.raise(ioerr);
None
}
}
}
}

impl Reader for TcpStream {
Expand Down Expand Up @@ -90,6 +113,17 @@ impl TcpListener {
}
}
}

pub fn socket_name(&mut self) -> Option<IpAddr> {
match (**self).socket_name() {
Ok(sn) => Some(sn),
Err(ioerr) => {
rtdebug!("failed to get socket name: %?", ioerr);
io_error::cond.raise(ioerr);
None
}
}
}
}

impl Listener<TcpStream> for TcpListener {
Expand Down Expand Up @@ -534,4 +568,61 @@ mod test {
}
}

#[cfg(test)]
fn socket_name(addr: IpAddr) {
do run_in_newsched_task {
do spawntask_immediately {
let listener = TcpListener::bind(addr);

assert!(listener.is_some());
let mut listener = listener.unwrap();

// Make sure socket_name gives
// us the socket we binded to.
let so_name = listener.socket_name();
assert!(so_name.is_some());
assert_eq!(addr, so_name.unwrap());

}
}
}

#[cfg(test)]
fn peer_name(addr: IpAddr) {
do run_in_newsched_task {
do spawntask_immediately {
let mut listener = TcpListener::bind(addr);

listener.accept();
}

do spawntask_immediately {
let stream = TcpStream::connect(addr);

assert!(stream.is_some());
let mut stream = stream.unwrap();

// Make sure peer_name gives us the
// address/port of the peer we've
// connected to.
let peer_name = stream.peer_name();
assert!(peer_name.is_some());
assert_eq!(addr, peer_name.unwrap());
}
}
}

#[test]
fn socket_and_peer_name_ip4() {
peer_name(next_test_ip4());
socket_name(next_test_ip4());
}

#[test]
fn socket_and_peer_name_ip6() {
// XXX: peer name is not consistent
//peer_name(next_test_ip6());
socket_name(next_test_ip6());
}

}
42 changes: 41 additions & 1 deletion src/libstd/rt/io/net/udp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use result::{Ok, Err};
use rt::io::net::ip::IpAddr;
use rt::io::{Reader, Writer};
use rt::io::{io_error, read_error, EndOfFile};
use rt::rtio::{RtioUdpSocketObject, RtioUdpSocket, IoFactory, IoFactoryObject};
use rt::rtio::{RtioSocket, RtioUdpSocketObject, RtioUdpSocket, IoFactory, IoFactoryObject};
use rt::local::Local;

pub struct UdpSocket(~RtioUdpSocketObject);
Expand Down Expand Up @@ -53,6 +53,17 @@ impl UdpSocket {
pub fn connect(self, other: IpAddr) -> UdpStream {
UdpStream { socket: self, connectedTo: other }
}

pub fn socket_name(&mut self) -> Option<IpAddr> {
match (***self).socket_name() {
Ok(sn) => Some(sn),
Err(ioerr) => {
rtdebug!("failed to get socket name: %?", ioerr);
io_error::cond.raise(ioerr);
None
}
}
}
}

pub struct UdpStream {
Expand Down Expand Up @@ -252,4 +263,33 @@ mod test {
}
}
}

#[cfg(test)]
fn socket_name(addr: IpAddr) {
do run_in_newsched_task {
do spawntask_immediately {
let server = UdpSocket::bind(addr);

assert!(server.is_some());
let mut server = server.unwrap();

// Make sure socket_name gives
// us the socket we binded to.
let so_name = server.socket_name();
assert!(so_name.is_some());
assert_eq!(addr, so_name.unwrap());

}
}
}

#[test]
fn socket_name_ip4() {
socket_name(next_test_ip4());
}

#[test]
fn socket_name_ip6() {
socket_name(next_test_ip6());
}
}
32 changes: 16 additions & 16 deletions src/libstd/rt/rtio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,39 +52,39 @@ pub trait IoFactory {

pub trait RtioTcpListener : RtioSocket {
fn accept(&mut self) -> Result<~RtioTcpStreamObject, IoError>;
fn accept_simultaneously(&mut self);
fn dont_accept_simultaneously(&mut self);
fn accept_simultaneously(&mut self) -> Result<(), IoError>;
fn dont_accept_simultaneously(&mut self) -> Result<(), IoError>;
}

pub trait RtioTcpStream : RtioSocket {
fn read(&mut self, buf: &mut [u8]) -> Result<uint, IoError>;
fn write(&mut self, buf: &[u8]) -> Result<(), IoError>;
fn peer_name(&mut self) -> IpAddr;
fn control_congestion(&mut self);
fn nodelay(&mut self);
fn keepalive(&mut self, delay_in_seconds: uint);
fn letdie(&mut self);
fn peer_name(&mut self) -> Result<IpAddr, IoError>;
fn control_congestion(&mut self) -> Result<(), IoError>;
fn nodelay(&mut self) -> Result<(), IoError>;
fn keepalive(&mut self, delay_in_seconds: uint) -> Result<(), IoError>;
fn letdie(&mut self) -> Result<(), IoError>;
}

pub trait RtioSocket {
fn socket_name(&mut self) -> IpAddr;
fn socket_name(&mut self) -> Result<IpAddr, IoError>;
}

pub trait RtioUdpSocket : RtioSocket {
fn recvfrom(&mut self, buf: &mut [u8]) -> Result<(uint, IpAddr), IoError>;
fn sendto(&mut self, buf: &[u8], dst: IpAddr) -> Result<(), IoError>;

fn join_multicast(&mut self, multi: IpAddr);
fn leave_multicast(&mut self, multi: IpAddr);
fn join_multicast(&mut self, multi: IpAddr) -> Result<(), IoError>;
fn leave_multicast(&mut self, multi: IpAddr) -> Result<(), IoError>;

fn loop_multicast_locally(&mut self);
fn dont_loop_multicast_locally(&mut self);
fn loop_multicast_locally(&mut self) -> Result<(), IoError>;
fn dont_loop_multicast_locally(&mut self) -> Result<(), IoError>;

fn multicast_time_to_live(&mut self, ttl: int);
fn time_to_live(&mut self, ttl: int);
fn multicast_time_to_live(&mut self, ttl: int) -> Result<(), IoError>;
fn time_to_live(&mut self, ttl: int) -> Result<(), IoError>;

fn hear_broadcasts(&mut self);
fn ignore_broadcasts(&mut self);
fn hear_broadcasts(&mut self) -> Result<(), IoError>;
fn ignore_broadcasts(&mut self) -> Result<(), IoError>;
}

pub trait RtioTimer {
Expand Down
4 changes: 2 additions & 2 deletions src/libstd/rt/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ pub fn run_in_newsched_task(f: ~fn()) {
let on_exit: ~fn(bool) = |exit_status| rtassert!(exit_status);
let mut task = ~Task::new_root(&mut sched.stack_pool,
f.take());
rtdebug!("newsched_task: %x", to_uint(task));
rtdebug!("newsched_task: %x", ::borrow::to_uint(task));
task.death.on_exit = Some(on_exit);
sched.enqueue_task(task);
sched.run();
Expand Down Expand Up @@ -145,7 +145,7 @@ pub fn spawntask(f: ~fn()) {
}
};

rtdebug!("new task pointer: %x", to_uint(task));
rtdebug!("new task pointer: %x", ::borrow::to_uint(task));

let sched = Local::take::<Scheduler>();
rtdebug!("spawntask scheduling the new task");
Expand Down
2 changes: 1 addition & 1 deletion src/libstd/rt/uv/async.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ impl AsyncWatcher {

extern fn async_cb(handle: *uvll::uv_async_t, status: c_int) {
let mut watcher: AsyncWatcher = NativeHandle::from_native_handle(handle);
let status = status_to_maybe_uv_error(watcher.native_handle(), status);
let status = status_to_maybe_uv_error(watcher, status);
let data = watcher.get_watcher_data();
let cb = data.async_cb.get_ref();
(*cb)(watcher, status);
Expand Down
2 changes: 1 addition & 1 deletion src/libstd/rt/uv/idle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ impl IdleWatcher {
let mut idle_watcher: IdleWatcher = NativeHandle::from_native_handle(handle);
let data = idle_watcher.get_watcher_data();
let cb: &IdleCallback = data.idle_cb.get_ref();
let status = status_to_maybe_uv_error(handle, status);
let status = status_to_maybe_uv_error(idle_watcher, status);
(*cb)(idle_watcher, status);
}
}
Expand Down
8 changes: 4 additions & 4 deletions src/libstd/rt/uv/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -282,14 +282,14 @@ pub fn uv_error_to_io_error(uverr: UvError) -> IoError {
}

/// Given a uv handle, convert a callback status to a UvError
// XXX: Follow the pattern below by parameterizing over T: Watcher, not T
pub fn status_to_maybe_uv_error<T>(handle: *T, status: c_int) -> Option<UvError> {
pub fn status_to_maybe_uv_error<T, U: Watcher + NativeHandle<*T>>(handle: U,
status: c_int) -> Option<UvError> {
if status != -1 {
None
} else {
unsafe {
rtdebug!("handle: %x", handle as uint);
let loop_ = uvll::get_loop_for_uv_handle(handle);
rtdebug!("handle: %x", handle.native_handle() as uint);
let loop_ = uvll::get_loop_for_uv_handle(handle.native_handle());
rtdebug!("loop: %x", loop_ as uint);
let err = uvll::last_error(loop_);
Some(UvError(err))
Expand Down
Loading