@@ -3,7 +3,7 @@ use r_efi::protocols::tcp4;
33
44use crate :: io;
55use crate :: net:: SocketAddrV4 ;
6- use crate :: ptr:: NonNull ;
6+ use crate :: ptr:: { self , NonNull } ;
77use crate :: sync:: atomic:: { AtomicBool , Ordering } ;
88use crate :: sys:: pal:: helpers;
99use crate :: time:: { Duration , Instant } ;
@@ -12,20 +12,21 @@ const TYPE_OF_SERVICE: u8 = 8;
1212const TIME_TO_LIVE : u8 = 255 ;
1313
1414pub ( crate ) struct Tcp4 {
15+ handle : NonNull < crate :: ffi:: c_void > ,
1516 protocol : NonNull < tcp4:: Protocol > ,
1617 flag : AtomicBool ,
17- #[ expect( dead_code) ]
1818 service_binding : helpers:: ServiceProtocol ,
1919}
2020
2121const DEFAULT_ADDR : efi:: Ipv4Address = efi:: Ipv4Address { addr : [ 0u8 ; 4 ] } ;
2222
2323impl Tcp4 {
2424 pub ( crate ) fn new ( ) -> io:: Result < Self > {
25- let service_binding = helpers:: ServiceProtocol :: open ( tcp4:: SERVICE_BINDING_PROTOCOL_GUID ) ?;
26- let protocol = helpers:: open_protocol ( service_binding. child_handle ( ) , tcp4:: PROTOCOL_GUID ) ?;
25+ let ( service_binding, handle) =
26+ helpers:: ServiceProtocol :: open ( tcp4:: SERVICE_BINDING_PROTOCOL_GUID ) ?;
27+ let protocol = helpers:: open_protocol ( handle, tcp4:: PROTOCOL_GUID ) ?;
2728
28- Ok ( Self { service_binding, protocol, flag : AtomicBool :: new ( false ) } )
29+ Ok ( Self { service_binding, handle , protocol, flag : AtomicBool :: new ( false ) } )
2930 }
3031
3132 pub ( crate ) fn configure (
@@ -42,11 +43,14 @@ impl Tcp4 {
4243 ( DEFAULT_ADDR , 0 )
4344 } ;
4445
45- // FIXME: Remove when passive connections with proper subnet handling are added
46- assert ! ( station_address. is_none( ) ) ;
47- let use_default_address = efi:: Boolean :: TRUE ;
48- let ( station_address, station_port) = ( DEFAULT_ADDR , 0 ) ;
49- let subnet_mask = helpers:: ipv4_to_r_efi ( crate :: net:: Ipv4Addr :: new ( 0 , 0 , 0 , 0 ) ) ;
46+ let use_default_address: r_efi:: efi:: Boolean = station_address. is_none ( ) . into ( ) ;
47+ let ( station_address, station_port) = if let Some ( x) = station_address {
48+ ( helpers:: ipv4_to_r_efi ( * x. ip ( ) ) , x. port ( ) )
49+ } else {
50+ ( DEFAULT_ADDR , 0 )
51+ } ;
52+ let subnet_mask = crate :: net:: Ipv4Addr :: new ( 255 , 255 , 255 , 0 ) ;
53+ let subnet_mask = helpers:: ipv4_to_r_efi ( subnet_mask) ;
5054
5155 let mut config_data = tcp4:: ConfigData {
5256 type_of_service : TYPE_OF_SERVICE ,
@@ -60,7 +64,7 @@ impl Tcp4 {
6064 station_port,
6165 subnet_mask,
6266 } ,
63- control_option : crate :: ptr:: null_mut ( ) ,
67+ control_option : ptr:: null_mut ( ) ,
6468 } ;
6569
6670 let r = unsafe { ( ( * protocol) . configure ) ( protocol, & mut config_data) } ;
@@ -74,17 +78,49 @@ impl Tcp4 {
7478 let r = unsafe {
7579 ( ( * protocol) . get_mode_data ) (
7680 protocol,
77- crate :: ptr:: null_mut ( ) ,
81+ ptr:: null_mut ( ) ,
7882 & mut config_data,
79- crate :: ptr:: null_mut ( ) ,
80- crate :: ptr:: null_mut ( ) ,
81- crate :: ptr:: null_mut ( ) ,
83+ ptr:: null_mut ( ) ,
84+ ptr:: null_mut ( ) ,
85+ ptr:: null_mut ( ) ,
8286 )
8387 } ;
8488
8589 if r. is_error ( ) { Err ( io:: Error :: from_raw_os_error ( r. as_usize ( ) ) ) } else { Ok ( config_data) }
8690 }
8791
92+ pub ( crate ) fn accept ( & self ) -> io:: Result < Self > {
93+ let evt = unsafe { self . create_evt ( ) } ?;
94+ let completion_token =
95+ tcp4:: CompletionToken { event : evt. as_ptr ( ) , status : Status :: SUCCESS } ;
96+ let mut listen_token =
97+ tcp4:: ListenToken { completion_token, new_child_handle : ptr:: null_mut ( ) } ;
98+
99+ let protocol = self . protocol . as_ptr ( ) ;
100+ let r = unsafe { ( ( * protocol) . accept ) ( protocol, & mut listen_token) } ;
101+ if r. is_error ( ) {
102+ return Err ( io:: Error :: from_raw_os_error ( r. as_usize ( ) ) ) ;
103+ }
104+
105+ unsafe { self . wait_or_cancel ( None , & mut listen_token. completion_token ) } ?;
106+
107+ if completion_token. status . is_error ( ) {
108+ Err ( io:: Error :: from_raw_os_error ( completion_token. status . as_usize ( ) ) )
109+ } else {
110+ let handle = NonNull :: new ( listen_token. new_child_handle ) . unwrap ( ) ;
111+ let protocol = helpers:: open_protocol ( handle, tcp4:: PROTOCOL_GUID ) ?;
112+
113+ // The spec does not seem to state if we need to call ServiceBinding->DestroyChild for
114+ // this handle
115+ Ok ( Self {
116+ handle,
117+ service_binding : self . service_binding ,
118+ protocol,
119+ flag : AtomicBool :: new ( false ) ,
120+ } )
121+ }
122+ }
123+
88124 pub ( crate ) fn connect ( & self , timeout : Option < Duration > ) -> io:: Result < ( ) > {
89125 let evt = unsafe { self . create_evt ( ) } ?;
90126 let completion_token =
@@ -263,6 +299,12 @@ impl Tcp4 {
263299 }
264300}
265301
302+ impl Drop for Tcp4 {
303+ fn drop ( & mut self ) {
304+ let _ = self . service_binding . destroy_child ( self . handle ) ;
305+ }
306+ }
307+
266308extern "efiapi" fn toggle_atomic_flag ( _: r_efi:: efi:: Event , ctx : * mut crate :: ffi:: c_void ) {
267309 let flag = unsafe { AtomicBool :: from_ptr ( ctx. cast ( ) ) } ;
268310 flag. store ( true , Ordering :: Relaxed ) ;
0 commit comments