use std::net::SocketAddr;
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[non_exhaustive]
pub struct StunMessage {
pub class: StunClass,
pub method: u16,
pub transaction_id: [u8; 12],
pub mapped_address: Option<SocketAddr>,
pub username: Option<String>,
pub software: Option<String>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))]
#[non_exhaustive]
pub enum StunClass {
Request,
Indication,
SuccessResponse,
ErrorResponse,
}
impl StunClass {
pub fn from_type_bits(type_word: u16) -> Self {
let c0 = (type_word >> 4) & 0x01;
let c1 = (type_word >> 8) & 0x01;
match (c1, c0) {
(0, 0) => Self::Request,
(0, 1) => Self::Indication,
(1, 0) => Self::SuccessResponse,
(1, 1) => Self::ErrorResponse,
_ => unreachable!(),
}
}
pub fn as_str(&self) -> &'static str {
match self {
Self::Request => "request",
Self::Indication => "indication",
Self::SuccessResponse => "success_response",
Self::ErrorResponse => "error_response",
}
}
}
pub(crate) fn extract_method(type_word: u16) -> u16 {
let m0 = type_word & 0x000f;
let m4 = (type_word >> 5) & 0x0007; let m7 = (type_word >> 9) & 0x001f; (m7 << 7) | (m4 << 4) | m0
}