Skip to content

Commit

Permalink
implement getaddrinfo in rust
Browse files Browse the repository at this point in the history
  • Loading branch information
coolyjg committed Sep 4, 2023
1 parent 3759b58 commit 16eda15
Show file tree
Hide file tree
Showing 8 changed files with 47 additions and 37 deletions.
3 changes: 3 additions & 0 deletions api/arceos_posix_api/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ typedef struct {{
"iovec",
"clockid_t",
"rlimit",
"addrinfo",
];
let allow_vars = [
"O_.*",
Expand All @@ -61,6 +62,8 @@ typedef struct {{
"EPOLL_CTL_.*",
"EPOLL.*",
"RLIMIT_.*",
"EAI_.*",
"MAXADDRS",
];

#[derive(Debug)]
Expand Down
1 change: 1 addition & 0 deletions api/arceos_posix_api/ctypes.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <pthread.h>
#include <stddef.h>
Expand Down
2 changes: 1 addition & 1 deletion api/arceos_posix_api/src/imp/stdio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ pub struct Stdout;

impl Write for Stdout {
fn write(&mut self, buf: &[u8]) -> AxResult<usize> {
Ok(console_write_bytes(buf)?)
console_write_bytes(buf)
}

fn flush(&mut self) -> AxResult {
Expand Down
26 changes: 0 additions & 26 deletions ulib/axlibc/c/network.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,32 +14,6 @@

int h_errno;

/*Only IPv4. Ports are always 0. Ignore service and hint. Results' ai_flags, ai_socktype,
* ai_protocol and ai_canonname are 0 or NULL. */
int getaddrinfo(const char *__restrict node, const char *__restrict service,
const struct addrinfo *__restrict hints, struct addrinfo **__restrict res)
{
struct sockaddr *addrs = (struct sockaddr *)malloc(MAXADDRS * sizeof(struct sockaddr));
int res_len = ax_getaddrinfo(node, service, addrs, MAXADDRS);
if (res_len < 0)
return EAI_FAIL;
if (res_len == 0)
return EAI_NONAME;
struct addrinfo *_res = (struct addrinfo *)calloc(res_len, sizeof(struct addrinfo));
for (int i = 0; i < res_len; i++) {
(_res + i)->ai_family = AF_INET;
(_res + i)->ai_addrlen = sizeof(struct sockaddr);
(_res + i)->ai_addr = (addrs + i);
(_res + i)->ai_next = (_res + i + 1);
// TODO: This is a hard-code part, only return TCP parameters
(_res + i)->ai_socktype = SOCK_STREAM;
(_res + i)->ai_protocol = IPPROTO_TCP;
}
(_res + res_len - 1)->ai_next = NULL;
*res = _res;
return 0;
}

void freeaddrinfo(struct addrinfo *__restrict res)
{
free(res->ai_addr);
Expand Down
2 changes: 2 additions & 0 deletions ulib/axlibc/cbindgen.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ sys_includes = [
"sys/select.h",
"sys/time.h",
"pthread.h",
"netdb.h",
]

[export.rename]
Expand All @@ -24,6 +25,7 @@ sys_includes = [
"iovec" = "struct iovec"
"tm" = "struct tm"
"rlimit" = "struct rlimit"
"addrinfo" = "struct addrinfo"

[fn]
no_return = "__attribute__((noreturn))"
7 changes: 3 additions & 4 deletions ulib/axlibc/include/netdb.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
#ifndef _NETDB_H
#define _NETDB_H

#ifdef AX_CONFIG_NET

#include <netinet/in.h>

struct addrinfo {
Expand Down Expand Up @@ -76,8 +74,9 @@ const char *hstrerror(int ecode);
#define MAXSERVS 2
#define MAXADDRS 48

int getaddrinfo(const char *__restrict, const char *__restrict, const struct addrinfo *__restrict,
struct addrinfo **__restrict);
#ifdef AX_CONFIG_NET

int getaddrinfo(const char *, const char *, const struct addrinfo *, struct addrinfo **);
void freeaddrinfo(struct addrinfo *);
const char *gai_strerror(int __ecode);

Expand Down
2 changes: 1 addition & 1 deletion ulib/axlibc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ pub use self::fs::{ax_open, fstat, getcwd, lseek, lstat, stat};

#[cfg(feature = "net")]
pub use self::socket::{
accept, ax_getaddrinfo, bind, connect, getpeername, getsockname, listen, recv, recvfrom, send,
accept, getaddrinfo, bind, connect, getpeername, getsockname, listen, recv, recvfrom, send,
sendto, shutdown, socket,
};

Expand Down
41 changes: 36 additions & 5 deletions ulib/axlibc/src/socket.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
use alloc::vec::Vec;
use arceos_posix_api::{
sys_accept, sys_bind, sys_connect, sys_getaddrinfo, sys_getpeername, sys_getsockname,
sys_listen, sys_recv, sys_recvfrom, sys_send, sys_sendto, sys_shutdown, sys_socket,
};
use core::ffi::{c_char, c_int, c_void};
use core::{
ffi::{c_char, c_int, c_void},
mem::size_of,
};

use crate::{ctypes, utils::e};

Expand Down Expand Up @@ -136,15 +140,42 @@ pub unsafe extern "C" fn shutdown(

/// Query addresses for a domain name.
///
/// Only IPv4. Ports are always 0. Ignore service and hint.
/// Results' ai_flags and ai_canonname are 0 or NULL.
///
/// Return address number if success.
#[no_mangle]
pub unsafe extern "C" fn ax_getaddrinfo(
pub unsafe extern "C" fn getaddrinfo(
node: *const c_char,
service: *const c_char,
addrs: *mut ctypes::sockaddr,
len: ctypes::size_t,
_hints: *const ctypes::addrinfo,
res: *mut *mut ctypes::addrinfo,
) -> c_int {
e(sys_getaddrinfo(node, service, addrs, len))
let addrs = [ctypes::sockaddr::default(); ctypes::MAXADDRS as usize].as_mut_ptr();
let ret = e(sys_getaddrinfo(node, service, addrs, ctypes::MAXADDRS as _));
if ret < 0 {
return ctypes::EAI_FAIL;
}
if ret == 0 {
return ctypes::EAI_NONAME;
}
let mut _parsed_res = Vec::with_capacity(ret as usize);
_parsed_res.fill(ctypes::addrinfo::default());
let parsed_res = _parsed_res.as_mut_ptr();
unsafe {
(0..ret).for_each(|i| {
(*(parsed_res.add(i as usize))).ai_family = ctypes::AF_INET as _;
(*(parsed_res.add(i as usize))).ai_addrlen = size_of::<ctypes::sockaddr>() as _;
(*(parsed_res.add(i as usize))).ai_addr = addrs.add(i as usize);
(*(parsed_res.add(i as usize))).ai_next = parsed_res.add(i as usize + 1);
// TODO: This is a hard-code part, only return TCP parameters
(*(parsed_res.add(i as usize))).ai_socktype = ctypes::SOCK_STREAM as _;
(*(parsed_res.add(i as usize))).ai_protocol = ctypes::IPPROTO_TCP as _;
});
(*(parsed_res.add(ret as usize - 1))).ai_next = core::ptr::null_mut();
*res = parsed_res;
}
0
}

/// Get current address to which the socket sockfd is bound.
Expand Down

0 comments on commit 16eda15

Please sign in to comment.