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