Skip to content

Commit f289754

Browse files
committed
Add accept_from returning remote address
1 parent e4895d3 commit f289754

File tree

3 files changed

+75
-0
lines changed

3 files changed

+75
-0
lines changed

changelog/2609.added.md

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add `accept_from` function returning the remote-address.

src/sys/socket/mod.rs

+35
Original file line numberDiff line numberDiff line change
@@ -2364,6 +2364,41 @@ pub fn accept4(sockfd: RawFd, flags: SockFlag) -> Result<RawFd> {
23642364
Errno::result(res)
23652365
}
23662366

2367+
/// Accept a connection on a socket, returning the remote address.
2368+
///
2369+
/// [Further reading](https://man7.org/linux/man-pages/man2/accept.2.html)
2370+
#[cfg(any(
2371+
all(
2372+
target_os = "android",
2373+
any(
2374+
target_arch = "aarch64",
2375+
target_arch = "x86",
2376+
target_arch = "x86_64"
2377+
)
2378+
),
2379+
freebsdlike,
2380+
netbsdlike,
2381+
target_os = "emscripten",
2382+
target_os = "fuchsia",
2383+
solarish,
2384+
target_os = "linux",
2385+
))]
2386+
pub fn accept_from<S: SockaddrLike>(sockfd: RawFd, flags: SockFlag) -> Result<(RawFd, Option<S>)> {
2387+
let mut storage = std::mem::MaybeUninit::<libc::sockaddr_storage>::uninit();
2388+
let mut socklen = std::mem::size_of::<libc::sockaddr_storage>() as libc::socklen_t;
2389+
let res = unsafe {
2390+
libc::accept4(sockfd, storage.as_mut_ptr().cast(), &mut socklen as *mut _, flags.bits())
2391+
};
2392+
2393+
let sock = Errno::result(res)?;
2394+
let addr = unsafe {
2395+
let storage = storage.assume_init();
2396+
S::from_raw((&storage as *const libc::sockaddr_storage).cast(), Some(socklen))
2397+
};
2398+
2399+
Ok((sock, addr))
2400+
}
2401+
23672402
/// Initiate a connection on a socket
23682403
///
23692404
/// [Further reading](https://pubs.opengroup.org/onlinepubs/9699919799/functions/connect.html)

test/sys/test_socket.rs

+39
Original file line numberDiff line numberDiff line change
@@ -3161,3 +3161,42 @@ fn can_open_routing_socket() {
31613161
socket(AddressFamily::Route, SockType::Raw, SockFlag::empty(), None)
31623162
.expect("Failed to open routing socket");
31633163
}
3164+
3165+
// cfg needed for capability check.
3166+
#[cfg(linux_android)]
3167+
#[test]
3168+
fn test_accept_from() {
3169+
use nix::sys::socket::{accept_from, bind, connect, listen, socket};
3170+
use nix::sys::socket::{Backlog, SockFlag, SockType, SockaddrIn};
3171+
use std::net::Ipv4Addr;
3172+
3173+
let sock_addr = SockaddrIn::from_str("127.0.0.1:6780").unwrap();
3174+
let listener = socket(
3175+
AddressFamily::Inet,
3176+
SockType::Stream,
3177+
SockFlag::empty(),
3178+
None,
3179+
)
3180+
.expect("listener socket failed");
3181+
bind(listener.as_raw_fd(), &sock_addr).expect("bind failed");
3182+
listen(&listener, Backlog::MAXCONN).expect("listen failed");
3183+
3184+
let connector = socket(
3185+
AddressFamily::Inet,
3186+
SockType::Stream,
3187+
SockFlag::empty(),
3188+
None,
3189+
)
3190+
.expect("connector socket failed");
3191+
3192+
let send_thread =
3193+
std::thread::spawn(move || connect(connector.as_raw_fd(), &sock_addr));
3194+
let (_peer, address) =
3195+
accept_from::<SockaddrIn>(listener.as_raw_fd(), SockFlag::empty())
3196+
.unwrap();
3197+
let address = address.expect("no address");
3198+
3199+
assert_eq!(address.ip(), Ipv4Addr::LOCALHOST);
3200+
3201+
send_thread.join().unwrap().unwrap();
3202+
}

0 commit comments

Comments
 (0)