@@ -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