use std::io;
use std::os::fd::RawFd;
use std::time::Duration;
use o3::marker::ThreadBound;
use crate::driver::token::Token;
use crate::io::fd::{Fd, FdSlot};
use crate::driver::token::kind::ACCEPT;
use crate::driver::token::kind::CONNECT;
use crate::driver::token::kind::OPEN;
use crate::driver::token::kind::READ;
use crate::driver::token::kind::RECV;
use crate::driver::token::kind::SEND;
use crate::driver::token::kind::SOCKET;
use crate::driver::token::kind::STAT;
use crate::driver::token::kind::TIMER;
use crate::driver::token::kind::WRITE;
use libc::c_char;
use libc::msghdr;
use libc::sockaddr;
use libc::socklen_t;
use libc::stat;
#[derive(Clone, Copy)]
pub struct TimerSpec {
sec: i64,
nsec: i64,
}
impl From<Duration> for TimerSpec {
fn from(value: Duration) -> Self {
Self {
sec: value.as_secs().min(i64::MAX as u64) as i64,
nsec: i64::from(value.subsec_nanos()),
}
}
}
pub(crate) enum SqeInner {
Send {
slot: FdSlot,
ptr: *const u8,
len: u32,
ud: Token,
},
WriteFd {
fd: RawFd,
ptr: *const u8,
len: u32,
offset: u64,
ud: Token,
},
OpenAt {
dir: RawFd,
path: *const c_char,
flags: i32,
mode: u32,
ud: Token,
},
Read {
fd: RawFd,
ptr: *mut u8,
len: u32,
offset: u64,
ud: Token,
},
StatPath {
path: *const c_char,
stat: *mut stat,
ud: Token,
},
StatFd {
fd: RawFd,
stat: *mut stat,
ud: Token,
},
SendMsg {
slot: FdSlot,
msg: *const msghdr,
ud: Token,
},
AcceptOneshot {
listener: FdSlot,
addr_ptr: *mut sockaddr,
addrlen_ptr: *mut socklen_t,
ud: Token,
},
RecvMulti {
slot: FdSlot,
ud: Token,
},
RecvMsgMulti {
slot: FdSlot,
msghdr: *const msghdr,
ud: Token,
},
Quickack,
Cancel {
target: Token,
},
Interval {
sec: i64,
nsec: i64,
ud: Token,
},
CancelCreate {
slot: FdSlot,
},
SocketAt {
domain: i32,
socket_type: i32,
protocol: i32,
slot: FdSlot,
ud: Token,
},
Connect {
slot: FdSlot,
addr_ptr: *const sockaddr,
addr_len: u32,
ud: Token,
},
}
pub struct Sqe(pub(crate) SqeInner, ThreadBound);
#[repr(transparent)]
pub struct RawSqe(Sqe);
impl Sqe {
fn new(inner: SqeInner) -> Self {
Self(inner, ThreadBound::NEW)
}
pub(crate) fn from_retained(retained: crate::backend::RetainedSqe) -> Self {
retained.0.0
}
}
impl RawSqe {
fn new(inner: SqeInner) -> Self {
Self(Sqe::new(inner))
}
pub fn send(fd: &Fd, buf: &[u8], op: Token) -> Self {
Self::send_at(fd.slot(), buf, op)
}
fn send_at(slot: FdSlot, buf: &[u8], op: Token) -> Self {
Self::new(SqeInner::Send {
slot,
ptr: buf.as_ptr(),
len: buf.len() as u32,
ud: op.with_kind(SEND),
})
}
pub fn write_fd(fd: RawFd, buf: &[u8], offset: u64, op: Token) -> Self {
Self::new(SqeInner::WriteFd {
fd,
ptr: buf.as_ptr(),
len: buf.len() as u32,
offset,
ud: op.with_kind(WRITE),
})
}
pub fn openat(dir: RawFd, path: *const c_char, flags: i32, mode: u32, op: Token) -> Self {
Self::new(SqeInner::OpenAt {
dir,
path,
flags,
mode,
ud: op.with_kind(OPEN),
})
}
pub fn read(fd: RawFd, buf: &mut [u8], offset: u64, op: Token) -> Self {
Self::read_raw(fd, buf.as_mut_ptr(), buf.len(), offset, op.with_kind(READ))
}
pub fn read_raw(fd: RawFd, ptr: *mut u8, len: usize, offset: u64, op: Token) -> Self {
Self::new(SqeInner::Read {
fd,
ptr,
len: len as u32,
offset,
ud: op,
})
}
pub fn stat_path(path: *const c_char, stat: *mut stat, op: Token) -> Self {
Self::new(SqeInner::StatPath {
path,
stat,
ud: op.with_kind(STAT),
})
}
pub fn stat_fd(fd: RawFd, stat: *mut stat, op: Token) -> Self {
Self::new(SqeInner::StatFd {
fd,
stat,
ud: op.with_kind(STAT),
})
}
pub fn recv_multi(fd: &Fd, _buf_group: u16, op: Token) -> Self {
Self::new(SqeInner::RecvMulti {
slot: fd.slot(),
ud: op.with_kind(RECV),
})
}
pub fn recv_discard(_fd: &Fd, _remaining: u64, _op: Token) -> Self {
unreachable!()
}
pub fn accept_oneshot(
listener: &Fd,
addr_ptr: *mut sockaddr,
addrlen_ptr: *mut socklen_t,
op: Token,
) -> Self {
Self::new(SqeInner::AcceptOneshot {
listener: listener.slot(),
addr_ptr,
addrlen_ptr,
ud: op.with_kind(ACCEPT),
})
}
pub fn recv_msg_multi(fd: &Fd, msghdr: &msghdr, _buf_group: u16, op: Token) -> Self {
Self::new(SqeInner::RecvMsgMulti {
slot: fd.slot(),
msghdr: msghdr as *const _,
ud: op.with_kind(RECV),
})
}
pub fn send_msg(fd: &Fd, msg: &msghdr, op: Token) -> Self {
Self::new(SqeInner::SendMsg {
slot: fd.slot(),
msg: msg as *const _,
ud: op.with_kind(SEND),
})
}
}
impl Sqe {
pub const SUPPORTS_RECV_DISCARD: bool = false;
pub fn quickack(_fd: &Fd) -> Self {
Self::new(SqeInner::Quickack)
}
pub fn cancel(target: Token, kind: u8) -> Self {
Self::new(SqeInner::Cancel {
target: target.with_kind(kind),
})
}
pub fn interval(timer: &'static TimerSpec, op: Token) -> Self {
Self::new(SqeInner::Interval {
sec: timer.sec,
nsec: timer.nsec,
ud: op.with_kind(TIMER),
})
}
pub fn cancel_create(slot: FdSlot) -> Self {
Self::new(SqeInner::CancelCreate { slot })
}
pub fn socket(
domain: i32,
socket_type: i32,
protocol: i32,
fd: &Fd,
op: Token,
) -> io::Result<Self> {
Self::socket_at(domain, socket_type, protocol, fd.slot(), op)
}
pub(crate) fn socket_at(
domain: i32,
socket_type: i32,
protocol: i32,
slot: FdSlot,
op: Token,
) -> io::Result<Self> {
Ok(Self::new(SqeInner::SocketAt {
domain,
socket_type,
protocol,
slot,
ud: op.with_kind(SOCKET),
}))
}
}
impl RawSqe {
pub fn connect(fd: &Fd, addr_ptr: *const sockaddr, addr_len: u32, op: Token) -> Self {
Self::new(SqeInner::Connect {
slot: fd.slot(),
addr_ptr,
addr_len,
ud: op.with_kind(CONNECT),
})
}
}