capsules_extra/net/udp/
udp_recv.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5//! Definition and implementation for the UDP reception interface.
6//!
7//! It follows the same virtualization model as that described in
8//! `udp_send.rs`, except that no queueing is needed because received
9//! packets are immediately dispatched to the appropriate capsule /
10//! app. Once again, port binding for userspace apps is managed
11//! separately by the UDP userspace driver, which must correctly check
12//! bindings of kernel apps to ensure correctness when dispatching
13//! received packets to the appropriate client.
14
15use crate::net::ipv6::ip_utils::IPAddr;
16use crate::net::ipv6::ipv6_recv::IP6RecvClient;
17use crate::net::ipv6::IP6Header;
18use crate::net::udp::driver::UDPDriver;
19use crate::net::udp::udp_port_table::{PortQuery, UdpPortBindingRx};
20use crate::net::udp::UDPHeader;
21
22use kernel::collections::list::{List, ListLink, ListNode};
23use kernel::debug;
24use kernel::utilities::cells::{MapCell, OptionalCell};
25
26pub struct MuxUdpReceiver<'a> {
27    rcvr_list: List<'a, UDPReceiver<'a>>,
28    driver: OptionalCell<&'static UDPDriver<'static>>,
29}
30
31impl<'a> MuxUdpReceiver<'a> {
32    pub fn new() -> MuxUdpReceiver<'a> {
33        MuxUdpReceiver {
34            rcvr_list: List::new(),
35            driver: OptionalCell::empty(),
36        }
37    }
38
39    pub fn add_client(&self, rcvr: &'a UDPReceiver<'a>) {
40        self.rcvr_list.push_tail(rcvr);
41    }
42
43    pub fn set_driver(&self, driver_ref: &'static UDPDriver) {
44        self.driver.replace(driver_ref);
45    }
46}
47
48impl IP6RecvClient for MuxUdpReceiver<'_> {
49    fn receive(&self, ip_header: IP6Header, payload: &[u8]) {
50        if let Some((offset, udp_header)) = UDPHeader::decode(payload).done() {
51            let len = udp_header.get_len() as usize;
52            let dst_port = udp_header.get_dst_port();
53            if len > payload.len() {
54                debug!("[UDP_RECV] Error: Received UDP length too long");
55                return;
56            }
57            for rcvr in self.rcvr_list.iter() {
58                match rcvr.binding.take() {
59                    Some(binding) => {
60                        if binding.get_port() == dst_port {
61                            rcvr.client.map(|client| {
62                                client.receive(
63                                    ip_header.get_src_addr(),
64                                    ip_header.get_dst_addr(),
65                                    udp_header.get_src_port(),
66                                    udp_header.get_dst_port(),
67                                    &payload[offset..],
68                                );
69                            });
70                            rcvr.binding.replace(binding);
71                            break;
72                        }
73                        rcvr.binding.replace(binding);
74                    }
75                    // The UDPReceiver used by the driver will not have a binding
76                    None => {
77                        if let Some(driver) = self.driver.take() {
78                            if driver.is_bound(dst_port) {
79                                driver.receive(
80                                    ip_header.get_src_addr(),
81                                    ip_header.get_dst_addr(),
82                                    udp_header.get_src_port(),
83                                    udp_header.get_dst_port(),
84                                    &payload[offset..],
85                                );
86                                self.driver.replace(driver);
87                                break;
88                            }
89                            self.driver.replace(driver);
90                        }
91                    }
92                }
93            }
94        }
95    }
96}
97
98/// Client interface trait to receive UDP packets.
99///
100/// Intended to received packets passed up the network stack to the
101/// UDPReceiver, and then distributes them to userland applications
102/// from there.  Kernel apps can also instantiate structs that
103/// implement this trait in order to receive UDP packets
104pub trait UDPRecvClient {
105    fn receive(
106        &self,
107        src_addr: IPAddr,
108        dst_addr: IPAddr,
109        src_port: u16,
110        dst_port: u16,
111        payload: &[u8],
112    );
113}
114
115/// This struct is set as the client of the MuxUdpReceiver, and passes
116/// received packets up to whatever app layer client assigns itself
117/// as the UDPRecvClient held by this UDPReceiver.
118pub struct UDPReceiver<'a> {
119    client: OptionalCell<&'a dyn UDPRecvClient>,
120    binding: MapCell<UdpPortBindingRx>,
121    next: ListLink<'a, UDPReceiver<'a>>,
122}
123
124impl<'a> ListNode<'a, UDPReceiver<'a>> for UDPReceiver<'a> {
125    fn next(&'a self) -> &'a ListLink<'a, UDPReceiver<'a>> {
126        &self.next
127    }
128}
129
130impl<'a> UDPReceiver<'a> {
131    pub fn new() -> UDPReceiver<'a> {
132        UDPReceiver {
133            client: OptionalCell::empty(),
134            binding: MapCell::empty(),
135            next: ListLink::empty(),
136        }
137    }
138
139    pub fn set_client(&self, client: &'a dyn UDPRecvClient) {
140        self.client.set(client);
141    }
142
143    pub fn get_binding(&self) -> Option<UdpPortBindingRx> {
144        self.binding.take()
145    }
146
147    pub fn is_bound(&self) -> bool {
148        self.binding.is_some()
149    }
150
151    pub fn set_binding(&self, binding: UdpPortBindingRx) -> Option<UdpPortBindingRx> {
152        self.binding.replace(binding)
153    }
154}