diff --git a/kernel/src/net/iface/any_socket.rs b/kernel/src/net/iface/any_socket.rs index 792316c32..5a3fb6757 100644 --- a/kernel/src/net/iface/any_socket.rs +++ b/kernel/src/net/iface/any_socket.rs @@ -29,8 +29,8 @@ pub(super) enum SocketFamily { impl AnyUnboundSocket { pub fn new_tcp(observer: Weak>) -> Self { let raw_tcp_socket = { - let rx_buffer = smoltcp::socket::tcp::SocketBuffer::new(vec![0u8; RECV_BUF_LEN]); - let tx_buffer = smoltcp::socket::tcp::SocketBuffer::new(vec![0u8; SEND_BUF_LEN]); + let rx_buffer = smoltcp::socket::tcp::SocketBuffer::new(vec![0u8; TCP_RECV_BUF_LEN]); + let tx_buffer = smoltcp::socket::tcp::SocketBuffer::new(vec![0u8; TCP_SEND_BUF_LEN]); RawTcpSocket::new(rx_buffer, tx_buffer) }; AnyUnboundSocket { @@ -44,7 +44,7 @@ impl AnyUnboundSocket { let metadata = smoltcp::socket::udp::PacketMetadata::EMPTY; let rx_buffer = smoltcp::socket::udp::PacketBuffer::new( vec![metadata; UDP_METADATA_LEN], - vec![0u8; UDP_RECEIVE_PAYLOAD_LEN], + vec![0u8; UDP_RECV_PAYLOAD_LEN], ); let tx_buffer = smoltcp::socket::udp::PacketBuffer::new( vec![metadata; UDP_METADATA_LEN], @@ -209,10 +209,10 @@ impl Drop for AnyBoundSocketInner { } // For TCP -pub const RECV_BUF_LEN: usize = 65536; -pub const SEND_BUF_LEN: usize = 65536; +pub const TCP_RECV_BUF_LEN: usize = 65536; +pub const TCP_SEND_BUF_LEN: usize = 65536; // For UDP +pub const UDP_SEND_PAYLOAD_LEN: usize = 65536; +pub const UDP_RECV_PAYLOAD_LEN: usize = 65536; const UDP_METADATA_LEN: usize = 256; -const UDP_SEND_PAYLOAD_LEN: usize = 65536; -const UDP_RECEIVE_PAYLOAD_LEN: usize = 65536; diff --git a/kernel/src/net/iface/mod.rs b/kernel/src/net/iface/mod.rs index f13fb538f..40596afd9 100644 --- a/kernel/src/net/iface/mod.rs +++ b/kernel/src/net/iface/mod.rs @@ -14,7 +14,8 @@ mod util; mod virtio; pub use any_socket::{ - AnyBoundSocket, AnyUnboundSocket, RawTcpSocket, RawUdpSocket, RECV_BUF_LEN, SEND_BUF_LEN, + AnyBoundSocket, AnyUnboundSocket, RawTcpSocket, RawUdpSocket, TCP_RECV_BUF_LEN, + TCP_SEND_BUF_LEN, UDP_RECV_PAYLOAD_LEN, UDP_SEND_PAYLOAD_LEN, }; pub use loopback::IfaceLoopback; use ostd::sync::LocalIrqDisabled; diff --git a/kernel/src/net/socket/ip/datagram/mod.rs b/kernel/src/net/socket/ip/datagram/mod.rs index c7819c688..d97771aae 100644 --- a/kernel/src/net/socket/ip/datagram/mod.rs +++ b/kernel/src/net/socket/ip/datagram/mod.rs @@ -9,12 +9,15 @@ use super::{common::get_ephemeral_endpoint, IpEndpoint, UNSPECIFIED_LOCAL_ENDPOI use crate::{ events::{IoEvents, Observer}, fs::{file_handle::FileLike, utils::StatusFlags}, + match_sock_option_mut, net::{ poll_ifaces, socket::{ + options::{Error as SocketError, SocketOption}, util::{ copy_message_from_user, copy_message_to_user, create_message_buffer, - send_recv_flags::SendRecvFlags, socket_addr::SocketAddr, MessageHeader, + options::SocketOptionSet, send_recv_flags::SendRecvFlags, socket_addr::SocketAddr, + MessageHeader, }, Socket, }, @@ -27,7 +30,21 @@ use crate::{ mod bound; mod unbound; +#[derive(Debug, Clone)] +struct OptionSet { + socket: SocketOptionSet, + // TODO: UDP option set +} + +impl OptionSet { + fn new() -> Self { + let socket = SocketOptionSet::new_udp(); + OptionSet { socket } + } +} + pub struct DatagramSocket { + options: RwLock, inner: RwLock>, nonblocking: AtomicBool, pollee: Pollee, @@ -80,6 +97,7 @@ impl DatagramSocket { inner: RwLock::new(Takeable::new(Inner::Unbound(unbound_datagram))), nonblocking: AtomicBool::new(nonblocking), pollee, + options: RwLock::new(OptionSet::new()), } }) } @@ -352,6 +370,22 @@ impl Socket for DatagramSocket { Ok((copied_bytes, message_header)) } + + fn get_option(&self, option: &mut dyn SocketOption) -> Result<()> { + match_sock_option_mut!(option, { + socket_errors: SocketError => { + self.options.write().socket.get_and_clear_sock_errors(socket_errors); + return Ok(()); + }, + _ => () + }); + + self.options.read().socket.get_option(option) + } + + fn set_option(&self, option: &dyn SocketOption) -> Result<()> { + self.options.write().socket.set_option(option) + } } impl Observer<()> for DatagramSocket { diff --git a/kernel/src/net/socket/ip/stream/mod.rs b/kernel/src/net/socket/ip/stream/mod.rs index fdab69e69..1e153f177 100644 --- a/kernel/src/net/socket/ip/stream/mod.rs +++ b/kernel/src/net/socket/ip/stream/mod.rs @@ -19,16 +19,11 @@ use crate::{ net::{ poll_ifaces, socket::{ - options::{ - Error as SocketError, Linger, RecvBuf, ReuseAddr, ReusePort, SendBuf, SocketOption, - }, + options::{Error as SocketError, SocketOption}, util::{ copy_message_from_user, copy_message_to_user, create_message_buffer, - options::{SocketOptionSet, MIN_RECVBUF, MIN_SENDBUF}, - send_recv_flags::SendRecvFlags, - shutdown_cmd::SockShutdownCmd, - socket_addr::SocketAddr, - MessageHeader, + options::SocketOptionSet, send_recv_flags::SendRecvFlags, + shutdown_cmd::SockShutdownCmd, socket_addr::SocketAddr, MessageHeader, }, Socket, }, @@ -561,15 +556,9 @@ impl Socket for StreamSocket { } fn get_option(&self, option: &mut dyn SocketOption) -> Result<()> { - // Note that the socket error has to be handled separately, because it is automatically - // cleared after reading. match_sock_option_mut!(option, { socket_errors: SocketError => { - let mut options = self.options.write(); - let sock_errors = options.socket.sock_errors(); - socket_errors.set(sock_errors); - options.socket.set_sock_errors(None); - + self.options.write().socket.get_and_clear_sock_errors(socket_errors); return Ok(()); }, _ => () @@ -577,25 +566,12 @@ impl Socket for StreamSocket { let options = self.options.read(); + match options.socket.get_option(option) { + Err(err) if err.error() == Errno::ENOPROTOOPT => (), + res => return res.map(|_| ()), + } + match_sock_option_mut!(option, { - // Socket options: - socket_reuse_addr: ReuseAddr => { - let reuse_addr = options.socket.reuse_addr(); - socket_reuse_addr.set(reuse_addr); - }, - socket_send_buf: SendBuf => { - let send_buf = options.socket.send_buf(); - socket_send_buf.set(send_buf); - }, - socket_recv_buf: RecvBuf => { - let recv_buf = options.socket.recv_buf(); - socket_recv_buf.set(recv_buf); - }, - socket_reuse_port: ReusePort => { - let reuse_port = options.socket.reuse_port(); - socket_reuse_port.set(reuse_port); - }, - // TCP options: tcp_no_delay: NoDelay => { let no_delay = options.tcp.no_delay(); tcp_no_delay.set(no_delay); @@ -628,39 +604,14 @@ impl Socket for StreamSocket { fn set_option(&self, option: &dyn SocketOption) -> Result<()> { let mut options = self.options.write(); + match options.socket.set_option(option) { + Err(err) if err.error() == Errno::ENOPROTOOPT => (), + res => return res, + } + // 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: 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: 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: ReuseAddr => { - let reuse_addr = socket_reuse_addr.get().unwrap(); - options.socket.set_reuse_addr(*reuse_addr); - }, - socket_reuse_port: ReusePort => { - let reuse_port = socket_reuse_port.get().unwrap(); - options.socket.set_reuse_port(*reuse_port); - }, - socket_linger: Linger => { - let linger = socket_linger.get().unwrap(); - options.socket.set_linger(*linger); - }, - // TCP options: tcp_no_delay: NoDelay => { let no_delay = tcp_no_delay.get().unwrap(); options.tcp.set_no_delay(*no_delay); diff --git a/kernel/src/net/socket/util/options.rs b/kernel/src/net/socket/util/options.rs index 023c080d3..f7f8ddd52 100644 --- a/kernel/src/net/socket/util/options.rs +++ b/kernel/src/net/socket/util/options.rs @@ -3,7 +3,13 @@ use core::time::Duration; use crate::{ - net::iface::{RECV_BUF_LEN, SEND_BUF_LEN}, + match_sock_option_mut, match_sock_option_ref, + net::{ + iface::{TCP_RECV_BUF_LEN, TCP_SEND_BUF_LEN, UDP_RECV_PAYLOAD_LEN, UDP_SEND_PAYLOAD_LEN}, + socket::options::{ + Error as SocketError, Linger, RecvBuf, ReuseAddr, ReusePort, SendBuf, SocketOption, + }, + }, prelude::*, }; @@ -26,11 +32,101 @@ impl SocketOptionSet { sock_errors: None, reuse_addr: false, reuse_port: false, - send_buf: SEND_BUF_LEN as u32, - recv_buf: RECV_BUF_LEN as u32, + send_buf: TCP_SEND_BUF_LEN as u32, + recv_buf: TCP_RECV_BUF_LEN as u32, linger: LingerOption::default(), } } + + /// Return the default socket level options for udp socket. + pub fn new_udp() -> Self { + Self { + sock_errors: None, + reuse_addr: false, + reuse_port: false, + send_buf: UDP_SEND_PAYLOAD_LEN as u32, + recv_buf: UDP_RECV_PAYLOAD_LEN as u32, + linger: LingerOption::default(), + } + } + + /// Gets and clears the socket error. + /// + /// When processing the `getsockopt` system call, the socket error is automatically cleared + /// after reading. This method should be called to provide this behavior. + pub fn get_and_clear_sock_errors(&mut self, option: &mut SocketError) { + option.set(self.sock_errors()); + self.set_sock_errors(None); + } + + /// Gets socket-level options. + /// + /// Note that the socket error has to be handled separately, because it is automatically + /// cleared after reading. This method does not handle it. Instead, + /// [`Self::get_and_clear_socket_errors`] should be used. + pub fn get_option(&self, option: &mut dyn SocketOption) -> Result<()> { + match_sock_option_mut!(option, { + socket_reuse_addr: ReuseAddr => { + let reuse_addr = self.reuse_addr(); + socket_reuse_addr.set(reuse_addr); + }, + socket_send_buf: SendBuf => { + let send_buf = self.send_buf(); + socket_send_buf.set(send_buf); + }, + socket_recv_buf: RecvBuf => { + let recv_buf = self.recv_buf(); + socket_recv_buf.set(recv_buf); + }, + socket_reuse_port: ReusePort => { + let reuse_port = self.reuse_port(); + socket_reuse_port.set(reuse_port); + }, + socket_linger: Linger => { + let linger = self.linger(); + socket_linger.set(linger); + }, + _ => return_errno_with_message!(Errno::ENOPROTOOPT, "the socket option to get is unknown") + }); + Ok(()) + } + + /// Sets socket-level options. + pub fn set_option(&mut self, option: &dyn SocketOption) -> Result<()> { + match_sock_option_ref!(option, { + socket_recv_buf: RecvBuf => { + let recv_buf = socket_recv_buf.get().unwrap(); + if *recv_buf <= MIN_RECVBUF { + self.set_recv_buf(MIN_RECVBUF); + } else { + self.set_recv_buf(*recv_buf); + } + }, + socket_send_buf: SendBuf => { + let send_buf = socket_send_buf.get().unwrap(); + if *send_buf <= MIN_SENDBUF { + self.set_send_buf(MIN_SENDBUF); + } else { + self.set_send_buf(*send_buf); + } + }, + socket_reuse_addr: ReuseAddr => { + let reuse_addr = socket_reuse_addr.get().unwrap(); + self.set_reuse_addr(*reuse_addr); + }, + socket_reuse_port: ReusePort => { + let reuse_port = socket_reuse_port.get().unwrap(); + self.set_reuse_port(*reuse_port); + }, + socket_linger: Linger => { + let linger = socket_linger.get().unwrap(); + self.set_linger(*linger); + }, + _ => return_errno_with_message!(Errno::ENOPROTOOPT, "the socket option to be set is unknown") + }); + + Ok(()) + } } pub const MIN_SENDBUF: u32 = 2304;