use alloc::boxed::Box;
use alloc::sync::Arc;
use alloc::vec::Vec;
use core::future::{self, Future};
use core::task::Poll::{Pending, Ready};
use core::time::Duration;
use async_trait::async_trait;
#[cfg(any(feature = "tcp", feature = "udp"))]
use smoltcp::wire::{IpEndpoint, IpListenEndpoint};
use crate::arch::kernel::core_local::core_scheduler;
use crate::executor::block_on;
use crate::fs::{DirectoryEntry, FileAttr, SeekWhence};
use crate::io;
mod eventfd;
#[cfg(any(feature = "tcp", feature = "udp", feature = "vsock"))]
pub(crate) mod socket;
pub(crate) mod stdio;
pub(crate) const STDIN_FILENO: FileDescriptor = 0;
pub(crate) const STDOUT_FILENO: FileDescriptor = 1;
pub(crate) const STDERR_FILENO: FileDescriptor = 2;
#[cfg(any(feature = "tcp", feature = "udp", feature = "vsock"))]
#[derive(Debug)]
pub(crate) enum Endpoint {
#[cfg(any(feature = "tcp", feature = "udp"))]
Ip(IpEndpoint),
#[cfg(feature = "vsock")]
Vsock(socket::vsock::VsockEndpoint),
}
#[cfg(any(feature = "tcp", feature = "udp", feature = "vsock"))]
#[derive(Debug)]
pub(crate) enum ListenEndpoint {
#[cfg(any(feature = "tcp", feature = "udp"))]
Ip(IpListenEndpoint),
#[cfg(feature = "vsock")]
Vsock(socket::vsock::VsockListenEndpoint),
}
#[allow(dead_code)]
#[derive(Debug, PartialEq)]
pub(crate) enum SocketOption {
TcpNoDelay,
}
#[allow(dead_code)]
#[derive(Debug, PartialEq)]
pub(crate) enum IoCtl {
NonBlocking,
}
pub(crate) type FileDescriptor = i32;
bitflags! {
#[derive(Debug, Copy, Clone, Default)]
pub struct OpenOption: i32 {
const O_RDONLY = 0o0000;
const O_WRONLY = 0o0001;
const O_RDWR = 0o0002;
const O_CREAT = 0o0100;
const O_EXCL = 0o0200;
const O_TRUNC = 0o1000;
const O_APPEND = 0o2000;
const O_DIRECT = 0o40000;
const O_DIRECTORY = 0o200000;
}
}
bitflags! {
#[derive(Debug, Copy, Clone, Default)]
pub struct PollEvent: i16 {
const POLLIN = 0x1;
const POLLPRI = 0x2;
const POLLOUT = 0x4;
const POLLERR = 0x8;
const POLLHUP = 0x10;
const POLLNVAL = 0x20;
const POLLRDNORM = 0x040;
const POLLRDBAND = 0x080;
const POLLWRNORM = 0x0100;
const POLLWRBAND = 0x0200;
const POLLRDHUP = 0x2000;
}
}
#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
pub struct PollFd {
pub fd: i32,
pub events: PollEvent,
pub revents: PollEvent,
}
bitflags! {
#[derive(Debug, Default, Copy, Clone)]
pub struct EventFlags: i16 {
const EFD_SEMAPHORE = 0o1;
const EFD_NONBLOCK = 0o4000;
const EFD_CLOEXEC = 0o40000;
}
}
bitflags! {
#[derive(Debug, Copy, Clone)]
pub struct AccessPermission: u32 {
const S_IFMT = 0o170000;
const S_IFSOCK = 0o140000;
const S_IFLNK = 0o120000;
const S_IFREG = 0o100000;
const S_IFBLK = 0o060000;
const S_IFDIR = 0o040000;
const S_IFCHR = 0o020000;
const S_IFIFO = 0o010000;
const S_IRUSR = 0o400;
const S_IWUSR = 0o200;
const S_IXUSR = 0o100;
const S_IRWXU = 0o700;
const S_IRGRP = 0o040;
const S_IWGRP = 0o020;
const S_IXGRP = 0o010;
const S_IRWXG = 0o070;
const S_IROTH = 0o004;
const S_IWOTH = 0o002;
const S_IXOTH = 0o001;
const S_IRWXO = 0o007;
const _ = !0;
}
}
impl Default for AccessPermission {
fn default() -> Self {
AccessPermission::from_bits(0o666).unwrap()
}
}
#[async_trait]
pub(crate) trait ObjectInterface: Sync + Send + core::fmt::Debug {
async fn poll(&self, _event: PollEvent) -> io::Result<PollEvent> {
Ok(PollEvent::empty())
}
async fn read(&self, _buf: &mut [u8]) -> io::Result<usize> {
Err(io::Error::ENOSYS)
}
async fn write(&self, _buf: &[u8]) -> io::Result<usize> {
Err(io::Error::ENOSYS)
}
async fn lseek(&self, _offset: isize, _whence: SeekWhence) -> io::Result<isize> {
Err(io::Error::EINVAL)
}
async fn fstat(&self) -> io::Result<FileAttr> {
Err(io::Error::EINVAL)
}
async fn readdir(&self) -> io::Result<Vec<DirectoryEntry>> {
Err(io::Error::EINVAL)
}
#[cfg(any(feature = "tcp", feature = "udp", feature = "vsock"))]
async fn accept(&self) -> io::Result<(Arc<dyn ObjectInterface>, Endpoint)> {
Err(io::Error::EINVAL)
}
#[cfg(any(feature = "tcp", feature = "udp", feature = "vsock"))]
async fn connect(&self, _endpoint: Endpoint) -> io::Result<()> {
Err(io::Error::EINVAL)
}
#[cfg(any(feature = "tcp", feature = "udp", feature = "vsock"))]
async fn bind(&self, _name: ListenEndpoint) -> io::Result<()> {
Err(io::Error::EINVAL)
}
#[cfg(any(feature = "tcp", feature = "udp", feature = "vsock"))]
async fn listen(&self, _backlog: i32) -> io::Result<()> {
Err(io::Error::EINVAL)
}
#[cfg(any(feature = "tcp", feature = "udp", feature = "vsock"))]
async fn setsockopt(&self, _opt: SocketOption, _optval: bool) -> io::Result<()> {
Err(io::Error::ENOTSOCK)
}
#[cfg(any(feature = "tcp", feature = "udp", feature = "vsock"))]
async fn getsockopt(&self, _opt: SocketOption) -> io::Result<bool> {
Err(io::Error::ENOTSOCK)
}
#[cfg(any(feature = "tcp", feature = "udp", feature = "vsock"))]
async fn getsockname(&self) -> io::Result<Option<Endpoint>> {
Ok(None)
}
#[cfg(any(feature = "tcp", feature = "udp", feature = "vsock"))]
#[allow(dead_code)]
async fn getpeername(&self) -> io::Result<Option<Endpoint>> {
Ok(None)
}
#[cfg(any(feature = "tcp", feature = "udp", feature = "vsock"))]
async fn recvfrom(&self, _buffer: &mut [u8]) -> io::Result<(usize, Endpoint)> {
Err(io::Error::ENOSYS)
}
#[cfg(any(feature = "tcp", feature = "udp", feature = "vsock"))]
async fn sendto(&self, _buffer: &[u8], _endpoint: Endpoint) -> io::Result<usize> {
Err(io::Error::ENOSYS)
}
#[cfg(any(feature = "tcp", feature = "udp", feature = "vsock"))]
async fn shutdown(&self, _how: i32) -> io::Result<()> {
Err(io::Error::ENOSYS)
}
async fn ioctl(&self, _cmd: IoCtl, _value: bool) -> io::Result<()> {
Err(io::Error::ENOSYS)
}
}
pub(crate) fn read(fd: FileDescriptor, buf: &mut [u8]) -> io::Result<usize> {
let obj = get_object(fd)?;
if buf.is_empty() {
return Ok(0);
}
block_on(obj.read(buf), None)
}
pub(crate) fn lseek(fd: FileDescriptor, offset: isize, whence: SeekWhence) -> io::Result<isize> {
let obj = get_object(fd)?;
block_on(obj.lseek(offset, whence), None)
}
pub(crate) fn write(fd: FileDescriptor, buf: &[u8]) -> io::Result<usize> {
let obj = get_object(fd)?;
if buf.is_empty() {
return Ok(0);
}
block_on(obj.write(buf), None)
}
async fn poll_fds(fds: &mut [PollFd]) -> io::Result<u64> {
future::poll_fn(|cx| {
let mut counter: u64 = 0;
for i in &mut *fds {
let fd = i.fd;
i.revents = PollEvent::empty();
let mut pinned_obj = core::pin::pin!(core_scheduler().get_object(fd));
if let Ready(Ok(obj)) = pinned_obj.as_mut().poll(cx) {
let mut pinned = core::pin::pin!(obj.poll(i.events));
if let Ready(Ok(e)) = pinned.as_mut().poll(cx) {
if !e.is_empty() {
counter += 1;
i.revents = e;
}
}
}
}
if counter > 0 {
Ready(Ok(counter))
} else {
Pending
}
})
.await
}
pub fn poll(fds: &mut [PollFd], timeout: Option<Duration>) -> io::Result<u64> {
let result = block_on(poll_fds(fds), timeout);
if let Err(ref e) = result {
if timeout.is_some() {
if *e == io::Error::EAGAIN {
return Ok(0);
}
}
}
result
}
pub fn fstat(fd: FileDescriptor) -> io::Result<FileAttr> {
let obj = get_object(fd)?;
block_on(obj.fstat(), None)
}
pub fn eventfd(initval: u64, flags: EventFlags) -> io::Result<FileDescriptor> {
let obj = self::eventfd::EventFd::new(initval, flags);
let fd = block_on(core_scheduler().insert_object(Arc::new(obj)), None)?;
Ok(fd)
}
pub(crate) fn get_object(fd: FileDescriptor) -> io::Result<Arc<dyn ObjectInterface>> {
block_on(core_scheduler().get_object(fd), None)
}
pub(crate) fn insert_object(obj: Arc<dyn ObjectInterface>) -> io::Result<FileDescriptor> {
block_on(core_scheduler().insert_object(obj), None)
}
pub(crate) fn dup_object(fd: FileDescriptor) -> io::Result<FileDescriptor> {
block_on(core_scheduler().dup_object(fd), None)
}
pub(crate) fn remove_object(fd: FileDescriptor) -> io::Result<Arc<dyn ObjectInterface>> {
block_on(core_scheduler().remove_object(fd), None)
}