@@ -19,6 +19,7 @@ use io;
1919use net:: { ToSocketAddrs , SocketAddr , Shutdown } ;
2020use sys_common:: net as net_imp;
2121use sys_common:: { AsInner , FromInner } ;
22+ use time:: Duration ;
2223
2324/// A structure which represents a TCP stream between a local socket and a
2425/// remote socket.
@@ -139,6 +140,50 @@ impl TcpStream {
139140 pub fn set_keepalive ( & self , seconds : Option < u32 > ) -> io:: Result < ( ) > {
140141 self . 0 . set_keepalive ( seconds)
141142 }
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+ }
142187}
143188
144189#[ stable( feature = "rust1" , since = "1.0.0" ) ]
@@ -262,6 +307,7 @@ mod tests {
262307 use net:: test:: { next_test_ip4, next_test_ip6} ;
263308 use sync:: mpsc:: channel;
264309 use sys_common:: AsInner ;
310+ use time:: Duration ;
265311 use thread;
266312
267313 fn each_ip ( f : & mut FnMut ( SocketAddr ) ) {
@@ -855,4 +901,69 @@ mod tests {
855901 stream_inner) ;
856902 assert_eq ! ( format!( "{:?}" , stream) , compare) ;
857903 }
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+ }
858969}
0 commit comments