mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-28 20:03:22 +00:00
Refactor sock option implementations
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
782cd05ade
commit
f8eca84a99
@ -1,18 +1,14 @@
|
||||
use core::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
use crate::events::IoEvents;
|
||||
use crate::fs::file_handle::FileLike;
|
||||
use crate::fs::utils::StatusFlags;
|
||||
use crate::net::iface::IpEndpoint;
|
||||
|
||||
use crate::net::socket::util::send_recv_flags::SendRecvFlags;
|
||||
use crate::net::socket::util::socket_addr::SocketAddr;
|
||||
use crate::net::socket::Socket;
|
||||
use crate::prelude::*;
|
||||
use crate::process::signal::Poller;
|
||||
use crate::{
|
||||
fs::file_handle::FileLike,
|
||||
net::socket::{
|
||||
util::{send_recv_flags::SendRecvFlags, sockaddr::SocketAddr},
|
||||
Socket,
|
||||
},
|
||||
prelude::*,
|
||||
};
|
||||
|
||||
use self::bound::BoundDatagram;
|
||||
use self::unbound::UnboundDatagram;
|
||||
@ -129,7 +125,7 @@ impl FileLike for DatagramSocket {
|
||||
self.inner.read().poll(mask, poller)
|
||||
}
|
||||
|
||||
fn as_socket(&self) -> Option<&dyn Socket> {
|
||||
fn as_socket(self: Arc<Self>) -> Option<Arc<dyn Socket>> {
|
||||
Some(self)
|
||||
}
|
||||
|
||||
@ -152,14 +148,14 @@ impl FileLike for DatagramSocket {
|
||||
}
|
||||
|
||||
impl Socket for DatagramSocket {
|
||||
fn bind(&self, sockaddr: SocketAddr) -> Result<()> {
|
||||
let endpoint = sockaddr.try_into()?;
|
||||
fn bind(&self, socket_addr: SocketAddr) -> Result<()> {
|
||||
let endpoint = socket_addr.try_into()?;
|
||||
self.inner.write().bind(endpoint)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn connect(&self, sockaddr: SocketAddr) -> Result<()> {
|
||||
let endpoint = sockaddr.try_into()?;
|
||||
fn connect(&self, socket_addr: SocketAddr) -> Result<()> {
|
||||
let endpoint = socket_addr.try_into()?;
|
||||
let bound = self.try_bind_empheral(&endpoint)?;
|
||||
bound.set_remote_endpoint(endpoint);
|
||||
Ok(())
|
||||
|
@ -1,8 +1,7 @@
|
||||
mod always_some;
|
||||
mod common;
|
||||
mod datagram;
|
||||
mod stream;
|
||||
pub mod stream;
|
||||
|
||||
pub use datagram::DatagramSocket;
|
||||
pub use stream::options as tcp_options;
|
||||
pub use stream::StreamSocket;
|
||||
|
@ -1,26 +1,25 @@
|
||||
use crate::events::IoEvents;
|
||||
use crate::fs::file_handle::FileLike;
|
||||
use crate::fs::utils::StatusFlags;
|
||||
use crate::net::socket::ip::tcp_options::{
|
||||
TcpCongestion, TcpMaxseg, TcpWindowClamp, DEFAULT_MAXSEG,
|
||||
};
|
||||
use crate::net::socket::options::{
|
||||
SockOption, SocketError, SocketLinger, SocketOptions, SocketRecvBuf, SocketReuseAddr,
|
||||
SocketReusePort, SocketSendBuf, MIN_RECVBUF, MIN_SENDBUF,
|
||||
Error, Linger, RecvBuf, ReuseAddr, ReusePort, SendBuf, SocketOption,
|
||||
};
|
||||
use crate::net::socket::util::options::{SocketOptionSet, MIN_RECVBUF, MIN_SENDBUF};
|
||||
use crate::net::socket::util::{
|
||||
send_recv_flags::SendRecvFlags, shutdown_cmd::SockShutdownCmd, sockaddr::SocketAddr,
|
||||
send_recv_flags::SendRecvFlags, shutdown_cmd::SockShutdownCmd, socket_addr::SocketAddr,
|
||||
};
|
||||
use crate::net::socket::Socket;
|
||||
use crate::prelude::*;
|
||||
use crate::process::signal::Poller;
|
||||
use crate::{match_sock_option_mut, match_sock_option_ref};
|
||||
use options::{Congestion, MaxSegment, WindowClamp};
|
||||
use util::{TcpOptionSet, DEFAULT_MAXSEG};
|
||||
|
||||
use connected::ConnectedStream;
|
||||
use connecting::ConnectingStream;
|
||||
use init::InitStream;
|
||||
use listen::ListenStream;
|
||||
use options::{TcpNoDelay, TcpOptions};
|
||||
use options::NoDelay;
|
||||
use smoltcp::wire::IpEndpoint;
|
||||
|
||||
mod connected;
|
||||
@ -28,9 +27,12 @@ mod connecting;
|
||||
mod init;
|
||||
mod listen;
|
||||
pub mod options;
|
||||
mod util;
|
||||
|
||||
pub use self::util::CongestionControl;
|
||||
|
||||
pub struct StreamSocket {
|
||||
options: RwLock<Options>,
|
||||
options: RwLock<OptionSet>,
|
||||
state: RwLock<State>,
|
||||
}
|
||||
|
||||
@ -46,22 +48,22 @@ enum State {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct Options {
|
||||
socket: SocketOptions,
|
||||
tcp: TcpOptions,
|
||||
struct OptionSet {
|
||||
socket: SocketOptionSet,
|
||||
tcp: TcpOptionSet,
|
||||
}
|
||||
|
||||
impl Options {
|
||||
impl OptionSet {
|
||||
fn new() -> Self {
|
||||
let socket = SocketOptions::new_tcp();
|
||||
let tcp = TcpOptions::new();
|
||||
Options { socket, tcp }
|
||||
let socket = SocketOptionSet::new_tcp();
|
||||
let tcp = TcpOptionSet::new();
|
||||
OptionSet { socket, tcp }
|
||||
}
|
||||
}
|
||||
|
||||
impl StreamSocket {
|
||||
pub fn new(nonblocking: bool) -> Self {
|
||||
let options = Options::new();
|
||||
let options = OptionSet::new();
|
||||
let state = State::Init(InitStream::new(nonblocking));
|
||||
Self {
|
||||
options: RwLock::new(options),
|
||||
@ -143,14 +145,14 @@ impl FileLike for StreamSocket {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn as_socket(&self) -> Option<&dyn Socket> {
|
||||
fn as_socket(self: Arc<Self>) -> Option<Arc<dyn Socket>> {
|
||||
Some(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Socket for StreamSocket {
|
||||
fn bind(&self, sockaddr: SocketAddr) -> Result<()> {
|
||||
let endpoint = sockaddr.try_into()?;
|
||||
fn bind(&self, socket_addr: SocketAddr) -> Result<()> {
|
||||
let endpoint = socket_addr.try_into()?;
|
||||
let state = self.state.read();
|
||||
match &*state {
|
||||
State::Init(init_stream) => init_stream.bind(endpoint),
|
||||
@ -158,8 +160,8 @@ impl Socket for StreamSocket {
|
||||
}
|
||||
}
|
||||
|
||||
fn connect(&self, sockaddr: SocketAddr) -> Result<()> {
|
||||
let remote_endpoint = sockaddr.try_into()?;
|
||||
fn connect(&self, socket_addr: SocketAddr) -> Result<()> {
|
||||
let remote_endpoint = socket_addr.try_into()?;
|
||||
|
||||
let connecting_stream = self.do_connect(&remote_endpoint)?;
|
||||
match connecting_stream.wait_conn() {
|
||||
@ -206,7 +208,7 @@ impl Socket for StreamSocket {
|
||||
let accepted_socket = {
|
||||
let state = RwLock::new(State::Connected(connected_stream));
|
||||
Arc::new(StreamSocket {
|
||||
options: RwLock::new(Options::new()),
|
||||
options: RwLock::new(OptionSet::new()),
|
||||
state,
|
||||
})
|
||||
};
|
||||
@ -279,40 +281,40 @@ impl Socket for StreamSocket {
|
||||
connected_stream.sendto(buf, flags)
|
||||
}
|
||||
|
||||
fn option(&self, option: &mut dyn SockOption) -> Result<()> {
|
||||
fn get_option(&self, option: &mut dyn SocketOption) -> Result<()> {
|
||||
let options = self.options.read();
|
||||
match_sock_option_mut!(option, {
|
||||
// Socket Options
|
||||
socket_errors: SocketError => {
|
||||
socket_errors: Error => {
|
||||
let sock_errors = options.socket.sock_errors();
|
||||
socket_errors.set_output(sock_errors);
|
||||
socket_errors.set(sock_errors);
|
||||
},
|
||||
socket_reuse_addr: SocketReuseAddr => {
|
||||
socket_reuse_addr: ReuseAddr => {
|
||||
let reuse_addr = options.socket.reuse_addr();
|
||||
socket_reuse_addr.set_output(reuse_addr);
|
||||
socket_reuse_addr.set(reuse_addr);
|
||||
},
|
||||
socket_send_buf: SocketSendBuf => {
|
||||
socket_send_buf: SendBuf => {
|
||||
let send_buf = options.socket.send_buf();
|
||||
socket_send_buf.set_output(send_buf);
|
||||
socket_send_buf.set(send_buf);
|
||||
},
|
||||
socket_recv_buf: SocketRecvBuf => {
|
||||
socket_recv_buf: RecvBuf => {
|
||||
let recv_buf = options.socket.recv_buf();
|
||||
socket_recv_buf.set_output(recv_buf);
|
||||
socket_recv_buf.set(recv_buf);
|
||||
},
|
||||
socket_reuse_port: SocketReusePort => {
|
||||
socket_reuse_port: ReusePort => {
|
||||
let reuse_port = options.socket.reuse_port();
|
||||
socket_reuse_port.set_output(reuse_port);
|
||||
socket_reuse_port.set(reuse_port);
|
||||
},
|
||||
// Tcp Options
|
||||
tcp_no_delay: TcpNoDelay => {
|
||||
tcp_no_delay: NoDelay => {
|
||||
let no_delay = options.tcp.no_delay();
|
||||
tcp_no_delay.set_output(no_delay);
|
||||
tcp_no_delay.set(no_delay);
|
||||
},
|
||||
tcp_congestion: TcpCongestion => {
|
||||
tcp_congestion: Congestion => {
|
||||
let congestion = options.tcp.congestion();
|
||||
tcp_congestion.set_output(congestion);
|
||||
tcp_congestion.set(congestion);
|
||||
},
|
||||
tcp_maxseg: TcpMaxseg => {
|
||||
tcp_maxseg: MaxSegment => {
|
||||
// It will always return the default MSS value defined above for an unconnected socket
|
||||
// and always return the actual current MSS for a connected one.
|
||||
|
||||
@ -321,64 +323,64 @@ impl Socket for StreamSocket {
|
||||
State::Init(_) | State::Listen(_) | State::Connecting(_) => DEFAULT_MAXSEG,
|
||||
State::Connected(_) => options.tcp.maxseg(),
|
||||
};
|
||||
tcp_maxseg.set_output(maxseg);
|
||||
tcp_maxseg.set(maxseg);
|
||||
},
|
||||
tcp_window_clamp: TcpWindowClamp => {
|
||||
tcp_window_clamp: WindowClamp => {
|
||||
let window_clamp = options.tcp.window_clamp();
|
||||
tcp_window_clamp.set_output(window_clamp);
|
||||
tcp_window_clamp.set(window_clamp);
|
||||
},
|
||||
_ => return_errno_with_message!(Errno::ENOPROTOOPT, "get unknown option")
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_option(&self, option: &dyn SockOption) -> Result<()> {
|
||||
fn set_option(&self, option: &dyn SocketOption) -> Result<()> {
|
||||
let mut options = self.options.write();
|
||||
// FIXME: here we have only set the value of the option, without actually
|
||||
// making any real modifications.
|
||||
match_sock_option_ref!(option, {
|
||||
// Socket options
|
||||
socket_recv_buf: SocketRecvBuf => {
|
||||
let recv_buf = socket_recv_buf.input().unwrap();
|
||||
socket_recv_buf: RecvBuf => {
|
||||
let recv_buf = socket_recv_buf.get().unwrap();
|
||||
if *recv_buf <= MIN_RECVBUF {
|
||||
options.socket.set_recv_buf(MIN_RECVBUF);
|
||||
} else{
|
||||
options.socket.set_recv_buf(*recv_buf);
|
||||
}
|
||||
},
|
||||
socket_send_buf: SocketSendBuf => {
|
||||
let send_buf = socket_send_buf.input().unwrap();
|
||||
socket_send_buf: SendBuf => {
|
||||
let send_buf = socket_send_buf.get().unwrap();
|
||||
if *send_buf <= MIN_SENDBUF {
|
||||
options.socket.set_send_buf(MIN_SENDBUF);
|
||||
} else {
|
||||
options.socket.set_send_buf(*send_buf);
|
||||
}
|
||||
},
|
||||
socket_reuse_addr: SocketReuseAddr => {
|
||||
let reuse_addr = socket_reuse_addr.input().unwrap();
|
||||
socket_reuse_addr: ReuseAddr => {
|
||||
let reuse_addr = socket_reuse_addr.get().unwrap();
|
||||
options.socket.set_reuse_addr(*reuse_addr);
|
||||
},
|
||||
socket_reuse_port: SocketReusePort => {
|
||||
let reuse_port = socket_reuse_port.input().unwrap();
|
||||
socket_reuse_port: ReusePort => {
|
||||
let reuse_port = socket_reuse_port.get().unwrap();
|
||||
options.socket.set_reuse_port(*reuse_port);
|
||||
},
|
||||
socket_linger: SocketLinger => {
|
||||
let linger = socket_linger.input().unwrap();
|
||||
socket_linger: Linger => {
|
||||
let linger = socket_linger.get().unwrap();
|
||||
options.socket.set_linger(*linger);
|
||||
},
|
||||
// Tcp options
|
||||
tcp_no_delay: TcpNoDelay => {
|
||||
let no_delay = tcp_no_delay.input().unwrap();
|
||||
tcp_no_delay: NoDelay => {
|
||||
let no_delay = tcp_no_delay.get().unwrap();
|
||||
options.tcp.set_no_delay(*no_delay);
|
||||
},
|
||||
tcp_congestion: TcpCongestion => {
|
||||
let congestion = tcp_congestion.input().unwrap();
|
||||
tcp_congestion: Congestion => {
|
||||
let congestion = tcp_congestion.get().unwrap();
|
||||
options.tcp.set_congestion(*congestion);
|
||||
},
|
||||
tcp_maxseg: TcpMaxseg => {
|
||||
tcp_maxseg: MaxSegment => {
|
||||
const MIN_MAXSEG: u32 = 536;
|
||||
const MAX_MAXSEG: u32 = 65535;
|
||||
let maxseg = tcp_maxseg.input().unwrap();
|
||||
let maxseg = tcp_maxseg.get().unwrap();
|
||||
|
||||
if *maxseg < MIN_MAXSEG || *maxseg > MAX_MAXSEG {
|
||||
return_errno_with_message!(Errno::EINVAL, "New maxseg should be in allowed range.");
|
||||
@ -386,8 +388,8 @@ impl Socket for StreamSocket {
|
||||
|
||||
options.tcp.set_maxseg(*maxseg);
|
||||
},
|
||||
tcp_window_clamp: TcpWindowClamp => {
|
||||
let window_clamp = tcp_window_clamp.input().unwrap();
|
||||
tcp_window_clamp: WindowClamp => {
|
||||
let window_clamp = tcp_window_clamp.get().unwrap();
|
||||
let half_recv_buf = (options.socket.recv_buf()) / 2;
|
||||
if *window_clamp <= half_recv_buf {
|
||||
options.tcp.set_window_clamp(half_recv_buf);
|
||||
|
@ -1,67 +1,10 @@
|
||||
use crate::impl_sock_options;
|
||||
use crate::prelude::*;
|
||||
use crate::impl_socket_options;
|
||||
|
||||
#[derive(Debug, Clone, Copy, CopyGetters, Setters)]
|
||||
#[get_copy = "pub"]
|
||||
#[set = "pub"]
|
||||
pub struct TcpOptions {
|
||||
no_delay: bool,
|
||||
congestion: Congestion,
|
||||
maxseg: u32,
|
||||
window_clamp: u32,
|
||||
}
|
||||
use super::CongestionControl;
|
||||
|
||||
pub const DEFAULT_MAXSEG: u32 = 536;
|
||||
pub const DEFAULT_WINDOW_CLAMP: u32 = 0x8000_0000;
|
||||
|
||||
impl TcpOptions {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
no_delay: false,
|
||||
congestion: Congestion::Reno,
|
||||
maxseg: DEFAULT_MAXSEG,
|
||||
window_clamp: DEFAULT_WINDOW_CLAMP,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for TcpOptions {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum Congestion {
|
||||
Reno,
|
||||
Cubic,
|
||||
}
|
||||
|
||||
impl Congestion {
|
||||
const RENO: &'static str = "reno";
|
||||
const CUBIC: &'static str = "cubic";
|
||||
|
||||
pub fn new(name: &str) -> Result<Self> {
|
||||
let congestion = match name {
|
||||
Self::RENO => Self::Reno,
|
||||
Self::CUBIC => Self::Cubic,
|
||||
_ => return_errno_with_message!(Errno::EINVAL, "unsupported congestion name"),
|
||||
};
|
||||
|
||||
Ok(congestion)
|
||||
}
|
||||
|
||||
pub fn name(&self) -> &'static str {
|
||||
match self {
|
||||
Self::Reno => Self::RENO,
|
||||
Self::Cubic => Self::CUBIC,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl_sock_options!(
|
||||
pub struct TcpNoDelay<input = bool, output = bool> {}
|
||||
pub struct TcpCongestion<input = Congestion, output = Congestion> {}
|
||||
pub struct TcpMaxseg<input = u32, output = u32> {}
|
||||
pub struct TcpWindowClamp<input = u32, output = u32> {}
|
||||
impl_socket_options!(
|
||||
pub struct NoDelay(bool);
|
||||
pub struct Congestion(CongestionControl);
|
||||
pub struct MaxSegment(u32);
|
||||
pub struct WindowClamp(u32);
|
||||
);
|
||||
|
59
services/libs/aster-std/src/net/socket/ip/stream/util.rs
Normal file
59
services/libs/aster-std/src/net/socket/ip/stream/util.rs
Normal file
@ -0,0 +1,59 @@
|
||||
use crate::prelude::*;
|
||||
|
||||
#[derive(Debug, Clone, Copy, CopyGetters, Setters)]
|
||||
#[get_copy = "pub"]
|
||||
#[set = "pub"]
|
||||
pub struct TcpOptionSet {
|
||||
no_delay: bool,
|
||||
congestion: CongestionControl,
|
||||
maxseg: u32,
|
||||
window_clamp: u32,
|
||||
}
|
||||
|
||||
pub const DEFAULT_MAXSEG: u32 = 536;
|
||||
pub const DEFAULT_WINDOW_CLAMP: u32 = 0x8000_0000;
|
||||
|
||||
impl TcpOptionSet {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
no_delay: false,
|
||||
congestion: CongestionControl::Reno,
|
||||
maxseg: DEFAULT_MAXSEG,
|
||||
window_clamp: DEFAULT_WINDOW_CLAMP,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for TcpOptionSet {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum CongestionControl {
|
||||
Reno,
|
||||
Cubic,
|
||||
}
|
||||
|
||||
impl CongestionControl {
|
||||
const RENO: &'static str = "reno";
|
||||
const CUBIC: &'static str = "cubic";
|
||||
|
||||
pub fn new(name: &str) -> Result<Self> {
|
||||
let congestion = match name {
|
||||
Self::RENO => Self::Reno,
|
||||
Self::CUBIC => Self::Cubic,
|
||||
_ => return_errno_with_message!(Errno::EINVAL, "unsupported congestion name"),
|
||||
};
|
||||
|
||||
Ok(congestion)
|
||||
}
|
||||
|
||||
pub fn name(&self) -> &'static str {
|
||||
match self {
|
||||
Self::Reno => Self::RENO,
|
||||
Self::Cubic => Self::CUBIC,
|
||||
}
|
||||
}
|
||||
}
|
@ -1,9 +1,10 @@
|
||||
use crate::{fs::file_handle::FileLike, prelude::*};
|
||||
|
||||
use self::options::SockOption;
|
||||
use self::options::SocketOption;
|
||||
pub use self::util::options::LingerOption;
|
||||
pub use self::util::send_recv_flags::SendRecvFlags;
|
||||
pub use self::util::shutdown_cmd::SockShutdownCmd;
|
||||
pub use self::util::sockaddr::SocketAddr;
|
||||
pub use self::util::socket_addr::SocketAddr;
|
||||
|
||||
pub mod ip;
|
||||
pub mod options;
|
||||
@ -12,13 +13,13 @@ mod util;
|
||||
|
||||
/// Operations defined on a socket.
|
||||
pub trait Socket: FileLike + Send + Sync {
|
||||
/// Assign the address specified by sockaddr to the socket
|
||||
fn bind(&self, sockaddr: SocketAddr) -> Result<()> {
|
||||
/// Assign the address specified by socket_addr to the socket
|
||||
fn bind(&self, socket_addr: SocketAddr) -> Result<()> {
|
||||
return_errno_with_message!(Errno::EINVAL, "bind not implemented");
|
||||
}
|
||||
|
||||
/// Build connection for a given address
|
||||
fn connect(&self, sockaddr: SocketAddr) -> Result<()> {
|
||||
fn connect(&self, socket_addr: SocketAddr) -> Result<()> {
|
||||
return_errno_with_message!(Errno::EINVAL, "connect not implemented");
|
||||
}
|
||||
|
||||
@ -47,13 +48,14 @@ pub trait Socket: FileLike + Send + Sync {
|
||||
return_errno_with_message!(Errno::EINVAL, "getpeername not implemented");
|
||||
}
|
||||
|
||||
/// Get options on the socket
|
||||
fn option(&self, option: &mut dyn SockOption) -> Result<()> {
|
||||
/// Get options on the socket. The resulted option will put in the `option` parameter, if
|
||||
/// this method returns success.
|
||||
fn get_option(&self, option: &mut dyn SocketOption) -> Result<()> {
|
||||
return_errno_with_message!(Errno::EINVAL, "getsockopt not implemented");
|
||||
}
|
||||
|
||||
/// Set options on the socket
|
||||
fn set_option(&self, option: &dyn SockOption) -> Result<()> {
|
||||
/// Set options on the socket.
|
||||
fn set_option(&self, option: &dyn SocketOption) -> Result<()> {
|
||||
return_errno_with_message!(Errno::EINVAL, "setsockopt not implemented");
|
||||
}
|
||||
|
||||
|
83
services/libs/aster-std/src/net/socket/options/macros.rs
Normal file
83
services/libs/aster-std/src/net/socket/options/macros.rs
Normal file
@ -0,0 +1,83 @@
|
||||
#[macro_export]
|
||||
macro_rules! impl_socket_options {
|
||||
($(
|
||||
$(#[$outer:meta])*
|
||||
pub struct $name: ident ( $value_ty:ty );
|
||||
)*) => {
|
||||
$(
|
||||
$(#[$outer])*
|
||||
#[derive(Debug)]
|
||||
pub struct $name (Option<$value_ty>);
|
||||
|
||||
impl $name {
|
||||
pub fn new() -> Self {
|
||||
Self (None)
|
||||
}
|
||||
|
||||
pub fn get(&self) -> Option<&$value_ty> {
|
||||
self.0.as_ref()
|
||||
}
|
||||
|
||||
pub fn set(&mut self, value: $value_ty) {
|
||||
self.0 = Some(value);
|
||||
}
|
||||
}
|
||||
|
||||
impl $crate::net::socket::SocketOption for $name {
|
||||
fn as_any(&self) -> &dyn core::any::Any {
|
||||
self
|
||||
}
|
||||
|
||||
fn as_any_mut(&mut self) -> &mut dyn core::any::Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for $name {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! match_sock_option_ref {
|
||||
(
|
||||
$option:expr, {
|
||||
$( $bind: ident : $ty:ty => $arm:expr ),*,
|
||||
_ => $default:expr
|
||||
}
|
||||
) => {{
|
||||
let __option : &dyn SocketOption = $option;
|
||||
$(
|
||||
if let Some($bind) = __option.as_any().downcast_ref::<$ty>() {
|
||||
$arm
|
||||
} else
|
||||
)*
|
||||
{
|
||||
$default
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! match_sock_option_mut {
|
||||
(
|
||||
$option:expr, {
|
||||
$( $bind: ident : $ty:ty => $arm:expr ),*,
|
||||
_ => $default:expr
|
||||
}
|
||||
) => {{
|
||||
let __option : &mut dyn SocketOption = $option;
|
||||
$(
|
||||
if let Some($bind) = __option.as_any_mut().downcast_mut::<$ty>() {
|
||||
$arm
|
||||
} else
|
||||
)*
|
||||
{
|
||||
$default
|
||||
}
|
||||
}};
|
||||
}
|
@ -1,113 +1,21 @@
|
||||
use crate::impl_socket_options;
|
||||
use crate::prelude::*;
|
||||
mod macros;
|
||||
|
||||
mod socket;
|
||||
use super::LingerOption;
|
||||
|
||||
pub use socket::{
|
||||
LingerOption, SockErrors, SocketError, SocketLinger, SocketOptions, SocketRecvBuf,
|
||||
SocketReuseAddr, SocketReusePort, SocketSendBuf, MIN_RECVBUF, MIN_SENDBUF,
|
||||
};
|
||||
|
||||
pub trait SockOption: Any + Send + Sync + Debug {
|
||||
/// Socket options. This trait represents all options that can be set or got for a socket, including
|
||||
/// socket level options and options for specific socket type like tcp socket.
|
||||
pub trait SocketOption: Any + Send + Sync + Debug {
|
||||
fn as_any(&self) -> &dyn Any;
|
||||
fn as_any_mut(&mut self) -> &mut dyn Any;
|
||||
}
|
||||
|
||||
// The following macros are mainly from occlum/ngo.
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! impl_sock_options {
|
||||
($(
|
||||
$(#[$outer:meta])*
|
||||
pub struct $name: ident <input=$input:ty, output=$output:ty> {}
|
||||
)*) => {
|
||||
$(
|
||||
$(#[$outer])*
|
||||
#[derive(Debug)]
|
||||
pub struct $name {
|
||||
input: Option<$input>,
|
||||
output: Option<$output>,
|
||||
}
|
||||
|
||||
impl $name {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
input: None,
|
||||
output: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn input(&self) -> Option<&$input> {
|
||||
self.input.as_ref()
|
||||
}
|
||||
|
||||
pub fn set_input(&mut self, input: $input) {
|
||||
self.input = Some(input);
|
||||
}
|
||||
|
||||
pub fn output(&self) -> Option<&$output> {
|
||||
self.output.as_ref()
|
||||
}
|
||||
|
||||
pub fn set_output(&mut self, output: $output) {
|
||||
self.output = Some(output);
|
||||
}
|
||||
}
|
||||
|
||||
impl $crate::net::socket::SockOption for $name {
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
}
|
||||
|
||||
fn as_any_mut(&mut self) -> &mut dyn Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for $name {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! match_sock_option_ref {
|
||||
(
|
||||
$option:expr, {
|
||||
$( $bind: ident : $ty:ty => $arm:expr ),*,
|
||||
_ => $default:expr
|
||||
}
|
||||
) => {{
|
||||
let __option : &dyn SockOption = $option;
|
||||
$(
|
||||
if let Some($bind) = __option.as_any().downcast_ref::<$ty>() {
|
||||
$arm
|
||||
} else
|
||||
)*
|
||||
{
|
||||
$default
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! match_sock_option_mut {
|
||||
(
|
||||
$option:expr, {
|
||||
$( $bind: ident : $ty:ty => $arm:expr ),*,
|
||||
_ => $default:expr
|
||||
}
|
||||
) => {{
|
||||
let __option : &mut dyn SockOption = $option;
|
||||
$(
|
||||
if let Some($bind) = __option.as_any_mut().downcast_mut::<$ty>() {
|
||||
$arm
|
||||
} else
|
||||
)*
|
||||
{
|
||||
$default
|
||||
}
|
||||
}};
|
||||
}
|
||||
impl_socket_options!(
|
||||
pub struct ReuseAddr(bool);
|
||||
pub struct ReusePort(bool);
|
||||
pub struct SendBuf(u32);
|
||||
pub struct RecvBuf(u32);
|
||||
pub struct Error(Option<crate::error::Error>);
|
||||
pub struct Linger(LingerOption);
|
||||
);
|
||||
|
@ -1,86 +0,0 @@
|
||||
use core::time::Duration;
|
||||
|
||||
use crate::impl_sock_options;
|
||||
use crate::net::iface::{RECV_BUF_LEN, SEND_BUF_LEN};
|
||||
use crate::prelude::*;
|
||||
|
||||
#[derive(Debug, Clone, CopyGetters, Setters)]
|
||||
#[get_copy = "pub"]
|
||||
#[set = "pub"]
|
||||
pub struct SocketOptions {
|
||||
sock_errors: SockErrors,
|
||||
reuse_addr: bool,
|
||||
reuse_port: bool,
|
||||
send_buf: u32,
|
||||
recv_buf: u32,
|
||||
linger: LingerOption,
|
||||
}
|
||||
|
||||
impl SocketOptions {
|
||||
pub fn new_tcp() -> Self {
|
||||
Self {
|
||||
sock_errors: SockErrors::no_error(),
|
||||
reuse_addr: false,
|
||||
reuse_port: false,
|
||||
send_buf: SEND_BUF_LEN as u32,
|
||||
recv_buf: RECV_BUF_LEN as u32,
|
||||
linger: LingerOption::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub const MIN_SENDBUF: u32 = 2304;
|
||||
pub const MIN_RECVBUF: u32 = 2304;
|
||||
|
||||
impl_sock_options!(
|
||||
pub struct SocketReuseAddr<input = bool, output = bool> {}
|
||||
pub struct SocketReusePort<input = bool, output = bool> {}
|
||||
pub struct SocketSendBuf<input = u32, output = u32> {}
|
||||
pub struct SocketRecvBuf<input = u32, output = u32> {}
|
||||
pub struct SocketError<input = (), output = SockErrors> {}
|
||||
pub struct SocketLinger<input = LingerOption, output = LingerOption> {}
|
||||
);
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct SockErrors(Option<Error>);
|
||||
|
||||
impl SockErrors {
|
||||
pub const fn no_error() -> Self {
|
||||
Self(None)
|
||||
}
|
||||
|
||||
pub const fn with_error(error: Error) -> Self {
|
||||
Self(Some(error))
|
||||
}
|
||||
|
||||
pub const fn error(&self) -> Option<&Error> {
|
||||
self.0.as_ref()
|
||||
}
|
||||
|
||||
pub const fn as_i32(&self) -> i32 {
|
||||
match &self.0 {
|
||||
None => 0,
|
||||
Some(err) => err.error() as i32,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy)]
|
||||
pub struct LingerOption {
|
||||
is_on: bool,
|
||||
timeout: Duration,
|
||||
}
|
||||
|
||||
impl LingerOption {
|
||||
pub fn new(is_on: bool, timeout: Duration) -> Self {
|
||||
Self { is_on, timeout }
|
||||
}
|
||||
|
||||
pub fn is_on(&self) -> bool {
|
||||
self.is_on
|
||||
}
|
||||
|
||||
pub fn timeout(&self) -> Duration {
|
||||
self.timeout
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
use crate::fs::utils::Dentry;
|
||||
use crate::net::socket::util::sockaddr::SocketAddr;
|
||||
use crate::net::socket::util::socket_addr::SocketAddr;
|
||||
use crate::prelude::*;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
|
@ -5,7 +5,7 @@ use crate::fs::utils::{Dentry, InodeType, StatusFlags};
|
||||
use crate::net::socket::unix::addr::UnixSocketAddrBound;
|
||||
use crate::net::socket::unix::UnixSocketAddr;
|
||||
use crate::net::socket::util::send_recv_flags::SendRecvFlags;
|
||||
use crate::net::socket::util::sockaddr::SocketAddr;
|
||||
use crate::net::socket::util::socket_addr::SocketAddr;
|
||||
use crate::net::socket::{SockShutdownCmd, Socket};
|
||||
use crate::prelude::*;
|
||||
use crate::process::signal::Poller;
|
||||
@ -78,7 +78,7 @@ impl UnixStreamSocket {
|
||||
}
|
||||
|
||||
impl FileLike for UnixStreamSocket {
|
||||
fn as_socket(&self) -> Option<&dyn Socket> {
|
||||
fn as_socket(self: Arc<Self>) -> Option<Arc<dyn Socket>> {
|
||||
Some(self)
|
||||
}
|
||||
|
||||
@ -132,8 +132,8 @@ impl FileLike for UnixStreamSocket {
|
||||
}
|
||||
|
||||
impl Socket for UnixStreamSocket {
|
||||
fn bind(&self, sockaddr: SocketAddr) -> Result<()> {
|
||||
let addr = UnixSocketAddr::try_from(sockaddr)?;
|
||||
fn bind(&self, socket_addr: SocketAddr) -> Result<()> {
|
||||
let addr = UnixSocketAddr::try_from(socket_addr)?;
|
||||
|
||||
let init = match &*self.0.read() {
|
||||
State::Init(init) => init.clone(),
|
||||
@ -147,9 +147,9 @@ impl Socket for UnixStreamSocket {
|
||||
init.bind(&addr)
|
||||
}
|
||||
|
||||
fn connect(&self, sockaddr: SocketAddr) -> Result<()> {
|
||||
fn connect(&self, socket_addr: SocketAddr) -> Result<()> {
|
||||
let remote_addr = {
|
||||
let unix_socket_addr = UnixSocketAddr::try_from(sockaddr)?;
|
||||
let unix_socket_addr = UnixSocketAddr::try_from(socket_addr)?;
|
||||
match unix_socket_addr {
|
||||
UnixSocketAddr::Abstract(abstract_name) => {
|
||||
UnixSocketAddrBound::Abstract(abstract_name)
|
||||
|
@ -1,3 +1,4 @@
|
||||
pub mod options;
|
||||
pub mod send_recv_flags;
|
||||
pub mod shutdown_cmd;
|
||||
pub mod sockaddr;
|
||||
pub mod socket_addr;
|
||||
|
53
services/libs/aster-std/src/net/socket/util/options.rs
Normal file
53
services/libs/aster-std/src/net/socket/util/options.rs
Normal file
@ -0,0 +1,53 @@
|
||||
use core::time::Duration;
|
||||
|
||||
use crate::net::iface::{RECV_BUF_LEN, SEND_BUF_LEN};
|
||||
use crate::prelude::*;
|
||||
|
||||
#[derive(Debug, Clone, CopyGetters, Setters)]
|
||||
#[get_copy = "pub"]
|
||||
#[set = "pub"]
|
||||
pub struct SocketOptionSet {
|
||||
sock_errors: Option<Error>,
|
||||
reuse_addr: bool,
|
||||
reuse_port: bool,
|
||||
send_buf: u32,
|
||||
recv_buf: u32,
|
||||
linger: LingerOption,
|
||||
}
|
||||
|
||||
impl SocketOptionSet {
|
||||
/// Return the default socket level options for tcp socket.
|
||||
pub fn new_tcp() -> Self {
|
||||
Self {
|
||||
sock_errors: None,
|
||||
reuse_addr: false,
|
||||
reuse_port: false,
|
||||
send_buf: SEND_BUF_LEN as u32,
|
||||
recv_buf: RECV_BUF_LEN as u32,
|
||||
linger: LingerOption::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub const MIN_SENDBUF: u32 = 2304;
|
||||
pub const MIN_RECVBUF: u32 = 2304;
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy)]
|
||||
pub struct LingerOption {
|
||||
is_on: bool,
|
||||
timeout: Duration,
|
||||
}
|
||||
|
||||
impl LingerOption {
|
||||
pub fn new(is_on: bool, timeout: Duration) -> Self {
|
||||
Self { is_on, timeout }
|
||||
}
|
||||
|
||||
pub fn is_on(&self) -> bool {
|
||||
self.is_on
|
||||
}
|
||||
|
||||
pub fn timeout(&self) -> Duration {
|
||||
self.timeout
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user