use crate::{
error::GenetlinkError,
message::{map_from_rawgenlmsg, map_to_rawgenlmsg, RawGenlMessage},
resolver::Resolver,
};
use futures::{lock::Mutex, Stream, StreamExt};
use netlink_packet_core::{NetlinkMessage, NetlinkPayload};
use netlink_packet_generic::{GenlFamily, GenlHeader, GenlMessage};
use netlink_packet_utils::{DecodeError, Emitable, ParseableParametrized};
use netlink_proto::{sys::SocketAddr, ConnectionHandle};
use std::{fmt::Debug, sync::Arc};
#[derive(Clone, Debug)]
pub struct GenetlinkHandle {
handle: ConnectionHandle<RawGenlMessage>,
resolver: Arc<Mutex<Resolver>>,
}
impl GenetlinkHandle {
pub(crate) fn new(handle: ConnectionHandle<RawGenlMessage>) -> Self {
Self {
handle,
resolver: Arc::new(Mutex::new(Resolver::new())),
}
}
pub async fn resolve_family_id<F>(&self) -> Result<u16, GenetlinkError>
where
F: GenlFamily,
{
self.resolver
.lock()
.await
.query_family_id(self, F::family_name())
.await
}
pub async fn clear_family_id_cache(&self) {
self.resolver.lock().await.clear_cache();
}
pub async fn request<F>(
&mut self,
mut message: NetlinkMessage<GenlMessage<F>>,
) -> Result<
impl Stream<Item = Result<NetlinkMessage<GenlMessage<F>>, DecodeError>>,
GenetlinkError,
>
where
F: GenlFamily
+ Emitable
+ ParseableParametrized<[u8], GenlHeader>
+ Debug,
{
self.resolve_message_family_id(&mut message).await?;
self.send_request(message)
}
pub fn send_request<F>(
&mut self,
message: NetlinkMessage<GenlMessage<F>>,
) -> Result<
impl Stream<Item = Result<NetlinkMessage<GenlMessage<F>>, DecodeError>>,
GenetlinkError,
>
where
F: GenlFamily
+ Emitable
+ ParseableParametrized<[u8], GenlHeader>
+ Debug,
{
let raw_msg = map_to_rawgenlmsg(message);
let stream = self.handle.request(raw_msg, SocketAddr::new(0, 0))?;
Ok(stream.map(map_from_rawgenlmsg))
}
pub async fn notify<F>(
&mut self,
mut message: NetlinkMessage<GenlMessage<F>>,
) -> Result<(), GenetlinkError>
where
F: GenlFamily
+ Emitable
+ ParseableParametrized<[u8], GenlHeader>
+ Debug,
{
self.resolve_message_family_id(&mut message).await?;
self.send_notify(message)
}
pub fn send_notify<F>(
&mut self,
message: NetlinkMessage<GenlMessage<F>>,
) -> Result<(), GenetlinkError>
where
F: GenlFamily
+ Emitable
+ ParseableParametrized<[u8], GenlHeader>
+ Debug,
{
let raw_msg = map_to_rawgenlmsg(message);
self.handle.notify(raw_msg, SocketAddr::new(0, 0))?;
Ok(())
}
async fn resolve_message_family_id<F>(
&mut self,
message: &mut NetlinkMessage<GenlMessage<F>>,
) -> Result<(), GenetlinkError>
where
F: GenlFamily + Debug,
{
if let NetlinkPayload::InnerMessage(genlmsg) = &mut message.payload {
if genlmsg.family_id() == 0 {
let id = self.resolve_family_id::<F>().await?;
genlmsg.set_resolved_family_id(id);
}
}
Ok(())
}
}