use std::{
borrow::{Borrow, BorrowMut},
marker::PhantomData,
os::fd::{AsFd as _, AsRawFd, RawFd},
};
use crate::{
maps::{
check_kv_size, hash_map, sock::SockMapFd, IterableMap, MapData, MapError, MapFd, MapIter,
MapKeys,
},
sys::{bpf_map_lookup_elem, SyscallError},
Pod,
};
#[doc(alias = "BPF_MAP_TYPE_SOCKHASH")]
pub struct SockHash<T, K> {
pub(crate) inner: T,
_k: PhantomData<K>,
}
impl<T: Borrow<MapData>, K: Pod> SockHash<T, K> {
pub(crate) fn new(map: T) -> Result<Self, MapError> {
let data = map.borrow();
check_kv_size::<K, u32>(data)?;
Ok(Self {
inner: map,
_k: PhantomData,
})
}
pub fn get(&self, key: &K, flags: u64) -> Result<RawFd, MapError> {
let fd = self.inner.borrow().fd().as_fd();
let value = bpf_map_lookup_elem(fd, key, flags).map_err(|(_, io_error)| SyscallError {
call: "bpf_map_lookup_elem",
io_error,
})?;
value.ok_or(MapError::KeyNotFound)
}
pub fn iter(&self) -> MapIter<'_, K, RawFd, Self> {
MapIter::new(self)
}
pub fn keys(&self) -> MapKeys<'_, K> {
MapKeys::new(self.inner.borrow())
}
pub fn fd(&self) -> &SockMapFd {
let fd: &MapFd = self.inner.borrow().fd();
unsafe { std::mem::transmute(fd) }
}
}
impl<T: BorrowMut<MapData>, K: Pod> SockHash<T, K> {
pub fn insert<I: AsRawFd>(
&mut self,
key: impl Borrow<K>,
value: I,
flags: u64,
) -> Result<(), MapError> {
hash_map::insert(
self.inner.borrow_mut(),
key.borrow(),
&value.as_raw_fd(),
flags,
)
}
pub fn remove(&mut self, key: &K) -> Result<(), MapError> {
hash_map::remove(self.inner.borrow_mut(), key)
}
}
impl<T: Borrow<MapData>, K: Pod> IterableMap<K, RawFd> for SockHash<T, K> {
fn map(&self) -> &MapData {
self.inner.borrow()
}
fn get(&self, key: &K) -> Result<RawFd, MapError> {
Self::get(self, key, 0)
}
}