diff --git a/Cargo.toml b/Cargo.toml index 6be63c75d2..ae55d65676 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -85,6 +85,3 @@ lto = true [patch.crates-io] crate_interface = { path = "crates/crate_interface" } - -[patch."https://github.com/rcore-os/smoltcp.git"] -smoltcp = { git = "https://github.com/c0per/smoltcp", branch = "starryos" } diff --git a/modules/axnet/Cargo.toml b/modules/axnet/Cargo.toml index ecfc518e34..69f4f1cd05 100644 --- a/modules/axnet/Cargo.toml +++ b/modules/axnet/Cargo.toml @@ -15,7 +15,9 @@ smoltcp = [] # 启用ip协议与否 ip = [] -default = ["smoltcp"] +signal = [] + +default = ["smoltcp", "signal"] [dependencies] log = "0.4" @@ -29,10 +31,11 @@ axsync = { path = "../axsync" } axtask = { path = "../axtask" } axdriver = { path = "../axdriver", features = ["net"] } axio = { path = "../../crates/axio" } +crate_interface = { path = "../../crates/crate_interface" } [dependencies.smoltcp] git = "https://github.com/rcore-os/smoltcp.git" -rev = "2ade274" +rev = "b7134a3" default-features = false features = [ "alloc", "log", # no std diff --git a/modules/axnet/src/smoltcp_impl/mod.rs b/modules/axnet/src/smoltcp_impl/mod.rs index 57026a790f..881b2abc12 100644 --- a/modules/axnet/src/smoltcp_impl/mod.rs +++ b/modules/axnet/src/smoltcp_impl/mod.rs @@ -92,11 +92,11 @@ impl<'a> SocketSetWrapper<'a> { pub fn new_udp_socket() -> socket::udp::Socket<'a> { let udp_rx_buffer = socket::udp::PacketBuffer::new( - vec![socket::udp::PacketMetadata::EMPTY; 8], + vec![socket::udp::PacketMetadata::EMPTY; 256], vec![0; UDP_RX_BUF_LEN], ); let udp_tx_buffer = socket::udp::PacketBuffer::new( - vec![socket::udp::PacketMetadata::EMPTY; 8], + vec![socket::udp::PacketMetadata::EMPTY; 256], vec![0; UDP_TX_BUF_LEN], ); socket::udp::Socket::new(udp_rx_buffer, udp_tx_buffer) diff --git a/modules/axnet/src/smoltcp_impl/tcp.rs b/modules/axnet/src/smoltcp_impl/tcp.rs index 7521acc407..a0d756b1be 100644 --- a/modules/axnet/src/smoltcp_impl/tcp.rs +++ b/modules/axnet/src/smoltcp_impl/tcp.rs @@ -12,6 +12,9 @@ use smoltcp::iface::SocketHandle; use smoltcp::socket::tcp::{self, ConnectError, State}; use smoltcp::wire::{IpEndpoint, IpListenEndpoint}; +#[cfg(feature = "signal")] +use crate_interface::{call_interface, def_interface}; + use super::addr::{from_core_sockaddr, into_core_sockaddr, is_unspecified, UNSPECIFIED_ENDPOINT}; use super::{SocketSetWrapper, LISTEN_TABLE, SOCKET_SET}; @@ -27,6 +30,16 @@ const STATE_CONNECTING: u8 = 2; const STATE_CONNECTED: u8 = 3; const STATE_LISTENING: u8 = 4; +#[cfg(feature = "signal")] +#[def_interface] +/// Handler to send signals. +pub trait SignalCaller { + /// Handles interrupt requests for the given IRQ number. + fn send_signal(tid: isize, signum: isize); + /// Return true if current task have a signal pending. + fn current_have_signal() -> bool; +} + /// A TCP socket that provides POSIX-like APIs. /// /// - [`connect`] is for TCP clients. @@ -307,19 +320,19 @@ impl TcpSocket { let handle = unsafe { self.handle.get().read().unwrap() }; self.block_on(|| { SOCKET_SET.with_socket_mut::(handle, |socket| { - if !socket.is_active() { - // not open - ax_err!(ConnectionRefused, "socket recv() failed") - } else if !socket.may_recv() { - // connection closed - Ok(0) - } else if socket.recv_queue() > 0 { + if socket.recv_queue() > 0 { // data available // TODO: use socket.recv(|buf| {...}) let len = socket .recv_slice(buf) .map_err(|_| ax_err_type!(BadState, "socket recv() failed"))?; Ok(len) + } else if !socket.is_active() { + // not open + ax_err!(ConnectionRefused, "socket recv() failed") + } else if !socket.may_recv() { + // connection closed + Ok(0) } else { // no more data Err(AxError::WouldBlock) @@ -343,19 +356,19 @@ impl TcpSocket { let handle = unsafe { self.handle.get().read().unwrap() }; self.block_on(|| { SOCKET_SET.with_socket_mut::(handle, |socket| { - if !socket.is_active() { - // not open - ax_err!(ConnectionRefused, "socket recv() failed") - } else if !socket.may_recv() { - // connection closed - Ok(0) - } else if socket.recv_queue() > 0 { + if socket.recv_queue() > 0 { // data available // TODO: use socket.recv(|buf| {...}) let len = socket .recv_slice(buf) .map_err(|_| ax_err_type!(BadState, "socket recv() failed"))?; Ok(len) + } else if !socket.is_active() { + // not open + ax_err!(ConnectionRefused, "socket recv() failed") + } else if !socket.may_recv() { + // connection closed + Ok(0) } else { // no more data if current_ticks() > expire_at { @@ -609,6 +622,10 @@ impl TcpSocket { f() } else { loop { + #[cfg(feature = "signal")] + if call_interface!(SignalCaller::current_have_signal) { + return Err(AxError::Interrupted); + } SOCKET_SET.poll_interfaces(); match f() { Ok(t) => return Ok(t), diff --git a/modules/axnet/src/smoltcp_impl/udp.rs b/modules/axnet/src/smoltcp_impl/udp.rs index 1e65914014..25b0b15c63 100644 --- a/modules/axnet/src/smoltcp_impl/udp.rs +++ b/modules/axnet/src/smoltcp_impl/udp.rs @@ -7,6 +7,9 @@ use axio::{PollState, Read, Write}; use axsync::Mutex; use spin::RwLock; +#[cfg(feature = "signal")] +use crate_interface::{call_interface, def_interface}; + use smoltcp::iface::SocketHandle; use smoltcp::socket::udp::{self, BindError, SendError}; use smoltcp::wire::{IpEndpoint, IpListenEndpoint}; @@ -14,12 +17,23 @@ use smoltcp::wire::{IpEndpoint, IpListenEndpoint}; use super::addr::{from_core_sockaddr, into_core_sockaddr, is_unspecified, UNSPECIFIED_ENDPOINT}; use super::{SocketSetWrapper, SOCKET_SET}; +#[cfg(feature = "signal")] +#[def_interface] +/// Handler to send signals. +pub trait SignalCaller { + /// Handles interrupt requests for the given IRQ number. + fn send_signal(tid: isize, signum: isize); + /// Return true if current task have a signal pending. + fn current_have_signal() -> bool; +} + /// A UDP socket that provides POSIX-like APIs. pub struct UdpSocket { handle: SocketHandle, local_addr: RwLock>, peer_addr: RwLock>, nonblock: AtomicBool, + reuse_addr: AtomicBool, } impl UdpSocket { @@ -33,6 +47,7 @@ impl UdpSocket { local_addr: RwLock::new(None), peer_addr: RwLock::new(None), nonblock: AtomicBool::new(false), + reuse_addr: AtomicBool::new(false), } } @@ -79,6 +94,22 @@ impl UdpSocket { }); } + /// Returns whether this socket is in reuse address mode. + #[inline] + pub fn is_reuse_addr(&self) -> bool { + self.reuse_addr.load(Ordering::Acquire) + } + + /// Moves this UDP socket into or out of reuse address mode. + /// + /// When a socket is bound, the `SO_REUSEADDR` option allows multiple sockets to be bound to the + /// same address if they are bound to different local addresses. This option must be set before + /// calling `bind`. + #[inline] + pub fn set_reuse_addr(&self, reuse_addr: bool) { + self.reuse_addr.store(reuse_addr, Ordering::Release); + } + /// Binds an unbound socket to the given address and port. /// /// It's must be called before [`send_to`](Self::send_to) and @@ -99,7 +130,10 @@ impl UdpSocket { port: local_endpoint.port, }; - SOCKET_SET.bind_check(local_endpoint.addr, local_endpoint.port)?; + if !self.is_reuse_addr() { + // Check if the address is already in use + SOCKET_SET.bind_check(local_endpoint.addr, local_endpoint.port)?; + } SOCKET_SET.with_socket_mut::(self.handle, |socket| { socket.bind(endpoint).or_else(|e| match e { @@ -295,6 +329,10 @@ impl UdpSocket { f() } else { loop { + #[cfg(feature = "signal")] + if call_interface!(SignalCaller::current_have_signal) { + return Err(AxError::Interrupted); + } SOCKET_SET.poll_interfaces(); match f() { Ok(t) => return Ok(t), diff --git a/modules/axprocess/src/signal.rs b/modules/axprocess/src/signal.rs index 44a3796634..dbcd08bc90 100644 --- a/modules/axprocess/src/signal.rs +++ b/modules/axprocess/src/signal.rs @@ -329,4 +329,8 @@ impl SignalCaller for SignalCallerImpl { fn send_signal(tid: isize, signum: isize) { send_signal_to_thread(tid, signum).unwrap(); } + + fn current_have_signal() -> bool { + current_process().have_signals().is_some() + } } diff --git a/modules/axtask/src/stat.rs b/modules/axtask/src/stat.rs index 4f5ec19edd..ed9122228b 100644 --- a/modules/axtask/src/stat.rs +++ b/modules/axtask/src/stat.rs @@ -56,6 +56,8 @@ pub struct TimeStat { pub trait SignalCaller { /// Handles interrupt requests for the given IRQ number. fn send_signal(tid: isize, signum: isize); + /// Return true if current task have a signal pending. + fn current_have_signal() -> bool; } #[allow(unused)] diff --git a/ulib/axstarry/src/syscall_fs/ctype/epoll.rs b/ulib/axstarry/src/syscall_fs/ctype/epoll.rs index 018bda8373..01a8a30980 100644 --- a/ulib/axstarry/src/syscall_fs/ctype/epoll.rs +++ b/ulib/axstarry/src/syscall_fs/ctype/epoll.rs @@ -44,6 +44,9 @@ pub struct EpollEvent { pub event_type: EpollEventType, /// 事件中使用到的数据,如fd等 pub data: u64, + pub fd: i32, + pub data_u32: u32, + pub data_u64: u64, } numeric_enum_macro::numeric_enum! { @@ -105,7 +108,8 @@ impl EpollFile { // 添加事件 EpollCtl::ADD => { if inner.monitor_list.contains_key(&fd) { - return Err(SyscallError::EEXIST); + // return Err(SyscallError::EEXIST); + inner.monitor_list.insert(fd, event); } inner.monitor_list.insert(fd, event); } @@ -181,6 +185,9 @@ impl EpollFile { ret_events.push(EpollEvent { event_type: EpollEventType::EPOLLERR, data: req_event.data, + fd: -1, + data_u32: 0, + data_u64: 0, }); } } diff --git a/ulib/axstarry/src/syscall_fs/fs_syscall_id.rs b/ulib/axstarry/src/syscall_fs/fs_syscall_id.rs index 1bd7c9c845..83ebb8cf7b 100644 --- a/ulib/axstarry/src/syscall_fs/fs_syscall_id.rs +++ b/ulib/axstarry/src/syscall_fs/fs_syscall_id.rs @@ -115,6 +115,7 @@ numeric_enum_macro::numeric_enum! { SELECT = 23, PSELECT6 = 270, READLINK = 89, + CHMOD = 90, PREADLINKAT = 267, FSTAT = 5, LSTAT = 6, @@ -124,5 +125,7 @@ numeric_enum_macro::numeric_enum! { RENAMEAT = 264, RENAMEAT2 = 316, COPYFILERANGE = 326, + EPOLL_CREATE1 = 291, + EPOLL_PWAIT = 281, } } diff --git a/ulib/axstarry/src/syscall_fs/imp/epoll.rs b/ulib/axstarry/src/syscall_fs/imp/epoll.rs index e3cad4bd67..8f45414b08 100644 --- a/ulib/axstarry/src/syscall_fs/imp/epoll.rs +++ b/ulib/axstarry/src/syscall_fs/imp/epoll.rs @@ -91,6 +91,10 @@ pub fn syscall_epoll_wait(args: [usize; 6]) -> SyscallResult { let max_event = max_event as usize; let process = current_process(); let start: VirtAddr = (event as usize).into(); + // FIXME: this is a temporary solution + // the memory will out of mapped memory if the max_event is too large + // maybe give the max_event a limit is a better solution + let max_event = core::cmp::min(max_event, 400); let end = start + max_event * core::mem::size_of::(); if process.manual_alloc_range_for_lazy(start, end).is_err() { return Err(SyscallError::EFAULT); @@ -112,6 +116,7 @@ pub fn syscall_epoll_wait(args: [usize; 6]) -> SyscallResult { } else { usize::MAX }; + drop(fd_table); let ret_events = epoll_file.epoll_wait(timeout); if ret_events.is_err() { return Err(SyscallError::EINTR); diff --git a/ulib/axstarry/src/syscall_fs/imp/poll.rs b/ulib/axstarry/src/syscall_fs/imp/poll.rs index 400378dc78..c783e7defd 100644 --- a/ulib/axstarry/src/syscall_fs/imp/poll.rs +++ b/ulib/axstarry/src/syscall_fs/imp/poll.rs @@ -397,9 +397,17 @@ pub fn syscall_pselect6(args: [usize; 6]) -> SyscallResult { if current_ticks() as usize > expire_time { return Ok(0); } + // TODO: fix this and use mask to ignore specific signal + // #[cfg(feature = "signal")] + // if process.have_signals().is_some() { + // if process.signal_modules + // return Err(SyscallError::EINTR); + // } #[cfg(feature = "signal")] - if process.have_signals().is_some() { - return Err(SyscallError::EINTR); + if let Some(signalno) = process.have_signals() { + if signalno == 9 { + return Ok(0); + } } } } diff --git a/ulib/axstarry/src/syscall_fs/mod.rs b/ulib/axstarry/src/syscall_fs/mod.rs index 86cb143665..e27906c833 100644 --- a/ulib/axstarry/src/syscall_fs/mod.rs +++ b/ulib/axstarry/src/syscall_fs/mod.rs @@ -92,5 +92,11 @@ pub fn fs_syscall(syscall_id: fs_syscall_id::FsSyscallId, args: [usize; 6]) -> S READLINK => syscall_readlink(args), #[cfg(target_arch = "x86_64")] CREAT => Err(axerrno::LinuxError::EPERM), + #[cfg(target_arch = "x86_64")] + EPOLL_CREATE1 => unimplemented!("epoll_create1"), + #[cfg(target_arch = "x86_64")] + EPOLL_PWAIT => unimplemented!("epoll_ctl"), + #[cfg(target_arch = "x86_64")] + CHMOD => Ok(0), } } diff --git a/ulib/axstarry/src/syscall_net/imp.rs b/ulib/axstarry/src/syscall_net/imp.rs index d211731b09..08d14cc140 100644 --- a/ulib/axstarry/src/syscall_net/imp.rs +++ b/ulib/axstarry/src/syscall_net/imp.rs @@ -481,8 +481,7 @@ pub fn syscall_set_sock_opt(args: [usize; 6]) -> SyscallResult { return Ok(0); }; - option.set(socket, opt); - Ok(0) + option.set(socket, opt) } } } diff --git a/ulib/axstarry/src/syscall_net/socket.rs b/ulib/axstarry/src/syscall_net/socket.rs index 35b57e099a..505c362d3e 100644 --- a/ulib/axstarry/src/syscall_net/socket.rs +++ b/ulib/axstarry/src/syscall_net/socket.rs @@ -106,26 +106,26 @@ impl IpOption { match self { IpOption::IP_MULTICAST_IF => { // 我们只会使用LOOPBACK作为多播接口 - Ok((0)) + Ok(0) } IpOption::IP_MULTICAST_TTL => { let mut inner = socket.inner.lock(); match &mut *inner { SocketInner::Udp(s) => { let ttl = u8::from_ne_bytes(<[u8; 1]>::try_from(&opt[0..1]).unwrap()); - s.set_socket_ttl(ttl as u8); - Ok((0)) + s.set_socket_ttl(ttl); + Ok(0) } _ => panic!("setsockopt IP_MULTICAST_TTL on a non-udp socket"), } } - IpOption::IP_MULTICAST_LOOP => Ok((0)), + IpOption::IP_MULTICAST_LOOP => Ok(0), IpOption::IP_ADD_MEMBERSHIP => { let multicast_addr = IpAddr::v4(opt[0], opt[1], opt[2], opt[3]); let interface_addr = IpAddr::v4(opt[4], opt[5], opt[6], opt[7]); // TODO add membership error handling add_membership(multicast_addr, interface_addr); - Ok((0)) + Ok(0) } } } @@ -135,13 +135,12 @@ impl SocketOption { pub fn set(&self, socket: &Socket, opt: &[u8]) -> SyscallResult { match self { SocketOption::SO_REUSEADDR => { - // unimplemented!("wait for implementation of SO_REUSEADDR"); if opt.len() < 4 { panic!("can't read a int from socket opt value"); } let opt_value = i32::from_ne_bytes(<[u8; 4]>::try_from(&opt[0..4]).unwrap()); socket.set_reuse_addr(opt_value != 0); - Ok((0)) + Ok(0) } SocketOption::SO_DONTROUTE => { if opt.len() < 4 { @@ -152,7 +151,7 @@ impl SocketOption { socket.set_reuse_addr(opt_value != 0); // socket.reuse_addr = opt_value != 0; - Ok((0)) + Ok(0) } SocketOption::SO_SNDBUF => { if opt.len() < 4 { @@ -163,7 +162,7 @@ impl SocketOption { socket.set_send_buf_size(opt_value as u64); // socket.send_buf_size = opt_value as usize; - Ok((0)) + Ok(0) } SocketOption::SO_RCVBUF => { if opt.len() < 4 { @@ -174,7 +173,7 @@ impl SocketOption { socket.set_recv_buf_size(opt_value as u64); // socket.recv_buf_size = opt_value as usize; - Ok((0)) + Ok(0) } SocketOption::SO_KEEPALIVE => { if opt.len() < 4 { @@ -205,7 +204,7 @@ impl SocketOption { drop(inner); socket.set_recv_buf_size(opt_value as u64); // socket.recv_buf_size = opt_value as usize; - Ok((0)) + Ok(0) } SocketOption::SO_RCVTIMEO => { if opt.len() < size_of::() { @@ -218,7 +217,7 @@ impl SocketOption { } else { Some(timeout) }); - Ok((0)) + Ok(0) } SocketOption::SO_ERROR => { panic!("can't set SO_ERROR"); @@ -336,7 +335,7 @@ impl SocketOption { } impl TcpSocketOption { - pub fn set(&self, raw_socket: &Socket, opt: &[u8]) { + pub fn set(&self, raw_socket: &Socket, opt: &[u8]) -> SyscallResult { let mut inner = raw_socket.inner.lock(); let socket = match &mut *inner { SocketInner::Tcp(ref mut s) => s, @@ -352,10 +351,15 @@ impl TcpSocketOption { let _ = socket.set_nagle_enabled(opt_value == 0); let _ = socket.flush(); + Ok(0) + } + TcpSocketOption::TCP_INFO => { + // TODO: support the protocal + Ok(0) } - TcpSocketOption::TCP_INFO => panic!("[setsockopt()] try to set TCP_INFO"), TcpSocketOption::TCP_CONGESTION => { - raw_socket.set_congestion(String::from_utf8(Vec::from(opt)).unwrap()) + raw_socket.set_congestion(String::from_utf8(Vec::from(opt)).unwrap()); + Ok(0) } _ => { unimplemented!() @@ -425,7 +429,6 @@ pub struct Socket { recv_timeout: Mutex>, // fake options - reuse_addr: AtomicBool, dont_route: bool, send_buf_size: AtomicU64, recv_buf_size: AtomicU64, @@ -445,7 +448,11 @@ impl Socket { *self.recv_timeout.lock() } fn get_reuse_addr(&self) -> bool { - self.reuse_addr.load(core::sync::atomic::Ordering::Acquire) + let inner = self.inner.lock(); + match &*inner { + SocketInner::Tcp(s) => unimplemented!("get_reuse_addr on other socket"), + SocketInner::Udp(s) => s.is_reuse_addr(), + } } fn get_send_buf_size(&self) -> u64 { @@ -467,8 +474,11 @@ impl Socket { } fn set_reuse_addr(&self, flag: bool) { - self.reuse_addr - .store(flag, core::sync::atomic::Ordering::Release) + let inner = self.inner.lock(); + match &*inner { + SocketInner::Tcp(s) => unimplemented!("set_reuse_addr on other socket"), + SocketInner::Udp(s) => s.set_reuse_addr(flag), + } } fn set_send_buf_size(&self, size: u64) { @@ -500,7 +510,6 @@ impl Socket { inner: Mutex::new(inner), close_exec: false, recv_timeout: Mutex::new(None), - reuse_addr: AtomicBool::new(false), dont_route: false, send_buf_size: AtomicU64::new(64 * 1024), recv_buf_size: AtomicU64::new(64 * 1024), @@ -604,7 +613,6 @@ impl Socket { inner: Mutex::new(SocketInner::Tcp(new_socket)), close_exec: false, recv_timeout: Mutex::new(None), - reuse_addr: AtomicBool::new(false), dont_route: false, send_buf_size: AtomicU64::new(64 * 1024), recv_buf_size: AtomicU64::new(64 * 1024),