@@ -6,6 +6,7 @@ use crate::net::SocketAddrV4;
6
6
use crate :: ptr:: NonNull ;
7
7
use crate :: sync:: atomic:: { AtomicBool , Ordering } ;
8
8
use crate :: sys:: pal:: helpers;
9
+ use crate :: time:: { Duration , Instant } ;
9
10
10
11
const TYPE_OF_SERVICE : u8 = 8 ;
11
12
const TIME_TO_LIVE : u8 = 255 ;
@@ -66,7 +67,7 @@ impl Tcp4 {
66
67
if r. is_error ( ) { Err ( crate :: io:: Error :: from_raw_os_error ( r. as_usize ( ) ) ) } else { Ok ( ( ) ) }
67
68
}
68
69
69
- pub ( crate ) fn connect ( & self ) -> io:: Result < ( ) > {
70
+ pub ( crate ) fn connect ( & self , timeout : Option < Duration > ) -> io:: Result < ( ) > {
70
71
let evt = unsafe { self . create_evt ( ) } ?;
71
72
let completion_token =
72
73
tcp4:: CompletionToken { event : evt. as_ptr ( ) , status : Status :: SUCCESS } ;
@@ -79,7 +80,7 @@ impl Tcp4 {
79
80
return Err ( io:: Error :: from_raw_os_error ( r. as_usize ( ) ) ) ;
80
81
}
81
82
82
- self . wait_for_flag ( ) ;
83
+ unsafe { self . wait_or_cancel ( timeout , & mut conn_token . completion_token ) } ? ;
83
84
84
85
if completion_token. status . is_error ( ) {
85
86
Err ( io:: Error :: from_raw_os_error ( completion_token. status . as_usize ( ) ) )
@@ -88,7 +89,7 @@ impl Tcp4 {
88
89
}
89
90
}
90
91
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 > {
92
93
let evt = unsafe { self . create_evt ( ) } ?;
93
94
let completion_token =
94
95
tcp4:: CompletionToken { event : evt. as_ptr ( ) , status : Status :: SUCCESS } ;
@@ -119,7 +120,7 @@ impl Tcp4 {
119
120
return Err ( io:: Error :: from_raw_os_error ( r. as_usize ( ) ) ) ;
120
121
}
121
122
122
- self . wait_for_flag ( ) ;
123
+ unsafe { self . wait_or_cancel ( timeout , & mut token . completion_token ) } ? ;
123
124
124
125
if completion_token. status . is_error ( ) {
125
126
Err ( io:: Error :: from_raw_os_error ( completion_token. status . as_usize ( ) ) )
@@ -128,7 +129,7 @@ impl Tcp4 {
128
129
}
129
130
}
130
131
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 > {
132
133
let evt = unsafe { self . create_evt ( ) } ?;
133
134
let completion_token =
134
135
tcp4:: CompletionToken { event : evt. as_ptr ( ) , status : Status :: SUCCESS } ;
@@ -158,7 +159,7 @@ impl Tcp4 {
158
159
return Err ( io:: Error :: from_raw_os_error ( r. as_usize ( ) ) ) ;
159
160
}
160
161
161
- self . wait_for_flag ( ) ;
162
+ unsafe { self . wait_or_cancel ( timeout , & mut token . completion_token ) } ? ;
162
163
163
164
if completion_token. status . is_error ( ) {
164
165
Err ( io:: Error :: from_raw_os_error ( completion_token. status . as_usize ( ) ) )
@@ -167,6 +168,46 @@ impl Tcp4 {
167
168
}
168
169
}
169
170
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
+
170
211
unsafe fn create_evt ( & self ) -> io:: Result < helpers:: OwnedEvent > {
171
212
self . flag . store ( false , Ordering :: Relaxed ) ;
172
213
helpers:: OwnedEvent :: new (
@@ -177,10 +218,19 @@ impl Tcp4 {
177
218
)
178
219
}
179
220
180
- fn wait_for_flag ( & self ) {
221
+ fn wait_for_flag ( & self , timeout : Option < Duration > ) -> bool {
222
+ let start = Instant :: now ( ) ;
223
+
181
224
while !self . flag . load ( Ordering :: Relaxed ) {
182
225
let _ = self . poll ( ) ;
226
+ if let Some ( t) = timeout {
227
+ if Instant :: now ( ) . duration_since ( start) >= t {
228
+ return false ;
229
+ }
230
+ }
183
231
}
232
+
233
+ true
184
234
}
185
235
186
236
fn poll ( & self ) -> io:: Result < ( ) > {
0 commit comments