use std::{
borrow::{Borrow, BorrowMut},
os::fd::{AsFd as _, AsRawFd, RawFd},
};
use crate::{
maps::{check_bounds, check_kv_size, sock::SockMapFd, MapData, MapError, MapFd, MapKeys},
sys::{bpf_map_delete_elem, bpf_map_update_elem, SyscallError},
};
#[doc(alias = "BPF_MAP_TYPE_SOCKMAP")]
pub struct SockMap<T> {
pub(crate) inner: T,
}
impl<T: Borrow<MapData>> SockMap<T> {
pub(crate) fn new(map: T) -> Result<Self, MapError> {
let data = map.borrow();
check_kv_size::<u32, RawFd>(data)?;
Ok(Self { inner: map })
}
pub fn indices(&self) -> MapKeys<'_, u32> {
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>> SockMap<T> {
pub fn set<I: AsRawFd>(&mut self, index: u32, socket: &I, flags: u64) -> Result<(), MapError> {
let data = self.inner.borrow_mut();
let fd = data.fd().as_fd();
check_bounds(data, index)?;
bpf_map_update_elem(fd, Some(&index), &socket.as_raw_fd(), flags).map_err(
|(_, io_error)| SyscallError {
call: "bpf_map_update_elem",
io_error,
},
)?;
Ok(())
}
pub fn clear_index(&mut self, index: &u32) -> Result<(), MapError> {
let data = self.inner.borrow_mut();
let fd = data.fd().as_fd();
check_bounds(data, *index)?;
bpf_map_delete_elem(fd, index)
.map(|_| ())
.map_err(|(_, io_error)| {
SyscallError {
call: "bpf_map_delete_elem",
io_error,
}
.into()
})
}
}