use std::marker::PhantomData;
use std::mem::{ManuallyDrop, MaybeUninit};
use std::os::fd::RawFd;
use std::{ptr, slice};
use crate::io::{Buf, BufMut, BufMutParts, BufMutSlice, BufSlice, ReadBuf, ReadBufPool};
use crate::io_uring::io::PoolBufParts;
use crate::io_uring::op::{FdIter, FdOp, FdOpExtract, Op, OpReturn};
use crate::io_uring::{libc, sq};
use crate::net::{
AcceptFlag, AddressStorage, Domain, Level, Name, NoAddress, Opt, OptionStorage, Protocol,
RecvFlag, SendCall, SendFlag, SocketAddress, Type, option,
};
use crate::{AsyncFd, SubmissionQueue, asan, fd, msan};
pub(crate) use crate::unix::MsgHeader;
pub(crate) struct SocketOp;
impl Op for SocketOp {
type Output = AsyncFd;
type Resources = fd::Kind;
type Args = (Domain, Type, Protocol);
#[allow(clippy::cast_sign_loss)]
fn fill_submission(
fd_kind: &mut Self::Resources,
(domain, r#type, protocol): &mut Self::Args,
submission: &mut sq::Submission,
) {
submission.0.opcode = libc::IORING_OP_SOCKET as u8;
submission.0.fd = domain.0;
submission.0.__bindgen_anon_1 = libc::io_uring_sqe__bindgen_ty_1 {
off: r#type.0.into(),
};
submission.0.len = protocol.0;
submission.0.__bindgen_anon_3 = libc::io_uring_sqe__bindgen_ty_3 { rw_flags: 0 };
fd_kind.create_flags(submission);
}
#[allow(clippy::cast_possible_wrap)]
fn map_ok(sq: &SubmissionQueue, fd_kind: Self::Resources, (_, fd): OpReturn) -> Self::Output {
unsafe { AsyncFd::from_raw(fd as RawFd, fd_kind, sq.clone()) }
}
}
pub(crate) struct BindOp<A>(PhantomData<*const A>);
impl<A: SocketAddress> FdOp for BindOp<A> {
type Output = ();
type Resources = AddressStorage<A::Storage>;
type Args = ();
fn fill_submission(
fd: &AsyncFd,
address: &mut Self::Resources,
(): &mut Self::Args,
submission: &mut sq::Submission,
) {
submission.0.opcode = libc::IORING_OP_BIND as u8;
submission.0.fd = fd.fd();
let (ptr, length) = unsafe { A::as_ptr(&address.0) };
submission.0.__bindgen_anon_1 = libc::io_uring_sqe__bindgen_ty_1 {
addr2: u64::from(length),
};
submission.0.__bindgen_anon_2 = libc::io_uring_sqe__bindgen_ty_2 {
addr: ptr.addr() as u64,
};
}
fn map_ok(_: &AsyncFd, _: Self::Resources, (_, n): OpReturn) -> Self::Output {
debug_assert!(n == 0);
}
}
pub(crate) struct ListenOp;
impl FdOp for ListenOp {
type Output = ();
type Resources = ();
type Args = libc::c_int;
#[allow(clippy::cast_sign_loss)]
fn fill_submission(
fd: &AsyncFd,
(): &mut Self::Resources,
backlog: &mut Self::Args,
submission: &mut sq::Submission,
) {
submission.0.opcode = libc::IORING_OP_LISTEN as u8;
submission.0.fd = fd.fd();
submission.0.len = *backlog as u32;
}
fn map_ok(_: &AsyncFd, (): Self::Resources, (_, n): OpReturn) -> Self::Output {
debug_assert!(n == 0);
}
}
pub(crate) struct ConnectOp<A>(PhantomData<*const A>);
impl<A: SocketAddress> FdOp for ConnectOp<A> {
type Output = ();
type Resources = AddressStorage<A::Storage>;
type Args = ();
fn fill_submission(
fd: &AsyncFd,
address: &mut Self::Resources,
(): &mut Self::Args,
submission: &mut sq::Submission,
) {
submission.0.opcode = libc::IORING_OP_CONNECT as u8;
submission.0.fd = fd.fd();
let (ptr, length) = unsafe { A::as_ptr(&address.0) };
submission.0.__bindgen_anon_1 = libc::io_uring_sqe__bindgen_ty_1 {
off: u64::from(length),
};
submission.0.__bindgen_anon_2 = libc::io_uring_sqe__bindgen_ty_2 {
addr: ptr.addr() as u64,
};
}
fn map_ok(_: &AsyncFd, _: Self::Resources, (_, n): OpReturn) -> Self::Output {
debug_assert!(n == 0);
}
}
pub(crate) struct SocketNameOp<A>(PhantomData<*const A>);
impl<A: SocketAddress> FdOp for SocketNameOp<A> {
type Output = A;
type Resources = AddressStorage<(MaybeUninit<A::Storage>, libc::socklen_t)>;
type Args = Name;
fn fill_submission(
fd: &AsyncFd,
resources: &mut Self::Resources,
name: &mut Self::Args,
submission: &mut sq::Submission,
) {
let (ptr, length) = unsafe { A::as_mut_ptr(&mut (resources.0).0) };
let address_length = &mut (resources.0).1;
*address_length = length;
submission.0.opcode = libc::IORING_OP_URING_CMD as u8;
submission.0.fd = fd.fd();
submission.0.__bindgen_anon_1 = libc::io_uring_sqe__bindgen_ty_1 {
__bindgen_anon_1: libc::io_uring_sqe__bindgen_ty_1__bindgen_ty_1 {
cmd_op: libc::SOCKET_URING_OP_GETSOCKNAME,
__pad1: 0,
},
};
submission.0.__bindgen_anon_2 = libc::io_uring_sqe__bindgen_ty_2 {
addr: ptr.addr() as u64,
};
submission.0.__bindgen_anon_5 = libc::io_uring_sqe__bindgen_ty_5 {
optlen: match name {
Name::Local => 1,
Name::Peer => 0,
},
};
submission.0.__bindgen_anon_6 = libc::io_uring_sqe__bindgen_ty_6 {
__bindgen_anon_1: ManuallyDrop::new(libc::io_uring_sqe__bindgen_ty_6__bindgen_ty_1 {
addr3: ptr::from_mut(address_length).addr() as u64,
__pad2: [0; 1],
}),
};
}
fn map_ok(_: &AsyncFd, resources: Self::Resources, _: OpReturn) -> Self::Output {
msan::unpoison_region(
ptr::from_ref(&(resources.0).1).cast(),
size_of::<libc::socklen_t>(),
);
msan::unpoison_region((resources.0).0.as_ptr().cast(), (resources.0).1 as usize);
unsafe { A::init((resources.0).0, (resources.0).1) }
}
}
pub(crate) struct RecvOp<B>(PhantomData<*const B>);
impl<B: BufMut> FdOp for RecvOp<B> {
type Output = B;
type Resources = B;
type Args = RecvFlag;
#[allow(clippy::cast_sign_loss)]
fn fill_submission(
fd: &AsyncFd,
buf: &mut Self::Resources,
flags: &mut Self::Args,
submission: &mut sq::Submission,
) {
submission.0.opcode = libc::IORING_OP_RECV as u8;
submission.0.fd = fd.fd();
submission.0.__bindgen_anon_3 = libc::io_uring_sqe__bindgen_ty_3 { msg_flags: flags.0 };
match buf.parts() {
BufMutParts::Buf { ptr, len } => {
submission.0.__bindgen_anon_2 = libc::io_uring_sqe__bindgen_ty_2 {
addr: ptr.addr() as u64,
};
submission.0.len = len;
asan::poison_region(ptr.cast(), len as usize);
}
BufMutParts::Pool(PoolBufParts(buf_group)) => {
submission.0.__bindgen_anon_4.buf_group = buf_group;
submission.0.flags |= libc::IOSQE_BUFFER_SELECT;
}
}
}
fn map_ok(_: &AsyncFd, mut buf: Self::Resources, (flags, n): OpReturn) -> Self::Output {
let (ptr, len) = unsafe { buf.parts_mut() };
if let Some(buf_id) = flags.buf_id() {
unsafe { buf.buffer_init(buf_id, n) };
} else {
asan::unpoison_region(ptr.cast(), len as usize);
msan::unpoison_region(ptr.cast(), n as usize);
unsafe { buf.set_init(n as usize) };
}
buf
}
}
pub(crate) struct MultishotRecvOp;
impl FdIter for MultishotRecvOp {
type Output = ReadBuf;
type Resources = ReadBufPool;
type Args = RecvFlag;
#[allow(clippy::cast_sign_loss)]
fn fill_submission(
fd: &AsyncFd,
buf_pool: &mut Self::Resources,
flags: &mut Self::Args,
submission: &mut sq::Submission,
) {
submission.0.opcode = libc::IORING_OP_RECV as u8;
submission.0.flags |= libc::IOSQE_BUFFER_SELECT;
submission.0.ioprio = libc::IORING_RECV_MULTISHOT as u16;
submission.0.fd = fd.fd();
submission.0.__bindgen_anon_3 = libc::io_uring_sqe__bindgen_ty_3 { msg_flags: flags.0 };
submission.0.__bindgen_anon_4.buf_group = buf_pool.shared.group_id();
}
fn map_next(_: &AsyncFd, buf_pool: &Self::Resources, (flags, n): OpReturn) -> Self::Output {
if let Some(buf_id) = flags.buf_id() {
unsafe { buf_pool.new_buffer(buf_id, n) }
} else {
debug_assert!(n == 0);
buf_pool.empty_buffer()
}
}
}
pub(crate) struct RecvVectoredOp<B, const N: usize>(PhantomData<*const B>);
impl<B: BufMutSlice<N>, const N: usize> FdOp for RecvVectoredOp<B, N> {
type Output = (B, libc::c_int);
type Resources = (B, MsgHeader, [crate::io::IoMutSlice; N]);
type Args = RecvFlag;
fn fill_submission(
fd: &AsyncFd,
(_, msg, iovecs): &mut Self::Resources,
flags: &mut Self::Args,
submission: &mut sq::Submission,
) {
let address = &mut MaybeUninit::new(NoAddress);
fill_recvmsg_submission::<NoAddress>(fd.fd(), msg, iovecs, address, *flags, submission);
}
fn map_ok(
_: &AsyncFd,
(mut bufs, msg, iovecs): Self::Resources,
(_, n): OpReturn,
) -> Self::Output {
asan::unpoison_iovecs_mut(&iovecs);
msan::unpoison_iovecs_mut(&iovecs, n as usize);
unsafe { bufs.set_init(n as usize) };
(bufs, msg.flags())
}
}
pub(crate) struct RecvFromOp<B, A>(PhantomData<*const (B, A)>);
impl<B: BufMut, A: SocketAddress> FdOp for RecvFromOp<B, A> {
type Output = (B, A, libc::c_int);
type Resources = (B, MsgHeader, crate::io::IoMutSlice, MaybeUninit<A::Storage>);
type Args = RecvFlag;
fn fill_submission(
fd: &AsyncFd,
(buf, msg, iovec, address): &mut Self::Resources,
flags: &mut Self::Args,
submission: &mut sq::Submission,
) {
let iovecs = slice::from_mut(&mut *iovec);
fill_recvmsg_submission::<A>(fd.fd(), msg, iovecs, address, *flags, submission);
match buf.parts() {
BufMutParts::Buf { ptr, len } => {
asan::poison_region(ptr.cast(), len as usize);
}
BufMutParts::Pool(PoolBufParts(buf_group)) => {
submission.0.__bindgen_anon_4.buf_group = buf_group;
submission.0.flags |= libc::IOSQE_BUFFER_SELECT;
}
}
}
fn map_ok(
_: &AsyncFd,
(mut buf, msg, iovec, address): Self::Resources,
(flags, n): OpReturn,
) -> Self::Output {
msan::unpoison_region(address.as_ptr().cast(), msg.address_len() as usize);
if let Some(buf_id) = flags.buf_id() {
unsafe { buf.buffer_init(buf_id, n) };
} else {
asan::unpoison_iovecs_mut(slice::from_ref(&iovec));
msan::unpoison_iovecs_mut(slice::from_ref(&iovec), n as usize);
unsafe { buf.set_init(n as usize) };
}
let address = unsafe { A::init(address, msg.address_len()) };
(buf, address, msg.flags())
}
}
pub(crate) struct RecvFromVectoredOp<B, A, const N: usize>(PhantomData<*const (B, A)>);
impl<B: BufMutSlice<N>, A: SocketAddress, const N: usize> FdOp for RecvFromVectoredOp<B, A, N> {
type Output = (B, A, libc::c_int);
type Resources = (
B,
MsgHeader,
[crate::io::IoMutSlice; N],
MaybeUninit<A::Storage>,
);
type Args = RecvFlag;
fn fill_submission(
fd: &AsyncFd,
(_, msg, iovecs, address): &mut Self::Resources,
flags: &mut Self::Args,
submission: &mut sq::Submission,
) {
fill_recvmsg_submission::<A>(fd.fd(), msg, iovecs, address, *flags, submission);
}
fn map_ok(
_: &AsyncFd,
(mut bufs, msg, iovecs, address): Self::Resources,
(_, n): OpReturn,
) -> Self::Output {
asan::unpoison_iovecs_mut(&iovecs);
msan::unpoison_iovecs_mut(&iovecs, n as usize);
msan::unpoison_region(address.as_ptr().cast(), msg.address_len() as usize);
unsafe { bufs.set_init(n as usize) };
let address = unsafe { A::init(address, msg.address_len()) };
(bufs, address, msg.flags())
}
}
#[allow(clippy::cast_sign_loss)] fn fill_recvmsg_submission<A: SocketAddress>(
fd: RawFd,
msg: &mut MsgHeader,
iovecs: &mut [crate::io::IoMutSlice],
address: &mut MaybeUninit<A::Storage>,
flags: RecvFlag,
submission: &mut sq::Submission,
) {
let ptr = unsafe { msg.init_recv::<A>(address, iovecs) };
submission.0.opcode = libc::IORING_OP_RECVMSG as u8;
submission.0.fd = fd;
submission.0.__bindgen_anon_2 = libc::io_uring_sqe__bindgen_ty_2 {
addr: ptr.addr() as u64,
};
asan::poison_iovecs_mut(iovecs);
submission.0.__bindgen_anon_3 = libc::io_uring_sqe__bindgen_ty_3 { msg_flags: flags.0 };
submission.0.len = 1;
}
pub(crate) struct SendOp<B>(PhantomData<*const B>);
impl<B: Buf> FdOp for SendOp<B> {
type Output = usize;
type Resources = B;
type Args = (SendCall, SendFlag);
#[allow(clippy::cast_sign_loss)]
fn fill_submission(
fd: &AsyncFd,
buf: &mut Self::Resources,
(send_op, flags): &mut Self::Args,
submission: &mut sq::Submission,
) {
submission.0.opcode = match *send_op {
SendCall::Normal => libc::IORING_OP_SEND as u8,
SendCall::ZeroCopy => libc::IORING_OP_SEND_ZC as u8,
};
let (buf_ptr, buf_len) = unsafe { buf.parts() };
submission.0.fd = fd.fd();
submission.0.__bindgen_anon_2 = libc::io_uring_sqe__bindgen_ty_2 {
addr: buf_ptr.addr() as u64,
};
asan::poison_region(buf_ptr.cast(), buf_len as usize);
submission.0.__bindgen_anon_3 = libc::io_uring_sqe__bindgen_ty_3 { msg_flags: flags.0 };
submission.0.len = buf_len;
}
fn map_ok(fd: &AsyncFd, resources: Self::Resources, ret: OpReturn) -> Self::Output {
Self::map_ok_extract(fd, resources, ret).1
}
}
impl<B: Buf> FdOpExtract for SendOp<B> {
type ExtractOutput = (B, usize);
fn map_ok_extract(_: &AsyncFd, buf: Self::Resources, (_, n): OpReturn) -> Self::ExtractOutput {
let (ptr, len) = unsafe { buf.parts() };
asan::unpoison_region(ptr.cast(), len as usize);
(buf, n as usize)
}
}
pub(crate) struct SendToOp<B, A = NoAddress>(PhantomData<*const (B, A)>);
impl<B: Buf, A: SocketAddress> FdOp for SendToOp<B, A> {
type Output = usize;
type Resources = (B, AddressStorage<A::Storage>);
type Args = (SendCall, SendFlag);
#[allow(clippy::cast_sign_loss)]
fn fill_submission(
fd: &AsyncFd,
(buf, address): &mut Self::Resources,
(send_op, flags): &mut Self::Args,
submission: &mut sq::Submission,
) {
submission.0.opcode = match *send_op {
SendCall::Normal => libc::IORING_OP_SEND as u8,
SendCall::ZeroCopy => libc::IORING_OP_SEND_ZC as u8,
};
let (buf_ptr, buf_len) = unsafe { buf.parts() };
let (address_ptr, address_length) = unsafe { A::as_ptr(&address.0) };
submission.0.fd = fd.fd();
submission.0.__bindgen_anon_1.addr2 = address_ptr.addr() as u64;
submission.0.__bindgen_anon_2 = libc::io_uring_sqe__bindgen_ty_2 {
addr: buf_ptr.addr() as u64,
};
asan::poison_region(buf_ptr.cast(), buf_len as usize);
submission.0.__bindgen_anon_3 = libc::io_uring_sqe__bindgen_ty_3 { msg_flags: flags.0 };
submission.0.__bindgen_anon_5.__bindgen_anon_1.addr_len = address_length as u16;
submission.0.len = buf_len;
}
fn map_ok(fd: &AsyncFd, resources: Self::Resources, ret: OpReturn) -> Self::Output {
Self::map_ok_extract(fd, resources, ret).1
}
}
impl<B: Buf, A: SocketAddress> FdOpExtract for SendToOp<B, A> {
type ExtractOutput = (B, usize);
fn map_ok_extract(
_: &AsyncFd,
(buf, _): Self::Resources,
(_, n): OpReturn,
) -> Self::ExtractOutput {
let (buf_ptr, buf_len) = unsafe { buf.parts() };
asan::unpoison_region(buf_ptr.cast(), buf_len as usize);
(buf, n as usize)
}
}
pub(crate) struct SendMsgOp<B, A, const N: usize>(PhantomData<*const (B, A)>);
impl<B: BufSlice<N>, A: SocketAddress, const N: usize> FdOp for SendMsgOp<B, A, N> {
type Output = usize;
type Resources = (
B,
MsgHeader,
[crate::io::IoSlice; N],
AddressStorage<A::Storage>,
);
type Args = (SendCall, SendFlag);
#[allow(clippy::cast_sign_loss)]
fn fill_submission(
fd: &AsyncFd,
(_, msg, iovecs, address): &mut Self::Resources,
(send_op, flags): &mut Self::Args,
submission: &mut sq::Submission,
) {
let ptr = unsafe { msg.init_send::<A>(&mut address.0, iovecs) };
submission.0.opcode = match *send_op {
SendCall::Normal => libc::IORING_OP_SENDMSG as u8,
SendCall::ZeroCopy => libc::IORING_OP_SENDMSG_ZC as u8,
};
submission.0.fd = fd.fd();
submission.0.__bindgen_anon_2 = libc::io_uring_sqe__bindgen_ty_2 {
addr: ptr.addr() as u64,
};
asan::poison_iovecs(iovecs);
submission.0.__bindgen_anon_3 = libc::io_uring_sqe__bindgen_ty_3 { msg_flags: flags.0 };
submission.0.len = 1;
}
fn map_ok(fd: &AsyncFd, resources: Self::Resources, ret: OpReturn) -> Self::Output {
Self::map_ok_extract(fd, resources, ret).1
}
}
impl<B: BufSlice<N>, A: SocketAddress, const N: usize> FdOpExtract for SendMsgOp<B, A, N> {
type ExtractOutput = (B, usize);
fn map_ok_extract(
_: &AsyncFd,
(buf, _, iovecs, _): Self::Resources,
(_, n): OpReturn,
) -> Self::ExtractOutput {
asan::unpoison_iovecs(&iovecs);
(buf, n as usize)
}
}
pub(crate) struct AcceptOp<A>(PhantomData<*const A>);
impl<A: SocketAddress> FdOp for AcceptOp<A> {
type Output = (AsyncFd, A);
type Resources = AddressStorage<(MaybeUninit<A::Storage>, libc::socklen_t)>;
type Args = AcceptFlag;
#[allow(clippy::cast_sign_loss)] fn fill_submission(
fd: &AsyncFd,
resources: &mut Self::Resources,
flags: &mut Self::Args,
submission: &mut sq::Submission,
) {
let fd_kind = fd.kind();
let (ptr, length) = unsafe { A::as_mut_ptr(&mut (resources.0).0) };
let address_length = &mut (resources.0).1;
*address_length = length;
submission.0.opcode = libc::IORING_OP_ACCEPT as u8;
submission.0.fd = fd.fd();
submission.0.__bindgen_anon_1 = libc::io_uring_sqe__bindgen_ty_1 {
off: ptr::from_mut(address_length).addr() as u64,
};
submission.0.__bindgen_anon_2 = libc::io_uring_sqe__bindgen_ty_2 {
addr: ptr.addr() as u64,
};
submission.0.__bindgen_anon_3 = libc::io_uring_sqe__bindgen_ty_3 {
accept_flags: flags.0 | fd_kind.cloexec_flag() as u32,
};
submission.set_async();
fd_kind.create_flags(submission);
}
#[allow(clippy::cast_possible_wrap)]
fn map_ok(lfd: &AsyncFd, resources: Self::Resources, (_, fd): OpReturn) -> Self::Output {
msan::unpoison_region(
ptr::from_ref(&(resources.0).1).cast(),
size_of::<libc::socklen_t>(),
);
msan::unpoison_region((resources.0).0.as_ptr().cast(), (resources.0).1 as usize);
let sq = lfd.sq.clone();
let socket = unsafe { AsyncFd::from_raw(fd as RawFd, lfd.kind(), sq) };
let address = unsafe { A::init((resources.0).0, (resources.0).1) };
(socket, address)
}
}
pub(crate) struct MultishotAcceptOp;
impl FdIter for MultishotAcceptOp {
type Output = AsyncFd;
type Resources = ();
type Args = AcceptFlag;
#[allow(clippy::cast_sign_loss)] fn fill_submission(
fd: &AsyncFd,
(): &mut Self::Resources,
flags: &mut Self::Args,
submission: &mut sq::Submission,
) {
let fd_kind = fd.kind();
submission.0.opcode = libc::IORING_OP_ACCEPT as u8;
submission.0.ioprio = libc::IORING_ACCEPT_MULTISHOT as u16;
submission.0.fd = fd.fd();
submission.0.__bindgen_anon_3 = libc::io_uring_sqe__bindgen_ty_3 {
accept_flags: flags.0 | fd_kind.cloexec_flag() as u32,
};
submission.set_async();
fd_kind.create_flags(submission);
}
#[allow(clippy::cast_possible_wrap)]
fn map_next(lfd: &AsyncFd, (): &Self::Resources, (_, fd): OpReturn) -> Self::Output {
let sq = lfd.sq.clone();
unsafe { AsyncFd::from_raw(fd as RawFd, lfd.kind(), sq) }
}
}
pub(crate) struct SocketOptionOp<T>(PhantomData<*const T>);
impl<T: option::Get> FdOp for SocketOptionOp<T> {
type Output = T::Output;
type Resources = OptionStorage<MaybeUninit<T::Storage>>;
type Args = (Level, Opt);
#[allow(clippy::cast_sign_loss)] fn fill_submission(
fd: &AsyncFd,
value: &mut Self::Resources,
(level, optname): &mut Self::Args,
submission: &mut sq::Submission,
) {
submission.0.opcode = libc::IORING_OP_URING_CMD as u8;
submission.0.fd = fd.fd();
submission.0.__bindgen_anon_1 = libc::io_uring_sqe__bindgen_ty_1 {
__bindgen_anon_1: libc::io_uring_sqe__bindgen_ty_1__bindgen_ty_1 {
cmd_op: libc::SOCKET_URING_OP_GETSOCKOPT,
__pad1: 0,
},
};
submission.0.__bindgen_anon_2 = libc::io_uring_sqe__bindgen_ty_2 {
__bindgen_anon_1: libc::io_uring_sqe__bindgen_ty_2__bindgen_ty_1 {
level: level.0,
optname: optname.0,
},
};
let (optval, optlen) = unsafe { T::as_mut_ptr(&mut value.0) };
submission.0.__bindgen_anon_5 = libc::io_uring_sqe__bindgen_ty_5 { optlen };
submission.0.__bindgen_anon_6 = libc::io_uring_sqe__bindgen_ty_6 {
optval: ManuallyDrop::new(optval.addr() as u64),
};
asan::poison_region(optval.cast_const().cast(), optlen as usize);
}
fn map_ok(_: &AsyncFd, mut value: Self::Resources, (_, n): OpReturn) -> Self::Output {
let (_, optlen) = unsafe { T::as_mut_ptr(&mut value.0) };
asan::unpoison_region(value.0.as_ptr().cast(), optlen as usize);
msan::unpoison_region(value.0.as_ptr().cast(), n as usize);
unsafe { T::init(value.0, n) }
}
}
pub(crate) struct SetSocketOptionOp<T>(PhantomData<*const T>);
impl<T: option::Set> FdOp for SetSocketOptionOp<T> {
type Output = ();
type Resources = OptionStorage<T::Storage>;
type Args = (Level, Opt);
#[allow(clippy::cast_sign_loss)] fn fill_submission(
fd: &AsyncFd,
value: &mut Self::Resources,
(level, optname): &mut Self::Args,
submission: &mut sq::Submission,
) {
submission.0.opcode = libc::IORING_OP_URING_CMD as u8;
submission.0.fd = fd.fd();
submission.0.__bindgen_anon_1 = libc::io_uring_sqe__bindgen_ty_1 {
__bindgen_anon_1: libc::io_uring_sqe__bindgen_ty_1__bindgen_ty_1 {
cmd_op: libc::SOCKET_URING_OP_SETSOCKOPT,
__pad1: 0,
},
};
submission.0.__bindgen_anon_2 = libc::io_uring_sqe__bindgen_ty_2 {
__bindgen_anon_1: libc::io_uring_sqe__bindgen_ty_2__bindgen_ty_1 {
level: level.0,
optname: optname.0,
},
};
submission.0.__bindgen_anon_5 = libc::io_uring_sqe__bindgen_ty_5 {
optlen: size_of::<T::Storage>() as u32,
};
submission.0.__bindgen_anon_6 = libc::io_uring_sqe__bindgen_ty_6 {
optval: ManuallyDrop::new(ptr::from_ref(&value.0).addr() as u64),
};
asan::poison_region(ptr::from_ref(&value.0).cast(), size_of::<T::Storage>());
}
fn map_ok(_: &AsyncFd, value: Self::Resources, (_, n): OpReturn) -> Self::Output {
asan::unpoison_region(ptr::from_ref(&value.0).cast(), size_of::<T::Storage>());
debug_assert!(n == 0);
}
}
pub(crate) struct ShutdownOp;
impl FdOp for ShutdownOp {
type Output = ();
type Resources = ();
type Args = std::net::Shutdown;
#[allow(clippy::cast_sign_loss)] fn fill_submission(
fd: &AsyncFd,
(): &mut Self::Resources,
how: &mut Self::Args,
submission: &mut sq::Submission,
) {
submission.0.opcode = libc::IORING_OP_SHUTDOWN as u8;
submission.0.fd = fd.fd();
submission.0.len = match how {
std::net::Shutdown::Read => libc::SHUT_RD,
std::net::Shutdown::Write => libc::SHUT_WR,
std::net::Shutdown::Both => libc::SHUT_RDWR,
} as u32;
}
fn map_ok(_: &AsyncFd, (): Self::Resources, (_, n): OpReturn) -> Self::Output {
debug_assert!(n == 0);
}
}