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
use core::sync::atomic::{AtomicUsize, Ordering};
use keyable_arc::KeyableWeak;
use super::{connected::Connected, endpoint::Endpoint, UnixStreamSocket};
@ -38,6 +40,11 @@ impl Listener {
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 {
self.backlog.poll(mask, poller)
}
@ -135,7 +142,7 @@ impl BacklogTable {
struct Backlog {
addr: UnixSocketAddrBound,
pollee: Pollee,
backlog: usize,
backlog: AtomicUsize,
incoming_endpoints: Mutex<VecDeque<Endpoint>>,
}
@ -144,7 +151,7 @@ impl Backlog {
Self {
addr,
pollee: Pollee::new(IoEvents::empty()),
backlog,
backlog: AtomicUsize::new(backlog),
incoming_endpoints: Mutex::new(VecDeque::with_capacity(backlog)),
}
}
@ -155,7 +162,7 @@ impl Backlog {
fn push_incoming(&self, endpoint: Endpoint) -> Result<()> {
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");
}
endpoints.push_back(endpoint);
@ -173,6 +180,10 @@ impl Backlog {
.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 {
// Lock to avoid any events may change pollee state when we poll
let _lock = self.incoming_endpoints.lock();

View File

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