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}