mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-08 21:06:48 +00:00
Fix error codes in bind
This commit is contained in:
parent
a345e11b96
commit
6f915133b5
@ -30,6 +30,14 @@ impl UnixSocketAddr {
|
||||
Ok(bound)
|
||||
}
|
||||
|
||||
pub(super) fn bind_unnamed(&self) -> Result<()> {
|
||||
if matches!(self, UnixSocketAddr::Unnamed) {
|
||||
Ok(())
|
||||
} else {
|
||||
return_errno_with_message!(Errno::EINVAL, "the socket is already bound");
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn connect(&self) -> Result<UnixSocketAddrKey> {
|
||||
let bound = match self {
|
||||
Self::Unnamed => return_errno_with_message!(
|
||||
|
@ -1,16 +1,22 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use core::ops::Deref;
|
||||
|
||||
use ostd::sync::PreemptDisabled;
|
||||
|
||||
use crate::{
|
||||
events::{IoEvents, Observer},
|
||||
fs::utils::{Channel, Consumer, Producer},
|
||||
net::socket::{unix::addr::UnixSocketAddrBound, SockShutdownCmd},
|
||||
net::socket::{
|
||||
unix::{addr::UnixSocketAddrBound, UnixSocketAddr},
|
||||
SockShutdownCmd,
|
||||
},
|
||||
prelude::*,
|
||||
process::signal::{Pollee, Poller},
|
||||
};
|
||||
|
||||
pub(super) struct Connected {
|
||||
addr: Option<UnixSocketAddrBound>,
|
||||
peer_addr: Option<UnixSocketAddrBound>,
|
||||
addr: AddrView,
|
||||
reader: Consumer<u8>,
|
||||
writer: Producer<u8>,
|
||||
}
|
||||
@ -27,15 +33,15 @@ impl Connected {
|
||||
let (writer_this, reader_peer) =
|
||||
Channel::with_capacity_and_pollees(DEFAULT_BUF_SIZE, writer_pollee, None).split();
|
||||
|
||||
let (addr_this, addr_peer) = AddrView::new_pair(addr, peer_addr);
|
||||
|
||||
let this = Connected {
|
||||
addr: addr.clone(),
|
||||
peer_addr: peer_addr.clone(),
|
||||
addr: addr_this,
|
||||
reader: reader_this,
|
||||
writer: writer_this,
|
||||
};
|
||||
let peer = Connected {
|
||||
addr: peer_addr,
|
||||
peer_addr: addr,
|
||||
addr: addr_peer,
|
||||
reader: reader_peer,
|
||||
writer: writer_peer,
|
||||
};
|
||||
@ -43,12 +49,25 @@ impl Connected {
|
||||
(this, peer)
|
||||
}
|
||||
|
||||
pub(super) fn addr(&self) -> Option<&UnixSocketAddrBound> {
|
||||
self.addr.as_ref()
|
||||
pub(super) fn addr(&self) -> Option<UnixSocketAddrBound> {
|
||||
self.addr.addr().deref().as_ref().cloned()
|
||||
}
|
||||
|
||||
pub(super) fn peer_addr(&self) -> Option<&UnixSocketAddrBound> {
|
||||
self.peer_addr.as_ref()
|
||||
pub(super) fn peer_addr(&self) -> Option<UnixSocketAddrBound> {
|
||||
self.addr.peer_addr()
|
||||
}
|
||||
|
||||
pub(super) fn bind(&self, addr_to_bind: UnixSocketAddr) -> Result<()> {
|
||||
let mut addr = self.addr.addr();
|
||||
|
||||
if addr.is_some() {
|
||||
return addr_to_bind.bind_unnamed();
|
||||
}
|
||||
|
||||
let bound_addr = addr_to_bind.bind()?;
|
||||
*addr = Some(bound_addr);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(super) fn try_read(&self, buf: &mut [u8]) -> Result<usize> {
|
||||
@ -123,4 +142,38 @@ pub(super) fn combine_io_events(
|
||||
events & (mask | IoEvents::ALWAYS_POLL)
|
||||
}
|
||||
|
||||
struct AddrView {
|
||||
addr: Arc<SpinLock<Option<UnixSocketAddrBound>>>,
|
||||
peer: Arc<SpinLock<Option<UnixSocketAddrBound>>>,
|
||||
}
|
||||
|
||||
impl AddrView {
|
||||
fn new_pair(
|
||||
first: Option<UnixSocketAddrBound>,
|
||||
second: Option<UnixSocketAddrBound>,
|
||||
) -> (AddrView, AddrView) {
|
||||
let first = Arc::new(SpinLock::new(first));
|
||||
let second = Arc::new(SpinLock::new(second));
|
||||
|
||||
let view1 = AddrView {
|
||||
addr: first.clone(),
|
||||
peer: second.clone(),
|
||||
};
|
||||
let view2 = AddrView {
|
||||
addr: second,
|
||||
peer: first,
|
||||
};
|
||||
|
||||
(view1, view2)
|
||||
}
|
||||
|
||||
fn addr(&self) -> SpinLockGuard<Option<UnixSocketAddrBound>, PreemptDisabled> {
|
||||
self.addr.lock()
|
||||
}
|
||||
|
||||
fn peer_addr(&self) -> Option<UnixSocketAddrBound> {
|
||||
self.peer.lock().as_ref().cloned()
|
||||
}
|
||||
}
|
||||
|
||||
const DEFAULT_BUF_SIZE: usize = 65536;
|
||||
|
@ -37,7 +37,7 @@ impl Init {
|
||||
|
||||
pub(super) fn bind(&mut self, addr_to_bind: UnixSocketAddr) -> Result<()> {
|
||||
if self.addr.is_some() {
|
||||
return_errno_with_message!(Errno::EINVAL, "the socket is already bound");
|
||||
return addr_to_bind.bind_unnamed();
|
||||
}
|
||||
|
||||
let bound_addr = addr_to_bind.bind()?;
|
||||
|
@ -50,7 +50,7 @@ impl Listener {
|
||||
|
||||
pub(super) fn try_accept(&self) -> Result<(Arc<dyn FileLike>, SocketAddr)> {
|
||||
let connected = self.backlog.pop_incoming()?;
|
||||
let peer_addr = connected.peer_addr().cloned().into();
|
||||
let peer_addr = connected.peer_addr().into();
|
||||
|
||||
let socket = UnixStreamSocket::new_connected(connected, false);
|
||||
Ok((socket, peer_addr))
|
||||
|
@ -229,11 +229,11 @@ impl Socket for UnixStreamSocket {
|
||||
|
||||
match self.state.write().as_mut() {
|
||||
State::Init(init) => init.bind(addr),
|
||||
_ => return_errno_with_message!(
|
||||
Errno::EINVAL,
|
||||
"cannot bind a listening or connected socket"
|
||||
),
|
||||
// FIXME: Maybe binding a connected socket should also be allowed?
|
||||
State::Connected(connected) => connected.bind(addr),
|
||||
State::Listen(_) => {
|
||||
// Listening sockets are always already bound.
|
||||
addr.bind_unnamed()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -315,7 +315,7 @@ impl Socket for UnixStreamSocket {
|
||||
let addr = match self.state.read().as_ref() {
|
||||
State::Init(init) => init.addr().cloned(),
|
||||
State::Listen(listen) => Some(listen.addr().clone()),
|
||||
State::Connected(connected) => connected.addr().cloned(),
|
||||
State::Connected(connected) => connected.addr(),
|
||||
};
|
||||
|
||||
Ok(addr.into())
|
||||
@ -323,8 +323,10 @@ impl Socket for UnixStreamSocket {
|
||||
|
||||
fn peer_addr(&self) -> Result<SocketAddr> {
|
||||
let peer_addr = match self.state.read().as_ref() {
|
||||
State::Connected(connected) => connected.peer_addr().cloned(),
|
||||
_ => return_errno_with_message!(Errno::ENOTCONN, "the socket is not connected"),
|
||||
State::Connected(connected) => connected.peer_addr(),
|
||||
State::Init(_) | State::Listen(_) => {
|
||||
return_errno_with_message!(Errno::ENOTCONN, "the socket is not connected")
|
||||
}
|
||||
};
|
||||
|
||||
Ok(peer_addr.into())
|
||||
|
@ -211,6 +211,62 @@ FN_TEST(getpeername)
|
||||
}
|
||||
END_TEST()
|
||||
|
||||
FN_TEST(bind)
|
||||
{
|
||||
TEST_ERRNO(bind(sk_bound, (struct sockaddr *)&UNIX_ADDR("\0Z"),
|
||||
PATH_OFFSET + 1),
|
||||
EINVAL);
|
||||
|
||||
TEST_ERRNO(bind(sk_listen, (struct sockaddr *)&UNIX_ADDR("\0Z"),
|
||||
PATH_OFFSET + 1),
|
||||
EINVAL);
|
||||
|
||||
TEST_SUCC(bind(sk_bound, (struct sockaddr *)&UNNAMED_ADDR,
|
||||
UNNAMED_ADDRLEN));
|
||||
|
||||
TEST_SUCC(bind(sk_listen, (struct sockaddr *)&UNNAMED_ADDR,
|
||||
UNNAMED_ADDRLEN));
|
||||
}
|
||||
END_TEST()
|
||||
|
||||
FN_TEST(bind_connected)
|
||||
{
|
||||
int fildes[2];
|
||||
struct sockaddr_un addr;
|
||||
socklen_t addrlen;
|
||||
|
||||
TEST_SUCC(socketpair(PF_UNIX, SOCK_STREAM, 0, fildes));
|
||||
|
||||
TEST_SUCC(bind(fildes[0], (struct sockaddr *)&UNIX_ADDR("\0X"),
|
||||
PATH_OFFSET + 2));
|
||||
addrlen = sizeof(addr);
|
||||
TEST_RES(getpeername(fildes[1], (struct sockaddr *)&addr, &addrlen),
|
||||
addrlen == PATH_OFFSET + 2 && memcmp(&addr, &UNIX_ADDR("\0X"),
|
||||
PATH_OFFSET + 2) == 0);
|
||||
|
||||
TEST_SUCC(bind(fildes[1], (struct sockaddr *)&UNIX_ADDR("\0Y"),
|
||||
PATH_OFFSET + 2));
|
||||
addrlen = sizeof(addr);
|
||||
TEST_RES(getpeername(fildes[0], (struct sockaddr *)&addr, &addrlen),
|
||||
addrlen == PATH_OFFSET + 2 && memcmp(&addr, &UNIX_ADDR("\0Y"),
|
||||
PATH_OFFSET + 2) == 0);
|
||||
|
||||
TEST_ERRNO(bind(fildes[0], (struct sockaddr *)&UNIX_ADDR("\0Z"),
|
||||
PATH_OFFSET + 2),
|
||||
EINVAL);
|
||||
TEST_ERRNO(bind(fildes[1], (struct sockaddr *)&UNIX_ADDR("\0Z"),
|
||||
PATH_OFFSET + 2),
|
||||
EINVAL);
|
||||
TEST_SUCC(bind(fildes[0], (struct sockaddr *)&UNNAMED_ADDR,
|
||||
UNNAMED_ADDRLEN));
|
||||
TEST_SUCC(bind(fildes[1], (struct sockaddr *)&UNNAMED_ADDR,
|
||||
UNNAMED_ADDRLEN));
|
||||
|
||||
TEST_SUCC(close(fildes[0]));
|
||||
TEST_SUCC(close(fildes[1]));
|
||||
}
|
||||
END_TEST()
|
||||
|
||||
FN_TEST(connect)
|
||||
{
|
||||
TEST_ERRNO(connect(sk_unbound, (struct sockaddr *)&BOUND_ADDR,
|
||||
|
Loading…
x
Reference in New Issue
Block a user