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