@@ -19,6 +19,7 @@ use io;
19
19
use net:: { ToSocketAddrs , SocketAddr , Shutdown } ;
20
20
use sys_common:: net as net_imp;
21
21
use sys_common:: { AsInner , FromInner } ;
22
+ use time:: Duration ;
22
23
23
24
/// A structure which represents a TCP stream between a local socket and a
24
25
/// remote socket.
@@ -139,6 +140,50 @@ impl TcpStream {
139
140
pub fn set_keepalive ( & self , seconds : Option < u32 > ) -> io:: Result < ( ) > {
140
141
self . 0 . set_keepalive ( seconds)
141
142
}
143
+
144
+ /// Sets the read timeout to the timeout specified.
145
+ ///
146
+ /// If the value specified is `None`, then `read` calls will block
147
+ /// indefinitely. It is an error to pass the zero `Duration` to this
148
+ /// method.
149
+ #[ unstable( feature = "socket_timeout" , reason = "RFC 1047 - recently added" ) ]
150
+ pub fn set_read_timeout ( & self , dur : Option < Duration > ) -> io:: Result < ( ) > {
151
+ self . 0 . set_read_timeout ( dur)
152
+ }
153
+
154
+ /// Sets the write timeout to the timeout specified.
155
+ ///
156
+ /// If the value specified is `None`, then `write` calls will block
157
+ /// indefinitely. It is an error to pass the zero `Duration` to this
158
+ /// method.
159
+ #[ unstable( feature = "socket_timeout" , reason = "RFC 1047 - recently added" ) ]
160
+ pub fn set_write_timeout ( & self , dur : Option < Duration > ) -> io:: Result < ( ) > {
161
+ self . 0 . set_write_timeout ( dur)
162
+ }
163
+
164
+ /// Returns the read timeout of this socket.
165
+ ///
166
+ /// If the timeout is `None`, then `read` calls will block indefinitely.
167
+ ///
168
+ /// # Note
169
+ ///
170
+ /// Some platforms do not provide access to the current timeout.
171
+ #[ unstable( feature = "socket_timeout" , reason = "RFC 1047 - recently added" ) ]
172
+ pub fn read_timeout ( & self ) -> io:: Result < Option < Duration > > {
173
+ self . 0 . read_timeout ( )
174
+ }
175
+
176
+ /// Returns the write timeout of this socket.
177
+ ///
178
+ /// If the timeout is `None`, then `write` calls will block indefinitely.
179
+ ///
180
+ /// # Note
181
+ ///
182
+ /// Some platforms do not provide access to the current timeout.
183
+ #[ unstable( feature = "socket_timeout" , reason = "RFC 1047 - recently added" ) ]
184
+ pub fn write_timeout ( & self ) -> io:: Result < Option < Duration > > {
185
+ self . 0 . write_timeout ( )
186
+ }
142
187
}
143
188
144
189
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
@@ -262,6 +307,7 @@ mod tests {
262
307
use net:: test:: { next_test_ip4, next_test_ip6} ;
263
308
use sync:: mpsc:: channel;
264
309
use sys_common:: AsInner ;
310
+ use time:: Duration ;
265
311
use thread;
266
312
267
313
fn each_ip ( f : & mut FnMut ( SocketAddr ) ) {
@@ -855,4 +901,69 @@ mod tests {
855
901
stream_inner) ;
856
902
assert_eq ! ( format!( "{:?}" , stream) , compare) ;
857
903
}
904
+
905
+ #[ test]
906
+ fn timeouts ( ) {
907
+ let addr = next_test_ip4 ( ) ;
908
+ let listener = t ! ( TcpListener :: bind( & addr) ) ;
909
+
910
+ let stream = t ! ( TcpStream :: connect( & ( "localhost" , addr. port( ) ) ) ) ;
911
+ let dur = Duration :: new ( 15410 , 0 ) ;
912
+
913
+ assert_eq ! ( None , t!( stream. read_timeout( ) ) ) ;
914
+
915
+ t ! ( stream. set_read_timeout( Some ( dur) ) ) ;
916
+ assert_eq ! ( Some ( dur) , t!( stream. read_timeout( ) ) ) ;
917
+
918
+ assert_eq ! ( None , t!( stream. write_timeout( ) ) ) ;
919
+
920
+ t ! ( stream. set_write_timeout( Some ( dur) ) ) ;
921
+ assert_eq ! ( Some ( dur) , t!( stream. write_timeout( ) ) ) ;
922
+
923
+ t ! ( stream. set_read_timeout( None ) ) ;
924
+ assert_eq ! ( None , t!( stream. read_timeout( ) ) ) ;
925
+
926
+ t ! ( stream. set_write_timeout( None ) ) ;
927
+ assert_eq ! ( None , t!( stream. write_timeout( ) ) ) ;
928
+ }
929
+
930
+ #[ test]
931
+ fn test_read_timeout ( ) {
932
+ let addr = next_test_ip4 ( ) ;
933
+ let listener = t ! ( TcpListener :: bind( & addr) ) ;
934
+
935
+ let mut stream = t ! ( TcpStream :: connect( & ( "localhost" , addr. port( ) ) ) ) ;
936
+ t ! ( stream. set_read_timeout( Some ( Duration :: from_millis( 1000 ) ) ) ) ;
937
+
938
+ let mut buf = [ 0 ; 10 ] ;
939
+ let wait = Duration :: span ( || {
940
+ let kind = stream. read ( & mut buf) . err ( ) . expect ( "expected error" ) . kind ( ) ;
941
+ assert ! ( kind == ErrorKind :: WouldBlock || kind == ErrorKind :: TimedOut ) ;
942
+ } ) ;
943
+ assert ! ( wait > Duration :: from_millis( 400 ) ) ;
944
+ assert ! ( wait < Duration :: from_millis( 1600 ) ) ;
945
+ }
946
+
947
+ #[ test]
948
+ fn test_read_with_timeout ( ) {
949
+ let addr = next_test_ip4 ( ) ;
950
+ let listener = t ! ( TcpListener :: bind( & addr) ) ;
951
+
952
+ let mut stream = t ! ( TcpStream :: connect( & ( "localhost" , addr. port( ) ) ) ) ;
953
+ t ! ( stream. set_read_timeout( Some ( Duration :: from_millis( 1000 ) ) ) ) ;
954
+
955
+ let mut other_end = t ! ( listener. accept( ) ) . 0 ;
956
+ t ! ( other_end. write_all( b"hello world" ) ) ;
957
+
958
+ let mut buf = [ 0 ; 11 ] ;
959
+ t ! ( stream. read( & mut buf) ) ;
960
+ assert_eq ! ( b"hello world" , & buf[ ..] ) ;
961
+
962
+ let wait = Duration :: span ( || {
963
+ let kind = stream. read ( & mut buf) . err ( ) . expect ( "expected error" ) . kind ( ) ;
964
+ assert ! ( kind == ErrorKind :: WouldBlock || kind == ErrorKind :: TimedOut ) ;
965
+ } ) ;
966
+ assert ! ( wait > Duration :: from_millis( 400 ) ) ;
967
+ assert ! ( wait < Duration :: from_millis( 1600 ) ) ;
968
+ }
858
969
}
0 commit comments