Skip to content

Commit

Permalink
IPv6 support for UDP and TCP.
Browse files Browse the repository at this point in the history
  • Loading branch information
Eric Reed committed Jul 2, 2013
1 parent 42f3f06 commit e6c5779
Show file tree
Hide file tree
Showing 9 changed files with 877 additions and 131 deletions.
207 changes: 200 additions & 7 deletions src/libstd/rt/io/net/tcp.rs
Expand Up @@ -148,7 +148,7 @@ mod test {
}

#[test]
fn smoke_test() {
fn smoke_test_ip4() {
do run_in_newsched_task {
let addr = next_test_ip4();

Expand All @@ -168,7 +168,27 @@ mod test {
}

#[test]
fn read_eof() {
fn smoke_test_ip6() {
do run_in_newsched_task {
let addr = next_test_ip6();

do spawntask_immediately {
let mut listener = TcpListener::bind(addr);
let mut stream = listener.accept();
let mut buf = [0];
stream.read(buf);
assert!(buf[0] == 99);
}

do spawntask_immediately {
let mut stream = TcpStream::connect(addr);
stream.write([99]);
}
}
}

#[test]
fn read_eof_ip4() {
do run_in_newsched_task {
let addr = next_test_ip4();

Expand All @@ -188,7 +208,27 @@ mod test {
}

#[test]
fn read_eof_twice() {
fn read_eof_ip6() {
do run_in_newsched_task {
let addr = next_test_ip6();

do spawntask_immediately {
let mut listener = TcpListener::bind(addr);
let mut stream = listener.accept();
let mut buf = [0];
let nread = stream.read(buf);
assert!(nread.is_none());
}

do spawntask_immediately {
let _stream = TcpStream::connect(addr);
// Close
}
}
}

#[test]
fn read_eof_twice_ip4() {
do run_in_newsched_task {
let addr = next_test_ip4();

Expand All @@ -210,7 +250,29 @@ mod test {
}

#[test]
fn write_close() {
fn read_eof_twice_ip6() {
do run_in_newsched_task {
let addr = next_test_ip6();

do spawntask_immediately {
let mut listener = TcpListener::bind(addr);
let mut stream = listener.accept();
let mut buf = [0];
let nread = stream.read(buf);
assert!(nread.is_none());
let nread = stream.read(buf);
assert!(nread.is_none());
}

do spawntask_immediately {
let _stream = TcpStream::connect(addr);
// Close
}
}
}

#[test]
fn write_close_ip4() {
do run_in_newsched_task {
let addr = next_test_ip4();

Expand Down Expand Up @@ -239,7 +301,36 @@ mod test {
}

#[test]
fn multiple_connect_serial() {
fn write_close_ip6() {
do run_in_newsched_task {
let addr = next_test_ip6();

do spawntask_immediately {
let mut listener = TcpListener::bind(addr);
let mut stream = listener.accept();
let buf = [0];
loop {
let mut stop = false;
do io_error::cond.trap(|e| {
// NB: ECONNRESET on linux, EPIPE on mac
assert!(e.kind == ConnectionReset || e.kind == BrokenPipe);
stop = true;
}).in {
stream.write(buf);
}
if stop { break }
}
}

do spawntask_immediately {
let _stream = TcpStream::connect(addr);
// Close
}
}
}

#[test]
fn multiple_connect_serial_ip4() {
do run_in_newsched_task {
let addr = next_test_ip4();
let max = 10;
Expand All @@ -264,7 +355,32 @@ mod test {
}

#[test]
fn multiple_connect_interleaved_greedy_schedule() {
fn multiple_connect_serial_ip6() {
do run_in_newsched_task {
let addr = next_test_ip6();
let max = 10;

do spawntask_immediately {
let mut listener = TcpListener::bind(addr);
for max.times {
let mut stream = listener.accept();
let mut buf = [0];
stream.read(buf);
assert_eq!(buf[0], 99);
}
}

do spawntask_immediately {
for max.times {
let mut stream = TcpStream::connect(addr);
stream.write([99]);
}
}
}
}

#[test]
fn multiple_connect_interleaved_greedy_schedule_ip4() {
do run_in_newsched_task {
let addr = next_test_ip4();
static MAX: int = 10;
Expand Down Expand Up @@ -303,7 +419,46 @@ mod test {
}

#[test]
fn multiple_connect_interleaved_lazy_schedule() {
fn multiple_connect_interleaved_greedy_schedule_ip6() {
do run_in_newsched_task {
let addr = next_test_ip6();
static MAX: int = 10;

do spawntask_immediately {
let mut listener = TcpListener::bind(addr);
for int::range(0, MAX) |i| {
let stream = Cell::new(listener.accept());
rtdebug!("accepted");
// Start another task to handle the connection
do spawntask_immediately {
let mut stream = stream.take();
let mut buf = [0];
stream.read(buf);
assert!(buf[0] == i as u8);
rtdebug!("read");
}
}
}

connect(0, addr);

fn connect(i: int, addr: IpAddr) {
if i == MAX { return }

do spawntask_immediately {
rtdebug!("connecting");
let mut stream = TcpStream::connect(addr);
// Connect again before writing
connect(i + 1, addr);
rtdebug!("writing");
stream.write([i as u8]);
}
}
}
}

#[test]
fn multiple_connect_interleaved_lazy_schedule_ip4() {
do run_in_newsched_task {
let addr = next_test_ip4();
static MAX: int = 10;
Expand Down Expand Up @@ -340,5 +495,43 @@ mod test {
}
}
}
#[test]
fn multiple_connect_interleaved_lazy_schedule_ip6() {
do run_in_newsched_task {
let addr = next_test_ip6();
static MAX: int = 10;

do spawntask_immediately {
let mut listener = TcpListener::bind(addr);
for int::range(0, MAX) |_| {
let stream = Cell::new(listener.accept());
rtdebug!("accepted");
// Start another task to handle the connection
do spawntask_later {
let mut stream = stream.take();
let mut buf = [0];
stream.read(buf);
assert!(buf[0] == 99);
rtdebug!("read");
}
}
}

connect(0, addr);

fn connect(i: int, addr: IpAddr) {
if i == MAX { return }

do spawntask_later {
rtdebug!("connecting");
let mut stream = TcpStream::connect(addr);
// Connect again before writing
connect(i + 1, addr);
rtdebug!("writing");
stream.write([99]);
}
}
}
}

}
73 changes: 71 additions & 2 deletions src/libstd/rt/io/net/udp.rs
Expand Up @@ -115,7 +115,7 @@ mod test {
}

#[test]
fn socket_smoke_test() {
fn socket_smoke_test_ip4() {
do run_in_newsched_task {
let server_ip = next_test_ip4();
let client_ip = next_test_ip4();
Expand Down Expand Up @@ -147,7 +147,39 @@ mod test {
}

#[test]
fn stream_smoke_test() {
fn socket_smoke_test_ip6() {
do run_in_newsched_task {
let server_ip = next_test_ip6();
let client_ip = next_test_ip6();

do spawntask_immediately {
match UdpSocket::bind(server_ip) {
Some(server) => {
let mut buf = [0];
match server.recvfrom(buf) {
Some((nread, src)) => {
assert_eq!(nread, 1);
assert_eq!(buf[0], 99);
assert_eq!(src, client_ip);
}
None => fail!()
}
}
None => fail!()
}
}

do spawntask_immediately {
match UdpSocket::bind(client_ip) {
Some(client) => client.sendto([99], server_ip),
None => fail!()
}
}
}
}

#[test]
fn stream_smoke_test_ip4() {
do run_in_newsched_task {
let server_ip = next_test_ip4();
let client_ip = next_test_ip4();
Expand Down Expand Up @@ -182,4 +214,41 @@ mod test {
}
}
}

#[test]
fn stream_smoke_test_ip6() {
do run_in_newsched_task {
let server_ip = next_test_ip6();
let client_ip = next_test_ip6();

do spawntask_immediately {
match UdpSocket::bind(server_ip) {
Some(server) => {
let server = ~server;
let mut stream = server.connect(client_ip);
let mut buf = [0];
match stream.read(buf) {
Some(nread) => {
assert_eq!(nread, 1);
assert_eq!(buf[0], 99);
}
None => fail!()
}
}
None => fail!()
}
}

do spawntask_immediately {
match UdpSocket::bind(client_ip) {
Some(client) => {
let client = ~client;
let mut stream = client.connect(server_ip);
stream.write([99]);
}
None => fail!()
}
}
}
}
}

0 comments on commit e6c5779

Please sign in to comment.