Fix behavior in UNIX socket listen()

This commit is contained in:
Ruihan Li
2024-08-15 13:45:00 +08:00
committed by Tate, Hongliang Tian
parent ac19a7e0e7
commit a3d4748d6b
3 changed files with 29 additions and 6 deletions

View File

@ -1,5 +1,7 @@
// SPDX-License-Identifier: MPL-2.0 // SPDX-License-Identifier: MPL-2.0
use core::sync::atomic::{AtomicUsize, Ordering};
use keyable_arc::KeyableWeak; use keyable_arc::KeyableWeak;
use super::{connected::Connected, endpoint::Endpoint, UnixStreamSocket}; use super::{connected::Connected, endpoint::Endpoint, UnixStreamSocket};
@ -38,6 +40,11 @@ impl Listener {
Ok((socket, peer_addr)) Ok((socket, peer_addr))
} }
pub(super) fn listen(&self, backlog: usize) -> Result<()> {
self.backlog.set_backlog(backlog);
Ok(())
}
pub(super) fn poll(&self, mask: IoEvents, poller: Option<&mut Poller>) -> IoEvents { pub(super) fn poll(&self, mask: IoEvents, poller: Option<&mut Poller>) -> IoEvents {
self.backlog.poll(mask, poller) self.backlog.poll(mask, poller)
} }
@ -135,7 +142,7 @@ impl BacklogTable {
struct Backlog { struct Backlog {
addr: UnixSocketAddrBound, addr: UnixSocketAddrBound,
pollee: Pollee, pollee: Pollee,
backlog: usize, backlog: AtomicUsize,
incoming_endpoints: Mutex<VecDeque<Endpoint>>, incoming_endpoints: Mutex<VecDeque<Endpoint>>,
} }
@ -144,7 +151,7 @@ impl Backlog {
Self { Self {
addr, addr,
pollee: Pollee::new(IoEvents::empty()), pollee: Pollee::new(IoEvents::empty()),
backlog, backlog: AtomicUsize::new(backlog),
incoming_endpoints: Mutex::new(VecDeque::with_capacity(backlog)), incoming_endpoints: Mutex::new(VecDeque::with_capacity(backlog)),
} }
} }
@ -155,7 +162,7 @@ impl Backlog {
fn push_incoming(&self, endpoint: Endpoint) -> Result<()> { fn push_incoming(&self, endpoint: Endpoint) -> Result<()> {
let mut endpoints = self.incoming_endpoints.lock(); let mut endpoints = self.incoming_endpoints.lock();
if endpoints.len() >= self.backlog { if endpoints.len() >= self.backlog.load(Ordering::Relaxed) {
return_errno_with_message!(Errno::ECONNREFUSED, "incoming_endpoints is full"); return_errno_with_message!(Errno::ECONNREFUSED, "incoming_endpoints is full");
} }
endpoints.push_back(endpoint); endpoints.push_back(endpoint);
@ -173,6 +180,10 @@ impl Backlog {
.ok_or_else(|| Error::with_message(Errno::EAGAIN, "no pending connection is available")) .ok_or_else(|| Error::with_message(Errno::EAGAIN, "no pending connection is available"))
} }
fn set_backlog(&self, backlog: usize) {
self.backlog.store(backlog, Ordering::Relaxed);
}
fn poll(&self, mask: IoEvents, poller: Option<&mut Poller>) -> IoEvents { fn poll(&self, mask: IoEvents, poller: Option<&mut Poller>) -> IoEvents {
// Lock to avoid any events may change pollee state when we poll // Lock to avoid any events may change pollee state when we poll
let _lock = self.incoming_endpoints.lock(); let _lock = self.incoming_endpoints.lock();

View File

@ -242,11 +242,11 @@ impl Socket for UnixStreamSocket {
"the socket is not bound", "the socket is not bound",
))? ))?
.clone(), .clone(),
State::Listen(_) => { State::Listen(listen) => {
return_errno_with_message!(Errno::EINVAL, "the socket is already listening") return listen.listen(backlog);
} }
State::Connected(_) => { State::Connected(_) => {
return_errno_with_message!(Errno::EISCONN, "the socket is already connected") return_errno_with_message!(Errno::EINVAL, "the socket is connected")
} }
}; };

View File

@ -218,3 +218,15 @@ FN_TEST(connect)
EISCONN); EISCONN);
} }
END_TEST() END_TEST()
FN_TEST(listen)
{
TEST_ERRNO(listen(sk_unbound, 10), EINVAL);
TEST_SUCC(listen(sk_listen, 10));
TEST_ERRNO(listen(sk_connected, 10), EINVAL);
TEST_ERRNO(listen(sk_accepted, 10), EINVAL);
}
END_TEST()