dope-core 0.15.0

The manifold runtime
Documentation
mod dispatch;
mod poll;
mod queue;

use std::{os::fd, process};

pub(in crate::backend::kqueue) use dispatch::Dispatch;
pub(in crate::backend::kqueue) use poll::Poll;
pub(in crate::backend::kqueue) use queue::Queue;

use crate::{
    backend::{
        self,
        kqueue::{descriptor, engine::lifecycle},
    },
    driver::{self, flight, route},
    io::{self, event::open, fd::handles},
    platform,
};

enum KernelData {
    Public(flight::raw::Echo),
    Shutdown,
    Empty,
}

impl KernelData {
    fn decode(raw: u64) -> Self {
        if raw == u64::MAX {
            return KernelData::Shutdown;
        }
        match unsafe { flight::raw::Echo::from_kernel(raw) } {
            Some(key) => KernelData::Public(key),
            None => KernelData::Empty,
        }
    }
}

type Buffer = <backend::Kqueue as platform::Buffer>::Token;

pub(crate) enum CreateOutcome {
    Ready {
        slot: handles::FixedSlot,
        fd: descriptor::Handle,
    },
    Failed {
        slot: handles::FixedSlot,
        errno: i32,
    },
    Cancelled {
        slot: handles::FixedSlot,
    },
}

impl CreateOutcome {
    pub(super) const fn slot(&self) -> Option<handles::FixedSlot> {
        match self {
            Self::Ready { slot, .. } | Self::Failed { slot, .. } | Self::Cancelled { slot } => {
                Some(*slot)
            }
        }
    }
}

pub(crate) enum Completion {
    AcceptSuccess {
        ud: flight::raw::Echo,
        accepted: handles::Accepted,
        more: bool,
    },
    AcceptFailure {
        ud: flight::raw::Echo,
        errno: i32,
        more: bool,
    },
    RecvData {
        ud: flight::raw::Echo,
        len: u32,
        more: bool,
        buffer: Buffer,
    },
    RecvControl {
        ud: flight::raw::Echo,
        result: i32,
        more: bool,
    },
    Send {
        ud: flight::raw::Echo,
        result: i32,
    },
    Connect {
        ud: flight::raw::Echo,
        result: i32,
    },
    Create {
        ud: flight::raw::Echo,
        outcome: CreateOutcome,
    },
    Opened {
        ud: flight::raw::Echo,
        fd: fd::OwnedFd,
    },
    OpenFailed {
        ud: flight::raw::Echo,
        error: open::Error,
    },
    Read {
        ud: flight::raw::Echo,
        result: i32,
    },
    Write {
        ud: flight::raw::Echo,
        result: i32,
    },
    Stat {
        ud: flight::raw::Echo,
        result: i32,
    },
    Sync {
        ud: flight::raw::Echo,
        result: i32,
    },
    Shutdown,
}

impl Completion {
    pub(crate) fn into_completion(
        self,
        files: &mut lifecycle::Files,
        drain: &flight::Drain<'_, '_>,
    ) -> io::Completion {
        let driver = drain.driver();
        match self {
            Self::AcceptSuccess { ud, accepted, more } => {
                let token = completion(ud, more, drain);
                io::Completion::accepted(token, accepted, more)
            }
            Self::AcceptFailure { ud, errno, more } => {
                let token = completion(ud, more, drain);
                io::Completion::accept_failed(token, errno, more)
            }
            Self::RecvData {
                ud,
                len,
                more,
                buffer,
            } => {
                let token = completion(ud, more, drain);
                io::Completion::received(token, len, more, buffer)
            }
            Self::RecvControl { ud, result, more } => {
                let token = completion(ud, more, drain);
                io::Completion::operation(token, result, more)
            }
            Self::Send { ud, result } | Self::Connect { ud, result } => {
                let token = terminal(ud, drain);
                io::Completion::operation(token, result, false)
            }
            Self::Create { ud, outcome } => match outcome {
                CreateOutcome::Ready { slot, fd } => {
                    files.install_outbound(slot, fd);
                    io::Completion::socket_created(terminal(ud, drain), slot)
                }
                CreateOutcome::Failed { slot, errno } => {
                    socket_failed(driver, terminal(ud, drain), slot, errno)
                }
                CreateOutcome::Cancelled { slot } => {
                    socket_failed(driver, terminal(ud, drain), slot, libc::ECANCELED)
                }
            },
            Self::Opened { ud, fd } => {
                io::Completion::opened(terminal(ud, drain), open::Opened::new(fd))
            }
            Self::OpenFailed { ud, error } => {
                io::Completion::open_failed(terminal(ud, drain), error)
            }
            Self::Read { ud, result }
            | Self::Write { ud, result }
            | Self::Stat { ud, result }
            | Self::Sync { ud, result } => {
                io::Completion::operation(terminal(ud, drain), result, false)
            }
            Self::Shutdown => io::Completion::shutdown(),
        }
    }

    pub(super) fn token(&self) -> Option<flight::raw::Echo> {
        match self {
            Self::AcceptSuccess { ud, .. }
            | Self::AcceptFailure { ud, .. }
            | Self::RecvData { ud, .. }
            | Self::RecvControl { ud, .. }
            | Self::Send { ud, .. }
            | Self::Connect { ud, .. }
            | Self::Create { ud, .. }
            | Self::Opened { ud, .. }
            | Self::OpenFailed { ud, .. }
            | Self::Read { ud, .. }
            | Self::Write { ud, .. }
            | Self::Stat { ud, .. }
            | Self::Sync { ud, .. } => Some(*ud),
            Self::Shutdown => None,
        }
    }
}

fn completion(key: flight::raw::Echo, more: bool, drain: &flight::Drain<'_, '_>) -> route::Token {
    let Some(completion) = drain.complete(key) else {
        process::abort();
    };
    let Some(token) = completion.resolve(more) else {
        process::abort();
    };
    token
}

fn terminal(key: flight::raw::Echo, drain: &flight::Drain<'_, '_>) -> route::Token {
    completion(key, false, drain)
}

fn socket_failed(
    driver: driver::Reference<'_>,
    token: route::Token,
    slot: handles::FixedSlot,
    errno: i32,
) -> io::Completion {
    if let Some(slots) = driver.outbound().complete_outbound_create_failure(slot) {
        driver.maintenance().defer_outbound_slots(slots);
    }
    io::Completion::socket_failure(token, errno)
}