lunatic_networking_api/
lib.rs

1mod 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
37/// This encapsulates the TCP-level connection, some connection
38/// state, and the underlying TLS-level session.
39pub 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
105// Register the networking APIs to the linker
106pub 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}