async_send_fd/
smol_stream.rs1use 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
20pub trait AsyncSendSmolStream {
22 fn send_stream(
23 &self,
24 fd: UnixStream,
25 ) -> impl std::future::Future<Output = Result<(), Error>> + Send;
26}
27
28pub 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}