@@ -6,6 +6,7 @@ use crate::net::SocketAddrV4;
66use crate :: ptr:: NonNull ;
77use crate :: sync:: atomic:: { AtomicBool , Ordering } ;
88use crate :: sys:: pal:: helpers;
9+ use crate :: time:: { Duration , Instant } ;
910
1011const TYPE_OF_SERVICE : u8 = 8 ;
1112const TIME_TO_LIVE : u8 = 255 ;
@@ -66,7 +67,7 @@ impl Tcp4 {
6667 if r. is_error ( ) { Err ( crate :: io:: Error :: from_raw_os_error ( r. as_usize ( ) ) ) } else { Ok ( ( ) ) }
6768 }
6869
69- pub ( crate ) fn connect ( & self ) -> io:: Result < ( ) > {
70+ pub ( crate ) fn connect ( & self , timeout : Option < Duration > ) -> io:: Result < ( ) > {
7071 let evt = unsafe { self . create_evt ( ) } ?;
7172 let completion_token =
7273 tcp4:: CompletionToken { event : evt. as_ptr ( ) , status : Status :: SUCCESS } ;
@@ -79,7 +80,7 @@ impl Tcp4 {
7980 return Err ( io:: Error :: from_raw_os_error ( r. as_usize ( ) ) ) ;
8081 }
8182
82- self . wait_for_flag ( ) ;
83+ unsafe { self . wait_or_cancel ( timeout , & mut conn_token . completion_token ) } ? ;
8384
8485 if completion_token. status . is_error ( ) {
8586 Err ( io:: Error :: from_raw_os_error ( completion_token. status . as_usize ( ) ) )
@@ -88,7 +89,7 @@ impl Tcp4 {
8889 }
8990 }
9091
91- pub ( crate ) fn write ( & self , buf : & [ u8 ] ) -> io:: Result < usize > {
92+ pub ( crate ) fn write ( & self , buf : & [ u8 ] , timeout : Option < Duration > ) -> io:: Result < usize > {
9293 let evt = unsafe { self . create_evt ( ) } ?;
9394 let completion_token =
9495 tcp4:: CompletionToken { event : evt. as_ptr ( ) , status : Status :: SUCCESS } ;
@@ -119,7 +120,7 @@ impl Tcp4 {
119120 return Err ( io:: Error :: from_raw_os_error ( r. as_usize ( ) ) ) ;
120121 }
121122
122- self . wait_for_flag ( ) ;
123+ unsafe { self . wait_or_cancel ( timeout , & mut token . completion_token ) } ? ;
123124
124125 if completion_token. status . is_error ( ) {
125126 Err ( io:: Error :: from_raw_os_error ( completion_token. status . as_usize ( ) ) )
@@ -128,7 +129,7 @@ impl Tcp4 {
128129 }
129130 }
130131
131- pub ( crate ) fn read ( & self , buf : & mut [ u8 ] ) -> io:: Result < usize > {
132+ pub ( crate ) fn read ( & self , buf : & mut [ u8 ] , timeout : Option < Duration > ) -> io:: Result < usize > {
132133 let evt = unsafe { self . create_evt ( ) } ?;
133134 let completion_token =
134135 tcp4:: CompletionToken { event : evt. as_ptr ( ) , status : Status :: SUCCESS } ;
@@ -158,7 +159,7 @@ impl Tcp4 {
158159 return Err ( io:: Error :: from_raw_os_error ( r. as_usize ( ) ) ) ;
159160 }
160161
161- self . wait_for_flag ( ) ;
162+ unsafe { self . wait_or_cancel ( timeout , & mut token . completion_token ) } ? ;
162163
163164 if completion_token. status . is_error ( ) {
164165 Err ( io:: Error :: from_raw_os_error ( completion_token. status . as_usize ( ) ) )
@@ -167,6 +168,46 @@ impl Tcp4 {
167168 }
168169 }
169170
171+ /// Wait for an event to finish. This is checked by an atomic boolean that is supposed to be set
172+ /// to true in the event callback.
173+ ///
174+ /// Optionally, allow specifying a timeout.
175+ ///
176+ /// If a timeout is provided, the operation (specified by its `EFI_TCP4_COMPLETION_TOKEN`) is
177+ /// canceled and Error of kind TimedOut is returned.
178+ ///
179+ /// # SAFETY
180+ ///
181+ /// Pointer to a valid `EFI_TCP4_COMPLETION_TOKEN`
182+ unsafe fn wait_or_cancel (
183+ & self ,
184+ timeout : Option < Duration > ,
185+ token : * mut tcp4:: CompletionToken ,
186+ ) -> io:: Result < ( ) > {
187+ if !self . wait_for_flag ( timeout) {
188+ let _ = unsafe { self . cancel ( token) } ;
189+ return Err ( io:: Error :: new ( io:: ErrorKind :: TimedOut , "Operation Timed out" ) ) ;
190+ }
191+
192+ Ok ( ( ) )
193+ }
194+
195+ /// Abort an asynchronous connection, listen, transmission or receive request.
196+ ///
197+ /// # SAFETY
198+ ///
199+ /// Pointer to a valid `EFI_TCP4_COMPLETION_TOKEN`
200+ unsafe fn cancel ( & self , token : * mut tcp4:: CompletionToken ) -> io:: Result < ( ) > {
201+ let protocol = self . protocol . as_ptr ( ) ;
202+
203+ let r = unsafe { ( ( * protocol) . cancel ) ( protocol, token) } ;
204+ if r. is_error ( ) {
205+ return Err ( io:: Error :: from_raw_os_error ( r. as_usize ( ) ) ) ;
206+ } else {
207+ Ok ( ( ) )
208+ }
209+ }
210+
170211 unsafe fn create_evt ( & self ) -> io:: Result < helpers:: OwnedEvent > {
171212 self . flag . store ( false , Ordering :: Relaxed ) ;
172213 helpers:: OwnedEvent :: new (
@@ -177,10 +218,19 @@ impl Tcp4 {
177218 )
178219 }
179220
180- fn wait_for_flag ( & self ) {
221+ fn wait_for_flag ( & self , timeout : Option < Duration > ) -> bool {
222+ let start = Instant :: now ( ) ;
223+
181224 while !self . flag . load ( Ordering :: Relaxed ) {
182225 let _ = self . poll ( ) ;
226+ if let Some ( t) = timeout {
227+ if Instant :: now ( ) . duration_since ( start) >= t {
228+ return false ;
229+ }
230+ }
183231 }
232+
233+ true
184234 }
185235
186236 fn poll ( & self ) -> io:: Result < ( ) > {
0 commit comments