@@ -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,50 @@ 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+ /// If token is NULL, then all pending tokens issued by EFI_TCP4_PROTOCOL.Connect(),
198+ /// EFI_TCP4_PROTOCOL.Accept(), EFI_TCP4_PROTOCOL.Transmit() or EFI_TCP4_PROTOCOL.Receive() are
199+ /// aborted.
200+ ///
201+ /// # SAFETY
202+ ///
203+ /// Pointer to a valid `EFI_TCP4_COMPLETION_TOKEN` or NULL
204+ unsafe fn cancel ( & self , token : * mut tcp4:: CompletionToken ) -> io:: Result < ( ) > {
205+ let protocol = self . protocol . as_ptr ( ) ;
206+
207+ let r = unsafe { ( ( * protocol) . cancel ) ( protocol, token) } ;
208+ if r. is_error ( ) {
209+ return Err ( io:: Error :: from_raw_os_error ( r. as_usize ( ) ) ) ;
210+ } else {
211+ Ok ( ( ) )
212+ }
213+ }
214+
170215 unsafe fn create_evt ( & self ) -> io:: Result < helpers:: OwnedEvent > {
171216 self . flag . store ( false , Ordering :: Relaxed ) ;
172217 helpers:: OwnedEvent :: new (
@@ -177,10 +222,19 @@ impl Tcp4 {
177222 )
178223 }
179224
180- fn wait_for_flag ( & self ) {
225+ fn wait_for_flag ( & self , timeout : Option < Duration > ) -> bool {
226+ let start = Instant :: now ( ) ;
227+
181228 while !self . flag . load ( Ordering :: Relaxed ) {
182229 let _ = self . poll ( ) ;
230+ if let Some ( t) = timeout {
231+ if Instant :: now ( ) . duration_since ( start) >= t {
232+ return false ;
233+ }
234+ }
183235 }
236+
237+ true
184238 }
185239
186240 fn poll ( & self ) -> io:: Result < ( ) > {
0 commit comments