1 // Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 use option::{Option, Some, None};
12 use result::{Ok, Err};
13 use rt::io::net::ip::SocketAddr;
14 use rt::io::{Reader, Writer, Listener};
15 use rt::io::{io_error, read_error, EndOfFile};
16 use rt::rtio::{IoFactory, IoFactoryObject,
17 RtioSocket, RtioTcpListener,
18 RtioTcpListenerObject, RtioTcpStream,
19 RtioTcpStreamObject, RtioStream};
22 pub struct TcpStream(~RtioTcpStreamObject);
25 fn new(s: ~RtioTcpStreamObject) -> TcpStream {
29 pub fn connect(addr: SocketAddr) -> Option<TcpStream> {
31 rtdebug!("borrowing io to connect");
32 let io: *mut IoFactoryObject = Local::unsafe_borrow();
33 rtdebug!("about to connect");
34 (*io).tcp_connect(addr)
38 Ok(s) => Some(TcpStream::new(s)),
40 rtdebug!("failed to connect: %?", ioerr);
41 io_error::cond.raise(ioerr);
47 pub fn peer_name(&mut self) -> Option<SocketAddr> {
48 match (**self).peer_name() {
51 rtdebug!("failed to get peer name: %?", ioerr);
52 io_error::cond.raise(ioerr);
58 pub fn socket_name(&mut self) -> Option<SocketAddr> {
59 match (**self).socket_name() {
62 rtdebug!("failed to get socket name: %?", ioerr);
63 io_error::cond.raise(ioerr);
70 impl Reader for TcpStream {
71 fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
72 match (***self).read(buf) {
73 Ok(read) => Some(read),
75 // EOF is indicated by returning None
76 if ioerr.kind != EndOfFile {
77 read_error::cond.raise(ioerr);
84 fn eof(&mut self) -> bool { fail!() }
87 impl Writer for TcpStream {
88 fn write(&mut self, buf: &[u8]) {
89 match (***self).write(buf) {
91 Err(ioerr) => io_error::cond.raise(ioerr),
95 fn flush(&mut self) { fail!() }
98 pub struct TcpListener(~RtioTcpListenerObject);
101 pub fn bind(addr: SocketAddr) -> Option<TcpListener> {
102 let listener = unsafe {
103 let io: *mut IoFactoryObject = Local::unsafe_borrow();
107 Ok(l) => Some(TcpListener(l)),
109 io_error::cond.raise(ioerr);
115 pub fn socket_name(&mut self) -> Option<SocketAddr> {
116 match (**self).socket_name() {
119 rtdebug!("failed to get socket name: %?", ioerr);
120 io_error::cond.raise(ioerr);
127 impl Listener<TcpStream> for TcpListener {
128 fn accept(&mut self) -> Option<TcpStream> {
129 match (**self).accept() {
130 Ok(s) => Some(TcpStream::new(s)),
132 io_error::cond.raise(ioerr);
144 use rt::io::net::ip::{Ipv4Addr, SocketAddr};
150 do run_in_newsched_task {
151 let mut called = false;
152 do io_error::cond.trap(|e| {
153 assert!(e.kind == PermissionDenied);
156 let addr = SocketAddr { ip: Ipv4Addr(0, 0, 0, 0), port: 1 };
157 let listener = TcpListener::bind(addr);
158 assert!(listener.is_none());
166 do run_in_newsched_task {
167 let mut called = false;
168 do io_error::cond.trap(|e| {
169 assert_eq!(e.kind, ConnectionRefused);
172 let addr = SocketAddr { ip: Ipv4Addr(0, 0, 0, 0), port: 1 };
173 let stream = TcpStream::connect(addr);
174 assert!(stream.is_none());
181 fn smoke_test_ip4() {
182 do run_in_newsched_task {
183 let addr = next_test_ip4();
186 let mut listener = TcpListener::bind(addr);
187 let mut stream = listener.accept();
190 assert!(buf[0] == 99);
194 let mut stream = TcpStream::connect(addr);
201 fn smoke_test_ip6() {
202 do run_in_newsched_task {
203 let addr = next_test_ip6();
206 let mut listener = TcpListener::bind(addr);
207 let mut stream = listener.accept();
210 assert!(buf[0] == 99);
214 let mut stream = TcpStream::connect(addr);
222 do run_in_newsched_task {
223 let addr = next_test_ip4();
226 let mut listener = TcpListener::bind(addr);
227 let mut stream = listener.accept();
229 let nread = stream.read(buf);
230 assert!(nread.is_none());
234 let _stream = TcpStream::connect(addr);
242 do run_in_newsched_task {
243 let addr = next_test_ip6();
246 let mut listener = TcpListener::bind(addr);
247 let mut stream = listener.accept();
249 let nread = stream.read(buf);
250 assert!(nread.is_none());
254 let _stream = TcpStream::connect(addr);
261 fn read_eof_twice_ip4() {
262 do run_in_newsched_task {
263 let addr = next_test_ip4();
266 let mut listener = TcpListener::bind(addr);
267 let mut stream = listener.accept();
269 let nread = stream.read(buf);
270 assert!(nread.is_none());
271 let nread = stream.read(buf);
272 assert!(nread.is_none());
276 let _stream = TcpStream::connect(addr);
283 fn read_eof_twice_ip6() {
284 do run_in_newsched_task {
285 let addr = next_test_ip6();
288 let mut listener = TcpListener::bind(addr);
289 let mut stream = listener.accept();
291 let nread = stream.read(buf);
292 assert!(nread.is_none());
293 let nread = stream.read(buf);
294 assert!(nread.is_none());
298 let _stream = TcpStream::connect(addr);
305 fn write_close_ip4() {
306 do run_in_newsched_task {
307 let addr = next_test_ip4();
310 let mut listener = TcpListener::bind(addr);
311 let mut stream = listener.accept();
314 let mut stop = false;
315 do io_error::cond.trap(|e| {
316 // NB: ECONNRESET on linux, EPIPE on mac
317 assert!(e.kind == ConnectionReset || e.kind == BrokenPipe);
327 let _stream = TcpStream::connect(addr);
334 fn write_close_ip6() {
335 do run_in_newsched_task {
336 let addr = next_test_ip6();
339 let mut listener = TcpListener::bind(addr);
340 let mut stream = listener.accept();
343 let mut stop = false;
344 do io_error::cond.trap(|e| {
345 // NB: ECONNRESET on linux, EPIPE on mac
346 assert!(e.kind == ConnectionReset || e.kind == BrokenPipe);
356 let _stream = TcpStream::connect(addr);
363 fn multiple_connect_serial_ip4() {
364 do run_in_newsched_task {
365 let addr = next_test_ip4();
369 let mut listener = TcpListener::bind(addr);
371 let mut stream = listener.accept();
374 assert_eq!(buf[0], 99);
380 let mut stream = TcpStream::connect(addr);
388 fn multiple_connect_serial_ip6() {
389 do run_in_newsched_task {
390 let addr = next_test_ip6();
394 let mut listener = TcpListener::bind(addr);
396 let mut stream = listener.accept();
399 assert_eq!(buf[0], 99);
405 let mut stream = TcpStream::connect(addr);
413 fn multiple_connect_interleaved_greedy_schedule_ip4() {
414 do run_in_newsched_task {
415 let addr = next_test_ip4();
416 static MAX: int = 10;
419 let mut listener = TcpListener::bind(addr);
420 for i in range(0, MAX) {
421 let stream = Cell::new(listener.accept());
422 rtdebug!("accepted");
423 // Start another task to handle the connection
425 let mut stream = stream.take();
428 assert!(buf[0] == i as u8);
436 fn connect(i: int, addr: SocketAddr) {
437 if i == MAX { return }
440 rtdebug!("connecting");
441 let mut stream = TcpStream::connect(addr);
442 // Connect again before writing
443 connect(i + 1, addr);
445 stream.write([i as u8]);
452 fn multiple_connect_interleaved_greedy_schedule_ip6() {
453 do run_in_newsched_task {
454 let addr = next_test_ip6();
455 static MAX: int = 10;
458 let mut listener = TcpListener::bind(addr);
459 for i in range(0, MAX) {
460 let stream = Cell::new(listener.accept());
461 rtdebug!("accepted");
462 // Start another task to handle the connection
464 let mut stream = stream.take();
467 assert!(buf[0] == i as u8);
475 fn connect(i: int, addr: SocketAddr) {
476 if i == MAX { return }
479 rtdebug!("connecting");
480 let mut stream = TcpStream::connect(addr);
481 // Connect again before writing
482 connect(i + 1, addr);
484 stream.write([i as u8]);
491 fn multiple_connect_interleaved_lazy_schedule_ip4() {
492 do run_in_newsched_task {
493 let addr = next_test_ip4();
494 static MAX: int = 10;
497 let mut listener = TcpListener::bind(addr);
498 for _ in range(0, MAX) {
499 let stream = Cell::new(listener.accept());
500 rtdebug!("accepted");
501 // Start another task to handle the connection
503 let mut stream = stream.take();
506 assert!(buf[0] == 99);
514 fn connect(i: int, addr: SocketAddr) {
515 if i == MAX { return }
518 rtdebug!("connecting");
519 let mut stream = TcpStream::connect(addr);
520 // Connect again before writing
521 connect(i + 1, addr);
529 fn multiple_connect_interleaved_lazy_schedule_ip6() {
530 do run_in_newsched_task {
531 let addr = next_test_ip6();
532 static MAX: int = 10;
535 let mut listener = TcpListener::bind(addr);
536 for _ in range(0, MAX) {
537 let stream = Cell::new(listener.accept());
538 rtdebug!("accepted");
539 // Start another task to handle the connection
541 let mut stream = stream.take();
544 assert!(buf[0] == 99);
552 fn connect(i: int, addr: SocketAddr) {
553 if i == MAX { return }
556 rtdebug!("connecting");
557 let mut stream = TcpStream::connect(addr);
558 // Connect again before writing
559 connect(i + 1, addr);
568 fn socket_name(addr: SocketAddr) {
569 do run_in_newsched_task {
571 let listener = TcpListener::bind(addr);
573 assert!(listener.is_some());
574 let mut listener = listener.unwrap();
576 // Make sure socket_name gives
577 // us the socket we binded to.
578 let so_name = listener.socket_name();
579 assert!(so_name.is_some());
580 assert_eq!(addr, so_name.unwrap());
587 fn peer_name(addr: SocketAddr) {
588 do run_in_newsched_task {
590 let mut listener = TcpListener::bind(addr);
596 let stream = TcpStream::connect(addr);
598 assert!(stream.is_some());
599 let mut stream = stream.unwrap();
601 // Make sure peer_name gives us the
602 // address/port of the peer we've
604 let peer_name = stream.peer_name();
605 assert!(peer_name.is_some());
606 assert_eq!(addr, peer_name.unwrap());
612 fn socket_and_peer_name_ip4() {
613 peer_name(next_test_ip4());
614 socket_name(next_test_ip4());
618 fn socket_and_peer_name_ip6() {
619 // XXX: peer name is not consistent
620 //peer_name(next_test_ip6());
621 socket_name(next_test_ip6());