@@ -44,6 +44,7 @@ pub use self::process::Process;
4444// Native I/O implementations
4545pub mod file;
4646pub mod process;
47+ pub mod net;
4748
4849type IoResult < T > = Result < T , IoError > ;
4950
@@ -55,12 +56,25 @@ fn unimpl() -> IoError {
5556 }
5657}
5758
58- fn last_error ( ) -> IoError {
59+ fn translate_error ( errno : i32 , detail : bool ) -> IoError {
5960 #[ cfg( windows) ]
6061 fn get_err ( errno : i32 ) -> ( io:: IoErrorKind , & ' static str ) {
6162 match errno {
6263 libc:: EOF => ( io:: EndOfFile , "end of file" ) ,
63- _ => ( io:: OtherIoError , "unknown error" ) ,
64+ libc:: WSAECONNREFUSED => ( io:: ConnectionRefused , "connection refused" ) ,
65+ libc:: WSAECONNRESET => ( io:: ConnectionReset , "connection reset" ) ,
66+ libc:: WSAEACCES => ( io:: PermissionDenied , "permission denied" ) ,
67+ libc:: WSAEWOULDBLOCK =>
68+ ( io:: ResourceUnavailable , "resource temporarily unavailable" ) ,
69+ libc:: WSAENOTCONN => ( io:: NotConnected , "not connected" ) ,
70+ libc:: WSAECONNABORTED => ( io:: ConnectionAborted , "connection aborted" ) ,
71+ libc:: WSAEADDRNOTAVAIL => ( io:: ConnectionRefused , "address not available" ) ,
72+ libc:: WSAEADDRINUSE => ( io:: ConnectionRefused , "address in use" ) ,
73+
74+ x => {
75+ debug ! ( "ignoring {}: {}" , x, os:: last_os_error( ) ) ;
76+ ( io:: OtherIoError , "unknown error" )
77+ }
6478 }
6579 }
6680
@@ -69,24 +83,38 @@ fn last_error() -> IoError {
6983 // XXX: this should probably be a bit more descriptive...
7084 match errno {
7185 libc:: EOF => ( io:: EndOfFile , "end of file" ) ,
86+ libc:: ECONNREFUSED => ( io:: ConnectionRefused , "connection refused" ) ,
87+ libc:: ECONNRESET => ( io:: ConnectionReset , "connection reset" ) ,
88+ libc:: EPERM | libc:: EACCES =>
89+ ( io:: PermissionDenied , "permission denied" ) ,
90+ libc:: EPIPE => ( io:: BrokenPipe , "broken pipe" ) ,
91+ libc:: ENOTCONN => ( io:: NotConnected , "not connected" ) ,
92+ libc:: ECONNABORTED => ( io:: ConnectionAborted , "connection aborted" ) ,
93+ libc:: EADDRNOTAVAIL => ( io:: ConnectionRefused , "address not available" ) ,
94+ libc:: EADDRINUSE => ( io:: ConnectionRefused , "address in use" ) ,
7295
7396 // These two constants can have the same value on some systems, but
7497 // different values on others, so we can't use a match clause
7598 x if x == libc:: EAGAIN || x == libc:: EWOULDBLOCK =>
7699 ( io:: ResourceUnavailable , "resource temporarily unavailable" ) ,
77100
78- _ => ( io:: OtherIoError , "unknown error" ) ,
101+ x => {
102+ debug ! ( "ignoring {}: {}" , x, os:: last_os_error( ) ) ;
103+ ( io:: OtherIoError , "unknown error" )
104+ }
79105 }
80106 }
81107
82- let ( kind, desc) = get_err ( os :: errno ( ) as i32 ) ;
108+ let ( kind, desc) = get_err ( errno) ;
83109 IoError {
84110 kind : kind,
85111 desc : desc,
86- detail : Some ( os:: last_os_error ( ) )
112+ detail : if detail { Some ( os:: last_os_error ( ) ) } else { None } ,
87113 }
88114}
89115
116+ fn last_error ( ) -> IoError { translate_error ( os:: errno ( ) as i32 , true ) }
117+
90118// unix has nonzero values as errors
91119fn mkerr_libc ( ret : libc:: c_int ) -> IoResult < ( ) > {
92120 if ret != 0 {
@@ -106,17 +134,37 @@ fn mkerr_winbool(ret: libc::c_int) -> IoResult<()> {
106134 }
107135}
108136
137+ #[ cfg( unix) ]
138+ fn retry ( f: || -> libc:: c_int) -> IoResult < libc:: c_int > {
139+ loop {
140+ match f ( ) {
141+ -1 if os:: errno ( ) as int == libc:: EINTR as int => { }
142+ -1 => return Err ( last_error ( ) ) ,
143+ n => return Ok ( n) ,
144+ }
145+ }
146+ }
147+
109148/// Implementation of rt::rtio's IoFactory trait to generate handles to the
110149/// native I/O functionality.
111- pub struct IoFactory ;
150+ pub struct IoFactory {
151+ priv cannot_construct_outside_of_this_module : ( )
152+ }
153+
154+ impl IoFactory {
155+ pub fn new ( ) -> IoFactory {
156+ net:: init ( ) ;
157+ IoFactory { cannot_construct_outside_of_this_module : ( ) }
158+ }
159+ }
112160
113161impl rtio:: IoFactory for IoFactory {
114162 // networking
115- fn tcp_connect ( & mut self , _addr : SocketAddr ) -> IoResult < ~RtioTcpStream > {
116- Err ( unimpl ( ) )
163+ fn tcp_connect ( & mut self , addr : SocketAddr ) -> IoResult < ~RtioTcpStream > {
164+ net :: TcpStream :: connect ( addr ) . map ( |s| ~s as ~ RtioTcpStream )
117165 }
118- fn tcp_bind ( & mut self , _addr : SocketAddr ) -> IoResult < ~RtioTcpListener > {
119- Err ( unimpl ( ) )
166+ fn tcp_bind ( & mut self , addr : SocketAddr ) -> IoResult < ~RtioTcpListener > {
167+ net :: TcpListener :: bind ( addr ) . map ( |s| ~s as ~ RtioTcpListener )
120168 }
121169 fn udp_bind ( & mut self , _addr : SocketAddr ) -> IoResult < ~RtioUdpSocket > {
122170 Err ( unimpl ( ) )
@@ -204,9 +252,7 @@ impl rtio::IoFactory for IoFactory {
204252 }
205253 fn tty_open ( & mut self , fd : c_int , _readable : bool ) -> IoResult < ~RtioTTY > {
206254 if unsafe { libc:: isatty ( fd) } != 0 {
207- // Don't ever close the stdio file descriptors, nothing good really
208- // comes of that.
209- Ok ( ~file:: FileDesc :: new ( fd, fd > libc:: STDERR_FILENO ) as ~RtioTTY )
255+ Ok ( ~file:: FileDesc :: new ( fd, true ) as ~RtioTTY )
210256 } else {
211257 Err ( IoError {
212258 kind : io:: MismatchedFileTypeForOperation ,
0 commit comments