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}