mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-09 13:26:48 +00:00
Split UDP logic into multiple files
The TCP logic consists of multiple files, each file representing a TCP state. Since the UPP logic also consists of two states, `BoundDatagram` and `UnboundDatagram`, this commit puts them into separate files, just like TCP does.
This commit is contained in:
parent
bc771de494
commit
9f28aae78d
111
services/libs/jinux-std/src/net/socket/ip/datagram/bound.rs
Normal file
111
services/libs/jinux-std/src/net/socket/ip/datagram/bound.rs
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
use crate::events::{IoEvents, Observer};
|
||||||
|
use crate::net::iface::IpEndpoint;
|
||||||
|
|
||||||
|
use crate::net::poll_ifaces;
|
||||||
|
use crate::process::signal::{Pollee, Poller};
|
||||||
|
use crate::{
|
||||||
|
net::{
|
||||||
|
iface::{AnyBoundSocket, RawUdpSocket},
|
||||||
|
socket::util::send_recv_flags::SendRecvFlags,
|
||||||
|
},
|
||||||
|
prelude::*,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct BoundDatagram {
|
||||||
|
bound_socket: Arc<AnyBoundSocket>,
|
||||||
|
remote_endpoint: RwLock<Option<IpEndpoint>>,
|
||||||
|
pollee: Pollee,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BoundDatagram {
|
||||||
|
pub fn new(bound_socket: Arc<AnyBoundSocket>, pollee: Pollee) -> Arc<Self> {
|
||||||
|
let bound = Arc::new(Self {
|
||||||
|
bound_socket,
|
||||||
|
remote_endpoint: RwLock::new(None),
|
||||||
|
pollee,
|
||||||
|
});
|
||||||
|
bound.bound_socket.set_observer(Arc::downgrade(&bound) as _);
|
||||||
|
bound
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn remote_endpoint(&self) -> Result<IpEndpoint> {
|
||||||
|
if let Some(endpoint) = *self.remote_endpoint.read() {
|
||||||
|
Ok(endpoint)
|
||||||
|
} else {
|
||||||
|
return_errno_with_message!(Errno::EINVAL, "remote endpoint is not specified")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_remote_endpoint(&self, endpoint: IpEndpoint) {
|
||||||
|
*self.remote_endpoint.write() = Some(endpoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn local_endpoint(&self) -> Result<IpEndpoint> {
|
||||||
|
if let Some(endpoint) = self.bound_socket.local_endpoint() {
|
||||||
|
Ok(endpoint)
|
||||||
|
} else {
|
||||||
|
return_errno_with_message!(Errno::EINVAL, "socket does not bind to local endpoint")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn try_recvfrom(
|
||||||
|
&self,
|
||||||
|
buf: &mut [u8],
|
||||||
|
flags: &SendRecvFlags,
|
||||||
|
) -> Result<(usize, IpEndpoint)> {
|
||||||
|
poll_ifaces();
|
||||||
|
let recv_slice = |socket: &mut RawUdpSocket| match socket.recv_slice(buf) {
|
||||||
|
Err(smoltcp::socket::udp::RecvError::Exhausted) => {
|
||||||
|
return_errno_with_message!(Errno::EAGAIN, "recv buf is empty")
|
||||||
|
}
|
||||||
|
Ok((len, remote_endpoint)) => Ok((len, remote_endpoint)),
|
||||||
|
};
|
||||||
|
self.bound_socket.raw_with(recv_slice)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn try_sendto(
|
||||||
|
&self,
|
||||||
|
buf: &[u8],
|
||||||
|
remote: Option<IpEndpoint>,
|
||||||
|
flags: SendRecvFlags,
|
||||||
|
) -> Result<usize> {
|
||||||
|
let remote_endpoint = remote
|
||||||
|
.or_else(|| self.remote_endpoint().ok())
|
||||||
|
.ok_or_else(|| Error::with_message(Errno::EINVAL, "udp should provide remote addr"))?;
|
||||||
|
let send_slice = |socket: &mut RawUdpSocket| match socket.send_slice(buf, remote_endpoint) {
|
||||||
|
Err(_) => return_errno_with_message!(Errno::ENOBUFS, "send udp packet fails"),
|
||||||
|
Ok(()) => Ok(buf.len()),
|
||||||
|
};
|
||||||
|
let len = self.bound_socket.raw_with(send_slice)?;
|
||||||
|
poll_ifaces();
|
||||||
|
Ok(len)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn poll(&self, mask: IoEvents, poller: Option<&Poller>) -> IoEvents {
|
||||||
|
self.pollee.poll(mask, poller)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_io_events(&self) {
|
||||||
|
self.bound_socket.raw_with(|socket: &mut RawUdpSocket| {
|
||||||
|
let pollee = &self.pollee;
|
||||||
|
|
||||||
|
if socket.can_recv() {
|
||||||
|
pollee.add_events(IoEvents::IN);
|
||||||
|
} else {
|
||||||
|
pollee.del_events(IoEvents::IN);
|
||||||
|
}
|
||||||
|
|
||||||
|
if socket.can_send() {
|
||||||
|
pollee.add_events(IoEvents::OUT);
|
||||||
|
} else {
|
||||||
|
pollee.del_events(IoEvents::OUT);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Observer<()> for BoundDatagram {
|
||||||
|
fn on_events(&self, _: &()) {
|
||||||
|
self.update_io_events();
|
||||||
|
}
|
||||||
|
}
|
@ -1,25 +1,27 @@
|
|||||||
use core::sync::atomic::{AtomicBool, Ordering};
|
use core::sync::atomic::{AtomicBool, Ordering};
|
||||||
|
|
||||||
use crate::events::{IoEvents, Observer};
|
use crate::events::IoEvents;
|
||||||
use crate::fs::utils::StatusFlags;
|
use crate::fs::utils::StatusFlags;
|
||||||
use crate::net::iface::IpEndpoint;
|
use crate::net::iface::IpEndpoint;
|
||||||
|
|
||||||
use crate::process::signal::{Pollee, Poller};
|
use crate::process::signal::Poller;
|
||||||
use crate::{
|
use crate::{
|
||||||
fs::file_handle::FileLike,
|
fs::file_handle::FileLike,
|
||||||
net::{
|
net::socket::{
|
||||||
iface::{AnyBoundSocket, AnyUnboundSocket, RawUdpSocket},
|
|
||||||
poll_ifaces,
|
|
||||||
socket::{
|
|
||||||
util::{send_recv_flags::SendRecvFlags, sockaddr::SocketAddr},
|
util::{send_recv_flags::SendRecvFlags, sockaddr::SocketAddr},
|
||||||
Socket,
|
Socket,
|
||||||
},
|
},
|
||||||
},
|
|
||||||
prelude::*,
|
prelude::*,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use self::bound::BoundDatagram;
|
||||||
|
use self::unbound::UnboundDatagram;
|
||||||
|
|
||||||
use super::always_some::AlwaysSome;
|
use super::always_some::AlwaysSome;
|
||||||
use super::common::{bind_socket, get_ephemeral_endpoint};
|
use super::common::get_ephemeral_endpoint;
|
||||||
|
|
||||||
|
mod bound;
|
||||||
|
mod unbound;
|
||||||
|
|
||||||
pub struct DatagramSocket {
|
pub struct DatagramSocket {
|
||||||
nonblocking: AtomicBool,
|
nonblocking: AtomicBool,
|
||||||
@ -31,139 +33,6 @@ enum Inner {
|
|||||||
Bound(Arc<BoundDatagram>),
|
Bound(Arc<BoundDatagram>),
|
||||||
}
|
}
|
||||||
|
|
||||||
struct UnboundDatagram {
|
|
||||||
unbound_socket: Box<AnyUnboundSocket>,
|
|
||||||
pollee: Pollee,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl UnboundDatagram {
|
|
||||||
fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
unbound_socket: Box::new(AnyUnboundSocket::new_udp()),
|
|
||||||
pollee: Pollee::new(IoEvents::empty()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn poll(&self, mask: IoEvents, poller: Option<&Poller>) -> IoEvents {
|
|
||||||
self.pollee.poll(mask, poller)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn bind(self, endpoint: IpEndpoint) -> core::result::Result<Arc<BoundDatagram>, (Error, Self)> {
|
|
||||||
let bound_socket = match bind_socket(self.unbound_socket, endpoint, false) {
|
|
||||||
Ok(bound_socket) => bound_socket,
|
|
||||||
Err((err, unbound_socket)) => {
|
|
||||||
return Err((
|
|
||||||
err,
|
|
||||||
Self {
|
|
||||||
unbound_socket,
|
|
||||||
pollee: self.pollee,
|
|
||||||
},
|
|
||||||
))
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let bound_endpoint = bound_socket.local_endpoint().unwrap();
|
|
||||||
bound_socket.raw_with(|socket: &mut RawUdpSocket| {
|
|
||||||
socket.bind(bound_endpoint).unwrap();
|
|
||||||
});
|
|
||||||
Ok(BoundDatagram::new(bound_socket, self.pollee))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct BoundDatagram {
|
|
||||||
bound_socket: Arc<AnyBoundSocket>,
|
|
||||||
remote_endpoint: RwLock<Option<IpEndpoint>>,
|
|
||||||
pollee: Pollee,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl BoundDatagram {
|
|
||||||
fn new(bound_socket: Arc<AnyBoundSocket>, pollee: Pollee) -> Arc<Self> {
|
|
||||||
let bound = Arc::new(Self {
|
|
||||||
bound_socket,
|
|
||||||
remote_endpoint: RwLock::new(None),
|
|
||||||
pollee,
|
|
||||||
});
|
|
||||||
bound.bound_socket.set_observer(Arc::downgrade(&bound) as _);
|
|
||||||
bound
|
|
||||||
}
|
|
||||||
|
|
||||||
fn remote_endpoint(&self) -> Result<IpEndpoint> {
|
|
||||||
if let Some(endpoint) = *self.remote_endpoint.read() {
|
|
||||||
Ok(endpoint)
|
|
||||||
} else {
|
|
||||||
return_errno_with_message!(Errno::EINVAL, "remote endpoint is not specified")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_remote_endpoint(&self, endpoint: IpEndpoint) {
|
|
||||||
*self.remote_endpoint.write() = Some(endpoint);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn local_endpoint(&self) -> Result<IpEndpoint> {
|
|
||||||
if let Some(endpoint) = self.bound_socket.local_endpoint() {
|
|
||||||
Ok(endpoint)
|
|
||||||
} else {
|
|
||||||
return_errno_with_message!(Errno::EINVAL, "socket does not bind to local endpoint")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn try_recvfrom(&self, buf: &mut [u8], flags: &SendRecvFlags) -> Result<(usize, IpEndpoint)> {
|
|
||||||
poll_ifaces();
|
|
||||||
let recv_slice = |socket: &mut RawUdpSocket| match socket.recv_slice(buf) {
|
|
||||||
Err(smoltcp::socket::udp::RecvError::Exhausted) => {
|
|
||||||
return_errno_with_message!(Errno::EAGAIN, "recv buf is empty")
|
|
||||||
}
|
|
||||||
Ok((len, remote_endpoint)) => Ok((len, remote_endpoint)),
|
|
||||||
};
|
|
||||||
self.bound_socket.raw_with(recv_slice)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn try_sendto(
|
|
||||||
&self,
|
|
||||||
buf: &[u8],
|
|
||||||
remote: Option<IpEndpoint>,
|
|
||||||
flags: SendRecvFlags,
|
|
||||||
) -> Result<usize> {
|
|
||||||
let remote_endpoint = remote
|
|
||||||
.or_else(|| self.remote_endpoint().ok())
|
|
||||||
.ok_or_else(|| Error::with_message(Errno::EINVAL, "udp should provide remote addr"))?;
|
|
||||||
let send_slice = |socket: &mut RawUdpSocket| match socket.send_slice(buf, remote_endpoint) {
|
|
||||||
Err(_) => return_errno_with_message!(Errno::ENOBUFS, "send udp packet fails"),
|
|
||||||
Ok(()) => Ok(buf.len()),
|
|
||||||
};
|
|
||||||
let len = self.bound_socket.raw_with(send_slice)?;
|
|
||||||
poll_ifaces();
|
|
||||||
Ok(len)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn poll(&self, mask: IoEvents, poller: Option<&Poller>) -> IoEvents {
|
|
||||||
self.pollee.poll(mask, poller)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update_io_events(&self) {
|
|
||||||
self.bound_socket.raw_with(|socket: &mut RawUdpSocket| {
|
|
||||||
let pollee = &self.pollee;
|
|
||||||
|
|
||||||
if socket.can_recv() {
|
|
||||||
pollee.add_events(IoEvents::IN);
|
|
||||||
} else {
|
|
||||||
pollee.del_events(IoEvents::IN);
|
|
||||||
}
|
|
||||||
|
|
||||||
if socket.can_send() {
|
|
||||||
pollee.add_events(IoEvents::OUT);
|
|
||||||
} else {
|
|
||||||
pollee.del_events(IoEvents::OUT);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Observer<()> for BoundDatagram {
|
|
||||||
fn on_events(&self, _: &()) {
|
|
||||||
self.update_io_events();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Inner {
|
impl Inner {
|
||||||
fn is_bound(&self) -> bool {
|
fn is_bound(&self) -> bool {
|
||||||
matches!(self, Inner::Bound { .. })
|
matches!(self, Inner::Bound { .. })
|
@ -0,0 +1,52 @@
|
|||||||
|
use crate::events::IoEvents;
|
||||||
|
use crate::net::iface::IpEndpoint;
|
||||||
|
|
||||||
|
use crate::net::socket::ip::common::bind_socket;
|
||||||
|
use crate::process::signal::{Pollee, Poller};
|
||||||
|
use crate::{
|
||||||
|
net::iface::{AnyUnboundSocket, RawUdpSocket},
|
||||||
|
prelude::*,
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::bound::BoundDatagram;
|
||||||
|
|
||||||
|
pub struct UnboundDatagram {
|
||||||
|
unbound_socket: Box<AnyUnboundSocket>,
|
||||||
|
pollee: Pollee,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UnboundDatagram {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
unbound_socket: Box::new(AnyUnboundSocket::new_udp()),
|
||||||
|
pollee: Pollee::new(IoEvents::empty()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn poll(&self, mask: IoEvents, poller: Option<&Poller>) -> IoEvents {
|
||||||
|
self.pollee.poll(mask, poller)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn bind(
|
||||||
|
self,
|
||||||
|
endpoint: IpEndpoint,
|
||||||
|
) -> core::result::Result<Arc<BoundDatagram>, (Error, Self)> {
|
||||||
|
let bound_socket = match bind_socket(self.unbound_socket, endpoint, false) {
|
||||||
|
Ok(bound_socket) => bound_socket,
|
||||||
|
Err((err, unbound_socket)) => {
|
||||||
|
return Err((
|
||||||
|
err,
|
||||||
|
Self {
|
||||||
|
unbound_socket,
|
||||||
|
pollee: self.pollee,
|
||||||
|
},
|
||||||
|
))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let bound_endpoint = bound_socket.local_endpoint().unwrap();
|
||||||
|
bound_socket.raw_with(|socket: &mut RawUdpSocket| {
|
||||||
|
socket.bind(bound_endpoint).unwrap();
|
||||||
|
});
|
||||||
|
Ok(BoundDatagram::new(bound_socket, self.pollee))
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user