Skip to main content

strate_net_silo/
transport.rs

1use smoltcp::{
2    socket::{tcp, udp},
3    wire::IpAddress,
4};
5use strate_net::IpcMessage;
6
7use crate::{
8    ipc::{reply_read, reply_write, write_data},
9    state::{NetworkStrate, TcpConnState, TcpListenerState, UdpConnState},
10};
11
12impl NetworkStrate {
13    pub(crate) fn handle_tcp_read(
14        &mut self,
15        sender: u64,
16        listener: TcpListenerState,
17        requested: usize,
18    ) -> IpcMessage {
19        if requested == 0 {
20            return reply_read(sender, &[]);
21        }
22        let socket = self.sockets.get_mut::<tcp::Socket>(listener.socket);
23        if !socket.is_open() || (!socket.is_listening() && !socket.is_active()) {
24            if listener.auto_relisten {
25                let _ = socket.listen(listener.port);
26            } else {
27                return IpcMessage::error_reply(sender, -104);
28            }
29        }
30
31        let mut data = [0u8; IpcMessage::READ_INLINE_CAPACITY];
32        if socket.can_recv() {
33            let want = requested.min(data.len());
34            match socket.recv_slice(&mut data[..want]) {
35                Ok(n) => return reply_read(sender, &data[..n]),
36                Err(_) => return IpcMessage::error_reply(sender, -5),
37            }
38        }
39
40        if socket.is_open() && !socket.may_recv() && !socket.may_send() {
41            socket.abort();
42            if listener.auto_relisten {
43                let _ = socket.listen(listener.port);
44            } else {
45                return IpcMessage::error_reply(sender, -104);
46            }
47        }
48        IpcMessage::error_reply(sender, -11)
49    }
50
51    pub(crate) fn handle_tcp_write(
52        &mut self,
53        sender: u64,
54        listener: TcpListenerState,
55        msg: &IpcMessage,
56    ) -> IpcMessage {
57        let socket = self.sockets.get_mut::<tcp::Socket>(listener.socket);
58        if !socket.is_open() || (!socket.is_listening() && !socket.is_active()) {
59            if listener.auto_relisten {
60                let _ = socket.listen(listener.port);
61            } else {
62                return IpcMessage::error_reply(sender, -104);
63            }
64        }
65
66        let data = write_data(msg);
67        if !socket.can_send() {
68            return IpcMessage::error_reply(sender, -11);
69        }
70
71        match socket.send_slice(data) {
72            Ok(n) => reply_write(sender, n),
73            Err(_) => IpcMessage::error_reply(sender, -11),
74        }
75    }
76
77    pub(crate) fn handle_tcp_conn_read(
78        &mut self,
79        sender: u64,
80        conn: TcpConnState,
81        requested: usize,
82    ) -> IpcMessage {
83        if requested == 0 {
84            return reply_read(sender, &[]);
85        }
86        let socket = self.sockets.get_mut::<tcp::Socket>(conn.socket);
87        if !socket.is_open() {
88            return IpcMessage::error_reply(sender, -104);
89        }
90        let state = socket.state();
91        if state == tcp::State::SynSent || state == tcp::State::SynReceived {
92            return IpcMessage::error_reply(sender, -115);
93        }
94
95        let mut data = [0u8; IpcMessage::READ_INLINE_CAPACITY];
96        if socket.can_recv() {
97            let want = requested.min(data.len());
98            match socket.recv_slice(&mut data[..want]) {
99                Ok(n) => reply_read(sender, &data[..n]),
100                Err(_) => IpcMessage::error_reply(sender, -5),
101            }
102        } else {
103            IpcMessage::error_reply(sender, -11)
104        }
105    }
106
107    pub(crate) fn handle_tcp_conn_write(
108        &mut self,
109        sender: u64,
110        conn: TcpConnState,
111        msg: &IpcMessage,
112    ) -> IpcMessage {
113        let socket = self.sockets.get_mut::<tcp::Socket>(conn.socket);
114        if !socket.is_open() {
115            return IpcMessage::error_reply(sender, -104);
116        }
117        let state = socket.state();
118        if state == tcp::State::SynSent || state == tcp::State::SynReceived {
119            return IpcMessage::error_reply(sender, -115);
120        }
121
122        let data = write_data(msg);
123        if !socket.can_send() {
124            return IpcMessage::error_reply(sender, -11);
125        }
126        match socket.send_slice(data) {
127            Ok(n) => reply_write(sender, n),
128            Err(_) => IpcMessage::error_reply(sender, -11),
129        }
130    }
131
132    pub(crate) fn handle_udp_bound_read(
133        &mut self,
134        sender: u64,
135        file_id: u64,
136        requested: usize,
137    ) -> IpcMessage {
138        if requested == 0 {
139            return reply_read(sender, &[]);
140        }
141        if let Some(reply) = self.drain_spilled_read(sender, file_id, requested) {
142            return reply;
143        }
144        let socket_handle = match self.udp_bound.get(&file_id) {
145            Some(state) => state.socket,
146            None => return IpcMessage::error_reply(sender, -9),
147        };
148
149        let (peer, out) = {
150            let socket = self.sockets.get_mut::<udp::Socket>(socket_handle);
151            let Ok((data, meta)) = socket.recv() else {
152                return IpcMessage::error_reply(sender, -11);
153            };
154
155            let mut out = alloc::vec![0u8; 19 + data.len()];
156            match meta.endpoint.addr {
157                IpAddress::Ipv4(src_ip) => {
158                    out[0] = 4;
159                    out[1..5].copy_from_slice(&src_ip.octets());
160                }
161                IpAddress::Ipv6(src_ip) => {
162                    out[0] = 6;
163                    out[1..17].copy_from_slice(&src_ip.octets());
164                }
165            }
166            out[17..19].copy_from_slice(&meta.endpoint.port.to_be_bytes());
167            out[19..].copy_from_slice(data);
168            (meta.endpoint, out)
169        };
170
171        if let Some(state) = self.udp_bound.get_mut(&file_id) {
172            state.last_peer = Some(peer);
173        }
174
175        self.reply_read_spilling(sender, file_id, requested, out)
176    }
177
178    pub(crate) fn handle_udp_bound_write(
179        &mut self,
180        sender: u64,
181        file_id: u64,
182        msg: &IpcMessage,
183    ) -> IpcMessage {
184        let state = match self.udp_bound.get(&file_id).copied() {
185            Some(state) => state,
186            None => return IpcMessage::error_reply(sender, -9),
187        };
188        let Some(peer) = state.last_peer else {
189            return IpcMessage::error_reply(sender, -89);
190        };
191
192        let socket = self.sockets.get_mut::<udp::Socket>(state.socket);
193        let data = write_data(msg);
194        if !socket.can_send() {
195            return IpcMessage::error_reply(sender, -11);
196        }
197        match socket.send_slice(data, peer) {
198            Ok(()) => reply_write(sender, data.len()),
199            Err(udp::SendError::BufferFull) => IpcMessage::error_reply(sender, -11),
200            Err(udp::SendError::Unaddressable) => IpcMessage::error_reply(sender, -22),
201        }
202    }
203
204    pub(crate) fn handle_udp_conn_read(
205        &mut self,
206        sender: u64,
207        file_id: u64,
208        conn: UdpConnState,
209        requested: usize,
210    ) -> IpcMessage {
211        if requested == 0 {
212            return reply_read(sender, &[]);
213        }
214        if let Some(reply) = self.drain_spilled_read(sender, file_id, requested) {
215            return reply;
216        }
217
218        let packet = {
219            let socket = self.sockets.get_mut::<udp::Socket>(conn.socket);
220            let mut packet = None;
221            while socket.can_recv() {
222                let Ok((data, meta)) = socket.recv() else {
223                    break;
224                };
225                if meta.endpoint.addr == conn.remote.addr && meta.endpoint.port == conn.remote.port
226                {
227                    packet = Some(data.to_vec());
228                    break;
229                }
230            }
231            packet
232        };
233        if let Some(packet) = packet {
234            return self.reply_read_spilling(sender, file_id, requested, packet);
235        }
236        IpcMessage::error_reply(sender, -11)
237    }
238
239    pub(crate) fn handle_udp_conn_write(
240        &mut self,
241        sender: u64,
242        conn: UdpConnState,
243        msg: &IpcMessage,
244    ) -> IpcMessage {
245        let socket = self.sockets.get_mut::<udp::Socket>(conn.socket);
246        let data = write_data(msg);
247        if !socket.can_send() {
248            return IpcMessage::error_reply(sender, -11);
249        }
250        match socket.send_slice(data, conn.remote) {
251            Ok(()) => reply_write(sender, data.len()),
252            Err(udp::SendError::BufferFull) => IpcMessage::error_reply(sender, -11),
253            Err(udp::SendError::Unaddressable) => IpcMessage::error_reply(sender, -22),
254        }
255    }
256}