rust_rcs_core/ffi/
net_ctrl.rs1extern crate libc;
16
17use std::{
18 ffi::{c_void, CStr},
19 net::SocketAddr,
20 ptr::NonNull,
21};
22
23#[cfg(any(
24 all(feature = "android", target_os = "android"),
25 all(feature = "ohos", all(target_os = "linux", target_env = "ohos"))
26))]
27use libc::c_char;
28
29pub struct NetworkRequestCallbackWrapper {
30 callback: Option<Box<dyn FnOnce(bool) + Send + Sync + 'static>>,
31}
32
33#[cfg(any(
34 all(feature = "android", target_os = "android"),
35 all(feature = "ohos", all(target_os = "linux", target_env = "ohos"))
36))]
37extern "C" fn network_activation_callback(ptr: *mut c_void, activated: bool) {
38 let data = ptr as *mut NetworkRequestCallbackWrapper;
39
40 unsafe {
41 if let Some(wrapper) = data.as_mut() {
42 if let Some(callback) = wrapper.callback.take() {
43 callback(activated);
44 }
45 }
46 }
47}
48
49#[repr(C)]
50pub struct NetworkRequestCHandle {
51 _data: [u8; 0],
52 _marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>,
53}
54
55pub struct NetworkRequestCHandleWrapper(NonNull<NetworkRequestCHandle>);
56
57impl Drop for NetworkRequestCHandleWrapper {
58 fn drop(&mut self) {
59 #[cfg(any(
60 all(feature = "android", target_os = "android"),
61 all(feature = "ohos", all(target_os = "linux", target_env = "ohos"))
62 ))]
63 let c_handle = self.0.as_ptr();
64 #[cfg(any(
65 all(feature = "android", target_os = "android"),
66 all(feature = "ohos", all(target_os = "linux", target_env = "ohos"))
67 ))]
68 unsafe {
69 platform_drop_network_request(c_handle);
70 }
71 }
72}
73
74unsafe impl Send for NetworkRequestCHandleWrapper {}
75
76#[repr(C)]
77pub struct NetworkInfoCHandle {
78 _data: [u8; 0],
79 _marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>,
80}
81
82pub struct NetworkInfoCHandleWrapper(NonNull<NetworkInfoCHandle>);
83
84impl Drop for NetworkInfoCHandleWrapper {
85 fn drop(&mut self) {
86 #[cfg(any(
87 all(feature = "android", target_os = "android"),
88 all(feature = "ohos", all(target_os = "linux", target_env = "ohos"))
89 ))]
90 let c_handle = self.0.as_ptr();
91 #[cfg(any(
92 all(feature = "android", target_os = "android"),
93 all(feature = "ohos", all(target_os = "linux", target_env = "ohos"))
94 ))]
95 unsafe {
96 platform_drop_network_info(c_handle);
97 }
98 }
99}
100
101unsafe impl Send for NetworkInfoCHandleWrapper {}
102
103#[repr(C)]
104pub struct DnsInfoCHandle {
105 _data: [u8; 0],
106 _marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>,
107}
108
109pub struct DnsInfoCHandleWrapper(NonNull<DnsInfoCHandle>);
110
111impl Drop for DnsInfoCHandleWrapper {
112 fn drop(&mut self) {
113 #[cfg(any(
114 all(feature = "android", target_os = "android"),
115 all(feature = "ohos", all(target_os = "linux", target_env = "ohos"))
116 ))]
117 let c_handle = self.0.as_ptr();
118 #[cfg(any(
119 all(feature = "android", target_os = "android"),
120 all(feature = "ohos", all(target_os = "linux", target_env = "ohos"))
121 ))]
122 unsafe {
123 platform_drop_dns_info(c_handle);
124 }
125 }
126}
127
128unsafe impl Send for DnsInfoCHandleWrapper {}
129
130#[cfg(any(
131 all(feature = "android", target_os = "android"),
132 all(feature = "ohos", all(target_os = "linux", target_env = "ohos"))
133))]
134extern "C" {
135 fn platform_activate_cellular_network(
136 ptr: *mut c_void,
137 callback: Option<extern "C" fn(*mut c_void, bool)>,
138 ) -> *mut NetworkRequestCHandle;
139 fn platform_drop_network_request(c_handle: *mut NetworkRequestCHandle);
140 fn platform_get_active_network_info() -> *mut NetworkInfoCHandle;
141 fn platform_get_network_type(network_info: *mut NetworkInfoCHandle) -> i32;
142 fn platform_get_network_dns_info(network_info: *mut NetworkInfoCHandle) -> *mut DnsInfoCHandle;
143 fn platform_get_dns_server(dns_info: *mut DnsInfoCHandle) -> *const c_char;
144 fn platform_drop_dns_info(dns_info: *mut DnsInfoCHandle);
145 fn platform_drop_network_info(network_info: *mut NetworkInfoCHandle);
146}
147
148pub fn activate_cellular_network<T>(callback: T) -> Option<NetworkRequestCHandleWrapper>
149where
150 T: 'static + FnOnce(bool) + Send + Sync,
151{
152 let wrapper = NetworkRequestCallbackWrapper {
153 callback: Some(Box::new(callback)),
154 };
155
156 let data = Box::into_raw(Box::new(wrapper));
157 let ptr = data as *mut c_void;
158
159 #[cfg(any(
160 all(feature = "android", target_os = "android"),
161 all(feature = "ohos", all(target_os = "linux", target_env = "ohos"))
162 ))]
163 unsafe {
164 if let Some(c_handle) =
165 platform_activate_cellular_network(ptr, Some(network_activation_callback)).as_mut()
166 {
167 return Some(NetworkRequestCHandleWrapper(
168 NonNull::new(c_handle).unwrap(),
169 ));
170 }
171 }
172
173 None
174}
175
176pub fn get_active_network_info() -> Option<NetworkInfoCHandleWrapper> {
177 #[cfg(any(
178 all(feature = "android", target_os = "android"),
179 all(feature = "ohos", all(target_os = "linux", target_env = "ohos"))
180 ))]
181 unsafe {
182 if let Some(network_info) = platform_get_active_network_info().as_mut() {
183 return Some(NetworkInfoCHandleWrapper(
184 NonNull::new(network_info).unwrap(),
185 ));
186 }
187 }
188
189 None
190}
191
192pub fn get_network_type(network_info: &NetworkInfoCHandleWrapper) -> i32 {
193 let network_info_c_handle = network_info.0.as_ptr();
194 #[cfg(any(
195 all(feature = "android", target_os = "android"),
196 all(feature = "ohos", all(target_os = "linux", target_env = "ohos"))
197 ))]
198 unsafe {
199 return platform_get_network_type(network_info_c_handle);
200 }
201
202 0
203}
204
205pub fn get_dns_info(network_info: &NetworkInfoCHandleWrapper) -> Option<DnsInfoCHandleWrapper> {
206 let network_info_c_handle = network_info.0.as_ptr();
207
208 #[cfg(any(
209 all(feature = "android", target_os = "android"),
210 all(feature = "ohos", all(target_os = "linux", target_env = "ohos"))
211 ))]
212 unsafe {
213 if let Some(dns_info) = platform_get_network_dns_info(network_info_c_handle).as_mut() {
214 return Some(DnsInfoCHandleWrapper(NonNull::new(dns_info).unwrap()));
215 }
216 }
217
218 None
219}
220
221pub fn get_dns_servers(dns_info: &DnsInfoCHandleWrapper) -> Vec<SocketAddr> {
222 let dns_info_c_handle = dns_info.0.as_ptr();
223
224 let mut v = Vec::new();
225
226 #[cfg(any(
227 all(feature = "android", target_os = "android"),
228 all(feature = "ohos", all(target_os = "linux", target_env = "ohos"))
229 ))]
230 unsafe {
231 while let Some(ptr) = platform_get_dns_server(dns_info_c_handle).as_ref() {
232 let str = CStr::from_ptr(ptr).to_string_lossy().into_owned();
233 if let Ok(dns_server) = str.parse::<SocketAddr>() {
234 v.push(dns_server);
235 }
236 }
237 }
238
239 v
240}
241
242pub fn get_active_dns_servers() -> Vec<SocketAddr> {
243 let mut v = Vec::new();
244
245 #[cfg(any(
246 all(feature = "android", target_os = "android"),
247 all(feature = "ohos", all(target_os = "linux", target_env = "ohos"))
248 ))]
249 unsafe {
250 if let Some(network_info) = platform_get_active_network_info().as_mut() {
251 if let Some(dns_info) = platform_get_network_dns_info(network_info).as_mut() {
252 while let Some(ptr) = platform_get_dns_server(dns_info).as_ref() {
253 let str = CStr::from_ptr(ptr).to_string_lossy().into_owned();
254 if let Ok(dns_server) = str.parse::<SocketAddr>() {
255 v.push(dns_server);
256 }
257 }
258 platform_drop_dns_info(dns_info);
259 }
260 }
261 }
262
263 v
264}