lunatic_networking_api/
lib.rs1mod dns;
2mod tcp;
3mod tls_tcp;
4mod udp;
5
6use std::convert::TryInto;
7use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
8use std::sync::Arc;
9use std::time::Duration;
10
11use anyhow::Result;
12use hash_map_id::HashMapId;
13use lunatic_error_api::ErrorCtx;
14use tokio::io::{split, ReadHalf, WriteHalf};
15use tokio::net::tcp::{OwnedReadHalf, OwnedWriteHalf};
16use tokio::sync::Mutex;
17
18use anyhow::anyhow;
19use tokio::net::{TcpListener, TcpStream, UdpSocket};
20use tokio_rustls::rustls::{Certificate, PrivateKey};
21use tokio_rustls::TlsStream;
22use wasmtime::Memory;
23use wasmtime::{Caller, Linker};
24
25use lunatic_common_api::IntoTrap;
26
27pub use dns::DnsIterator;
28
29pub struct TcpConnection {
30 pub reader: Mutex<OwnedReadHalf>,
31 pub writer: Mutex<OwnedWriteHalf>,
32 pub read_timeout: Mutex<Option<Duration>>,
33 pub write_timeout: Mutex<Option<Duration>>,
34 pub peek_timeout: Mutex<Option<Duration>>,
35}
36
37pub struct TlsConnection {
40 pub reader: Mutex<ReadHalf<TlsStream<TcpStream>>>,
41 pub writer: Mutex<WriteHalf<TlsStream<TcpStream>>>,
42 pub closing: bool,
43 pub clean_closure: bool,
44 pub read_timeout: Mutex<Option<Duration>>,
45 pub write_timeout: Mutex<Option<Duration>>,
46 pub peek_timeout: Mutex<Option<Duration>>,
47}
48
49pub struct TlsListener {
50 pub listener: TcpListener,
51 pub certs: Certificate,
52 pub keys: PrivateKey,
53}
54
55impl TlsConnection {
56 pub fn new(sock: TlsStream<TcpStream>) -> TlsConnection {
57 let (read_half, write_half) = split(sock);
58 TlsConnection {
59 reader: Mutex::new(read_half),
60 writer: Mutex::new(write_half),
61 closing: false,
62 clean_closure: false,
63 read_timeout: Mutex::new(None),
64 write_timeout: Mutex::new(None),
65 peek_timeout: Mutex::new(None),
66 }
67 }
68}
69
70impl TcpConnection {
71 pub fn new(stream: TcpStream) -> Self {
72 let (read_half, write_half) = stream.into_split();
73 TcpConnection {
74 reader: Mutex::new(read_half),
75 writer: Mutex::new(write_half),
76 read_timeout: Mutex::new(None),
77 write_timeout: Mutex::new(None),
78 peek_timeout: Mutex::new(None),
79 }
80 }
81}
82
83pub type TcpListenerResources = HashMapId<TcpListener>;
84pub type TlsListenerResources = HashMapId<TlsListener>;
85pub type TcpStreamResources = HashMapId<Arc<TcpConnection>>;
86pub type TlsStreamResources = HashMapId<Arc<TlsConnection>>;
87pub type UdpResources = HashMapId<Arc<UdpSocket>>;
88pub type DnsResources = HashMapId<DnsIterator>;
89
90pub trait NetworkingCtx {
91 fn tcp_listener_resources(&self) -> &TcpListenerResources;
92 fn tcp_listener_resources_mut(&mut self) -> &mut TcpListenerResources;
93 fn tcp_stream_resources(&self) -> &TcpStreamResources;
94 fn tcp_stream_resources_mut(&mut self) -> &mut TcpStreamResources;
95 fn tls_listener_resources(&self) -> &TlsListenerResources;
96 fn tls_listener_resources_mut(&mut self) -> &mut TlsListenerResources;
97 fn tls_stream_resources(&self) -> &TlsStreamResources;
98 fn tls_stream_resources_mut(&mut self) -> &mut TlsStreamResources;
99 fn udp_resources(&self) -> &UdpResources;
100 fn udp_resources_mut(&mut self) -> &mut UdpResources;
101 fn dns_resources(&self) -> &DnsResources;
102 fn dns_resources_mut(&mut self) -> &mut DnsResources;
103}
104
105pub fn register<T: NetworkingCtx + ErrorCtx + Send + 'static>(
107 linker: &mut Linker<T>,
108) -> Result<()> {
109 dns::register(linker)?;
110 tcp::register(linker)?;
111 tls_tcp::register(linker)?;
112 udp::register(linker)?;
113 Ok(())
114}
115
116fn socket_address<T: NetworkingCtx>(
117 caller: &Caller<T>,
118 memory: &Memory,
119 addr_type: u32,
120 addr_u8_ptr: u32,
121 port: u32,
122 flow_info: u32,
123 scope_id: u32,
124) -> Result<SocketAddr> {
125 Ok(match addr_type {
126 4 => {
127 let ip = memory
128 .data(caller)
129 .get(addr_u8_ptr as usize..(addr_u8_ptr + 4) as usize)
130 .or_trap("lunatic::network::socket_address*")?;
131 let addr = <Ipv4Addr as From<[u8; 4]>>::from(ip.try_into().expect("exactly 4 bytes"));
132 SocketAddrV4::new(addr, port as u16).into()
133 }
134 6 => {
135 let ip = memory
136 .data(caller)
137 .get(addr_u8_ptr as usize..(addr_u8_ptr + 16) as usize)
138 .or_trap("lunatic::network::socket_address*")?;
139 let addr = <Ipv6Addr as From<[u8; 16]>>::from(ip.try_into().expect("exactly 16 bytes"));
140 SocketAddrV6::new(addr, port as u16, flow_info, scope_id).into()
141 }
142 _ => return Err(anyhow!("Unsupported address type in socket_address*")),
143 })
144}