121 lines
3.1 KiB
Rust
121 lines
3.1 KiB
Rust
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
use core::sync::atomic::{AtomicBool, Ordering};
|
|
|
|
use super::{
|
|
connected::Connected,
|
|
listener::Listener,
|
|
socket::{SHUT_READ_EVENTS, SHUT_WRITE_EVENTS},
|
|
};
|
|
use crate::{
|
|
events::IoEvents,
|
|
fs::utils::EndpointState,
|
|
net::socket::{
|
|
unix::addr::{UnixSocketAddr, UnixSocketAddrBound},
|
|
util::SockShutdownCmd,
|
|
},
|
|
prelude::*,
|
|
process::signal::Pollee,
|
|
};
|
|
|
|
pub(super) struct Init {
|
|
addr: Option<UnixSocketAddrBound>,
|
|
is_read_shutdown: AtomicBool,
|
|
is_write_shutdown: AtomicBool,
|
|
}
|
|
|
|
impl Init {
|
|
pub(super) fn new() -> Self {
|
|
Self {
|
|
addr: None,
|
|
is_read_shutdown: AtomicBool::new(false),
|
|
is_write_shutdown: AtomicBool::new(false),
|
|
}
|
|
}
|
|
|
|
pub(super) fn bind(&mut self, addr_to_bind: UnixSocketAddr) -> Result<()> {
|
|
if self.addr.is_some() {
|
|
return addr_to_bind.bind_unnamed();
|
|
}
|
|
|
|
let bound_addr = addr_to_bind.bind()?;
|
|
self.addr = Some(bound_addr);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub(super) fn into_connected(
|
|
self,
|
|
peer_addr: UnixSocketAddrBound,
|
|
pollee: Pollee,
|
|
) -> (Connected, Connected) {
|
|
let Init {
|
|
addr,
|
|
is_read_shutdown,
|
|
is_write_shutdown,
|
|
} = self;
|
|
|
|
pollee.invalidate();
|
|
let (this_conn, peer_conn) = Connected::new_pair(
|
|
addr,
|
|
Some(peer_addr),
|
|
EndpointState::new(pollee, is_read_shutdown.into_inner()),
|
|
EndpointState::new(Pollee::new(), is_write_shutdown.into_inner()),
|
|
);
|
|
|
|
(this_conn, peer_conn)
|
|
}
|
|
|
|
pub(super) fn listen(
|
|
self,
|
|
backlog: usize,
|
|
pollee: Pollee,
|
|
) -> core::result::Result<Listener, (Error, Self)> {
|
|
let Some(addr) = self.addr else {
|
|
return Err((
|
|
Error::with_message(Errno::EINVAL, "the socket is not bound"),
|
|
self,
|
|
));
|
|
};
|
|
|
|
pollee.invalidate();
|
|
Ok(Listener::new(
|
|
addr,
|
|
backlog,
|
|
self.is_read_shutdown.into_inner(),
|
|
self.is_write_shutdown.into_inner(),
|
|
pollee,
|
|
))
|
|
}
|
|
|
|
pub(super) fn shutdown(&self, cmd: SockShutdownCmd, pollee: &Pollee) {
|
|
if cmd.shut_read() {
|
|
self.is_read_shutdown.store(true, Ordering::Relaxed);
|
|
pollee.notify(SHUT_READ_EVENTS);
|
|
}
|
|
|
|
if cmd.shut_write() {
|
|
self.is_write_shutdown.store(true, Ordering::Relaxed);
|
|
pollee.notify(SHUT_WRITE_EVENTS);
|
|
}
|
|
}
|
|
|
|
pub(super) fn addr(&self) -> Option<&UnixSocketAddrBound> {
|
|
self.addr.as_ref()
|
|
}
|
|
|
|
pub(super) fn is_read_shutdown(&self) -> bool {
|
|
self.is_read_shutdown.load(Ordering::Relaxed)
|
|
}
|
|
|
|
pub(super) fn is_write_shutdown(&self) -> bool {
|
|
self.is_write_shutdown.load(Ordering::Relaxed)
|
|
}
|
|
|
|
pub(super) fn check_io_events(&self) -> IoEvents {
|
|
// According to the Linux implementation, we always have `IoEvents::HUP` and
|
|
// `IoEvents::HUP` in this state.
|
|
IoEvents::OUT | IoEvents::HUP
|
|
}
|
|
}
|