#![allow(clippy::manual_range_contains)]
#![allow(clippy::new_without_default)]
use std::convert::TryFrom;
use std::fmt;
use std::io;
use std::net::SocketAddr;
use std::ops::Deref;
use serde::{Deserialize, Serialize};
use thiserror::Error;
mod stun;
pub use stun::StunMessage;
pub(crate) use stun::{
Class as StunClass, Method as StunMethod, StunError, StunTiming, TransId,
DEFAULT_MAX_RETRANSMITS,
};
mod id;
pub(crate) use id::Id;
pub(crate) const DATAGRAM_MTU: usize = 1150;
pub(crate) const DATAGRAM_MTU_WARN: usize = 1280;
pub(crate) const DATAGRAM_MAX_PACKET_SIZE: usize = 2000;
pub const MAX_RTP_OVERHEAD: usize = 80;
#[derive(Debug, Error)]
pub enum NetError {
#[error("{0}")]
Stun(#[from] StunError),
#[error("{0}")]
Io(#[from] io::Error),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Protocol {
Udp,
Tcp,
SslTcp,
Tls,
}
#[derive(Serialize, Deserialize)]
pub struct Transmit {
pub proto: Protocol,
pub source: SocketAddr,
pub destination: SocketAddr,
pub contents: DatagramSend,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct DatagramSend(Vec<u8>);
impl From<Vec<u8>> for DatagramSend {
fn from(value: Vec<u8>) -> Self {
DatagramSend(value)
}
}
impl From<DatagramSend> for Vec<u8> {
fn from(value: DatagramSend) -> Self {
value.0
}
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Receive<'a> {
pub proto: Protocol,
pub source: SocketAddr,
pub destination: SocketAddr,
#[serde(borrow)]
pub contents: DatagramRecv<'a>,
}
impl<'a> Receive<'a> {
pub fn new(
proto: Protocol,
source: SocketAddr,
destination: SocketAddr,
buf: &'a [u8],
) -> Result<Self, NetError> {
let contents = DatagramRecv::try_from(buf)?;
Ok(Receive {
proto,
source,
destination,
contents,
})
}
}
#[derive(Debug)]
pub struct StunPacket<'a> {
pub proto: Protocol,
pub source: SocketAddr,
pub destination: SocketAddr,
pub message: StunMessage<'a>,
}
#[derive(Serialize, Deserialize)]
pub struct DatagramRecv<'a> {
#[serde(borrow)]
pub(crate) inner: DatagramRecvInner<'a>,
}
#[allow(clippy::large_enum_variant)] #[derive(Serialize, Deserialize)]
pub(crate) enum DatagramRecvInner<'a> {
Stun(StunMessage<'a>),
Dtls(&'a [u8]),
Rtp(&'a [u8]),
Rtcp(&'a [u8]),
}
impl<'a> TryFrom<&'a [u8]> for DatagramRecv<'a> {
type Error = NetError;
fn try_from(value: &'a [u8]) -> Result<Self, Self::Error> {
use DatagramRecvInner::*;
let kind = MultiplexKind::try_from(value)?;
let inner = match kind {
MultiplexKind::Stun => Stun(StunMessage::parse(value)?),
MultiplexKind::Dtls => Dtls(value),
MultiplexKind::Rtp => Rtp(value),
MultiplexKind::Rtcp => Rtcp(value),
};
Ok(DatagramRecv { inner })
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub(crate) enum MultiplexKind {
Stun,
Dtls,
Rtp,
Rtcp,
}
impl<'a> TryFrom<&'a [u8]> for MultiplexKind {
type Error = io::Error;
fn try_from(value: &'a [u8]) -> Result<Self, io::Error> {
if value.is_empty() {
return Err(io::Error::new(io::ErrorKind::InvalidData, "Empty datagram"));
}
let byte0 = value[0];
let len = value.len();
if byte0 < 2 && len >= 20 {
Ok(MultiplexKind::Stun)
} else if byte0 >= 20 && byte0 < 64 {
Ok(MultiplexKind::Dtls)
} else if byte0 >= 128 && byte0 < 192 && len > 2 {
let byte1 = value[1];
let payload_type = byte1 & 0x7f;
Ok(if payload_type < 64 {
MultiplexKind::Rtp
} else if payload_type >= 64 && payload_type < 96 {
MultiplexKind::Rtcp
} else {
MultiplexKind::Rtp
})
} else {
Err(io::Error::new(
io::ErrorKind::InvalidData,
"Unknown datagram",
))
}
}
}
impl<'a> TryFrom<&'a Transmit> for Receive<'a> {
type Error = NetError;
fn try_from(t: &'a Transmit) -> Result<Self, Self::Error> {
Ok(Receive {
proto: t.proto,
source: t.source,
destination: t.destination,
contents: DatagramRecv::try_from(&t.contents[..])?,
})
}
}
impl fmt::Debug for Transmit {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Transmit")
.field("proto", &self.proto)
.field("source", &self.source)
.field("destination", &self.destination)
.field("len", &self.contents.len())
.finish()
}
}
impl Deref for DatagramSend {
type Target = [u8];
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl fmt::Debug for DatagramRecv<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.inner.fmt(f)
}
}
impl fmt::Debug for DatagramRecvInner<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Stun(v) => f.debug_tuple("Stun").field(v).finish(),
Self::Dtls(v) => write!(f, "Dtls(len: {})", v.len()),
Self::Rtp(v) => write!(f, "Rtp(len: {})", v.len()),
Self::Rtcp(v) => write!(f, "Rtcp(len: {})", v.len()),
}
}
}
impl TryFrom<&str> for Protocol {
type Error = ();
fn try_from(proto: &str) -> Result<Self, Self::Error> {
let proto = proto.to_lowercase();
match proto.as_str() {
"udp" => Ok(Protocol::Udp),
"tcp" => Ok(Protocol::Tcp),
"ssltcp" => Ok(Protocol::SslTcp),
"tls" => Ok(Protocol::Tls),
_ => Err(()),
}
}
}
impl From<Protocol> for &str {
fn from(proto: Protocol) -> Self {
match proto {
Protocol::Udp => "udp",
Protocol::Tcp => "tcp",
Protocol::SslTcp => "ssltcp",
Protocol::Tls => "tls",
}
}
}
impl fmt::Display for Protocol {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let x: &str = (*self).into();
write!(f, "{}", x)
}
}