rd_std/builtin/
local.rs

1use std::{
2    io::{self, ErrorKind},
3    net::SocketAddr,
4};
5
6use rd_interface::{
7    async_trait, impl_async_read_write,
8    registry::{EmptyConfig, NetFactory},
9    Address, INet, IntoDyn, Result, TcpListener, TcpStream, UdpSocket,
10};
11use tokio::net;
12
13pub struct LocalNet;
14pub struct CompatTcp(pub(crate) net::TcpStream);
15pub struct Listener(net::TcpListener);
16pub struct Udp(net::UdpSocket);
17
18impl LocalNet {
19    fn new() -> LocalNet {
20        LocalNet
21    }
22}
23async fn lookup_host(domain: String, port: u16) -> io::Result<SocketAddr> {
24    use tokio::net::lookup_host;
25
26    let domain = (domain.as_ref(), port);
27    lookup_host(domain)
28        .await?
29        .next()
30        .ok_or(ErrorKind::AddrNotAvailable.into())
31}
32
33impl_async_read_write!(CompatTcp, 0);
34
35#[async_trait]
36impl rd_interface::ITcpStream for CompatTcp {
37    async fn peer_addr(&self) -> Result<SocketAddr> {
38        self.0.peer_addr().map_err(Into::into)
39    }
40    async fn local_addr(&self) -> Result<SocketAddr> {
41        self.0.local_addr().map_err(Into::into)
42    }
43}
44impl CompatTcp {
45    fn new(t: net::TcpStream) -> CompatTcp {
46        CompatTcp(t)
47    }
48}
49
50#[async_trait]
51impl rd_interface::ITcpListener for Listener {
52    async fn accept(&self) -> Result<(TcpStream, SocketAddr)> {
53        let (socket, addr) = self.0.accept().await?;
54        Ok((CompatTcp::new(socket).into_dyn(), addr))
55    }
56
57    async fn local_addr(&self) -> Result<SocketAddr> {
58        self.0.local_addr().map_err(Into::into)
59    }
60}
61
62#[async_trait]
63impl rd_interface::IUdpSocket for Udp {
64    async fn recv_from(&self, buf: &mut [u8]) -> Result<(usize, SocketAddr)> {
65        self.0.recv_from(buf).await.map_err(Into::into)
66    }
67
68    async fn send_to(&self, buf: &[u8], addr: Address) -> Result<usize> {
69        let addr = addr.resolve(lookup_host).await?;
70        self.0.send_to(buf, addr).await.map_err(Into::into)
71    }
72
73    async fn local_addr(&self) -> Result<SocketAddr> {
74        self.0.local_addr().map_err(Into::into)
75    }
76}
77
78#[async_trait]
79impl INet for LocalNet {
80    async fn tcp_connect(
81        &self,
82        _ctx: &mut rd_interface::Context,
83        addr: Address,
84    ) -> Result<TcpStream> {
85        #[cfg(feature = "local_log")]
86        log::trace!("local::tcp_connect {:?} {:?}", _ctx, addr);
87        let addr = addr.resolve(lookup_host).await?;
88        Ok(CompatTcp::new(net::TcpStream::connect(addr).await?).into_dyn())
89    }
90
91    async fn tcp_bind(
92        &self,
93        _ctx: &mut rd_interface::Context,
94        addr: Address,
95    ) -> Result<TcpListener> {
96        #[cfg(feature = "local_log")]
97        log::trace!("local::tcp_bind {:?} {:?}", _ctx, addr);
98        let addr = addr.resolve(lookup_host).await?;
99        Ok(Listener(net::TcpListener::bind(addr).await?).into_dyn())
100    }
101
102    async fn udp_bind(&self, _ctx: &mut rd_interface::Context, addr: Address) -> Result<UdpSocket> {
103        #[cfg(feature = "local_log")]
104        log::trace!("local::udp_bind {:?} {:?}", _ctx, addr);
105        let addr = addr.resolve(lookup_host).await?;
106        Ok(Udp(net::UdpSocket::bind(addr).await?).into_dyn())
107    }
108}
109
110impl NetFactory for LocalNet {
111    const NAME: &'static str = "local";
112    type Config = EmptyConfig;
113    type Net = Self;
114
115    fn new(_nets: Vec<rd_interface::Net>, _config: Self::Config) -> Result<Self> {
116        Ok(LocalNet::new())
117    }
118}