faster_stun/
channel.rs

1use crate::{util, StunError};
2use std::convert::TryFrom;
3
4/// The ChannelData Message
5///
6/// The ChannelData message is used to carry application data between the
7/// client and the server.  
8/// It has the following format:
9///
10/// ```text
11/// 0                   1                   2                   3
12/// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
13/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
14/// |         Channel Number        |            Length             |
15/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
16/// |                                                               |
17/// /                       Application Data                        /
18/// /                                                               /
19/// |                                                               |
20/// |                               +-------------------------------+
21/// |                               |
22/// +-------------------------------+
23///
24///                               Figure 5
25/// ```
26///
27/// The Channel Number field specifies the number of the channel on which
28/// the data is traveling, and thus, the address of the peer that is
29/// sending or is to receive the data.
30///
31/// The Length field specifies the length in bytes of the application
32/// data field (i.e., it does not include the size of the ChannelData
33/// header).  Note that 0 is a valid length.
34///
35/// The Application Data field carries the data the client is trying to
36/// send to the peer, or that the peer is sending to the client.
37#[derive(Debug)]
38pub struct ChannelData<'a> {
39    /// channnel data bytes.
40    pub buf: &'a [u8],
41    /// channel number.
42    pub number: u16,
43}
44
45impl ChannelData<'_> {
46    /// # Unit Test
47    ///
48    /// ```
49    /// use faster_stun::*;
50    /// use std::convert::TryFrom;
51    ///
52    /// let buffer: [u8; 4] = [0x40, 0x00, 0x00, 0x40];
53    ///
54    /// let size = ChannelData::message_size(&buffer[..], false).unwrap();
55    /// assert_eq!(size, 68);
56    /// ```
57    pub fn message_size(buf: &[u8], is_tcp: bool) -> Result<usize, StunError> {
58        if !(buf.len() >= 4) {
59            return Err(StunError::InvalidInput);
60        }
61
62        if !(1..3).contains(&(buf[0] >> 6)) {
63            return Err(StunError::InvalidInput);
64        }
65
66        let mut size = (util::as_u16(&buf[2..4]) + 4) as usize;
67        if is_tcp && (size % 4) > 0 {
68            size += 4 - (size % 4);
69        }
70
71        Ok(size)
72    }
73}
74
75impl<'a> TryFrom<&'a [u8]> for ChannelData<'a> {
76    type Error = StunError;
77
78    /// # Unit Test
79    ///
80    /// ```
81    /// use faster_stun::*;
82    /// use std::convert::TryFrom;
83    ///
84    /// let buffer: [u8; 4] = [0x40, 0x00, 0x00, 0x00];
85    ///
86    /// let data = ChannelData::try_from(&buffer[..]).unwrap();
87    /// assert_eq!(data.number, 16384);
88    /// ```
89    fn try_from(buf: &'a [u8]) -> Result<Self, Self::Error> {
90        if !(buf.len() >= 4) {
91            return Err(StunError::InvalidInput);
92        }
93
94        let number = util::as_u16(&buf[..2]);
95        if !(0x4000..0xFFFF).contains(&number) {
96            return Err(StunError::InvalidInput);
97        }
98
99        let size = util::as_u16(&buf[2..4]) as usize;
100        if !(size <= buf.len() - 4) {
101            return Err(StunError::InvalidInput);
102        }
103
104        Ok(Self { buf, number })
105    }
106}
107
108impl AsRef<[u8]> for ChannelData<'_> {
109    fn as_ref(&self) -> &[u8] {
110        self.buf
111    }
112}
113
114impl std::ops::Deref for ChannelData<'_> {
115    type Target = [u8];
116
117    fn deref(&self) -> &Self::Target {
118        self.buf
119    }
120}