dope-net 0.30.0

Owned network transports for dope
Documentation
use std::mem;

use dope_core::{
    driver,
    driver::{
        retained::flight::{self, cancel},
        route::{self, Identity, KeyTag},
        schedule::ready,
    },
    io::{
        event::net::{connect, tuning},
        fd::handles,
        socket::{self, option, pending},
    },
};

use crate::link::{
    self,
    duplex::state,
    pool::{self, change::close},
};

pub(crate) enum Setup<'d, ID: Identity> {
    CreatingTargeted(Targeted<'d, ID, handles::Creation<'d>>),
    Idle(handles::Descriptor<'d>),
    IdleTargeted(Targeted<'d, ID, handles::Descriptor<'d>>),
    Tuning(pending::Tuning<'d>),
    TuningCancelled(pending::Tuning<'d, pending::Cancelled>),
    Connecting(Targeted<'d, ID, pending::Connection<'d>>, Intent),
    ConnectingCancelled(Targeted<'d, ID, pending::Connection<'d, pending::Cancelled>>),
    Done(handles::Descriptor<'d>),
    Connected(Targeted<'d, ID, handles::Descriptor<'d>>),
    Detached(ready::Handle<'d>),
}

#[derive(Clone, Copy)]
pub(crate) enum Intent {
    Live,
    Rejected,
}

pub(crate) struct Targeted<'d, ID: Identity, T> {
    inner: T,
    stored: pool::Stored<'d, ID>,
}

pub(crate) enum Close<'d, ID: Identity> {
    Creating(Targeted<'d, ID, handles::Creation<'d>>),
    Idle(handles::Descriptor<'d>),
    Done(handles::Descriptor<'d>),
    IdleTargeted(Targeted<'d, ID, handles::Descriptor<'d>>),
    Connected(Targeted<'d, ID, handles::Descriptor<'d>>),
}

pub(crate) enum Completion<C, E = dope_core::Errno> {
    Ready,
    Failed(E),
    Cancelled,
    Stale(C),
}

pub(crate) enum Submission {
    Pending,
    Failed(pending::Cause),
}

pub(crate) enum Cancellation {
    Ready,
    Pending,
    Retry,
    Rejected(cancel::Failure),
}

pub(crate) enum Retire<'d, ID: Identity> {
    Ready {
        close: Close<'d, ID>,
        handle: ready::Handle<'d>,
    },
    Pending(Setup<'d, ID>),
    Unavailable(Setup<'d, ID>),
}

impl<'d, ID: Identity> Setup<'d, ID> {
    pub(in crate::link) fn take(&mut self) -> Self {
        let detached = Self::Detached(self.ready_handle());
        mem::replace(self, detached)
    }

    pub(crate) fn targeted(socket: handles::Creation<'d>, stored: pool::Stored<'d, ID>) -> Self {
        Self::CreatingTargeted(Targeted::new(socket, stored))
    }

    pub(in crate::link) fn tuned(
        self,
        done: tuning::Completion<'d>,
        state: &state::State,
    ) -> (Self, Completion<tuning::Completion<'d>>) {
        match self {
            Self::Tuning(item) => {
                let (fd, result) = match item.complete(done) {
                    Ok(pair) => pair,
                    Err(mismatch) => {
                        let (item, done) = mismatch.into_parts();
                        return (Self::Tuning(item), Completion::Stale(done));
                    }
                };
                match result {
                    Ok(()) if state.is_closing() => (Self::Idle(fd), Completion::Cancelled),
                    Ok(()) => (Self::Done(fd), Completion::Ready),
                    Err(error) => (Self::Idle(fd), Completion::Failed(error)),
                }
            }
            Self::TuningCancelled(item) => {
                let (fd, result) = match item.complete(done) {
                    Ok(pair) => pair,
                    Err(mismatch) => {
                        let (item, done) = mismatch.into_parts();
                        return (Self::TuningCancelled(item), Completion::Stale(done));
                    }
                };
                match result {
                    Ok(()) => (Self::Idle(fd), Completion::Cancelled),
                    Err(error) => (Self::Idle(fd), Completion::Failed(error)),
                }
            }
            state => (state, Completion::Stale(done)),
        }
    }

    pub(in crate::link) fn created<A: socket::Prepared>(
        self,
        made: handles::CreatedSlot<'d>,
        opts: option::Set,
        addr: &A,
        target: route::Target<'d, ID>,
        flights: &flight::Slots<'d, ID>,
        driver: &mut driver::Context<'_, 'd>,
    ) -> (Self, Submission) {
        let targeted = match self {
            Self::CreatingTargeted(targeted) => targeted,
            state => return (state, Submission::Pending),
        };
        let (socket, stored) = targeted.into_parts();
        let fd = match made.try_join(socket) {
            Ok(join) => join.activate(),
            Err((socket, made)) => {
                drop(made);
                return (
                    Self::CreatingTargeted(Targeted::new(socket, stored)),
                    Submission::Pending,
                );
            }
        };
        match link::connect(fd, addr, target, flights, driver.reborrow(), opts) {
            Ok(conn) => (
                Self::Connecting(Targeted::new(conn, stored), Intent::Live),
                Submission::Pending,
            ),
            Err(reject) => {
                let (fd, cause) = reject.into_parts();
                (
                    Self::IdleTargeted(Targeted::new(fd, stored)),
                    Submission::Failed(cause),
                )
            }
        }
    }

    pub(crate) fn complete(
        self,
        done: connect::Completion<'d>,
    ) -> (Self, Completion<connect::Completion<'d>, connect::Error>) {
        if let Self::Connecting(targeted, intent) = self {
            let (item, stored) = targeted.into_parts();
            let (fd, result) = match item.complete(done) {
                Ok(pair) => pair,
                Err(mismatch) => {
                    let (item, done) = mismatch.into_parts();
                    return (
                        Self::Connecting(Targeted::new(item, stored), intent),
                        Completion::Stale(done),
                    );
                }
            };
            return match result {
                Ok(()) => (
                    Self::Connected(Targeted::new(fd, stored)),
                    match intent {
                        Intent::Live => Completion::Ready,
                        Intent::Rejected => Completion::Cancelled,
                    },
                ),
                Err(error) => (
                    Self::IdleTargeted(Targeted::new(fd, stored)),
                    Completion::Failed(error),
                ),
            };
        }
        if let Self::ConnectingCancelled(targeted) = self {
            let (item, stored) = targeted.into_parts();
            let (fd, result) = match item.complete(done) {
                Ok(pair) => pair,
                Err(mismatch) => {
                    let (item, done) = mismatch.into_parts();
                    return (
                        Self::ConnectingCancelled(Targeted::new(item, stored)),
                        Completion::Stale(done),
                    );
                }
            };
            return match result {
                Ok(()) => (
                    Self::Connected(Targeted::new(fd, stored)),
                    Completion::Cancelled,
                ),
                Err(error) => (
                    Self::IdleTargeted(Targeted::new(fd, stored)),
                    Completion::Failed(error),
                ),
            };
        }
        (self, Completion::Stale(done))
    }

    pub(crate) fn fd(&self) -> Option<&handles::Descriptor<'d>> {
        if let Self::Idle(fd) | Self::Done(fd) = self {
            return Some(fd);
        }
        if let Self::IdleTargeted(targeted) | Self::Connected(targeted) = self {
            return Some(targeted.inner());
        }
        self.pending_fd()
    }

    pub(crate) fn ready_handle(&self) -> ready::Handle<'d> {
        match self {
            Self::CreatingTargeted(targeted) => targeted.inner().ready_handle(),
            Self::Idle(fd) | Self::Done(fd) => fd.ready_handle(),
            Self::IdleTargeted(targeted) | Self::Connected(targeted) => {
                targeted.inner().ready_handle()
            }
            Self::Tuning(item) => item.fd().ready_handle(),
            Self::TuningCancelled(item) => item.fd().ready_handle(),
            Self::Connecting(targeted, _) => targeted.inner().fd().ready_handle(),
            Self::ConnectingCancelled(targeted) => targeted.inner().fd().ready_handle(),
            Self::Detached(handle) => *handle,
        }
    }

    #[inline]
    pub(crate) fn retire(self) -> Retire<'d, ID> {
        let (handle, close) = match self {
            Self::CreatingTargeted(value) => (value.inner().ready_handle(), Close::Creating(value)),
            Self::Idle(value) => (value.ready_handle(), Close::Idle(value)),
            Self::Done(value) => (value.ready_handle(), Close::Done(value)),
            Self::IdleTargeted(value) => (value.inner().ready_handle(), Close::IdleTargeted(value)),
            Self::Connected(value) => (value.inner().ready_handle(), Close::Connected(value)),
            pending @ (Self::Tuning(_)
            | Self::TuningCancelled(_)
            | Self::Connecting(..)
            | Self::ConnectingCancelled(_)) => return Retire::Pending(pending),
            unavailable @ Self::Detached(_) => return Retire::Unavailable(unavailable),
        };
        Retire::Ready { close, handle }
    }

    pub(crate) fn pending_fd(&self) -> Option<&handles::Descriptor<'d>> {
        if let Self::Tuning(item) = self {
            return Some(item.fd());
        }
        if let Self::TuningCancelled(item) = self {
            return Some(item.fd());
        }
        if let Self::Connecting(targeted, _) = self {
            return Some(targeted.inner().fd());
        }
        if let Self::ConnectingCancelled(targeted) = self {
            return Some(targeted.inner().fd());
        }
        None
    }

    pub(crate) fn cancel(self, driver: &mut driver::Context<'_, 'd>) -> (Self, Cancellation) {
        match self {
            Self::Tuning(item) => match item.cancel(driver) {
                pending::Cancellation::Submitted(item) => {
                    (Self::TuningCancelled(item), Cancellation::Pending)
                }
                pending::Cancellation::Retry { item, error: _ } => {
                    (Self::Tuning(item), Cancellation::Retry)
                }
            },
            Self::Connecting(targeted, Intent::Live) => {
                let (item, stored) = targeted.into_parts();
                match item.try_cancel(driver) {
                    Ok(item) => (
                        Self::ConnectingCancelled(Targeted::new(item, stored)),
                        Cancellation::Pending,
                    ),
                    Err((item, cause)) => {
                        let targeted = Targeted::new(item, stored);
                        match cause {
                            cancel::Error::Full(_) => (
                                Self::Connecting(targeted, Intent::Live),
                                Cancellation::Retry,
                            ),
                            cancel::Error::Rejected(cause) => (
                                Self::Connecting(targeted, Intent::Rejected),
                                Cancellation::Rejected(cause),
                            ),
                        }
                    }
                }
            }
            Self::Connecting(targeted, Intent::Rejected) => (
                Self::Connecting(targeted, Intent::Rejected),
                Cancellation::Pending,
            ),
            Self::TuningCancelled(item) => (Self::TuningCancelled(item), Cancellation::Pending),
            Self::ConnectingCancelled(targeted) => {
                (Self::ConnectingCancelled(targeted), Cancellation::Pending)
            }
            state => (state, Cancellation::Ready),
        }
    }

    pub(in crate::link) fn established(&self) -> Option<&handles::Descriptor<'d>> {
        if let Self::Done(fd) = self {
            return Some(fd);
        }
        self.connected()
    }

    pub(in crate::link) fn connected(&self) -> Option<&handles::Descriptor<'d>> {
        if let Self::Connected(targeted) = self {
            return Some(targeted.inner());
        }
        None
    }
}

impl<'d, ID: Identity, T> Targeted<'d, ID, T> {
    const fn new(inner: T, stored: pool::Stored<'d, ID>) -> Self {
        Self { inner, stored }
    }

    const fn inner(&self) -> &T {
        &self.inner
    }

    fn into_parts(self) -> (T, pool::Stored<'d, ID>) {
        (self.inner, self.stored)
    }
}

impl<'d, ID: Identity> Close<'d, ID> {
    pub(crate) const fn kind(&self) -> close::Kind {
        match self {
            Self::Done(_) => close::Kind::Connected,
            Self::Creating(_) | Self::Idle(_) | Self::IdleTargeted(_) | Self::Connected(_) => {
                close::Kind::Opening
            }
        }
    }

    pub(crate) fn restore(self) -> Setup<'d, ID> {
        match self {
            Self::Creating(value) => Setup::CreatingTargeted(value),
            Self::Idle(value) => Setup::Idle(value),
            Self::Done(value) => Setup::Done(value),
            Self::IdleTargeted(value) => Setup::IdleTargeted(value),
            Self::Connected(value) => Setup::Connected(value),
        }
    }

    pub(crate) fn close(self, driver: &mut driver::Context<'_, 'd>) {
        match self {
            Self::Creating(targeted) => targeted.inner.detach(),
            Self::Idle(fd) | Self::Done(fd) => fd.close(driver),
            Self::IdleTargeted(targeted) | Self::Connected(targeted) => {
                targeted.inner.close(driver)
            }
        }
    }
}

const _: () = {
    assert!(
        mem::size_of::<Targeted<'_, KeyTag<0>, handles::Descriptor<'_>>>()
            == mem::size_of::<handles::Descriptor<'_>>()
    );
    assert!(mem::size_of::<Setup<'_, KeyTag<0>>>() == 4 * mem::size_of::<usize>());
    assert!(
        mem::align_of::<Setup<'_, KeyTag<0>>>()
            == mem::align_of::<Option<pending::Connection<'_>>>()
    );
};