async_zeroconf/interface.rs
1use std::{ffi, fmt};
2
3use crate::ZeroconfError;
4
5/// Enum to hold the Interface a service should be advertised on.
6#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
7pub enum Interface {
8 /// Advertise on all interfaces
9 Unspecified,
10 /// Advertise on specified interface, e.g. as obtained by `if_nametoindex(3)`
11 Interface(u32),
12}
13
14impl fmt::Display for Interface {
15 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
16 match self {
17 Interface::Unspecified => write!(f, "Any"),
18 Interface::Interface(i) => write!(f, "Interface:{}", i),
19 }
20 }
21}
22
23impl Interface {
24 /// Create an `Interface` instance representing any interface.
25 pub fn new() -> Self {
26 Interface::Unspecified
27 }
28
29 /// Create an `Interface` instance from an interface name.
30 ///
31 /// # Examples
32 /// ```
33 /// # tokio_test::block_on(async {
34 /// let interface = async_zeroconf::Interface::from_ifname("lo0")?;
35 /// println!("{:?}", interface);
36 /// let service_ref = async_zeroconf::Service::new("Server", "_http._tcp", 80)
37 /// .set_interface(interface)
38 /// .publish().await?;
39 /// # let interface2 = async_zeroconf::Interface::from_ifname("unknown_if");
40 /// # assert!(interface2.is_err());
41 /// # Ok::<(), async_zeroconf::ZeroconfError>(())
42 /// # });
43 /// ```
44 pub fn from_ifname(name: &str) -> Result<Interface, ZeroconfError> {
45 let cname = ffi::CString::new(name)?;
46 let name_ptr = cname.as_ptr();
47 let index = unsafe { libc::if_nametoindex(name_ptr) };
48
49 if index == 0 {
50 Err(ZeroconfError::InterfaceNotFound(name.to_string()))
51 } else {
52 Ok(Interface::Interface(index))
53 }
54 }
55}
56
57impl Default for Interface {
58 fn default() -> Self {
59 Interface::new()
60 }
61}