-
Notifications
You must be signed in to change notification settings - Fork 15
Open
Description
I appears SmolSocket is general enough that it will work with other async runtimes; in particular it seems to work fine with compio. It might be worth aliasing the type to a more general name?
Working code:
use std::{future, net::{IpAddr, Ipv4Addr}};
use anyhow::{bail, Context, Result};
use futures::{stream, TryStreamExt};
use rtnetlink::{new_connection_with_socket, packet_route::{address::AddressAttribute, AddressFamily}, sys::SmolSocket};
const IFNAME: &str = "test0";
async fn get_if_addr(ifname: &str) -> Result<Ipv4Addr> {
let (connection, handle, _msgs) =
new_connection_with_socket::<SmolSocket>()?;
compio::runtime::spawn(connection)
.detach();
let link = handle
.link()
.get()
.match_name(ifname.to_string())
.execute()
.try_next().await?
.context("Failed to find interface {ifname}")?;
// Fetch link addresses
let addrs = handle
.address()
.get()
.set_link_index_filter(link.header.index)
.execute()
// Extract attributes
.try_filter_map(|a| {
future::ready(if a.header.family == AddressFamily::Inet {
Ok(Some(a.attributes))
} else {
Ok(None)
})
})
.map_ok(|attrs| {
stream::iter(
attrs
.into_iter()
.map(Ok::<AddressAttribute, rtnetlink::Error>),
)
})
.try_flatten()
.try_collect::<Vec<AddressAttribute>>().await?
// Extract relevant addresses
.into_iter()
.flat_map(|a| {
if let AddressAttribute::Address(addr) = a {
Some(addr)
} else {
None
}
})
.collect::<Vec<IpAddr>>();
if let IpAddr::V4(ipaddr) = addrs[0] {
Ok(ipaddr)
} else if addrs.is_empty() {
bail!("No IPv4 address found for interface {ifname}");
} else if addrs.len() > 1 {
bail!("Multiple IPv4 addresses found on for interface {ifname}")
} else {
bail!("Found non-IPv4 address on {ifname}; this is an internal logic error")
}
}
fn main() -> Result<()> {
compio::runtime::Runtime::new()?.block_on(async {
let ipaddr = get_if_addr(IFNAME).await?;
println!("IP is {ipaddr}");
Ok(())
})
}Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels