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, Acceptor};
15 use rt::io::{io_error, read_error, EndOfFile};
16 use rt::rtio::{IoFactory, IoFactoryObject,
18 RtioTcpListener, RtioTcpListenerObject,
19 RtioTcpAcceptor, RtioTcpAcceptorObject,
20 RtioTcpStream, RtioTcpStreamObject};
23 pub struct TcpStream(~RtioTcpStreamObject);
26 fn new(s: ~RtioTcpStreamObject) -> TcpStream {
30 pub fn connect(addr: SocketAddr) -> Option<TcpStream> {
32 rtdebug!("borrowing io to connect");
33 let io: *mut IoFactoryObject = Local::unsafe_borrow();
34 rtdebug!("about to connect");
35 (*io).tcp_connect(addr)
39 Ok(s) => Some(TcpStream::new(s)),
41 rtdebug!("failed to connect: %?", ioerr);
42 io_error::cond.raise(ioerr);
48 pub fn peer_name(&mut self) -> Option<SocketAddr> {
49 match (**self).peer_name() {
52 rtdebug!("failed to get peer name: %?", ioerr);
53 io_error::cond.raise(ioerr);
59 pub fn socket_name(&mut self) -> Option<SocketAddr> {
60 match (**self).socket_name() {
63 rtdebug!("failed to get socket name: %?", ioerr);
64 io_error::cond.raise(ioerr);
71 impl Reader for TcpStream {
72 fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
73 match (**self).read(buf) {
74 Ok(read) => Some(read),
76 // EOF is indicated by returning None
77 if ioerr.kind != EndOfFile {
78 read_error::cond.raise(ioerr);
85 fn eof(&mut self) -> bool { fail!() }
88 impl Writer for TcpStream {
89 fn write(&mut self, buf: &[u8]) {
90 match (**self).write(buf) {
92 Err(ioerr) => io_error::cond.raise(ioerr),
96 fn flush(&mut self) { fail!() }
99 pub struct TcpListener(~RtioTcpListenerObject);
102 pub fn bind(addr: SocketAddr) -> Option<TcpListener> {
103 let listener = unsafe {
104 let io: *mut IoFactoryObject = Local::unsafe_borrow();
108 Ok(l) => Some(TcpListener(l)),
110 io_error::cond.raise(ioerr);
116 pub fn socket_name(&mut self) -> Option<SocketAddr> {
117 match (**self).socket_name() {
120 rtdebug!("failed to get socket name: %?", ioerr);
121 io_error::cond.raise(ioerr);
128 impl Listener<TcpStream, TcpAcceptor> for TcpListener {
129 fn listen(self) -> Option<TcpAcceptor> {
130 match (**self).listen() {
131 Ok(acceptor) => Some(TcpAcceptor(acceptor)),
133 io_error::cond.raise(ioerr);
140 pub struct TcpAcceptor(~RtioTcpAcceptorObject);
142 impl Acceptor<TcpStream> for TcpAcceptor {
143 fn accept(&mut self) -> Option<TcpStream> {
144 match (**self).accept() {
145 Ok(s) => Some(TcpStream::new(s)),
147 io_error::cond.raise(ioerr);
159 use rt::io::net::ip::{Ipv4Addr, SocketAddr};
165 do run_in_newsched_task {
166 let mut called = false;
167 do io_error::cond.trap(|e| {
168 assert!(e.kind == PermissionDenied);
171 let addr = SocketAddr { ip: Ipv4Addr(0, 0, 0, 0), port: 1 };
172 let listener = TcpListener::bind(addr);
173 assert!(listener.is_none());
180 #[ignore(cfg(windows))] // FIXME #8811
182 do run_in_newsched_task {
183 let mut called = false;
184 do io_error::cond.trap(|e| {
185 assert_eq!(e.kind, ConnectionRefused);
188 let addr = SocketAddr { ip: Ipv4Addr(0, 0, 0, 0), port: 1 };
189 let stream = TcpStream::connect(addr);
190 assert!(stream.is_none());
197 fn smoke_test_ip4() {
198 do run_in_newsched_task {
199 let addr = next_test_ip4();
202 let mut acceptor = TcpListener::bind(addr).listen();
203 let mut stream = acceptor.accept();
206 assert!(buf[0] == 99);
210 let mut stream = TcpStream::connect(addr);
217 fn smoke_test_ip6() {
218 do run_in_newsched_task {
219 let addr = next_test_ip6();
222 let mut acceptor = TcpListener::bind(addr).listen();
223 let mut stream = acceptor.accept();
226 assert!(buf[0] == 99);
230 let mut stream = TcpStream::connect(addr);
238 do run_in_newsched_task {
239 let addr = next_test_ip4();
242 let mut acceptor = TcpListener::bind(addr).listen();
243 let mut stream = acceptor.accept();
245 let nread = stream.read(buf);
246 assert!(nread.is_none());
250 let _stream = TcpStream::connect(addr);
258 do run_in_newsched_task {
259 let addr = next_test_ip6();
262 let mut acceptor = TcpListener::bind(addr).listen();
263 let mut stream = acceptor.accept();
265 let nread = stream.read(buf);
266 assert!(nread.is_none());
270 let _stream = TcpStream::connect(addr);
277 #[ignore(cfg(windows))] // FIXME #8811
278 fn read_eof_twice_ip4() {
279 do run_in_newsched_task {
280 let addr = next_test_ip4();
283 let mut acceptor = TcpListener::bind(addr).listen();
284 let mut stream = acceptor.accept();
286 let nread = stream.read(buf);
287 assert!(nread.is_none());
288 let nread = stream.read(buf);
289 assert!(nread.is_none());
293 let _stream = TcpStream::connect(addr);
300 #[ignore(cfg(windows))] // FIXME #8811
301 fn read_eof_twice_ip6() {
302 do run_in_newsched_task {
303 let addr = next_test_ip6();
306 let mut acceptor = TcpListener::bind(addr).listen();
307 let mut stream = acceptor.accept();
309 let nread = stream.read(buf);
310 assert!(nread.is_none());
311 let nread = stream.read(buf);
312 assert!(nread.is_none());
316 let _stream = TcpStream::connect(addr);
323 #[ignore(cfg(windows))] // FIXME #8811
324 fn write_close_ip4() {
325 do run_in_newsched_task {
326 let addr = next_test_ip4();
329 let mut acceptor = TcpListener::bind(addr).listen();
330 let mut stream = acceptor.accept();
333 let mut stop = false;
334 do io_error::cond.trap(|e| {
335 // NB: ECONNRESET on linux, EPIPE on mac
336 assert!(e.kind == ConnectionReset || e.kind == BrokenPipe);
346 let _stream = TcpStream::connect(addr);
353 #[ignore(cfg(windows))] // FIXME #8811
354 fn write_close_ip6() {
355 do run_in_newsched_task {
356 let addr = next_test_ip6();
359 let mut acceptor = TcpListener::bind(addr).listen();
360 let mut stream = acceptor.accept();
363 let mut stop = false;
364 do io_error::cond.trap(|e| {
365 // NB: ECONNRESET on linux, EPIPE on mac
366 assert!(e.kind == ConnectionReset || e.kind == BrokenPipe);
376 let _stream = TcpStream::connect(addr);
383 fn multiple_connect_serial_ip4() {
384 do run_in_newsched_task {
385 let addr = next_test_ip4();
389 let mut acceptor = TcpListener::bind(addr).listen();
390 for ref mut stream in acceptor.incoming().take(max) {
393 assert_eq!(buf[0], 99);
399 let mut stream = TcpStream::connect(addr);
407 fn multiple_connect_serial_ip6() {
408 do run_in_newsched_task {
409 let addr = next_test_ip6();
413 let mut acceptor = TcpListener::bind(addr).listen();
414 for ref mut stream in acceptor.incoming().take(max) {
417 assert_eq!(buf[0], 99);
423 let mut stream = TcpStream::connect(addr);
431 fn multiple_connect_interleaved_greedy_schedule_ip4() {
432 do run_in_newsched_task {
433 let addr = next_test_ip4();
434 static MAX: int = 10;
437 let mut acceptor = TcpListener::bind(addr).listen();
438 for (i, stream) in acceptor.incoming().enumerate().take(MAX as uint) {
439 let stream = Cell::new(stream);
440 // Start another task to handle the connection
442 let mut stream = stream.take();
445 assert!(buf[0] == i as u8);
453 fn connect(i: int, addr: SocketAddr) {
454 if i == MAX { return }
457 rtdebug!("connecting");
458 let mut stream = TcpStream::connect(addr);
459 // Connect again before writing
460 connect(i + 1, addr);
462 stream.write([i as u8]);
469 fn multiple_connect_interleaved_greedy_schedule_ip6() {
470 do run_in_newsched_task {
471 let addr = next_test_ip6();
472 static MAX: int = 10;
475 let mut acceptor = TcpListener::bind(addr).listen();
476 for (i, stream) in acceptor.incoming().enumerate().take(MAX as uint) {
477 let stream = Cell::new(stream);
478 // Start another task to handle the connection
480 let mut stream = stream.take();
483 assert!(buf[0] == i as u8);
491 fn connect(i: int, addr: SocketAddr) {
492 if i == MAX { return }
495 rtdebug!("connecting");
496 let mut stream = TcpStream::connect(addr);
497 // Connect again before writing
498 connect(i + 1, addr);
500 stream.write([i as u8]);
507 fn multiple_connect_interleaved_lazy_schedule_ip4() {
508 do run_in_newsched_task {
509 let addr = next_test_ip4();
510 static MAX: int = 10;
513 let mut acceptor = TcpListener::bind(addr).listen();
514 for stream in acceptor.incoming().take(MAX as uint) {
515 let stream = Cell::new(stream);
516 // Start another task to handle the connection
518 let mut stream = stream.take();
521 assert!(buf[0] == 99);
529 fn connect(i: int, addr: SocketAddr) {
530 if i == MAX { return }
533 rtdebug!("connecting");
534 let mut stream = TcpStream::connect(addr);
535 // Connect again before writing
536 connect(i + 1, addr);
544 fn multiple_connect_interleaved_lazy_schedule_ip6() {
545 do run_in_newsched_task {
546 let addr = next_test_ip6();
547 static MAX: int = 10;
550 let mut acceptor = TcpListener::bind(addr).listen();
551 for stream in acceptor.incoming().take(MAX as uint) {
552 let stream = Cell::new(stream);
553 // Start another task to handle the connection
555 let mut stream = stream.take();
558 assert!(buf[0] == 99);
566 fn connect(i: int, addr: SocketAddr) {
567 if i == MAX { return }
570 rtdebug!("connecting");
571 let mut stream = TcpStream::connect(addr);
572 // Connect again before writing
573 connect(i + 1, addr);
582 fn socket_name(addr: SocketAddr) {
583 do run_in_newsched_task {
585 let mut listener = TcpListener::bind(addr).unwrap();
587 // Make sure socket_name gives
588 // us the socket we binded to.
589 let so_name = listener.socket_name();
590 assert!(so_name.is_some());
591 assert_eq!(addr, so_name.unwrap());
598 fn peer_name(addr: SocketAddr) {
599 do run_in_newsched_task {
601 let mut acceptor = TcpListener::bind(addr).listen();
607 let stream = TcpStream::connect(addr);
609 assert!(stream.is_some());
610 let mut stream = stream.unwrap();
612 // Make sure peer_name gives us the
613 // address/port of the peer we've
615 let peer_name = stream.peer_name();
616 assert!(peer_name.is_some());
617 assert_eq!(addr, peer_name.unwrap());
623 fn socket_and_peer_name_ip4() {
624 peer_name(next_test_ip4());
625 socket_name(next_test_ip4());
629 fn socket_and_peer_name_ip6() {
630 // XXX: peer name is not consistent
631 //peer_name(next_test_ip6());
632 socket_name(next_test_ip6());