async_send_fd/
smol_stream.rs

1use std::{
2    io::{Error, ErrorKind},
3    os::{
4        fd::AsFd,
5        unix::{
6            io::{AsRawFd, RawFd},
7            net::UnixStream as OsUnixStream,
8            prelude::FromRawFd,
9        },
10    },
11    sync::Arc,
12};
13
14use smol::{net::unix::UnixStream, Async};
15
16use passfd::FdPassingExt;
17
18use crate::{AsyncRecvFd, AsyncSendFd};
19
20/// A trait to send raw file descriptors
21pub trait AsyncSendSmolStream {
22    fn send_stream(
23        &self,
24        fd: UnixStream,
25    ) -> impl std::future::Future<Output = Result<(), Error>> + Send;
26}
27
28/// A trait to receive raw file descriptors
29pub trait AsyncRecvSmolStream {
30    fn recv_stream(&self) -> impl std::future::Future<Output = Result<UnixStream, Error>> + Send;
31}
32
33impl AsyncRecvFd for UnixStream {
34    async fn recv_fd(&self) -> Result<RawFd, Error> {
35        let async_io: Arc<Async<std::os::unix::net::UnixStream>> = self.clone().into();
36
37        loop {
38            async_io.readable().await?;
39
40            match async_io.as_fd().as_raw_fd().recv_fd() {
41                Err(ref e) if e.kind() == ErrorKind::WouldBlock => {
42                    continue;
43                }
44                r => return r,
45            }
46        }
47    }
48}
49
50impl AsyncSendFd for UnixStream {
51    async fn send_fd(&self, fd: RawFd) -> Result<(), Error> {
52        let async_io: Arc<Async<std::os::unix::net::UnixStream>> = self.clone().into();
53
54        loop {
55            async_io.writable().await?;
56
57            match async_io.as_fd().as_raw_fd().send_fd(fd) {
58                Err(ref e) if e.kind() == ErrorKind::WouldBlock => {
59                    continue;
60                }
61                r => return r,
62            }
63        }
64    }
65}
66
67impl AsyncSendSmolStream for UnixStream {
68    async fn send_stream(&self, stream: UnixStream) -> Result<(), Error> {
69        let fd = stream.as_fd().as_raw_fd();
70
71        self.send_fd(fd).await
72    }
73}
74
75impl AsyncRecvSmolStream for UnixStream {
76    async fn recv_stream(&self) -> Result<UnixStream, Error> {
77        let fd = self.recv_fd().await?;
78
79        let os_stream = unsafe { OsUnixStream::from_raw_fd(fd) };
80        UnixStream::try_from(os_stream)
81    }
82}