pub mod attribute;
pub mod channel;
pub mod message;
pub mod util;
use std::{error, fmt};
pub use channel::ChannelData;
pub use message::*;
#[derive(Debug)]
pub enum StunError {
InvalidInput,
UnsupportedIpFamily,
ShaFailed,
NotIntegrity,
IntegrityFailed,
NotCookie,
UnknownMethod,
FatalError,
Utf8Error,
}
impl error::Error for StunError {}
impl fmt::Display for StunError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{}",
match self {
Self::InvalidInput => "InvalidInput",
Self::UnsupportedIpFamily => "UnsupportedIpFamily",
Self::ShaFailed => "ShaFailed",
Self::NotIntegrity => "NotIntegrity",
Self::IntegrityFailed => "IntegrityFailed",
Self::NotCookie => "NotCookie",
Self::UnknownMethod => "UnknownMethod",
Self::FatalError => "FatalError",
Self::Utf8Error => "Utf8Error",
}
)
}
}
#[derive(PartialEq, Eq, Hash, Debug, Clone, Copy)]
pub enum Kind {
Request,
Response,
Error,
}
#[derive(PartialEq, Eq, Hash, Debug, Clone, Copy)]
pub enum Method {
Binding(Kind),
Allocate(Kind),
CreatePermission(Kind),
ChannelBind(Kind),
Refresh(Kind),
SendIndication,
DataIndication,
}
impl TryFrom<u16> for Method {
type Error = StunError;
fn try_from(value: u16) -> Result<Self, Self::Error> {
Ok(match value {
0x0001 => Self::Binding(Kind::Request),
0x0101 => Self::Binding(Kind::Response),
0x0111 => Self::Binding(Kind::Error),
0x0003 => Self::Allocate(Kind::Request),
0x0103 => Self::Allocate(Kind::Response),
0x0113 => Self::Allocate(Kind::Error),
0x0008 => Self::CreatePermission(Kind::Request),
0x0108 => Self::CreatePermission(Kind::Response),
0x0118 => Self::CreatePermission(Kind::Error),
0x0009 => Self::ChannelBind(Kind::Request),
0x0109 => Self::ChannelBind(Kind::Response),
0x0119 => Self::ChannelBind(Kind::Error),
0x0004 => Self::Refresh(Kind::Request),
0x0104 => Self::Refresh(Kind::Response),
0x0114 => Self::Refresh(Kind::Error),
0x0016 => Self::SendIndication,
0x0017 => Self::DataIndication,
_ => return Err(StunError::UnknownMethod),
})
}
}
impl From<Method> for u16 {
fn from(val: Method) -> Self {
match val {
Method::Binding(Kind::Request) => 0x0001,
Method::Binding(Kind::Response) => 0x0101,
Method::Binding(Kind::Error) => 0x0111,
Method::Allocate(Kind::Request) => 0x0003,
Method::Allocate(Kind::Response) => 0x0103,
Method::Allocate(Kind::Error) => 0x0113,
Method::CreatePermission(Kind::Request) => 0x0008,
Method::CreatePermission(Kind::Response) => 0x0108,
Method::CreatePermission(Kind::Error) => 0x0118,
Method::ChannelBind(Kind::Request) => 0x0009,
Method::ChannelBind(Kind::Response) => 0x0109,
Method::ChannelBind(Kind::Error) => 0x0119,
Method::Refresh(Kind::Request) => 0x0004,
Method::Refresh(Kind::Response) => 0x0104,
Method::Refresh(Kind::Error) => 0x0114,
Method::SendIndication => 0x0016,
Method::DataIndication => 0x0017,
}
}
}
#[derive(Debug)]
pub enum Payload<'a, 'b> {
Message(MessageReader<'a, 'b>),
ChannelData(ChannelData<'a>),
}
pub struct Decoder {
attrs: Vec<(attribute::AttrKind, &'static [u8])>,
}
impl Decoder {
pub fn new() -> Self {
Self {
attrs: Vec::with_capacity(10),
}
}
pub fn decode<'a>(&mut self, buf: &'a [u8]) -> Result<Payload<'a, '_>, StunError> {
assert!(buf.len() >= 4);
if !self.attrs.is_empty() {
self.attrs.clear();
}
let flag = buf[0] >> 6;
if flag > 3 {
return Err(StunError::InvalidInput);
}
Ok(if flag == 0 {
Payload::Message(MessageReader::decode(
unsafe { std::mem::transmute(buf) },
&mut self.attrs,
)?)
} else {
Payload::ChannelData(ChannelData::try_from(buf)?)
})
}
pub fn message_size(buf: &[u8], is_tcp: bool) -> Result<usize, StunError> {
let flag = buf[0] >> 6;
if flag > 3 {
return Err(StunError::InvalidInput);
}
Ok(if flag == 0 {
MessageReader::message_size(buf)?
} else {
ChannelData::message_size(buf, is_tcp)?
})
}
}
impl Default for Decoder {
fn default() -> Self {
Self::new()
}
}