Skip to content

Commit

Permalink
refactor getaddrinfo
Browse files Browse the repository at this point in the history
  • Loading branch information
equation314 committed Sep 5, 2023
1 parent 439a1b4 commit 5819627
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 63 deletions.
2 changes: 1 addition & 1 deletion api/arceos_posix_api/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ typedef struct {{
"iovec",
"clockid_t",
"rlimit",
"addrinfo",
"aibuf",
];
let allow_vars = [
"O_.*",
Expand Down
104 changes: 55 additions & 49 deletions api/arceos_posix_api/src/imp/net.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use alloc::{boxed::Box, sync::Arc, vec};
use alloc::{sync::Arc, vec, vec::Vec};
use core::ffi::{c_char, c_int, c_void};
use core::mem::size_of;
use core::net::{IpAddr, Ipv4Addr, SocketAddr, SocketAddrV4};
Expand Down Expand Up @@ -453,19 +453,19 @@ pub unsafe fn sys_getaddrinfo(
_hints: *const ctypes::addrinfo,
res: *mut *mut ctypes::addrinfo,
) -> c_int {
let addrs = Box::into_raw(Box::new(
[ctypes::sockaddr::default(); ctypes::MAXADDRS as usize],
)) as *mut ctypes::sockaddr;
let name = char_ptr_to_str(nodename);
let port = char_ptr_to_str(servname);
debug!("sys_getaddrinfo <= {:?} {:?}", name, port);
syscall_body!(sys_getaddrinfo, {
if nodename.is_null() && servname.is_null() {
return Ok(0);
}
if res.is_null() {
return Err(LinuxError::EFAULT);
}
let addr_slice =
unsafe { core::slice::from_raw_parts_mut(addrs, ctypes::MAXADDRS as usize) };
let ip_res = if let Ok(domain) = name {

let port = port.map_or(0, |p| p.parse::<u16>().unwrap_or(0));
let ip_addrs = if let Ok(domain) = name {
if let Ok(a) = domain.parse::<IpAddr>() {
vec![a]
} else {
Expand All @@ -474,55 +474,61 @@ pub unsafe fn sys_getaddrinfo(
} else {
vec![Ipv4Addr::LOCALHOST.into()]
};
for (i, item) in ip_res.iter().enumerate().take(ctypes::MAXADDRS as usize) {
addr_slice[i] = into_sockaddr(SocketAddr::new(
*item,
port.map_or(0, |p| p.parse::<u16>().unwrap_or(0)),
))
.0;

let len = ip_addrs.len().min(ctypes::MAXADDRS as usize);
if len == 0 {
return Ok(0);
}

let mut out: Vec<ctypes::aibuf> = Vec::with_capacity(len);
for (i, &ip) in ip_addrs.iter().enumerate().take(len) {
let buf = match ip {
IpAddr::V4(ip) => ctypes::aibuf {
ai: ctypes::addrinfo {
ai_family: ctypes::AF_INET as _,
ai_socktype: ctypes::SOCK_STREAM as _,
ai_protocol: ctypes::IPPROTO_TCP as _,
ai_addrlen: size_of::<ctypes::sockaddr_in>() as _,
ai_addr: core::ptr::null_mut(),
ai_canonname: core::ptr::null_mut(),
ai_next: core::ptr::null_mut(),
ai_flags: 0,
},
sa: ctypes::aibuf_sa {
sin: SocketAddrV4::new(ip, port).into(),
},
slot: i as i16,
lock: [0],
ref_: 0,
},
_ => panic!("IPv6 is not supported"),
};
out.push(buf);
out[i].ai.ai_addr =
unsafe { core::ptr::addr_of_mut!(out[i].sa.sin) as *mut ctypes::sockaddr };
if i > 0 {
out[i - 1].ai.ai_next = core::ptr::addr_of_mut!(out[i].ai);
}
}
let ret = ip_res.len().min(ctypes::MAXADDRS as usize);

*res = core::ptr::null_mut();
unsafe {
(0..ret).for_each(|i| {
let mut addrinfo = Box::<ctypes::addrinfo>::default();
addrinfo.ai_family = ctypes::AF_INET as _;
addrinfo.ai_addrlen = size_of::<ctypes::sockaddr>() as _;
addrinfo.ai_addr = addrs.add(i);
addrinfo.ai_next = core::ptr::null_mut();
// TODO: This is a hard-code part, only return TCP parameters
addrinfo.ai_socktype = ctypes::SOCK_STREAM as _;
addrinfo.ai_protocol = ctypes::IPPROTO_TCP as _;

let mut indirect = res;
let mut prev = core::ptr::null_mut();
while !(*indirect).is_null() {
prev = *indirect;
indirect = &mut (**indirect).ai_next;
}
*indirect = Box::into_raw(addrinfo);
if !prev.is_null() {
(*prev).ai_next = *indirect;
}
})
}
Ok(ret)
out[0].ref_ = len as i16;
unsafe { *res = core::ptr::addr_of_mut!(out[0].ai) };
core::mem::forget(out); // drop in `sys_freeaddrinfo`
Ok(len)
})
}

/// `struct addrinfo` deallocation api
/// Free queried `addrinfo` struct
pub unsafe fn sys_freeaddrinfo(res: *mut ctypes::addrinfo) {
let mut ai = res;
while !ai.is_null() {
let bai = unsafe { Box::from_raw(ai) };
if !bai.ai_addr.is_null() {
unsafe {
let _ = Box::from_raw(bai.ai_addr);
}
}
ai = bai.ai_next;
if res.is_null() {
return;
}
let aibuf_ptr = res as *mut ctypes::aibuf;
let len = (*aibuf_ptr).ref_ as usize;
assert!((*aibuf_ptr).slot == 0);
assert!(len > 0);
let vec = Vec::from_raw_parts(aibuf_ptr, len, len); // TODO: lock
drop(vec);
}

/// Get current address to which the socket sockfd is bound.
Expand Down
15 changes: 11 additions & 4 deletions api/arceos_posix_api/src/imp/stdio.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use axerrno::AxResult;
use axio::{prelude::*, BufReader, Result};
use axio::{prelude::*, BufReader};
use axsync::Mutex;

#[cfg(feature = "fd")]
Expand All @@ -18,6 +18,7 @@ struct StdinRaw;
struct StdoutRaw;

impl Read for StdinRaw {
// Non-blocking read, returns number of bytes read.
fn read(&mut self, buf: &mut [u8]) -> AxResult<usize> {
let mut read_len = 0;
while read_len < buf.len() {
Expand Down Expand Up @@ -46,9 +47,9 @@ pub struct Stdin {
inner: &'static Mutex<BufReader<StdinRaw>>,
}

impl Read for Stdin {
impl Stdin {
// Block until at least one byte is read.
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
fn read_blocked(&self, buf: &mut [u8]) -> AxResult<usize> {
let read_len = self.inner.lock().read(buf)?;
if buf.is_empty() || read_len > 0 {
return Ok(read_len);
Expand All @@ -64,6 +65,12 @@ impl Read for Stdin {
}
}

impl Read for Stdin {
fn read(&mut self, buf: &mut [u8]) -> AxResult<usize> {
self.read_blocked(buf)
}
}

pub struct Stdout {
inner: &'static Mutex<StdoutRaw>,
}
Expand Down Expand Up @@ -93,7 +100,7 @@ pub fn stdout() -> Stdout {
#[cfg(feature = "fd")]
impl super::fd_ops::FileLike for Stdin {
fn read(&self, buf: &mut [u8]) -> LinuxResult<usize> {
Ok(self.inner.lock().read(buf)?)
Ok(self.read_blocked(buf)?)
}

fn write(&self, _buf: &[u8]) -> LinuxResult<usize> {
Expand Down
6 changes: 4 additions & 2 deletions ulib/axlibc/c/fcntl.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@

#ifdef AX_CONFIG_FD

// TODO: remove these two functions in future work
int ax_open(const char *filename, int flags, mode_t mode);
// TODO: remove this function in future work
int ax_fcntl(int fd, int cmd, size_t arg);

int fcntl(int fd, int cmd, ... /* arg */)
Expand All @@ -23,6 +22,9 @@ int fcntl(int fd, int cmd, ... /* arg */)

#ifdef AX_CONFIG_FS

// TODO: remove this function in future work
int ax_open(const char *filename, int flags, mode_t mode);

int open(const char *filename, int flags, ...)
{
mode_t mode = 0;
Expand Down
1 change: 0 additions & 1 deletion ulib/axlibc/c/pthread.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdio.h>

int pthread_setcancelstate(int new, int *old)
{
Expand Down
10 changes: 4 additions & 6 deletions ulib/axlibc/src/net.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,13 +146,11 @@ pub unsafe extern "C" fn getaddrinfo(
res: *mut *mut ctypes::addrinfo,
) -> c_int {
let ret = e(sys_getaddrinfo(nodename, servname, hints, res));
if ret < 0 {
return ctypes::EAI_FAIL;
match ret {
r if r < 0 => ctypes::EAI_FAIL,
0 => ctypes::EAI_NONAME,
_ => 0,
}
if ret == 0 {
return ctypes::EAI_NONAME;
}
0
}

/// Free queried `addrinfo` struct
Expand Down

0 comments on commit 5819627

Please sign in to comment.