mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-08 21:06:48 +00:00
Fix error codes in get{sock,peer}name
This commit is contained in:
parent
8b094454aa
commit
51080c1925
@ -27,9 +27,8 @@ impl BoundDatagram {
|
||||
self.bound_socket.local_endpoint().unwrap()
|
||||
}
|
||||
|
||||
pub fn remote_endpoint(&self) -> Result<IpEndpoint> {
|
||||
pub fn remote_endpoint(&self) -> Option<IpEndpoint> {
|
||||
self.remote_endpoint
|
||||
.ok_or_else(|| Error::with_message(Errno::EINVAL, "remote endpoint is not specified"))
|
||||
}
|
||||
|
||||
pub fn set_remote_endpoint(&mut self, endpoint: &IpEndpoint) {
|
||||
|
@ -5,7 +5,7 @@ use core::sync::atomic::{AtomicBool, Ordering};
|
||||
use takeable::Takeable;
|
||||
|
||||
use self::{bound::BoundDatagram, unbound::UnboundDatagram};
|
||||
use super::common::get_ephemeral_endpoint;
|
||||
use super::{common::get_ephemeral_endpoint, UNSPECIFIED_LOCAL_ENDPOINT};
|
||||
use crate::{
|
||||
events::{IoEvents, Observer},
|
||||
fs::{file_handle::FileLike, utils::StatusFlags},
|
||||
@ -237,18 +237,21 @@ impl Socket for DatagramSocket {
|
||||
|
||||
fn addr(&self) -> Result<SocketAddr> {
|
||||
let inner = self.inner.read();
|
||||
let Inner::Bound(bound_datagram) = inner.as_ref() else {
|
||||
return_errno_with_message!(Errno::EINVAL, "the socket is not bound");
|
||||
};
|
||||
Ok(bound_datagram.local_endpoint().into())
|
||||
match inner.as_ref() {
|
||||
Inner::Unbound(unbound_datagram) => Ok(UNSPECIFIED_LOCAL_ENDPOINT.into()),
|
||||
Inner::Bound(bound_datagram) => Ok(bound_datagram.local_endpoint().into()),
|
||||
}
|
||||
}
|
||||
|
||||
fn peer_addr(&self) -> Result<SocketAddr> {
|
||||
let inner = self.inner.read();
|
||||
let Inner::Bound(bound_datagram) = inner.as_ref() else {
|
||||
return_errno_with_message!(Errno::EINVAL, "the socket is not bound");
|
||||
return_errno_with_message!(Errno::ENOTCONN, "the socket is not connected")
|
||||
};
|
||||
Ok(bound_datagram.remote_endpoint()?.into())
|
||||
bound_datagram
|
||||
.remote_endpoint()
|
||||
.map(|endpoint| endpoint.into())
|
||||
.ok_or_else(|| Error::with_message(Errno::ENOTCONN, "the socket is not connected"))
|
||||
}
|
||||
|
||||
// FIXME: respect RecvFromFlags
|
||||
|
@ -1,8 +1,18 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use crate::net::iface::{IpAddress, IpEndpoint, Ipv4Address};
|
||||
|
||||
mod common;
|
||||
mod datagram;
|
||||
pub mod stream;
|
||||
|
||||
pub use datagram::DatagramSocket;
|
||||
pub use stream::StreamSocket;
|
||||
|
||||
/// A local endpoint, which indicates that the local endpoint is unspecified.
|
||||
///
|
||||
/// According to the Linux man pages and the Linux implementation, `getsockname()` will _not_ fail
|
||||
/// even if the socket is unbound. Instead, it will return an unspecified socket address. This
|
||||
/// unspecified endpoint helps with that.
|
||||
const UNSPECIFIED_LOCAL_ENDPOINT: IpEndpoint =
|
||||
IpEndpoint::new(IpAddress::Ipv4(Ipv4Address::UNSPECIFIED), 0);
|
||||
|
@ -83,12 +83,10 @@ impl InitStream {
|
||||
.map_err(|(err, bound_socket)| (err, InitStream::Bound(bound_socket)))
|
||||
}
|
||||
|
||||
pub fn local_endpoint(&self) -> Result<IpEndpoint> {
|
||||
pub fn local_endpoint(&self) -> Option<IpEndpoint> {
|
||||
match self {
|
||||
InitStream::Unbound(_) => {
|
||||
return_errno_with_message!(Errno::EINVAL, "does not has local endpoint")
|
||||
}
|
||||
InitStream::Bound(bound_socket) => Ok(bound_socket.local_endpoint().unwrap()),
|
||||
InitStream::Unbound(_) => None,
|
||||
InitStream::Bound(bound_socket) => Some(bound_socket.local_endpoint().unwrap()),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,7 @@ use smoltcp::wire::IpEndpoint;
|
||||
use takeable::Takeable;
|
||||
use util::{TcpOptionSet, DEFAULT_MAXSEG};
|
||||
|
||||
use super::UNSPECIFIED_LOCAL_ENDPOINT;
|
||||
use crate::{
|
||||
events::{IoEvents, Observer},
|
||||
fs::{file_handle::FileLike, utils::StatusFlags},
|
||||
@ -385,7 +386,9 @@ impl Socket for StreamSocket {
|
||||
fn addr(&self) -> Result<SocketAddr> {
|
||||
let state = self.state.read();
|
||||
let local_endpoint = match state.as_ref() {
|
||||
State::Init(init_stream) => init_stream.local_endpoint()?,
|
||||
State::Init(init_stream) => init_stream
|
||||
.local_endpoint()
|
||||
.unwrap_or(UNSPECIFIED_LOCAL_ENDPOINT),
|
||||
State::Connecting(connecting_stream) => connecting_stream.local_endpoint(),
|
||||
State::Listen(listen_stream) => listen_stream.local_endpoint(),
|
||||
State::Connected(connected_stream) => connected_stream.local_endpoint(),
|
||||
@ -396,13 +399,10 @@ impl Socket for StreamSocket {
|
||||
fn peer_addr(&self) -> Result<SocketAddr> {
|
||||
let state = self.state.read();
|
||||
let remote_endpoint = match state.as_ref() {
|
||||
State::Init(init_stream) => {
|
||||
return_errno_with_message!(Errno::EINVAL, "init socket does not have peer")
|
||||
State::Init(_) | State::Listen(_) => {
|
||||
return_errno_with_message!(Errno::ENOTCONN, "the socket is not connected")
|
||||
}
|
||||
State::Connecting(connecting_stream) => connecting_stream.remote_endpoint(),
|
||||
State::Listen(listen_stream) => {
|
||||
return_errno_with_message!(Errno::EINVAL, "listening socket does not have peer")
|
||||
}
|
||||
State::Connected(connected_stream) => connected_stream.remote_endpoint(),
|
||||
};
|
||||
Ok(remote_endpoint.into())
|
||||
|
@ -77,3 +77,62 @@ FN_SETUP(accpected)
|
||||
} while (sk_accepted < 0);
|
||||
}
|
||||
END_SETUP()
|
||||
|
||||
FN_TEST(getsockname)
|
||||
{
|
||||
struct sockaddr_in saddr = { .sin_port = 0xbeef };
|
||||
struct sockaddr *psaddr = (struct sockaddr *)&saddr;
|
||||
socklen_t addrlen = sizeof(saddr);
|
||||
|
||||
TEST_RES(getsockname(sk_unbound, psaddr, &addrlen),
|
||||
addrlen == sizeof(saddr) && saddr.sin_port == 0);
|
||||
|
||||
TEST_RES(getsockname(sk_bound, psaddr, &addrlen),
|
||||
addrlen == sizeof(saddr) && saddr.sin_port == C_PORT);
|
||||
|
||||
TEST_RES(getsockname(sk_listen, psaddr, &addrlen),
|
||||
addrlen == sizeof(saddr) && saddr.sin_port == S_PORT);
|
||||
|
||||
TEST_RES(getsockname(sk_connected, psaddr, &addrlen),
|
||||
addrlen == sizeof(saddr) && saddr.sin_port != S_PORT);
|
||||
|
||||
TEST_RES(getsockname(sk_accepted, psaddr, &addrlen),
|
||||
addrlen == sizeof(saddr) && saddr.sin_port == S_PORT);
|
||||
}
|
||||
END_TEST()
|
||||
|
||||
FN_TEST(getpeername)
|
||||
{
|
||||
struct sockaddr_in saddr = { .sin_port = 0xbeef };
|
||||
struct sockaddr *psaddr = (struct sockaddr *)&saddr;
|
||||
socklen_t addrlen = sizeof(saddr);
|
||||
|
||||
TEST_ERRNO(getpeername(sk_unbound, psaddr, &addrlen), ENOTCONN);
|
||||
|
||||
TEST_ERRNO(getpeername(sk_bound, psaddr, &addrlen), ENOTCONN);
|
||||
|
||||
TEST_ERRNO(getpeername(sk_listen, psaddr, &addrlen), ENOTCONN);
|
||||
|
||||
TEST_RES(getpeername(sk_connected, psaddr, &addrlen),
|
||||
addrlen == sizeof(saddr) && saddr.sin_port == S_PORT);
|
||||
|
||||
TEST_RES(getpeername(sk_accepted, psaddr, &addrlen),
|
||||
addrlen == sizeof(saddr) && saddr.sin_port != S_PORT);
|
||||
}
|
||||
END_TEST()
|
||||
|
||||
FN_TEST(peername_is_peer_sockname)
|
||||
{
|
||||
struct sockaddr_in saddr = { .sin_port = 0xbeef };
|
||||
struct sockaddr *psaddr = (struct sockaddr *)&saddr;
|
||||
socklen_t addrlen = sizeof(saddr);
|
||||
int em_port;
|
||||
|
||||
TEST_RES(getsockname(sk_connected, psaddr, &addrlen),
|
||||
addrlen == sizeof(saddr));
|
||||
em_port = saddr.sin_port;
|
||||
|
||||
TEST_RES(getpeername(sk_accepted, psaddr, &addrlen),
|
||||
addrlen == sizeof(saddr) && saddr.sin_port == em_port);
|
||||
}
|
||||
END_TEST()
|
||||
|
@ -50,3 +50,35 @@ FN_SETUP(connected)
|
||||
sizeof(sk_addr)));
|
||||
}
|
||||
END_SETUP()
|
||||
|
||||
FN_TEST(getsockname)
|
||||
{
|
||||
struct sockaddr_in saddr = { .sin_port = 0xbeef };
|
||||
struct sockaddr *psaddr = (struct sockaddr *)&saddr;
|
||||
socklen_t addrlen = sizeof(saddr);
|
||||
|
||||
TEST_RES(getsockname(sk_unbound, psaddr, &addrlen),
|
||||
addrlen == sizeof(saddr) && saddr.sin_port == 0);
|
||||
|
||||
TEST_RES(getsockname(sk_bound, psaddr, &addrlen),
|
||||
addrlen == sizeof(saddr) && saddr.sin_port == C_PORT);
|
||||
|
||||
TEST_RES(getsockname(sk_connected, psaddr, &addrlen),
|
||||
addrlen == sizeof(saddr) && saddr.sin_port != C_PORT);
|
||||
}
|
||||
END_TEST()
|
||||
|
||||
FN_TEST(getpeername)
|
||||
{
|
||||
struct sockaddr_in saddr = { .sin_port = 0xbeef };
|
||||
struct sockaddr *psaddr = (struct sockaddr *)&saddr;
|
||||
socklen_t addrlen = sizeof(saddr);
|
||||
|
||||
TEST_ERRNO(getpeername(sk_unbound, psaddr, &addrlen), ENOTCONN);
|
||||
|
||||
TEST_ERRNO(getpeername(sk_bound, psaddr, &addrlen), ENOTCONN);
|
||||
|
||||
TEST_RES(getpeername(sk_connected, psaddr, &addrlen),
|
||||
addrlen == sizeof(saddr) && saddr.sin_port == C_PORT);
|
||||
}
|
||||
END_TEST()
|
||||
|
Loading…
x
Reference in New Issue
Block a user