dope-core 0.15.1

The manifold runtime
Documentation
use std::{mem, num};

use crate::{
    io::{datagram, socket::msg},
    platform,
};

#[repr(C, align(8))]
pub(crate) struct Control {
    buffer: Buffer,
    segment_size: num::NonZeroU16,
}

pub(crate) struct Capability;

impl platform::GsoMode for Control {
    type Capability = super::Capability;
    type Control = Self;

    const LIMITS: Option<datagram::GsoLimits> = Some(super::LIMITS);

    fn acquire() -> Option<Self::Capability> {
        Some(Capability)
    }

    fn limits(_: &Self::Capability) -> datagram::GsoLimits {
        super::LIMITS
    }

    fn control(_: Self::Capability, segment_size: num::NonZeroU16) -> Self::Control {
        Self {
            buffer: Buffer::new(),
            segment_size,
        }
    }

    fn release(control: Self::Control) -> (Self::Capability, num::NonZeroU16) {
        (Capability, control.segment_size)
    }

    fn attach<'a>(control: &'a mut Self::Control, msg: &mut msg::Builder<'a>) {
        let segment_size = control.segment_size.get();
        control.buffer.attach(msg, segment_size);
    }
}

struct Buffer([u8; 32]);

impl Buffer {
    const fn new() -> Self {
        Self([0; 32])
    }

    fn attach<'a>(&'a mut self, msg: &mut msg::Builder<'a>, segment_size: u16) {
        const DATA_LEN: u32 = mem::size_of::<u16>() as u32;
        let (buf, cap) = (self.0.as_mut_ptr(), self.0.len());
        unsafe {
            use std::ptr::{addr_of, copy_nonoverlapping};

            use libc::{CMSG_DATA, CMSG_LEN, CMSG_SPACE, SOL_UDP, UDP_SEGMENT};
            let controllen = CMSG_SPACE(DATA_LEN) as usize;
            debug_assert!(controllen <= cap);
            let hdr = buf.cast::<libc::cmsghdr>();
            (*hdr).cmsg_level = SOL_UDP;
            (*hdr).cmsg_type = UDP_SEGMENT;
            (*hdr).cmsg_len = CMSG_LEN(DATA_LEN) as _;
            copy_nonoverlapping(
                addr_of!(segment_size).cast::<u8>(),
                CMSG_DATA(hdr),
                DATA_LEN as usize,
            );
            msg.control(&self.0[..controllen]);
        }
    }
}