capsules_extra/net/udp/
udp.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//! This file contains the structs and methods associated with the UDP header.
6//! This includes getters and setters for the various header fields, as well
7//! as the standard encode/decode functionality required for serializing
8//! the struct for transmission.
9
10use crate::net::stream::decode_u16;
11use crate::net::stream::encode_u16;
12use crate::net::stream::SResult;
13
14// Note: All UDP Header fields are stored in network byte order
15
16/// The `UDPHeader` struct follows the layout for the UDP packet header.
17///
18/// Note that the implementation of this struct provides getters and setters
19/// for the various fields of the header, to avoid confusion with endian-ness.
20#[derive(Copy, Clone, Debug)]
21pub struct UDPHeader {
22    src_port: u16,
23    dst_port: u16,
24    len: u16,
25    cksum: u16,
26}
27
28impl Default for UDPHeader {
29    fn default() -> UDPHeader {
30        UDPHeader {
31            src_port: 0,
32            dst_port: 0,
33            len: 8,
34            cksum: 0,
35        }
36    }
37}
38
39impl UDPHeader {
40    pub fn new() -> UDPHeader {
41        UDPHeader::default()
42    }
43    // TODO: Always returns size of UDP header
44    pub fn get_offset(&self) -> usize {
45        8
46    }
47
48    pub fn set_dst_port(&mut self, port: u16) {
49        self.dst_port = port.to_be();
50    }
51    pub fn set_src_port(&mut self, port: u16) {
52        self.src_port = port.to_be();
53    }
54
55    pub fn set_len(&mut self, len: u16) {
56        self.len = len.to_be();
57    }
58
59    pub fn set_cksum(&mut self, cksum: u16) {
60        self.cksum = cksum.to_be();
61    }
62
63    pub fn get_src_port(&self) -> u16 {
64        u16::from_be(self.src_port)
65    }
66
67    pub fn get_dst_port(&self) -> u16 {
68        u16::from_be(self.dst_port)
69    }
70
71    pub fn get_len(&self) -> u16 {
72        u16::from_be(self.len)
73    }
74
75    pub fn get_cksum(&self) -> u16 {
76        u16::from_be(self.cksum)
77    }
78
79    pub fn get_hdr_size(&self) -> usize {
80        // TODO
81        8
82    }
83
84    /// This function serializes the `UDPHeader` into the provided buffer.
85    ///
86    /// # Arguments
87    ///
88    /// `buf` - A mutable buffer to serialize the `UDPHeader` into
89    /// `offset` - The current offset into the provided buffer
90    ///
91    /// # Return Value
92    ///
93    /// This function returns the new offset into the buffer wrapped in an
94    /// SResult.
95    pub fn encode(&self, buf: &mut [u8], offset: usize) -> SResult<usize> {
96        stream_len_cond!(buf, self.get_hdr_size() + offset);
97
98        let mut off = offset;
99        off = enc_consume!(buf, off; encode_u16, self.src_port);
100        off = enc_consume!(buf, off; encode_u16, self.dst_port);
101        off = enc_consume!(buf, off; encode_u16, self.len);
102        off = enc_consume!(buf, off; encode_u16, self.cksum);
103        stream_done!(off, off);
104    }
105
106    /// This function deserializes the `UDPHeader` from the provided buffer.
107    ///
108    /// # Arguments
109    ///
110    /// `buf` - The byte array corresponding to a serialized `UDPHeader`
111    ///
112    /// # Return Value
113    ///
114    /// This function returns a `UDPHeader` struct wrapped in an SResult
115    pub fn decode(buf: &[u8]) -> SResult<UDPHeader> {
116        stream_len_cond!(buf, 8);
117        let mut udp_header = Self::new();
118        let off = 0;
119        let (off, src_port) = dec_try!(buf, off; decode_u16);
120        udp_header.src_port = u16::from_be(src_port);
121        let (off, dst_port) = dec_try!(buf, off; decode_u16);
122        udp_header.dst_port = u16::from_be(dst_port);
123        let (off, len) = dec_try!(buf, off; decode_u16);
124        udp_header.len = u16::from_be(len);
125        let (off, cksum) = dec_try!(buf, off; decode_u16);
126        udp_header.cksum = u16::from_be(cksum);
127        stream_done!(off, udp_header);
128    }
129}