@@ -44,6 +44,7 @@ pub use self::process::Process;
44
44
// Native I/O implementations
45
45
pub mod file;
46
46
pub mod process;
47
+ pub mod net;
47
48
48
49
type IoResult < T > = Result < T , IoError > ;
49
50
@@ -55,12 +56,25 @@ fn unimpl() -> IoError {
55
56
}
56
57
}
57
58
58
- fn last_error ( ) -> IoError {
59
+ fn translate_error ( errno : i32 , detail : bool ) -> IoError {
59
60
#[ cfg( windows) ]
60
61
fn get_err ( errno : i32 ) -> ( io:: IoErrorKind , & ' static str ) {
61
62
match errno {
62
63
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
+ }
64
78
}
65
79
}
66
80
@@ -69,24 +83,38 @@ fn last_error() -> IoError {
69
83
// XXX: this should probably be a bit more descriptive...
70
84
match errno {
71
85
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" ) ,
72
95
73
96
// These two constants can have the same value on some systems, but
74
97
// different values on others, so we can't use a match clause
75
98
x if x == libc:: EAGAIN || x == libc:: EWOULDBLOCK =>
76
99
( io:: ResourceUnavailable , "resource temporarily unavailable" ) ,
77
100
78
- _ => ( io:: OtherIoError , "unknown error" ) ,
101
+ x => {
102
+ debug ! ( "ignoring {}: {}" , x, os:: last_os_error( ) ) ;
103
+ ( io:: OtherIoError , "unknown error" )
104
+ }
79
105
}
80
106
}
81
107
82
- let ( kind, desc) = get_err ( os :: errno ( ) as i32 ) ;
108
+ let ( kind, desc) = get_err ( errno) ;
83
109
IoError {
84
110
kind : kind,
85
111
desc : desc,
86
- detail : Some ( os:: last_os_error ( ) )
112
+ detail : if detail { Some ( os:: last_os_error ( ) ) } else { None } ,
87
113
}
88
114
}
89
115
116
+ fn last_error ( ) -> IoError { translate_error ( os:: errno ( ) as i32 , true ) }
117
+
90
118
// unix has nonzero values as errors
91
119
fn mkerr_libc ( ret : libc:: c_int ) -> IoResult < ( ) > {
92
120
if ret != 0 {
@@ -106,17 +134,37 @@ fn mkerr_winbool(ret: libc::c_int) -> IoResult<()> {
106
134
}
107
135
}
108
136
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
+
109
148
/// Implementation of rt::rtio's IoFactory trait to generate handles to the
110
149
/// 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
+ }
112
160
113
161
impl rtio:: IoFactory for IoFactory {
114
162
// 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 )
117
165
}
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 )
120
168
}
121
169
fn udp_bind ( & mut self , _addr : SocketAddr ) -> IoResult < ~RtioUdpSocket > {
122
170
Err ( unimpl ( ) )
@@ -204,9 +252,7 @@ impl rtio::IoFactory for IoFactory {
204
252
}
205
253
fn tty_open ( & mut self , fd : c_int , _readable : bool ) -> IoResult < ~RtioTTY > {
206
254
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 )
210
256
} else {
211
257
Err ( IoError {
212
258
kind : io:: MismatchedFileTypeForOperation ,
0 commit comments