Skip to content

Commit

Permalink
Merge pull request #51 from Miochyann/dev
Browse files Browse the repository at this point in the history
Modify some syscalls
Fix bugs in udp/tcp, pipe
  • Loading branch information
coolyjg authored Jan 22, 2024
2 parents 4153067 + 4947ca5 commit d5a8895
Show file tree
Hide file tree
Showing 15 changed files with 150 additions and 42 deletions.
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
# - `QEMU_LOG`: Enable QEMU logging (log file is "qemu.log")
# - `NET_DUMP`: Enable network packet dump (log file is "netdump.pcap")
# - `NET_DEV`: QEMU netdev backend types: user, tap
# - `START_PORT`: The starting port number for the open ports in QEMU (default is port 5555)
# - `PORT_NUM`: The number of open ports in QEMU (default is 5)
# * 9P options:
# - `V9P_PATH`: Host path for backend of virtio-9p
# - `NET_9P_ADDR`: Server address and port for 9P netdev
Expand Down Expand Up @@ -64,6 +66,8 @@ NET_9P_ADDR ?= 127.0.0.1:564
ANAME_9P ?= ./
PROTOCOL_9P ?= 9P2000.L

START_PORT ?= 5555
PORTS_NUM ?= 5
# Network options
IP ?= 10.0.2.15
GW ?= 10.0.2.2
Expand Down
6 changes: 6 additions & 0 deletions api/ruxos_posix_api/src/imp/net.rs
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ fn from_sockaddr(
pub fn sys_socket(domain: c_int, socktype: c_int, protocol: c_int) -> c_int {
debug!("sys_socket <= {} {} {}", domain, socktype, protocol);
let (domain, socktype, protocol) = (domain as u32, socktype as u32, protocol as u32);
pub const _SOCK_STREAM_NONBLOCK: u32 = ctypes::SOCK_STREAM | ctypes::SOCK_NONBLOCK;
syscall_body!(sys_socket, {
match (domain, socktype, protocol) {
(ctypes::AF_INET, ctypes::SOCK_STREAM, ctypes::IPPROTO_TCP)
Expand All @@ -251,6 +252,11 @@ pub fn sys_socket(domain: c_int, socktype: c_int, protocol: c_int) -> c_int {
| (ctypes::AF_INET, ctypes::SOCK_DGRAM, 0) => {
Socket::Udp(Mutex::new(UdpSocket::new())).add_to_fd_table()
}
(ctypes::AF_INET, _SOCK_STREAM_NONBLOCK, ctypes::IPPROTO_TCP) => {
let tcp_socket = TcpSocket::new();
tcp_socket.set_nonblocking(true);
Socket::Tcp(Mutex::new(tcp_socket)).add_to_fd_table()
}
_ => Err(LinuxError::EINVAL),
}
})
Expand Down
36 changes: 24 additions & 12 deletions api/ruxos_posix_api/src/imp/pipe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,26 +122,38 @@ impl FileLike for Pipe {
}
let mut read_size = 0usize;
let max_len = buf.len();
let mut ring_buffer = self.buffer.lock();
// First, check if there is data in the read end.
// This loop is only runs when the write end is open
// and there is no data available
loop {
let mut ring_buffer = self.buffer.lock();
let loop_read = ring_buffer.available_read();
// If there is no data
if loop_read == 0 {
if self.write_end_close() {
return Ok(read_size);
// write end is closed, read 0 bytes.
return Ok(0);
} else {
// write end is open
drop(ring_buffer);
// Data not ready, wait for write end
crate::sys_sched_yield(); // TODO: use synconize primitive
ring_buffer = self.buffer.lock();
}
drop(ring_buffer);
// Data not ready, wait for write end
crate::sys_sched_yield(); // TODO: use synconize primitive
continue;
} else {
break;
}
for _ in 0..loop_read {
if read_size == max_len {
return Ok(read_size);
}
buf[read_size] = ring_buffer.read_byte();
read_size += 1;
}
// read data
let loop_read = ring_buffer.available_read();
for _ in 0..loop_read {
if read_size == max_len {
return Ok(read_size);
}
buf[read_size] = ring_buffer.read_byte();
read_size += 1;
}
Ok(read_size)
}

fn write(&self, buf: &[u8]) -> LinuxResult<usize> {
Expand Down
7 changes: 6 additions & 1 deletion api/ruxos_posix_api/src/imp/stat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,10 @@ pub fn sys_umask(mode: ctypes::mode_t) -> ctypes::mode_t {

/// Returns the effective user ID of the calling process
pub fn sys_geteuid() -> core::ffi::c_uint {
syscall_body!(sys_geteuid, Ok(0))
syscall_body!(sys_geteuid, Ok(1000))
}

/// Returns the effective groupe ID of the calling process
pub fn sys_getegid() -> core::ffi::c_uint {
syscall_body!(sys_getegid, Ok(1000))
}
2 changes: 1 addition & 1 deletion api/ruxos_posix_api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ pub mod ctypes;
pub use imp::io::{sys_read, sys_readv, sys_write, sys_writev};
pub use imp::resources::{sys_getrlimit, sys_prlimit64, sys_setrlimit};
pub use imp::rt_sig::{sys_rt_sigaction, sys_rt_sigprocmask};
pub use imp::stat::{sys_geteuid, sys_umask};
pub use imp::stat::{sys_getegid, sys_geteuid, sys_umask};
pub use imp::sys::{sys_sysinfo, sys_uname};
pub use imp::sys_invalid;
pub use imp::task::{sys_exit, sys_getpid, sys_sched_yield};
Expand Down
44 changes: 44 additions & 0 deletions apps/c/udpserver/apps_udpserver.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# INTRODUCTION
| App | Extra modules | Enabled features | Description |
|-|-|-|-|
| [udpserver](../apps/c/udpserver) | axalloc, axnet, axdriver, axtask | alloc, paging, net, multitask | UDP server test|

# RUN
``` bash
make A=apps/c/udpserver MUSL=y NET=y ARCH=aarch64 run
```
# RESULT
```
8888888b. .d88888b. .d8888b.
888 Y88b d88P" "Y88b d88P Y88b
888 888 888 888 Y88b.
888 d88P 888 888 888 888 888 888 "Y888b.
8888888P" 888 888 `Y8bd8P' 888 888 "Y88b.
888 T88b 888 888 X88K 888 888 "888
888 T88b Y88b 888 .d8""8b. Y88b. .d88P Y88b d88P
888 T88b "Y88888 888 888 "Y88888P" "Y8888P"
arch = aarch64
platform = aarch64-qemu-virt
target = aarch64-unknown-none-softfloat
smp = 1
build_mode = release
log_level = warn
Hello, Ruxos C UDP server!
listen on: 0.0.0.0:5555
```
Then create a new terminal and run:
``` bash
chmod +x apps/c/udpserver/udpserver_test.sh
apps/c/udpserver/udpserver_test.sh
```
This will send a message to port 5555 of localhost , If the UDP service is running correctly the result will be:

```
Hello, Ruxos C UDP server!
listen on: 0.0.0.0:5555
recv: 1024 Bytes from 10.0.2.2:34774
Big message, it should fail#####################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################################
received message too long
```
2 changes: 1 addition & 1 deletion apps/c/udpserver/axbuild.mk
Original file line number Diff line number Diff line change
@@ -1 +1 @@
app-objs := udpserver.o
app-objs := udpserver.o
2 changes: 1 addition & 1 deletion apps/c/udpserver/features.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
alloc
paging
net
net
21 changes: 21 additions & 0 deletions apps/c/udpserver/udpserver_test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
echo "Hello, UDP Server!" | nc -u -w 1 localhost 5555 &
echo "Big message, it should fail\
#####################################################################\
#####################################################################\
#####################################################################\
#####################################################################\
#####################################################################\
#####################################################################\
#####################################################################\
#####################################################################\
#####################################################################\
#####################################################################\
#####################################################################\
#####################################################################\
#####################################################################\
#####################################################################\
#####################################################################\
#####################################################################\
#####################################################################\
#####################################################################\
#####################################################################" | nc -u -w 1 localhost 5555
11 changes: 8 additions & 3 deletions crates/axerrno/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ pub enum AxError {
/// An error returned when an operation could not be completed because a
/// call to `write()` returned [`Ok(0)`](Ok).
WriteZero,
/// It is a temporary error code that usually returns when a non_blocking operation
/// is not completed, prompting the caller to try again later.
InProgress,
}

/// A specialized [`Result`] type with [`AxError`] as the error type.
Expand Down Expand Up @@ -219,6 +222,7 @@ impl AxError {
Unsupported => "Operation not supported",
WouldBlock => "Operation would block",
WriteZero => "Write zero",
InProgress => "non_blocking operation is not completed",
}
}

Expand Down Expand Up @@ -270,6 +274,7 @@ impl From<AxError> for LinuxError {
Unsupported => LinuxError::ENOSYS,
UnexpectedEof | WriteZero => LinuxError::EIO,
WouldBlock => LinuxError::EAGAIN,
InProgress => LinuxError::EINPROGRESS,
}
}
}
Expand All @@ -292,13 +297,13 @@ mod tests {
#[test]
fn test_try_from() {
let max_code = core::mem::variant_count::<AxError>() as i32;
assert_eq!(max_code, 22);
assert_eq!(max_code, AxError::WriteZero.code());
assert_eq!(max_code, 23);
assert_eq!(max_code, AxError::InProgress.code());

assert_eq!(AxError::AddrInUse.code(), 1);
assert_eq!(Ok(AxError::AddrInUse), AxError::try_from(1));
assert_eq!(Ok(AxError::AlreadyExists), AxError::try_from(2));
assert_eq!(Ok(AxError::WriteZero), AxError::try_from(max_code));
assert_eq!(Ok(AxError::InProgress), AxError::try_from(max_code));
assert_eq!(Err(max_code + 1), AxError::try_from(max_code + 1));
assert_eq!(Err(0), AxError::try_from(0));
assert_eq!(Err(-1), AxError::try_from(-1));
Expand Down
39 changes: 21 additions & 18 deletions modules/axnet/src/smoltcp_impl/tcp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ impl TcpSocket {
#[inline]
pub fn local_addr(&self) -> AxResult<SocketAddr> {
match self.get_state() {
STATE_CONNECTED | STATE_LISTENING => {
STATE_CONNECTED | STATE_LISTENING | STATE_BUSY => {
Ok(into_core_sockaddr(unsafe { self.local_addr.get().read() }))
}
_ => Err(AxError::NotConnected),
Expand Down Expand Up @@ -165,21 +165,24 @@ impl TcpSocket {
})
.unwrap_or_else(|_| ax_err!(AlreadyExists, "socket connect() failed: already connected"))?; // EISCONN

// Here our state must be `CONNECTING`, and only one thread can run here.
if self.is_nonblocking() {
Err(AxError::WouldBlock)
} else {
self.block_on(|| {
let PollState { writable, .. } = self.poll_connect()?;
if !writable {
Err(AxError::WouldBlock)
} else if self.get_state() == STATE_CONNECTED {
Ok(())
} else {
ax_err!(ConnectionRefused, "socket connect() failed")
self.block_on(|| {
let PollState { writable, .. } = self.poll_connect()?;
if !writable {
// When set to non_blocking, directly return inporgress
if self.is_nonblocking() {
return Err(AxError::InProgress);
}
})
}
Err(AxError::WouldBlock)
} else if self.get_state() == STATE_CONNECTED {
Ok(())
} else {
// When set to non_blocking, directly return inporgress
if self.is_nonblocking() {
return Err(AxError::InProgress);
}
ax_err!(ConnectionRefused, "socket connect() failed")
}
})
}

/// Binds an unbound socket to the given address and port.
Expand All @@ -189,7 +192,7 @@ impl TcpSocket {
/// It's must be called before [`listen`](Self::listen) and
/// [`accept`](Self::accept).
pub fn bind(&self, mut local_addr: SocketAddr) -> AxResult {
self.update_state(STATE_CLOSED, STATE_CLOSED, || {
self.update_state(STATE_CLOSED, STATE_BUSY, || {
// TODO: check addr is available
if local_addr.port() == 0 {
local_addr.set_port(get_ephemeral_port()?);
Expand All @@ -213,7 +216,7 @@ impl TcpSocket {
/// It's must be called after [`bind`](Self::bind) and before
/// [`accept`](Self::accept).
pub fn listen(&self) -> AxResult {
self.update_state(STATE_CLOSED, STATE_LISTENING, || {
self.update_state(STATE_BUSY, STATE_LISTENING, || {
let bound_endpoint = self.bound_endpoint()?;
unsafe {
(*self.local_addr.get()).port = bound_endpoint.port;
Expand Down Expand Up @@ -513,7 +516,7 @@ impl Drop for TcpSocket {
}

fn get_ephemeral_port() -> AxResult<u16> {
const PORT_START: u16 = 0xc000;
const PORT_START: u16 = 0x15b3;
const PORT_END: u16 = 0xffff;
static CURR: Mutex<u16> = Mutex::new(PORT_START);

Expand Down
7 changes: 4 additions & 3 deletions modules/axnet/src/smoltcp_impl/udp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* See the Mulan PSL v2 for more details.
*/

use core::net::SocketAddr;
use core::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
use core::sync::atomic::{AtomicBool, Ordering};

use axerrno::{ax_err, ax_err_type, AxError, AxResult};
Expand Down Expand Up @@ -217,7 +217,8 @@ impl UdpSocket {

fn send_impl(&self, buf: &[u8], remote_endpoint: IpEndpoint) -> AxResult<usize> {
if self.local_addr.read().is_none() {
return ax_err!(NotConnected, "socket send() failed");
let res = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(0, 0, 0, 0), 0));
self.bind(res)?;
}

self.block_on(|| {
Expand Down Expand Up @@ -288,7 +289,7 @@ impl Drop for UdpSocket {
}

fn get_ephemeral_port() -> AxResult<u16> {
const PORT_START: u16 = 0xc000;
const PORT_START: u16 = 0x15b3;
const PORT_END: u16 = 0xffff;
static CURR: Mutex<u16> = Mutex::new(PORT_START);
let mut curr = CURR.lock();
Expand Down
7 changes: 6 additions & 1 deletion scripts/make/qemu.mk
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

QEMU := qemu-system-$(ARCH)

# Generate a list of ports
PORTS := $(shell seq $(START_PORT) $$(($(START_PORT) + $(PORTS_NUM) - 1)))
PORTS_TMP := ${foreach port,${PORTS},hostfwd=tcp::${port}-:${port},hostfwd=udp::${port}-:${port},}
PORTS_LIST := $(subst $(empty) $(empty),,$(PORTS_TMP))

ifeq ($(BUS), mmio)
vdev-suffix := device
else ifeq ($(BUS), pci)
Expand Down Expand Up @@ -39,7 +44,7 @@ qemu_args-$(V9P) += \
-device virtio-9p-$(vdev-suffix),fsdev=myid,mount_tag=rootfs

ifeq ($(NET_DEV), user)
qemu_args-$(NET) += -netdev user,id=net0,hostfwd=tcp::5555-:5555,hostfwd=udp::5555-:5555
qemu_args-$(NET) += -netdev user,id=net0,$(PORTS_LIST)
else ifeq ($(NET_DEV), tap)
qemu_args-$(NET) += -netdev tap,id=net0,ifname=tap0,script=no,downscript=no
else
Expand Down
3 changes: 2 additions & 1 deletion ulib/ruxmusl/src/syscall/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,8 @@ pub fn syscall(syscall_id: SyscallId, args: [usize; 6]) -> isize {
}
#[cfg(feature = "fs")]
SyscallId::FSYNC => ruxos_posix_api::sys_fsync(args[0] as c_int) as _,
SyscallId::GETEUID => ruxos_posix_api::sys_geteuid() as _,
SyscallId::GETEGID => ruxos_posix_api::sys_getegid() as _,
#[cfg(feature = "fs")]
SyscallId::FDATASYNC => ruxos_posix_api::sys_fdatasync(args[0] as c_int) as _,
#[allow(unreachable_code)]
Expand Down Expand Up @@ -221,7 +223,6 @@ pub fn syscall(syscall_id: SyscallId, args: [usize; 6]) -> isize {
SyscallId::UMASK => ruxos_posix_api::sys_umask(args[0] as ctypes::mode_t) as _,
#[cfg(feature = "multitask")]
SyscallId::GETPID => ruxos_posix_api::sys_getpid() as _,
SyscallId::GETEUID => ruxos_posix_api::sys_geteuid() as _,
SyscallId::SYSINFO => {
ruxos_posix_api::sys_sysinfo(args[0] as *mut ctypes::sysinfo) as _
}
Expand Down
1 change: 1 addition & 0 deletions ulib/ruxmusl/src/syscall/syscall_id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ pub enum SyscallId {
#[cfg(feature = "multitask")]
GETPID = 172,
GETEUID = 175,
GETEGID = 177,
SYSINFO = 179,
#[cfg(feature = "net")]
SOCKET = 198,
Expand Down

0 comments on commit d5a8895

Please sign in to comment.