@@ -3,7 +3,7 @@ use r_efi::protocols::tcp4;
3
3
4
4
use crate :: io;
5
5
use crate :: net:: SocketAddrV4 ;
6
- use crate :: ptr:: NonNull ;
6
+ use crate :: ptr:: { self , NonNull } ;
7
7
use crate :: sync:: atomic:: { AtomicBool , Ordering } ;
8
8
use crate :: sys:: pal:: helpers;
9
9
use crate :: time:: { Duration , Instant } ;
@@ -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 ,
@@ -60,7 +63,7 @@ impl Tcp4 {
60
63
station_port,
61
64
subnet_mask,
62
65
} ,
63
- control_option : crate :: ptr:: null_mut ( ) ,
66
+ control_option : ptr:: null_mut ( ) ,
64
67
} ;
65
68
66
69
let r = unsafe { ( ( * protocol) . configure ) ( protocol, & mut config_data) } ;
@@ -74,17 +77,44 @@ impl Tcp4 {
74
77
let r = unsafe {
75
78
( ( * protocol) . get_mode_data ) (
76
79
protocol,
77
- crate :: ptr:: null_mut ( ) ,
80
+ ptr:: null_mut ( ) ,
78
81
& mut config_data,
79
- crate :: ptr:: null_mut ( ) ,
80
- crate :: ptr:: null_mut ( ) ,
81
- crate :: ptr:: null_mut ( ) ,
82
+ ptr:: null_mut ( ) ,
83
+ ptr:: null_mut ( ) ,
84
+ ptr:: null_mut ( ) ,
82
85
)
83
86
} ;
84
87
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 : 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