mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-15 16:26: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()
|
self.bound_socket.local_endpoint().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remote_endpoint(&self) -> Result<IpEndpoint> {
|
pub fn remote_endpoint(&self) -> Option<IpEndpoint> {
|
||||||
self.remote_endpoint
|
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) {
|
pub fn set_remote_endpoint(&mut self, endpoint: &IpEndpoint) {
|
||||||
|
@ -5,7 +5,7 @@ use core::sync::atomic::{AtomicBool, Ordering};
|
|||||||
use takeable::Takeable;
|
use takeable::Takeable;
|
||||||
|
|
||||||
use self::{bound::BoundDatagram, unbound::UnboundDatagram};
|
use self::{bound::BoundDatagram, unbound::UnboundDatagram};
|
||||||
use super::common::get_ephemeral_endpoint;
|
use super::{common::get_ephemeral_endpoint, UNSPECIFIED_LOCAL_ENDPOINT};
|
||||||
use crate::{
|
use crate::{
|
||||||
events::{IoEvents, Observer},
|
events::{IoEvents, Observer},
|
||||||
fs::{file_handle::FileLike, utils::StatusFlags},
|
fs::{file_handle::FileLike, utils::StatusFlags},
|
||||||
@ -237,18 +237,21 @@ impl Socket for DatagramSocket {
|
|||||||
|
|
||||||
fn addr(&self) -> Result<SocketAddr> {
|
fn addr(&self) -> Result<SocketAddr> {
|
||||||
let inner = self.inner.read();
|
let inner = self.inner.read();
|
||||||
let Inner::Bound(bound_datagram) = inner.as_ref() else {
|
match inner.as_ref() {
|
||||||
return_errno_with_message!(Errno::EINVAL, "the socket is not bound");
|
Inner::Unbound(unbound_datagram) => Ok(UNSPECIFIED_LOCAL_ENDPOINT.into()),
|
||||||
};
|
Inner::Bound(bound_datagram) => Ok(bound_datagram.local_endpoint().into()),
|
||||||
Ok(bound_datagram.local_endpoint().into())
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn peer_addr(&self) -> Result<SocketAddr> {
|
fn peer_addr(&self) -> Result<SocketAddr> {
|
||||||
let inner = self.inner.read();
|
let inner = self.inner.read();
|
||||||
let Inner::Bound(bound_datagram) = inner.as_ref() else {
|
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
|
// FIXME: respect RecvFromFlags
|
||||||
|
@ -1,8 +1,18 @@
|
|||||||
// SPDX-License-Identifier: MPL-2.0
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
use crate::net::iface::{IpAddress, IpEndpoint, Ipv4Address};
|
||||||
|
|
||||||
mod common;
|
mod common;
|
||||||
mod datagram;
|
mod datagram;
|
||||||
pub mod stream;
|
pub mod stream;
|
||||||
|
|
||||||
pub use datagram::DatagramSocket;
|
pub use datagram::DatagramSocket;
|
||||||
pub use stream::StreamSocket;
|
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)))
|
.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 {
|
match self {
|
||||||
InitStream::Unbound(_) => {
|
InitStream::Unbound(_) => None,
|
||||||
return_errno_with_message!(Errno::EINVAL, "does not has local endpoint")
|
InitStream::Bound(bound_socket) => Some(bound_socket.local_endpoint().unwrap()),
|
||||||
}
|
|
||||||
InitStream::Bound(bound_socket) => Ok(bound_socket.local_endpoint().unwrap()),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@ use smoltcp::wire::IpEndpoint;
|
|||||||
use takeable::Takeable;
|
use takeable::Takeable;
|
||||||
use util::{TcpOptionSet, DEFAULT_MAXSEG};
|
use util::{TcpOptionSet, DEFAULT_MAXSEG};
|
||||||
|
|
||||||
|
use super::UNSPECIFIED_LOCAL_ENDPOINT;
|
||||||
use crate::{
|
use crate::{
|
||||||
events::{IoEvents, Observer},
|
events::{IoEvents, Observer},
|
||||||
fs::{file_handle::FileLike, utils::StatusFlags},
|
fs::{file_handle::FileLike, utils::StatusFlags},
|
||||||
@ -385,7 +386,9 @@ impl Socket for StreamSocket {
|
|||||||
fn addr(&self) -> Result<SocketAddr> {
|
fn addr(&self) -> Result<SocketAddr> {
|
||||||
let state = self.state.read();
|
let state = self.state.read();
|
||||||
let local_endpoint = match state.as_ref() {
|
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::Connecting(connecting_stream) => connecting_stream.local_endpoint(),
|
||||||
State::Listen(listen_stream) => listen_stream.local_endpoint(),
|
State::Listen(listen_stream) => listen_stream.local_endpoint(),
|
||||||
State::Connected(connected_stream) => connected_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> {
|
fn peer_addr(&self) -> Result<SocketAddr> {
|
||||||
let state = self.state.read();
|
let state = self.state.read();
|
||||||
let remote_endpoint = match state.as_ref() {
|
let remote_endpoint = match state.as_ref() {
|
||||||
State::Init(init_stream) => {
|
State::Init(_) | State::Listen(_) => {
|
||||||
return_errno_with_message!(Errno::EINVAL, "init socket does not have peer")
|
return_errno_with_message!(Errno::ENOTCONN, "the socket is not connected")
|
||||||
}
|
}
|
||||||
State::Connecting(connecting_stream) => connecting_stream.remote_endpoint(),
|
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(),
|
State::Connected(connected_stream) => connected_stream.remote_endpoint(),
|
||||||
};
|
};
|
||||||
Ok(remote_endpoint.into())
|
Ok(remote_endpoint.into())
|
||||||
|
@ -77,3 +77,62 @@ FN_SETUP(accpected)
|
|||||||
} while (sk_accepted < 0);
|
} while (sk_accepted < 0);
|
||||||
}
|
}
|
||||||
END_SETUP()
|
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)));
|
sizeof(sk_addr)));
|
||||||
}
|
}
|
||||||
END_SETUP()
|
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