@@ -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,55 @@ 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+             // EDK2 internals seem to assume a single ServiceBinding Protocol for TCP4 and TCP6, and 
111+             // thus does not use any service binding protocol data in destroying child sockets. It 
112+             // does seem to suggest that we need to cleanup even the protocols created by accept. To 
113+             // be on the safe side with other implementations, we will be using the same service 
114+             // binding protocol as the parent TCP4 handle. 
115+             // 
116+             // https://github.com/tianocore/edk2/blob/f80580f56b267c96f16f985dbf707b2f96947da4/NetworkPkg/TcpDxe/TcpDriver.c#L938 
117+ 
118+             let  handle = NonNull :: new ( listen_token. new_child_handle ) . unwrap ( ) ; 
119+             let  protocol = helpers:: open_protocol ( handle,  tcp4:: PROTOCOL_GUID ) ?; 
120+ 
121+             Ok ( Self  { 
122+                 handle, 
123+                 service_binding :  self . service_binding , 
124+                 protocol, 
125+                 flag :  AtomicBool :: new ( false ) , 
126+             } ) 
127+         } 
128+     } 
129+ 
88130    pub ( crate )  fn  connect ( & self ,  timeout :  Option < Duration > )  -> io:: Result < ( ) >  { 
89131        let  evt = unsafe  {  self . create_evt ( )  } ?; 
90132        let  completion_token =
@@ -263,6 +305,12 @@ impl Tcp4 {
263305    } 
264306} 
265307
308+ impl  Drop  for  Tcp4  { 
309+     fn  drop ( & mut  self )  { 
310+         let  _ = self . service_binding . destroy_child ( self . handle ) ; 
311+     } 
312+ } 
313+ 
266314extern  "efiapi"  fn  toggle_atomic_flag ( _:  r_efi:: efi:: Event ,  ctx :  * mut  crate :: ffi:: c_void )  { 
267315    let  flag = unsafe  {  AtomicBool :: from_ptr ( ctx. cast ( ) )  } ; 
268316    flag. store ( true ,  Ordering :: Relaxed ) ; 
0 commit comments