use std::io;
use std::os::fd::{FromRawFd, RawFd};
use crate::driver::backends::iouring::{MultishotCleanup, Submission as UringSubmission, UringMultishotOperation};
use crate::driver::helpers::io_handle::SharedIoHandle;
use crate::driver::helpers::socket::Socket;
use crate::driver::ops::{Completion, MultiOp};
use crate::runtime::local::CURRENT_DRIVER;
pub(crate) struct AcceptMulti {
io_handle: SharedIoHandle<socket2::Socket>,
pending_completion_limit: usize,
}
impl MultiOp<AcceptMulti> {
pub(crate) fn accept_multi(io_handle: &SharedIoHandle<socket2::Socket>) -> io::Result<Self> {
CURRENT_DRIVER.with(|handle| {
let driver = handle.upgrade().expect("Not in a runtime context");
let data = AcceptMulti {
io_handle: io_handle.clone(),
pending_completion_limit: driver.multishot_accept_capacity(),
};
Ok(driver.defer_multi_op(data))
})
}
}
unsafe impl UringMultishotOperation for AcceptMulti {
type Item = io::Result<Socket>;
fn submit(&mut self) -> UringSubmission {
use io_uring::{opcode, types};
opcode::AcceptMulti::new(types::Fd(self.io_handle.raw_fd()))
.flags(libc::SOCK_CLOEXEC | libc::SOCK_NONBLOCK)
.build()
}
fn complete_item(&mut self, completion: Completion) -> Option<Self::Item> {
Some((|| {
let raw_fd = completion.result? as RawFd;
let sock = unsafe { socket2::Socket::from_raw_fd(raw_fd) };
let socket = Socket::from_socket(sock)?;
socket.set_async_flags()?;
Ok(socket)
})())
}
fn submission_error(error: io::Error) -> Self::Item {
Err(error)
}
fn completion_cleanup(&self) -> MultishotCleanup {
MultishotCleanup::AcceptedFd
}
fn pending_completion_limit(&self) -> Option<usize> {
Some(self.pending_completion_limit)
}
}