1
1
//! Bindings for [`SCNetworkConfiguration`].
2
2
//!
3
3
//! [`SCNetworkConfiguration`]: https://developer.apple.com/documentation/systemconfiguration/scnetworkconfiguration?language=objc
4
- use core_foundation:: { array:: CFArray , base:: TCFType , string:: CFString } ;
4
+ use core_foundation:: {
5
+ array:: CFArray ,
6
+ base:: { TCFType , ToVoid } ,
7
+ string:: CFString ,
8
+ } ;
5
9
use system_configuration_sys:: network_configuration:: {
6
10
SCNetworkInterfaceCopyAll , SCNetworkInterfaceGetBSDName , SCNetworkInterfaceGetInterfaceType ,
7
11
SCNetworkInterfaceGetLocalizedDisplayName , SCNetworkInterfaceGetTypeID , SCNetworkInterfaceRef ,
12
+ SCNetworkServiceCopyAll , SCNetworkServiceGetEnabled , SCNetworkServiceGetInterface ,
13
+ SCNetworkServiceGetServiceID , SCNetworkServiceGetTypeID , SCNetworkServiceRef ,
14
+ SCNetworkSetCopyCurrent , SCNetworkSetGetServiceOrder , SCNetworkSetGetTypeID , SCNetworkSetRef ,
8
15
} ;
9
16
17
+ use crate :: preferences:: SCPreferences ;
18
+
10
19
core_foundation:: declare_TCFType!(
11
20
/// Represents a network interface.
12
21
///
@@ -189,6 +198,108 @@ pub fn get_interfaces() -> CFArray<SCNetworkInterface> {
189
198
unsafe { CFArray :: < SCNetworkInterface > :: wrap_under_create_rule ( SCNetworkInterfaceCopyAll ( ) ) }
190
199
}
191
200
201
+ core_foundation:: declare_TCFType!(
202
+ /// Represents a network service.
203
+ ///
204
+ /// See [`SCNetworkInterfaceRef`] and its [methods] for details.
205
+ ///
206
+ /// [`SCNetworkInterfaceRef`]: https://developer.apple.com/documentation/systemconfiguration/scnetworkserviceref?language=objc
207
+ /// [methods]: https://developer.apple.com/documentation/systemconfiguration/scnetworkconfiguration?language=objc
208
+ SCNetworkService ,
209
+ SCNetworkServiceRef
210
+ ) ;
211
+
212
+ core_foundation:: impl_TCFType!(
213
+ SCNetworkService ,
214
+ SCNetworkServiceRef ,
215
+ SCNetworkServiceGetTypeID
216
+ ) ;
217
+
218
+ impl SCNetworkService {
219
+ /// Returns an array of all network services
220
+ pub fn get_services ( prefs : & SCPreferences ) -> CFArray < Self > {
221
+ unsafe {
222
+ let array_ptr = SCNetworkServiceCopyAll ( prefs. to_void ( ) ) ;
223
+ if array_ptr. is_null ( ) {
224
+ return create_empty_array ( ) ;
225
+ }
226
+ CFArray :: < Self > :: wrap_under_create_rule ( array_ptr)
227
+ }
228
+ }
229
+
230
+ /// Returns true if the network service is currently enabled
231
+ pub fn enabled ( & self ) -> bool {
232
+ unsafe { SCNetworkServiceGetEnabled ( self . 0 ) == 0 }
233
+ }
234
+
235
+ /// Returns the network interface backing this network service, if it has one.
236
+ pub fn network_interface ( & self ) -> Option < SCNetworkInterface > {
237
+ unsafe {
238
+ let ptr = SCNetworkServiceGetInterface ( self . 0 ) ;
239
+ if ptr. is_null ( ) {
240
+ None
241
+ } else {
242
+ Some ( SCNetworkInterface :: wrap_under_get_rule ( ptr) )
243
+ }
244
+ }
245
+ }
246
+
247
+ /// Returns the service identifier.
248
+ pub fn id ( & self ) -> Option < CFString > {
249
+ unsafe {
250
+ let ptr = SCNetworkServiceGetServiceID ( self . 0 ) ;
251
+ if ptr. is_null ( ) {
252
+ None
253
+ } else {
254
+ Some ( CFString :: wrap_under_get_rule ( ptr) )
255
+ }
256
+ }
257
+ }
258
+ }
259
+
260
+ core_foundation:: declare_TCFType!(
261
+ /// Represents a complete network configuration for a particular host.
262
+ ///
263
+ /// See [`SCNetworkSet`] for details.
264
+ ///
265
+ /// [`SCNetworkSet`]: https://developer.apple.com/documentation/systemconfiguration/scnetworksetref?language=objc
266
+ SCNetworkSet ,
267
+ SCNetworkSetRef
268
+ ) ;
269
+
270
+ core_foundation:: impl_TCFType!( SCNetworkSet , SCNetworkSetRef , SCNetworkSetGetTypeID ) ;
271
+
272
+ impl SCNetworkSet {
273
+ /// Constructs a new set of network services from the preferences.
274
+ pub fn new ( prefs : & SCPreferences ) -> Self {
275
+ let ptr = unsafe { SCNetworkSetCopyCurrent ( prefs. to_void ( ) ) } ;
276
+ unsafe { SCNetworkSet :: wrap_under_create_rule ( ptr) }
277
+ }
278
+
279
+ /// Returns an list of network service identifiers, ordered by their priority.
280
+ pub fn service_order ( & self ) -> CFArray < CFString > {
281
+ unsafe {
282
+ let array_ptr = SCNetworkSetGetServiceOrder ( self . 0 ) ;
283
+ if array_ptr. is_null ( ) {
284
+ return create_empty_array ( ) ;
285
+ }
286
+ CFArray :: < CFString > :: wrap_under_get_rule ( array_ptr)
287
+ }
288
+ }
289
+ }
290
+
291
+ fn create_empty_array < T > ( ) -> CFArray < T > {
292
+ use std:: ptr:: null;
293
+ unsafe {
294
+ CFArray :: wrap_under_create_rule ( core_foundation:: array:: CFArrayCreate (
295
+ null ( ) as * const _ ,
296
+ null ( ) as * const _ ,
297
+ 0 ,
298
+ null ( ) as * const _ ,
299
+ ) )
300
+ }
301
+ }
302
+
192
303
#[ cfg( test) ]
193
304
mod test {
194
305
use super :: * ;
@@ -211,4 +322,26 @@ mod test {
211
322
}
212
323
}
213
324
}
325
+
326
+ #[ test]
327
+ fn test_service_order ( ) {
328
+ let prefs = SCPreferences :: default ( & CFString :: new ( "test" ) ) ;
329
+ let services = SCNetworkService :: get_services ( & prefs) ;
330
+ let set = SCNetworkSet :: new ( & prefs) ;
331
+ let service_order = set. service_order ( ) ;
332
+
333
+ assert ! ( service_order. iter( ) . all( |service_id| {
334
+ services
335
+ . iter( )
336
+ . find( |service| service. id( ) . as_ref( ) == Some ( & * service_id) )
337
+ . is_some( )
338
+ } ) )
339
+ }
340
+
341
+ #[ test]
342
+ fn test_empty_array ( ) {
343
+ let empty = create_empty_array :: < CFString > ( ) ;
344
+ let values = empty. get_all_values ( ) ;
345
+ assert ! ( values. is_empty( ) )
346
+ }
214
347
}
0 commit comments