moana_std 0.1.4

moana 用户标准库
Documentation
//! channel 系列 syscall 用户态接口(server 端)

use core::mem::MaybeUninit;

use moa_uapi::{
    channel::{ChanHandle, ChannelFlags, ConnId, ConnInfo, MsgInfo, RcvId, ReplyRecvArgs},
    error::{
        ERR_CHANNEL_CLOSED, ERR_CLIENT_GONE, ERR_FAULT, ERR_INVAL, ERR_NO_RESOURCE, ERR_NOT_FOUND,
        ERR_PERM, ERR_TIMEOUT,
    },
    sysnr::{
        SYSNR_CHANNEL_CLOSE, SYSNR_CHANNEL_CREATE, SYSNR_CONNECT_INFO, SYSNR_CONNECT_REJECT,
        SYSNR_MSG_INFO, SYSNR_MSG_READ, SYSNR_MSG_WRITE, SYSNR_RECV, SYSNR_REPLY_RECV,
        SYSNR_REPLYV,
    },
    types::{IoVec, Timeout},
};

/// channel 系列 syscall 返回类型
pub type Result<T> = core::result::Result<T, ChannelError>;

define_syscall_error! {
    /// channel 系列 syscall 错误
    pub enum ChannelError {
        /// 权限不足
        Perm = ERR_PERM,
        /// 句柄或 rcvid 不存在
        NotFound = ERR_NOT_FOUND,
        /// 无效参数
        Inval = ERR_INVAL,
        /// 资源配额耗尽
        NoResource = ERR_NO_RESOURCE,
        /// 无效指针
        Fault = ERR_FAULT,
        /// 超时
        Timeout = ERR_TIMEOUT,
        /// 通道已关闭
        ChannelClosed = ERR_CHANNEL_CLOSED,
        /// client 已离开
        ClientGone = ERR_CLIENT_GONE,
    }
}

/// 创建通道
///
/// `pulse_depth` 为每个 connection 的用户 pulse 队列深度上限。
pub fn channel_create(flags: ChannelFlags, pulse_depth: u32) -> Result<ChanHandle> {
    let ret = unsafe {
        super::arch::syscall2(SYSNR_CHANNEL_CREATE, flags.bits() as usize, pulse_depth as usize)
    };
    if ret < 0 { Err(ChannelError::from_raw(ret)) } else { Ok(ChanHandle::from_raw(ret as u32)) }
}

/// 销毁通道,断开所有连接
pub fn channel_close(chan: ChanHandle) -> Result<()> {
    let ret = unsafe { super::arch::syscall1(SYSNR_CHANNEL_CLOSE, chan.raw() as usize) };
    if ret < 0 { Err(ChannelError::from_raw(ret)) } else { Ok(()) }
}

/// 接收消息或 pulse
///
/// 返回 `RcvId`,通过 `is_pulse()` 判断是消息还是 pulse。
/// pulse 时 code/value 写入 iov buffer。
pub fn recv(
    chan: ChanHandle,
    iov: &mut [IoVec],
    timeout: Timeout,
    info: Option<&mut MsgInfo>,
) -> Result<RcvId> {
    let info_ptr = match info {
        Some(p) => p as *mut MsgInfo as usize,
        None => 0,
    };
    let ret = unsafe {
        super::arch::syscall5(
            SYSNR_RECV,
            chan.raw() as usize,
            iov.as_mut_ptr() as usize,
            iov.len(),
            timeout.raw() as usize,
            info_ptr,
        )
    };
    if ret < 0 { Err(ChannelError::from_raw(ret)) } else { Ok(RcvId::from_raw(ret as usize)) }
}

/// 回复消息
///
/// `status` 为 client `sendv` 的返回值(0 = 成功,非零 = 应用错误码)。支持乱序回复。
pub fn replyv(rcvid: RcvId, status: u32, iov: &[IoVec]) -> Result<()> {
    let ret = unsafe {
        super::arch::syscall4(
            SYSNR_REPLYV,
            rcvid.raw(),
            status as usize,
            iov.as_ptr() as usize,
            iov.len(),
        )
    };
    if ret < 0 { Err(ChannelError::from_raw(ret)) } else { Ok(()) }
}

/// 原子回复当前消息并接收下一条
pub fn reply_recv(
    chan: ChanHandle,
    rcvid: RcvId,
    status: u32,
    reply_iov: &[IoVec],
    recv_iov: &mut [IoVec],
    timeout: Timeout,
    info: Option<&mut MsgInfo>,
) -> Result<RcvId> {
    let args = ReplyRecvArgs {
        chan,
        rcvid,
        status,
        reply_iov: reply_iov.as_ptr(),
        reply_parts: reply_iov.len() as u32,
        recv_iov: recv_iov.as_mut_ptr(),
        recv_parts: recv_iov.len() as u32,
        timeout,
        info: match info {
            Some(p) => p as *mut MsgInfo,
            None => core::ptr::null_mut(),
        },
    };
    let ret = unsafe { super::arch::syscall1(SYSNR_REPLY_RECV, &raw const args as usize) };
    if ret < 0 { Err(ChannelError::from_raw(ret)) } else { Ok(RcvId::from_raw(ret as usize)) }
}

/// 读取 client 的发送 buffer
///
/// 返回实际读取的长度。
pub fn msg_read(rcvid: RcvId, offset: usize, buf: &mut [u8]) -> Result<usize> {
    let ret = unsafe {
        super::arch::syscall4(
            SYSNR_MSG_READ,
            rcvid.raw(),
            buf.as_mut_ptr() as usize,
            offset,
            buf.len(),
        )
    };
    if ret < 0 { Err(ChannelError::from_raw(ret)) } else { Ok(ret as usize) }
}

/// 写入 client 的回复 buffer
///
/// 返回实际写入的长度。
pub fn msg_write(rcvid: RcvId, offset: usize, data: &[u8]) -> Result<usize> {
    let ret = unsafe {
        super::arch::syscall4(
            SYSNR_MSG_WRITE,
            rcvid.raw(),
            data.as_ptr() as usize,
            offset,
            data.len(),
        )
    };
    if ret < 0 { Err(ChannelError::from_raw(ret)) } else { Ok(ret as usize) }
}

/// 查询已接收消息的详细信息
pub fn msg_info(rcvid: RcvId) -> Result<MsgInfo> {
    let mut info = MaybeUninit::<MsgInfo>::uninit();
    let ret =
        unsafe { super::arch::syscall2(SYSNR_MSG_INFO, rcvid.raw(), info.as_mut_ptr() as usize) };
    if ret < 0 { Err(ChannelError::from_raw(ret)) } else { Ok(unsafe { info.assume_init() }) }
}

/// 查询连接对应的 client 信息
pub fn connect_info(connid: ConnId) -> Result<ConnInfo> {
    let mut info = MaybeUninit::<ConnInfo>::uninit();
    let ret = unsafe {
        super::arch::syscall2(SYSNR_CONNECT_INFO, connid.raw() as usize, info.as_mut_ptr() as usize)
    };
    if ret < 0 { Err(ChannelError::from_raw(ret)) } else { Ok(unsafe { info.assume_init() }) }
}

/// 拒绝连接
///
/// 后续该连接上的 `sendv` 直接返回 `ERR_CONNECTION_REFUSED`。
pub fn connect_reject(connid: ConnId) -> Result<()> {
    let ret = unsafe { super::arch::syscall1(SYSNR_CONNECT_REJECT, connid.raw() as usize) };
    if ret < 0 { Err(ChannelError::from_raw(ret)) } else { Ok(()) }
}