Skip to content

Commit ee8318d

Browse files
authored
net: FromRawFd, AsRawFd, and from_std for TcpListener. (#262)
This enables socket configuration for the listener.
1 parent 78b269b commit ee8318d

File tree

1 file changed

+53
-4
lines changed

1 file changed

+53
-4
lines changed

src/net/tcp/listener.rs

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
use super::TcpStream;
2-
use crate::io::Socket;
3-
use std::{io, net::SocketAddr};
2+
use crate::io::{SharedFd, Socket};
3+
use std::{
4+
io,
5+
net::SocketAddr,
6+
os::unix::prelude::{AsRawFd, FromRawFd, RawFd},
7+
};
48

59
/// A TCP socket server, listening for connections.
610
///
@@ -53,6 +57,41 @@ impl TcpListener {
5357
Ok(TcpListener { inner: socket })
5458
}
5559

60+
/// Creates new `TcpListener` from a previously bound `std::net::TcpListener`.
61+
///
62+
/// This function is intended to be used to wrap a TCP listener from the
63+
/// standard library in the tokio-uring equivalent. The conversion assumes nothing
64+
/// about the underlying socket; it is left up to the user to decide what socket
65+
/// options are appropriate for their use case.
66+
///
67+
/// This can be used in conjunction with socket2's `Socket` interface to
68+
/// configure a socket before it's handed off, such as setting options like
69+
/// `reuse_address` or binding to multiple addresses.
70+
///
71+
/// # Example
72+
///
73+
/// ```
74+
/// tokio_uring::start(async {
75+
/// let address: std::net::SocketAddr = "[::0]:8443".parse().unwrap();
76+
/// let socket = tokio::net::TcpSocket::new_v6().unwrap();
77+
/// socket.set_reuseaddr(true).unwrap();
78+
/// socket.set_reuseport(true).unwrap();
79+
/// socket.bind(address).unwrap();
80+
///
81+
/// let listener = socket.listen(1024).unwrap();
82+
///
83+
/// let listener = tokio_uring::net::TcpListener::from_std(listener.into_std().unwrap());
84+
/// })
85+
/// ```
86+
pub fn from_std(socket: std::net::TcpListener) -> Self {
87+
let inner = Socket::from_std(socket);
88+
Self { inner }
89+
}
90+
91+
pub(crate) fn from_socket(inner: Socket) -> Self {
92+
Self { inner }
93+
}
94+
5695
/// Returns the local address that this listener is bound to.
5796
///
5897
/// This can be useful, for example, when binding to port 0 to
@@ -70,8 +109,6 @@ impl TcpListener {
70109
/// assert_eq!(addr, SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080)));
71110
/// ```
72111
pub fn local_addr(&self) -> io::Result<SocketAddr> {
73-
use std::os::unix::io::{AsRawFd, FromRawFd};
74-
75112
let fd = self.inner.as_raw_fd();
76113
// SAFETY: Our fd is the handle the kernel has given us for a TcpListener.
77114
// Create a std::net::TcpListener long enough to call its local_addr method
@@ -98,3 +135,15 @@ impl TcpListener {
98135
Ok((stream, socket_addr))
99136
}
100137
}
138+
139+
impl FromRawFd for TcpListener {
140+
unsafe fn from_raw_fd(fd: RawFd) -> Self {
141+
TcpListener::from_socket(Socket::from_shared_fd(SharedFd::new(fd)))
142+
}
143+
}
144+
145+
impl AsRawFd for TcpListener {
146+
fn as_raw_fd(&self) -> RawFd {
147+
self.inner.as_raw_fd()
148+
}
149+
}

0 commit comments

Comments
 (0)