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}