Skip to content

Commit 15310ba

Browse files
committed
auto merge of #8040 : luqmana/rust/rtn, r=brson
Implements various missing tcp & udp methods.. Also fixes handling ipv4-mapped/compatible ipv6 addresses and addresses the XXX on `status_to_maybe_uv_error`. r? @brson
2 parents c519474 + df67942 commit 15310ba

File tree

15 files changed

+546
-154
lines changed

15 files changed

+546
-154
lines changed

src/libstd/rt/io/net/ip.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,52 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
use num::FromStrRadix;
12+
use to_str::ToStr;
13+
1114
type Port = u16;
1215

1316
#[deriving(Eq, TotalEq)]
1417
pub enum IpAddr {
1518
Ipv4(u8, u8, u8, u8, Port),
1619
Ipv6(u16, u16, u16, u16, u16, u16, u16, u16, Port)
1720
}
21+
22+
impl ToStr for IpAddr {
23+
fn to_str(&self) -> ~str {
24+
match *self {
25+
Ipv4(a, b, c, d, p) =>
26+
fmt!("%u.%u.%u.%u:%u",
27+
a as uint, b as uint, c as uint, d as uint, p as uint),
28+
29+
// Ipv4 Compatible address
30+
Ipv6(0, 0, 0, 0, 0, 0, g, h, p) => {
31+
let a = fmt!("%04x", g as uint);
32+
let b = FromStrRadix::from_str_radix(a.slice(2, 4), 16).unwrap();
33+
let a = FromStrRadix::from_str_radix(a.slice(0, 2), 16).unwrap();
34+
let c = fmt!("%04x", h as uint);
35+
let d = FromStrRadix::from_str_radix(c.slice(2, 4), 16).unwrap();
36+
let c = FromStrRadix::from_str_radix(c.slice(0, 2), 16).unwrap();
37+
38+
fmt!("[::%u.%u.%u.%u]:%u", a, b, c, d, p as uint)
39+
}
40+
41+
// Ipv4-Mapped address
42+
Ipv6(0, 0, 0, 0, 0, 1, g, h, p) => {
43+
let a = fmt!("%04x", g as uint);
44+
let b = FromStrRadix::from_str_radix(a.slice(2, 4), 16).unwrap();
45+
let a = FromStrRadix::from_str_radix(a.slice(0, 2), 16).unwrap();
46+
let c = fmt!("%04x", h as uint);
47+
let d = FromStrRadix::from_str_radix(c.slice(2, 4), 16).unwrap();
48+
let c = FromStrRadix::from_str_radix(c.slice(0, 2), 16).unwrap();
49+
50+
fmt!("[::FFFF:%u.%u.%u.%u]:%u", a, b, c, d, p as uint)
51+
}
52+
53+
Ipv6(a, b, c, d, e, f, g, h, p) =>
54+
fmt!("[%x:%x:%x:%x:%x:%x:%x:%x]:%u",
55+
a as uint, b as uint, c as uint, d as uint,
56+
e as uint, f as uint, g as uint, h as uint, p as uint)
57+
}
58+
}
59+
}

src/libstd/rt/io/net/tcp.rs

Lines changed: 93 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@ use rt::io::net::ip::IpAddr;
1414
use rt::io::{Reader, Writer, Listener};
1515
use rt::io::{io_error, read_error, EndOfFile};
1616
use rt::rtio::{IoFactory, IoFactoryObject,
17-
RtioTcpListener, RtioTcpListenerObject,
18-
RtioTcpStream, RtioTcpStreamObject};
17+
RtioSocket, RtioTcpListener,
18+
RtioTcpListenerObject, RtioTcpStream,
19+
RtioTcpStreamObject};
1920
use rt::local::Local;
2021

2122
pub struct TcpStream(~RtioTcpStreamObject);
@@ -42,6 +43,28 @@ impl TcpStream {
4243
}
4344
}
4445
}
46+
47+
pub fn peer_name(&mut self) -> Option<IpAddr> {
48+
match (**self).peer_name() {
49+
Ok(pn) => Some(pn),
50+
Err(ioerr) => {
51+
rtdebug!("failed to get peer name: %?", ioerr);
52+
io_error::cond.raise(ioerr);
53+
None
54+
}
55+
}
56+
}
57+
58+
pub fn socket_name(&mut self) -> Option<IpAddr> {
59+
match (**self).socket_name() {
60+
Ok(sn) => Some(sn),
61+
Err(ioerr) => {
62+
rtdebug!("failed to get socket name: %?", ioerr);
63+
io_error::cond.raise(ioerr);
64+
None
65+
}
66+
}
67+
}
4568
}
4669

4770
impl Reader for TcpStream {
@@ -90,6 +113,17 @@ impl TcpListener {
90113
}
91114
}
92115
}
116+
117+
pub fn socket_name(&mut self) -> Option<IpAddr> {
118+
match (**self).socket_name() {
119+
Ok(sn) => Some(sn),
120+
Err(ioerr) => {
121+
rtdebug!("failed to get socket name: %?", ioerr);
122+
io_error::cond.raise(ioerr);
123+
None
124+
}
125+
}
126+
}
93127
}
94128

95129
impl Listener<TcpStream> for TcpListener {
@@ -534,4 +568,61 @@ mod test {
534568
}
535569
}
536570

571+
#[cfg(test)]
572+
fn socket_name(addr: IpAddr) {
573+
do run_in_newsched_task {
574+
do spawntask_immediately {
575+
let listener = TcpListener::bind(addr);
576+
577+
assert!(listener.is_some());
578+
let mut listener = listener.unwrap();
579+
580+
// Make sure socket_name gives
581+
// us the socket we binded to.
582+
let so_name = listener.socket_name();
583+
assert!(so_name.is_some());
584+
assert_eq!(addr, so_name.unwrap());
585+
586+
}
587+
}
588+
}
589+
590+
#[cfg(test)]
591+
fn peer_name(addr: IpAddr) {
592+
do run_in_newsched_task {
593+
do spawntask_immediately {
594+
let mut listener = TcpListener::bind(addr);
595+
596+
listener.accept();
597+
}
598+
599+
do spawntask_immediately {
600+
let stream = TcpStream::connect(addr);
601+
602+
assert!(stream.is_some());
603+
let mut stream = stream.unwrap();
604+
605+
// Make sure peer_name gives us the
606+
// address/port of the peer we've
607+
// connected to.
608+
let peer_name = stream.peer_name();
609+
assert!(peer_name.is_some());
610+
assert_eq!(addr, peer_name.unwrap());
611+
}
612+
}
613+
}
614+
615+
#[test]
616+
fn socket_and_peer_name_ip4() {
617+
peer_name(next_test_ip4());
618+
socket_name(next_test_ip4());
619+
}
620+
621+
#[test]
622+
fn socket_and_peer_name_ip6() {
623+
// XXX: peer name is not consistent
624+
//peer_name(next_test_ip6());
625+
socket_name(next_test_ip6());
626+
}
627+
537628
}

src/libstd/rt/io/net/udp.rs

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use result::{Ok, Err};
1313
use rt::io::net::ip::IpAddr;
1414
use rt::io::{Reader, Writer};
1515
use rt::io::{io_error, read_error, EndOfFile};
16-
use rt::rtio::{RtioUdpSocketObject, RtioUdpSocket, IoFactory, IoFactoryObject};
16+
use rt::rtio::{RtioSocket, RtioUdpSocketObject, RtioUdpSocket, IoFactory, IoFactoryObject};
1717
use rt::local::Local;
1818

1919
pub struct UdpSocket(~RtioUdpSocketObject);
@@ -53,6 +53,17 @@ impl UdpSocket {
5353
pub fn connect(self, other: IpAddr) -> UdpStream {
5454
UdpStream { socket: self, connectedTo: other }
5555
}
56+
57+
pub fn socket_name(&mut self) -> Option<IpAddr> {
58+
match (***self).socket_name() {
59+
Ok(sn) => Some(sn),
60+
Err(ioerr) => {
61+
rtdebug!("failed to get socket name: %?", ioerr);
62+
io_error::cond.raise(ioerr);
63+
None
64+
}
65+
}
66+
}
5667
}
5768

5869
pub struct UdpStream {
@@ -252,4 +263,33 @@ mod test {
252263
}
253264
}
254265
}
266+
267+
#[cfg(test)]
268+
fn socket_name(addr: IpAddr) {
269+
do run_in_newsched_task {
270+
do spawntask_immediately {
271+
let server = UdpSocket::bind(addr);
272+
273+
assert!(server.is_some());
274+
let mut server = server.unwrap();
275+
276+
// Make sure socket_name gives
277+
// us the socket we binded to.
278+
let so_name = server.socket_name();
279+
assert!(so_name.is_some());
280+
assert_eq!(addr, so_name.unwrap());
281+
282+
}
283+
}
284+
}
285+
286+
#[test]
287+
fn socket_name_ip4() {
288+
socket_name(next_test_ip4());
289+
}
290+
291+
#[test]
292+
fn socket_name_ip6() {
293+
socket_name(next_test_ip6());
294+
}
255295
}

src/libstd/rt/rtio.rs

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -52,39 +52,39 @@ pub trait IoFactory {
5252

5353
pub trait RtioTcpListener : RtioSocket {
5454
fn accept(&mut self) -> Result<~RtioTcpStreamObject, IoError>;
55-
fn accept_simultaneously(&mut self);
56-
fn dont_accept_simultaneously(&mut self);
55+
fn accept_simultaneously(&mut self) -> Result<(), IoError>;
56+
fn dont_accept_simultaneously(&mut self) -> Result<(), IoError>;
5757
}
5858

5959
pub trait RtioTcpStream : RtioSocket {
6060
fn read(&mut self, buf: &mut [u8]) -> Result<uint, IoError>;
6161
fn write(&mut self, buf: &[u8]) -> Result<(), IoError>;
62-
fn peer_name(&mut self) -> IpAddr;
63-
fn control_congestion(&mut self);
64-
fn nodelay(&mut self);
65-
fn keepalive(&mut self, delay_in_seconds: uint);
66-
fn letdie(&mut self);
62+
fn peer_name(&mut self) -> Result<IpAddr, IoError>;
63+
fn control_congestion(&mut self) -> Result<(), IoError>;
64+
fn nodelay(&mut self) -> Result<(), IoError>;
65+
fn keepalive(&mut self, delay_in_seconds: uint) -> Result<(), IoError>;
66+
fn letdie(&mut self) -> Result<(), IoError>;
6767
}
6868

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

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

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

80-
fn loop_multicast_locally(&mut self);
81-
fn dont_loop_multicast_locally(&mut self);
80+
fn loop_multicast_locally(&mut self) -> Result<(), IoError>;
81+
fn dont_loop_multicast_locally(&mut self) -> Result<(), IoError>;
8282

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

86-
fn hear_broadcasts(&mut self);
87-
fn ignore_broadcasts(&mut self);
86+
fn hear_broadcasts(&mut self) -> Result<(), IoError>;
87+
fn ignore_broadcasts(&mut self) -> Result<(), IoError>;
8888
}
8989

9090
pub trait RtioTimer {

src/libstd/rt/test.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ pub fn run_in_newsched_task(f: ~fn()) {
5050
let on_exit: ~fn(bool) = |exit_status| rtassert!(exit_status);
5151
let mut task = ~Task::new_root(&mut sched.stack_pool,
5252
f.take());
53-
rtdebug!("newsched_task: %x", to_uint(task));
53+
rtdebug!("newsched_task: %x", ::borrow::to_uint(task));
5454
task.death.on_exit = Some(on_exit);
5555
sched.enqueue_task(task);
5656
sched.run();
@@ -145,7 +145,7 @@ pub fn spawntask(f: ~fn()) {
145145
}
146146
};
147147

148-
rtdebug!("new task pointer: %x", to_uint(task));
148+
rtdebug!("new task pointer: %x", ::borrow::to_uint(task));
149149

150150
let sched = Local::take::<Scheduler>();
151151
rtdebug!("spawntask scheduling the new task");

src/libstd/rt/uv/async.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ impl AsyncWatcher {
3434

3535
extern fn async_cb(handle: *uvll::uv_async_t, status: c_int) {
3636
let mut watcher: AsyncWatcher = NativeHandle::from_native_handle(handle);
37-
let status = status_to_maybe_uv_error(watcher.native_handle(), status);
37+
let status = status_to_maybe_uv_error(watcher, status);
3838
let data = watcher.get_watcher_data();
3939
let cb = data.async_cb.get_ref();
4040
(*cb)(watcher, status);

src/libstd/rt/uv/idle.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ impl IdleWatcher {
4343
let mut idle_watcher: IdleWatcher = NativeHandle::from_native_handle(handle);
4444
let data = idle_watcher.get_watcher_data();
4545
let cb: &IdleCallback = data.idle_cb.get_ref();
46-
let status = status_to_maybe_uv_error(handle, status);
46+
let status = status_to_maybe_uv_error(idle_watcher, status);
4747
(*cb)(idle_watcher, status);
4848
}
4949
}

src/libstd/rt/uv/mod.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -282,14 +282,14 @@ pub fn uv_error_to_io_error(uverr: UvError) -> IoError {
282282
}
283283
284284
/// Given a uv handle, convert a callback status to a UvError
285-
// XXX: Follow the pattern below by parameterizing over T: Watcher, not T
286-
pub fn status_to_maybe_uv_error<T>(handle: *T, status: c_int) -> Option<UvError> {
285+
pub fn status_to_maybe_uv_error<T, U: Watcher + NativeHandle<*T>>(handle: U,
286+
status: c_int) -> Option<UvError> {
287287
if status != -1 {
288288
None
289289
} else {
290290
unsafe {
291-
rtdebug!("handle: %x", handle as uint);
292-
let loop_ = uvll::get_loop_for_uv_handle(handle);
291+
rtdebug!("handle: %x", handle.native_handle() as uint);
292+
let loop_ = uvll::get_loop_for_uv_handle(handle.native_handle());
293293
rtdebug!("loop: %x", loop_ as uint);
294294
let err = uvll::last_error(loop_);
295295
Some(UvError(err))

0 commit comments

Comments
 (0)