#![allow(private_interfaces)]
#![allow(private_bounds)]
#![allow(non_upper_case_globals)]
use crate::mmap::OwnedMmap;
use crate::ring::{Ring, XdpDesc};
use std::fmt::Display;
use std::os::fd::{AsRawFd as _, OwnedFd};
use std::sync::Arc;
use std::{io, ptr};
pub struct Socket<const t: _Direction> {
pub(crate) _inner: Option<Arc<Inner>>,
pub(crate) x_ring: Ring<XdpDesc>,
pub(crate) u_ring: Ring<u64>,
pub(crate) available: u32,
pub(crate) producer: u32,
pub(crate) consumer: u32,
pub(crate) frames: *mut u8,
pub(crate) raw_fd: libc::c_int,
}
#[derive(Debug)]
pub enum RingError {
RingFull,
RingEmpty,
NotAvailable,
InvalidIndex,
InvalidLength,
Io(io::Error),
}
impl Display for RingError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
RingError::RingFull => write!(f, "Ring is full"),
RingError::RingEmpty => write!(f, "Ring is empty"),
RingError::NotAvailable => write!(f, "Not enough available frames"),
RingError::InvalidIndex => write!(f, "Invalid index for ring access"),
RingError::InvalidLength => write!(f, "Invalid length for ring access"),
RingError::Io(e) => write!(f, "I/O error: {e}"),
}
}
}
impl<const t: _Direction> Socket<t>
where
Socket<t>: Seek_<t> + Commit_<t> + Send,
{
pub(crate) fn new(inner: Option<Arc<Inner>>, x_ring: Ring<XdpDesc>, u_ring: Ring<u64>) -> Self {
if let Some(inner) = inner {
let frames = inner.umem.0 as *mut u8;
let raw_fd = inner.fd.as_raw_fd();
Self {
frames,
available: x_ring.len as u32,
producer: 0,
consumer: 0,
raw_fd,
_inner: Some(inner),
x_ring,
u_ring,
}
} else {
Self::default()
}
}
#[inline]
pub fn seek(&mut self) -> Result<usize, RingError> {
self.seek_(1)
}
#[inline]
pub fn seek_n(&mut self, count: usize) -> Result<usize, RingError> {
self.seek_(count)
}
#[inline]
pub fn commit(&mut self) -> Result<(), RingError> {
self.commit_(1)
}
#[inline]
pub fn commit_n(&mut self, n: usize) -> Result<(), RingError> {
self.commit_(n)
}
#[inline]
pub fn frame_size(&self) -> usize {
self.x_ring.frame_size() as usize
}
}
unsafe impl<const t: _Direction> Send for Socket<t> {}
pub type _Direction = bool;
pub const _TX: _Direction = true;
pub const _RX: _Direction = false;
pub type TxSocket = Socket<_TX>;
pub type RxSocket = Socket<_RX>;
impl<const t: _Direction> Default for Socket<t> {
fn default() -> Self {
Self {
_inner: None,
x_ring: Default::default(),
u_ring: Default::default(),
available: 0,
producer: 0,
consumer: 0,
frames: ptr::null_mut(),
raw_fd: 0,
}
}
}
pub(crate) trait Seek_<const t: _Direction> {
fn seek_(&mut self, count: usize) -> Result<usize, RingError>;
}
pub(crate) trait Commit_<const t: _Direction> {
fn commit_(&mut self, count: usize) -> Result<(), RingError>;
}
pub(crate) struct Inner {
umem: OwnedMmap,
fd: OwnedFd,
}
impl Inner {
pub(crate) fn new(umem: OwnedMmap, fd: OwnedFd) -> Self {
Self { umem, fd }
}
}