Skip to content

Commit

Permalink
net: refactor TCP APIs
Browse files Browse the repository at this point in the history
- remove mutable reference to the TCP socket on connect/bind/listen
- eliminate unnecessary polling
- add support of listening on 0.0.0.0
- fix the issue that the TCP listener can listen on any address
  • Loading branch information
equation314 committed Jul 13, 2023
1 parent c7abd41 commit b23a16b
Show file tree
Hide file tree
Showing 18 changed files with 573 additions and 345 deletions.
4 changes: 2 additions & 2 deletions apps/c/httpserver/httpserver.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ int main()
struct sockaddr_in local, remote;
int addr_len = sizeof(remote);
local.sin_family = AF_INET;
if (inet_pton(AF_INET, "10.0.2.15", &(local.sin_addr)) != 1) {
if (inet_pton(AF_INET, "0.0.0.0", &(local.sin_addr)) != 1) {
perror("inet_pton() error");
return -1;
}
Expand All @@ -54,7 +54,7 @@ int main()
perror("listen() error");
return -1;
}
puts("listen on: http://10.0.2.15:5555/");
puts("listen on: http://0.0.0.0:5555/");
char buf[1024] = {};
int client;
char response[1024] = {};
Expand Down
2 changes: 1 addition & 1 deletion apps/c/iperf/axbuild.mk
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ app-objs := $(patsubst %.c,$(iperf_pkg)/src/%.o,$(iperf_src))

.PRECIOUS: $(APP)/%.c
$(APP)/%.c:
echo "Download iperf source code"
@echo "Download iperf source code"
wget https://downloads.es.net/pub/iperf/$(iperf_pkg).tar.gz -P $(APP)
tar -zxvf $(APP)/$(iperf_pkg).tar.gz -C $(APP) && rm -f $(APP)/$(iperf_pkg).tar.gz
patch -p1 -N -d $(iperf_dir) --no-backup-if-mismatch -r - < $(APP)/iperf.patch
4 changes: 2 additions & 2 deletions apps/c/iperf/iperf.patch
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,7 @@ index 73dc362..4bfe6f9 100644
}
diff --git a/src/main_server.c b/src/main_server.c
new file mode 100644
index 0000000..9d31a66
index 0000000..c9964ba
--- /dev/null
+++ b/src/main_server.c
@@ -0,0 +1,42 @@
Expand Down Expand Up @@ -445,7 +445,7 @@ index 0000000..9d31a66
+ iperf_defaults(test);
+ iperf_set_test_role(test, 's');
+ iperf_set_test_server_port(test, port);
+ iperf_set_test_bind_address(test, "10.0.2.15");
+ iperf_set_test_bind_address(test, "0.0.0.0");
+ consecutive_errors = 0;
+ for (;;) {
+ if (iperf_run_server(test) < 0) {
Expand Down
4 changes: 2 additions & 2 deletions apps/c/udpserver/udpserver.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ int main()
struct sockaddr_in local, remote;
int addr_len = sizeof(remote);
local.sin_family = AF_INET;
if (inet_pton(AF_INET, "10.0.2.15", &(local.sin_addr)) != 1) {
if (inet_pton(AF_INET, "0.0.0.0", &(local.sin_addr)) != 1) {
perror("inet_pton() error");
return -1;
}
Expand All @@ -26,7 +26,7 @@ int main()
perror("bind() error");
return -1;
}
puts("listen on: 10.0.2.15:5555");
puts("listen on: 0.0.0.0:5555");
char buf[1024] = {};
for (;;) {
ssize_t l =
Expand Down
4 changes: 2 additions & 2 deletions apps/net/echoserver/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use libax::io::{self, prelude::*};
use libax::net::{IpAddr, TcpListener, TcpStream};
use libax::thread;

const LOCAL_IP: &str = "10.0.2.15";
const LOCAL_IP: &str = "0.0.0.0";
const LOCAL_PORT: u16 = 5555;

fn reverse(buf: &[u8]) -> Vec<u8> {
Expand All @@ -39,7 +39,7 @@ fn echo_server(mut stream: TcpStream) -> io::Result {

fn accept_loop() -> io::Result {
let (addr, port) = (IpAddr::from_str(LOCAL_IP).unwrap(), LOCAL_PORT);
let mut listener = TcpListener::bind((addr, port).into())?;
let listener = TcpListener::bind((addr, port).into())?;
println!("listen on: {}", listener.local_addr().unwrap());

let mut i = 0;
Expand Down
4 changes: 2 additions & 2 deletions apps/net/httpserver/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use libax::io::{self, prelude::*};
use libax::net::{IpAddr, TcpListener, TcpStream};
use libax::thread;

const LOCAL_IP: &str = "10.0.2.15";
const LOCAL_IP: &str = "0.0.0.0";
const LOCAL_PORT: u16 = 5555;

macro_rules! header {
Expand Down Expand Up @@ -62,7 +62,7 @@ fn http_server(mut stream: TcpStream) -> io::Result {

fn accept_loop() -> io::Result {
let (addr, port) = (IpAddr::from_str(LOCAL_IP).unwrap(), LOCAL_PORT);
let mut listener = TcpListener::bind((addr, port).into())?;
let listener = TcpListener::bind((addr, port).into())?;
println!("listen on: http://{}/", listener.local_addr().unwrap());

let mut i = 0;
Expand Down
2 changes: 1 addition & 1 deletion apps/net/udpserver/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use core::str::FromStr;
use libax::io;
use libax::net::{IpAddr, UdpSocket};

const LOCAL_IP: &str = "10.0.2.15";
const LOCAL_IP: &str = "0.0.0.0";
const LOCAL_PORT: u16 = 5555;

fn receive_loop() -> io::Result {
Expand Down
79 changes: 76 additions & 3 deletions crates/axerrno/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
//! [`std::io::ErrorKind`]: https://doc.rust-lang.org/std/io/enum.ErrorKind.html

#![no_std]
#![feature(variant_count)]

use core::fmt;

mod linux_errno {
include!(concat!(env!("OUT_DIR"), "/linux_errno.rs"));
Expand All @@ -27,7 +30,7 @@ pub use linux_errno::LinuxError;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum AxError {
/// A socket address could not be bound because the address is already in use elsewhere.
AddrInUse,
AddrInUse = 1,
/// An entity already exists, often a file.
AlreadyExists,
/// Bad address.
Expand All @@ -36,6 +39,8 @@ pub enum AxError {
BadState,
/// The connection was refused by the remote server,
ConnectionRefused,
/// The connection was reset by the remote server.
ConnectionReset,
/// A non-empty directory was specified where an empty directory was expected.
DirectoryNotEmpty,
/// Data not valid for the operation were encountered.
Expand Down Expand Up @@ -183,14 +188,54 @@ impl AxError {
pub fn as_str(&self) -> &'static str {
use AxError::*;
match *self {
AddrInUse => "Address in use",
BadAddress => "Bad address",
BadState => "Bad internal state",
AlreadyExists => "Entity already exists",
ConnectionRefused => "Connection refused",
ConnectionReset => "Connection reset",
DirectoryNotEmpty => "Directory not empty",
InvalidData => "Invalid data",
Unsupported => "Operation not supported",
InvalidInput => "Invalid input parameter",
Io => "I/O error",
IsADirectory => "Is a directory",
NoMemory => "Out of memory",
NotADirectory => "Not a directory",
NotConnected => "Not connected",
NotFound => "Entity not found",
PermissionDenied => "Permission denied",
ResourceBusy => "Resource busy",
StorageFull => "No storage space",
UnexpectedEof => "Unexpected end of file",
Unsupported => "Operation not supported",
WouldBlock => "Operation would block",
WriteZero => "Write zero",
_ => LinuxError::from(*self).as_str(),
}
}

/// Returns the error code value in `i32`.
pub const fn code(self) -> i32 {
self as i32
}
}

impl TryFrom<i32> for AxError {
type Error = i32;

#[inline]
fn try_from(value: i32) -> Result<Self, Self::Error> {
if value > 0 && value <= core::mem::variant_count::<AxError>() as i32 {
Ok(unsafe { core::mem::transmute(value) })
} else {
Err(value)
}
}
}

impl fmt::Display for AxError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.as_str())
}
}

impl From<AxError> for LinuxError {
Expand All @@ -201,6 +246,7 @@ impl From<AxError> for LinuxError {
AlreadyExists => LinuxError::EEXIST,
BadAddress | BadState => LinuxError::EFAULT,
ConnectionRefused => LinuxError::ECONNREFUSED,
ConnectionReset => LinuxError::ECONNRESET,
DirectoryNotEmpty => LinuxError::ENOTEMPTY,
InvalidInput | InvalidData => LinuxError::EINVAL,
Io => LinuxError::EIO,
Expand All @@ -219,7 +265,34 @@ impl From<AxError> for LinuxError {
}
}

impl fmt::Display for LinuxError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.as_str())
}
}

#[doc(hidden)]
pub mod __priv {
pub use log::warn;
}

#[cfg(test)]
mod tests {
use crate::AxError;

#[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!(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!(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));
assert_eq!(Err(i32::MAX), AxError::try_from(i32::MAX));
}
}
2 changes: 1 addition & 1 deletion modules/axnet/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ cfg_if::cfg_if! {
}
}

pub use self::net_impl::resolve_socket_addr;
pub use self::net_impl::TcpSocket;
pub use self::net_impl::UdpSocket;
pub use self::net_impl::{poll_interfaces, resolve_socket_addr};
pub use smoltcp::wire::{IpAddress as IpAddr, IpEndpoint as SocketAddr, Ipv4Address as Ipv4Addr};

use axdriver::{prelude::*, AxDeviceContainer};
Expand Down
Loading

0 comments on commit b23a16b

Please sign in to comment.