@@ -15,7 +15,7 @@ pub(crate) struct Tcp4 {
15
15
protocol : NonNull < tcp4:: Protocol > ,
16
16
flag : AtomicBool ,
17
17
#[ expect( dead_code) ]
18
- service_binding : helpers:: ServiceProtocol ,
18
+ service_binding : Option < helpers:: ServiceProtocol > ,
19
19
}
20
20
21
21
const DEFAULT_ADDR : efi:: Ipv4Address = efi:: Ipv4Address { addr : [ 0u8 ; 4 ] } ;
@@ -25,7 +25,7 @@ impl Tcp4 {
25
25
let service_binding = helpers:: ServiceProtocol :: open ( tcp4:: SERVICE_BINDING_PROTOCOL_GUID ) ?;
26
26
let protocol = helpers:: open_protocol ( service_binding. child_handle ( ) , tcp4:: PROTOCOL_GUID ) ?;
27
27
28
- Ok ( Self { service_binding, protocol, flag : AtomicBool :: new ( false ) } )
28
+ Ok ( Self { service_binding : Some ( service_binding ) , protocol, flag : AtomicBool :: new ( false ) } )
29
29
}
30
30
31
31
pub ( crate ) fn configure (
@@ -42,11 +42,14 @@ impl Tcp4 {
42
42
( DEFAULT_ADDR , 0 )
43
43
} ;
44
44
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 ) ) ;
45
+ let use_default_address: r_efi:: efi:: Boolean = station_address. is_none ( ) . into ( ) ;
46
+ let ( station_address, station_port) = if let Some ( x) = station_address {
47
+ ( helpers:: ipv4_to_r_efi ( * x. ip ( ) ) , x. port ( ) )
48
+ } else {
49
+ ( DEFAULT_ADDR , 0 )
50
+ } ;
51
+ let subnet_mask = crate :: net:: Ipv4Addr :: new ( 255 , 255 , 255 , 0 ) ;
52
+ let subnet_mask = helpers:: ipv4_to_r_efi ( subnet_mask) ;
50
53
51
54
let mut config_data = tcp4:: ConfigData {
52
55
type_of_service : TYPE_OF_SERVICE ,
@@ -85,6 +88,33 @@ impl Tcp4 {
85
88
if r. is_error ( ) { Err ( io:: Error :: from_raw_os_error ( r. as_usize ( ) ) ) } else { Ok ( config_data) }
86
89
}
87
90
91
+ pub ( crate ) fn accept ( & self ) -> io:: Result < Self > {
92
+ let evt = unsafe { self . create_evt ( ) } ?;
93
+ let completion_token =
94
+ tcp4:: CompletionToken { event : evt. as_ptr ( ) , status : Status :: SUCCESS } ;
95
+ let mut listen_token =
96
+ tcp4:: ListenToken { completion_token, new_child_handle : crate :: ptr:: null_mut ( ) } ;
97
+
98
+ let protocol = self . protocol . as_ptr ( ) ;
99
+ let r = unsafe { ( ( * protocol) . accept ) ( protocol, & mut listen_token) } ;
100
+ if r. is_error ( ) {
101
+ return Err ( io:: Error :: from_raw_os_error ( r. as_usize ( ) ) ) ;
102
+ }
103
+
104
+ unsafe { self . wait_or_cancel ( None , & mut listen_token. completion_token ) } ?;
105
+
106
+ if completion_token. status . is_error ( ) {
107
+ Err ( io:: Error :: from_raw_os_error ( completion_token. status . as_usize ( ) ) )
108
+ } else {
109
+ let handle = NonNull :: new ( listen_token. new_child_handle ) . unwrap ( ) ;
110
+ let protocol = helpers:: open_protocol ( handle, tcp4:: PROTOCOL_GUID ) ?;
111
+
112
+ // The spec does not seem to state if we need to call ServiceBinding->DestroyChild for
113
+ // this handle
114
+ Ok ( Self { service_binding : None , protocol, flag : AtomicBool :: new ( false ) } )
115
+ }
116
+ }
117
+
88
118
pub ( crate ) fn connect ( & self , timeout : Option < Duration > ) -> io:: Result < ( ) > {
89
119
let evt = unsafe { self . create_evt ( ) } ?;
90
120
let completion_token =
0 commit comments