use alloc::boxed::Box;
use core::net::SocketAddr;
use crate::AddressFamily;
use stun_types::{
attribute::*,
message::{StunParseError, TransactionId},
};
#[derive(Debug, Clone)]
pub struct XorPeerAddress {
addr: XorSocketAddr,
}
impl AttributeStaticType for XorPeerAddress {
const TYPE: AttributeType = AttributeType::new(0x0012);
}
impl Attribute for XorPeerAddress {
fn get_type(&self) -> AttributeType {
Self::TYPE
}
fn length(&self) -> u16 {
self.addr.length()
}
}
impl AttributeWrite for XorPeerAddress {
fn to_raw(&self) -> RawAttribute<'_> {
self.addr.to_raw(self.get_type())
}
fn write_into_unchecked(&self, dest: &mut [u8]) {
self.write_header_unchecked(dest);
self.addr.write_into_unchecked(&mut dest[4..]);
}
}
impl AttributeFromRaw<'_> for XorPeerAddress {
fn from_raw_ref(raw: &RawAttribute) -> Result<Self, StunParseError>
where
Self: Sized,
{
Self::try_from(raw)
}
}
impl TryFrom<&RawAttribute<'_>> for XorPeerAddress {
type Error = StunParseError;
fn try_from(raw: &RawAttribute) -> Result<Self, Self::Error> {
raw.check_type_and_len(Self::TYPE, 4..=20)?;
Ok(Self {
addr: XorSocketAddr::from_raw(raw)?,
})
}
}
impl XorPeerAddress {
pub fn new(addr: SocketAddr, transaction: TransactionId) -> Self {
Self {
addr: XorSocketAddr::new(addr, transaction),
}
}
pub fn addr(&self, transaction: TransactionId) -> SocketAddr {
self.addr.addr(transaction)
}
}
impl core::fmt::Display for XorPeerAddress {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{}: {}", self.get_type(), self.addr)
}
}
#[derive(Debug, Clone)]
pub struct XorRelayedAddress {
addr: XorSocketAddr,
}
impl AttributeStaticType for XorRelayedAddress {
const TYPE: AttributeType = AttributeType::new(0x0016);
}
impl Attribute for XorRelayedAddress {
fn get_type(&self) -> AttributeType {
Self::TYPE
}
fn length(&self) -> u16 {
self.addr.length()
}
}
impl AttributeWrite for XorRelayedAddress {
fn to_raw(&self) -> RawAttribute<'_> {
self.addr.to_raw(self.get_type())
}
fn write_into_unchecked(&self, dest: &mut [u8]) {
self.write_header_unchecked(dest);
self.addr.write_into_unchecked(&mut dest[4..]);
}
}
impl AttributeFromRaw<'_> for XorRelayedAddress {
fn from_raw_ref(raw: &RawAttribute) -> Result<Self, StunParseError>
where
Self: Sized,
{
Self::try_from(raw)
}
}
impl TryFrom<&RawAttribute<'_>> for XorRelayedAddress {
type Error = StunParseError;
fn try_from(raw: &RawAttribute) -> Result<Self, Self::Error> {
if raw.get_type() != Self::TYPE {
return Err(StunParseError::WrongAttributeImplementation);
}
Ok(Self {
addr: XorSocketAddr::from_raw(raw)?,
})
}
}
impl XorRelayedAddress {
pub fn new(addr: SocketAddr, transaction: TransactionId) -> Self {
Self {
addr: XorSocketAddr::new(addr, transaction),
}
}
pub fn addr(&self, transaction: TransactionId) -> SocketAddr {
self.addr.addr(transaction)
}
}
impl core::fmt::Display for XorRelayedAddress {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{}: {}", self.get_type(), self.addr)
}
}
#[derive(Debug, Clone)]
pub struct RequestedAddressFamily {
family: AddressFamily,
}
impl AttributeStaticType for RequestedAddressFamily {
const TYPE: AttributeType = AttributeType::new(0x0017);
}
impl Attribute for RequestedAddressFamily {
fn get_type(&self) -> AttributeType {
Self::TYPE
}
fn length(&self) -> u16 {
4
}
}
impl AttributeWrite for RequestedAddressFamily {
fn to_raw(&self) -> RawAttribute<'_> {
let mut data = [0; 4];
data[0] = match self.family {
AddressFamily::IPV4 => 1,
AddressFamily::IPV6 => 2,
};
RawAttribute::new(self.get_type(), &data).into_owned()
}
fn write_into_unchecked(&self, dest: &mut [u8]) {
self.write_header_unchecked(dest);
dest[4] = match self.family {
AddressFamily::IPV4 => 1,
AddressFamily::IPV6 => 2,
};
dest[5] = 0;
dest[6] = 0;
dest[7] = 0;
}
}
impl AttributeFromRaw<'_> for RequestedAddressFamily {
fn from_raw_ref(raw: &RawAttribute) -> Result<Self, StunParseError>
where
Self: Sized,
{
Self::try_from(raw)
}
}
impl TryFrom<&RawAttribute<'_>> for RequestedAddressFamily {
type Error = StunParseError;
fn try_from(raw: &RawAttribute) -> Result<Self, Self::Error> {
if raw.get_type() != Self::TYPE {
return Err(StunParseError::WrongAttributeImplementation);
}
raw.check_type_and_len(Self::TYPE, 4..=4)?;
let family = match raw.value[0] {
1 => AddressFamily::IPV4,
2 => AddressFamily::IPV6,
_ => return Err(StunParseError::InvalidAttributeData),
};
Ok(Self { family })
}
}
impl RequestedAddressFamily {
pub fn new(family: AddressFamily) -> Self {
Self { family }
}
pub fn family(&self) -> AddressFamily {
self.family
}
}
impl core::fmt::Display for RequestedAddressFamily {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{}: {}", self.get_type(), self.family)
}
}
#[derive(Debug, Clone)]
pub struct AdditionalAddressFamily {
family: AddressFamily,
}
impl AttributeStaticType for AdditionalAddressFamily {
const TYPE: AttributeType = AttributeType::new(0x8000);
}
impl Attribute for AdditionalAddressFamily {
fn get_type(&self) -> AttributeType {
Self::TYPE
}
fn length(&self) -> u16 {
4
}
}
impl AttributeWrite for AdditionalAddressFamily {
fn to_raw(&self) -> RawAttribute<'_> {
let mut data = [0; 4];
data[0] = match self.family {
AddressFamily::IPV4 => 1,
AddressFamily::IPV6 => 2,
};
RawAttribute::new(self.get_type(), &data).into_owned()
}
fn write_into_unchecked(&self, dest: &mut [u8]) {
self.write_header_unchecked(dest);
dest[4] = match self.family {
AddressFamily::IPV4 => 1,
AddressFamily::IPV6 => 2,
};
dest[5] = 0;
dest[6] = 0;
dest[7] = 0;
}
}
impl AttributeFromRaw<'_> for AdditionalAddressFamily {
fn from_raw_ref(raw: &RawAttribute) -> Result<Self, StunParseError>
where
Self: Sized,
{
Self::try_from(raw)
}
}
impl TryFrom<&RawAttribute<'_>> for AdditionalAddressFamily {
type Error = StunParseError;
fn try_from(raw: &RawAttribute) -> Result<Self, Self::Error> {
if raw.get_type() != Self::TYPE {
return Err(StunParseError::WrongAttributeImplementation);
}
raw.check_type_and_len(Self::TYPE, 4..=4)?;
let family = match raw.value[0] {
2 => AddressFamily::IPV6,
_ => return Err(StunParseError::InvalidAttributeData),
};
Ok(Self { family })
}
}
impl AdditionalAddressFamily {
pub fn new(family: AddressFamily) -> Self {
if family == AddressFamily::IPV4 {
panic!("IPv4 is not supported in AdditionalAddressFamily");
}
Self { family }
}
pub fn family(&self) -> AddressFamily {
self.family
}
}
impl core::fmt::Display for AdditionalAddressFamily {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{}: {}", self.get_type(), self.family)
}
}
#[derive(Debug, Clone)]
pub struct AddressErrorCode {
family: AddressFamily,
error: ErrorCode,
}
impl AttributeStaticType for AddressErrorCode {
const TYPE: AttributeType = AttributeType::new(0x8001);
}
impl Attribute for AddressErrorCode {
fn get_type(&self) -> AttributeType {
Self::TYPE
}
fn length(&self) -> u16 {
self.error.length()
}
}
impl AttributeWrite for AddressErrorCode {
fn to_raw(&self) -> RawAttribute<'_> {
let raw = self.error.to_raw();
let mut data = raw.to_bytes();
data[4] = match self.family {
AddressFamily::IPV4 => 1,
AddressFamily::IPV6 => 2,
};
RawAttribute::new_owned(
self.get_type(),
Box::from(&data[4..4 + raw.length() as usize]),
)
}
fn write_into_unchecked(&self, dest: &mut [u8]) {
self.error.write_into_unchecked(dest);
self.write_header_unchecked(dest);
dest[4] = match self.family {
AddressFamily::IPV4 => 1,
AddressFamily::IPV6 => 2,
};
}
}
impl AttributeFromRaw<'_> for AddressErrorCode {
fn from_raw_ref(raw: &RawAttribute) -> Result<Self, StunParseError>
where
Self: Sized,
{
Self::try_from(raw)
}
}
impl TryFrom<&RawAttribute<'_>> for AddressErrorCode {
type Error = StunParseError;
fn try_from(raw: &RawAttribute) -> Result<Self, Self::Error> {
if raw.get_type() != Self::TYPE {
return Err(StunParseError::WrongAttributeImplementation);
}
let tmp_raw = RawAttribute::new(ErrorCode::TYPE, &raw.value);
let error = ErrorCode::from_raw_ref(&tmp_raw)?;
let family = match raw.value[0] {
1 => AddressFamily::IPV4,
2 => AddressFamily::IPV6,
_ => return Err(StunParseError::InvalidAttributeData),
};
Ok(Self { family, error })
}
}
impl AddressErrorCode {
pub fn new(family: AddressFamily, error: ErrorCode) -> Self {
Self { family, error }
}
pub fn family(&self) -> AddressFamily {
self.family
}
pub fn error(&self) -> &ErrorCode {
&self.error
}
}
impl core::fmt::Display for AddressErrorCode {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{}: {} {}", self.get_type(), self.family, self.error)
}
}
#[cfg(test)]
mod tests {
use super::*;
use alloc::{vec, vec::Vec};
use byteorder::{BigEndian, ByteOrder};
use core::net::{IpAddr, Ipv4Addr, Ipv6Addr};
use tracing::trace;
const ADDRS: [SocketAddr; 2] = [
SocketAddr::new(IpAddr::V4(Ipv4Addr::new(192, 168, 0, 1)), 40000),
SocketAddr::new(
IpAddr::V6(Ipv6Addr::new(
0xfd12, 0x3456, 0x789a, 0x01, 0x0, 0x0, 0x0, 0x1,
)),
41000,
),
];
#[test]
fn xor_peer_address_raw() {
let _log = crate::tests::test_init_log();
let transaction_id = 0x9876_5432_1098_7654_3210_9876.into();
for addr in ADDRS {
let mapped = XorPeerAddress::new(addr, transaction_id);
assert_eq!(mapped.get_type(), XorPeerAddress::TYPE);
assert_eq!(mapped.addr(transaction_id), addr);
let raw: RawAttribute = mapped.to_raw();
trace!("{}", raw);
assert_eq!(raw.get_type(), XorPeerAddress::TYPE);
let mapped2 = XorPeerAddress::try_from(&raw).unwrap();
assert_eq!(mapped2.get_type(), XorPeerAddress::TYPE);
assert_eq!(mapped2.addr(transaction_id), addr);
}
}
#[test]
fn xor_peer_address_raw_short() {
let _log = crate::tests::test_init_log();
let transaction_id = 0x9876_5432_1098_7654_3210_9876.into();
for addr in ADDRS {
let mapped = XorPeerAddress::new(addr, transaction_id);
assert_eq!(mapped.get_type(), XorPeerAddress::TYPE);
assert_eq!(mapped.addr(transaction_id), addr);
let raw: RawAttribute = mapped.to_raw();
let mut data: Vec<_> = raw.clone().into();
let len = data.len();
BigEndian::write_u16(&mut data[2..4], len as u16 - 4 - 1);
assert!(matches!(
XorPeerAddress::try_from(
&RawAttribute::from_bytes(data[..len - 1].as_ref()).unwrap()
),
Err(StunParseError::Truncated {
expected: _,
actual: _,
})
));
}
}
#[test]
fn xor_peer_address_raw_wrong_type() {
let _log = crate::tests::test_init_log();
let transaction_id = 0x9876_5432_1098_7654_3210_9876.into();
for addr in ADDRS {
let mapped = XorPeerAddress::new(addr, transaction_id);
assert_eq!(mapped.get_type(), XorPeerAddress::TYPE);
assert_eq!(mapped.addr(transaction_id), addr);
let raw: RawAttribute = mapped.to_raw();
let mut data: Vec<_> = raw.into();
BigEndian::write_u16(&mut data[0..2], 0);
assert!(matches!(
XorPeerAddress::try_from(&RawAttribute::from_bytes(data.as_ref()).unwrap()),
Err(StunParseError::WrongAttributeImplementation)
));
}
}
#[test]
fn xor_peer_address_write_into() {
let _log = crate::tests::test_init_log();
let transaction_id = 0x9876_5432_1098_7654_3210_9876.into();
for addr in ADDRS {
let mapped = XorPeerAddress::new(addr, transaction_id);
assert_eq!(mapped.get_type(), XorPeerAddress::TYPE);
assert_eq!(mapped.addr(transaction_id), addr);
let raw: RawAttribute = mapped.to_raw();
let mut dest = vec![0; raw.padded_len()];
mapped.write_into(&mut dest).unwrap();
let raw = RawAttribute::from_bytes(&dest).unwrap();
let mapped2 = XorPeerAddress::try_from(&raw).unwrap();
assert_eq!(mapped2.addr(transaction_id), addr);
}
}
#[test]
#[should_panic = "out of range"]
fn xor_peer_address_write_into_unchecked() {
let _log = crate::tests::test_init_log();
let transaction_id = 0x9876_5432_1098_7654_3210_9876.into();
let addr = ADDRS[0];
let mapped = XorPeerAddress::new(addr, transaction_id);
assert_eq!(mapped.get_type(), XorPeerAddress::TYPE);
assert_eq!(mapped.addr(transaction_id), addr);
let raw: RawAttribute = mapped.to_raw();
let mut dest = vec![0; raw.padded_len() - 1];
mapped.write_into_unchecked(&mut dest);
}
#[test]
fn xor_relayed_address_raw() {
let _log = crate::tests::test_init_log();
let transaction_id = 0x9876_5432_1098_7654_3210_9876.into();
for addr in ADDRS {
let mapped = XorRelayedAddress::new(addr, transaction_id);
assert_eq!(mapped.get_type(), XorRelayedAddress::TYPE);
assert_eq!(mapped.addr(transaction_id), addr);
let raw: RawAttribute = mapped.to_raw();
trace!("{}", raw);
assert_eq!(raw.get_type(), XorRelayedAddress::TYPE);
let mapped2 = XorRelayedAddress::try_from(&raw).unwrap();
assert_eq!(mapped2.get_type(), XorRelayedAddress::TYPE);
assert_eq!(mapped2.addr(transaction_id), addr);
}
}
#[test]
fn xor_relayed_address_raw_short() {
let _log = crate::tests::test_init_log();
let transaction_id = 0x9876_5432_1098_7654_3210_9876.into();
for addr in ADDRS {
let mapped = XorRelayedAddress::new(addr, transaction_id);
assert_eq!(mapped.get_type(), XorRelayedAddress::TYPE);
assert_eq!(mapped.addr(transaction_id), addr);
let raw: RawAttribute = mapped.to_raw();
let mut data: Vec<_> = raw.clone().into();
let len = data.len();
BigEndian::write_u16(&mut data[2..4], len as u16 - 4 - 1);
assert!(matches!(
XorRelayedAddress::try_from(
&RawAttribute::from_bytes(data[..len - 1].as_ref()).unwrap()
),
Err(StunParseError::Truncated {
expected: _,
actual: _,
})
));
}
}
#[test]
fn xor_relayed_address_raw_wrong_type() {
let _log = crate::tests::test_init_log();
let transaction_id = 0x9876_5432_1098_7654_3210_9876.into();
for addr in ADDRS {
let mapped = XorRelayedAddress::new(addr, transaction_id);
assert_eq!(mapped.get_type(), XorRelayedAddress::TYPE);
assert_eq!(mapped.addr(transaction_id), addr);
let raw: RawAttribute = mapped.to_raw();
let mut data: Vec<_> = raw.into();
BigEndian::write_u16(&mut data[0..2], 0);
assert!(matches!(
XorRelayedAddress::try_from(&RawAttribute::from_bytes(data.as_ref()).unwrap()),
Err(StunParseError::WrongAttributeImplementation)
));
}
}
#[test]
fn xor_relayed_address_write_into() {
let _log = crate::tests::test_init_log();
let transaction_id = 0x9876_5432_1098_7654_3210_9876.into();
for addr in ADDRS {
let mapped = XorRelayedAddress::new(addr, transaction_id);
assert_eq!(mapped.get_type(), XorRelayedAddress::TYPE);
assert_eq!(mapped.addr(transaction_id), addr);
let raw: RawAttribute = mapped.to_raw();
let mut dest = vec![0; raw.padded_len()];
mapped.write_into(&mut dest).unwrap();
let raw = RawAttribute::from_bytes(&dest).unwrap();
let mapped2 = XorRelayedAddress::try_from(&raw).unwrap();
assert_eq!(mapped2.addr(transaction_id), addr);
}
}
#[test]
#[should_panic = "out of range"]
fn xor_relayed_address_write_into_unchecked() {
let _log = crate::tests::test_init_log();
let transaction_id = 0x9876_5432_1098_7654_3210_9876.into();
let addr = ADDRS[0];
let mapped = XorRelayedAddress::new(addr, transaction_id);
assert_eq!(mapped.get_type(), XorRelayedAddress::TYPE);
assert_eq!(mapped.addr(transaction_id), addr);
let raw: RawAttribute = mapped.to_raw();
let mut dest = vec![0; raw.padded_len() - 1];
mapped.write_into_unchecked(&mut dest);
}
#[test]
fn requested_address_family_raw() {
let _log = crate::tests::test_init_log();
for family in [AddressFamily::IPV4, AddressFamily::IPV6] {
let mapped = RequestedAddressFamily::new(family);
assert_eq!(mapped.get_type(), RequestedAddressFamily::TYPE);
assert_eq!(mapped.family(), family);
let raw: RawAttribute = mapped.to_raw();
trace!("{}", raw);
assert_eq!(raw.get_type(), RequestedAddressFamily::TYPE);
let mapped2 = RequestedAddressFamily::try_from(&raw).unwrap();
assert_eq!(mapped2.get_type(), RequestedAddressFamily::TYPE);
assert_eq!(mapped2.family(), family);
}
}
#[test]
fn requested_address_family_raw_short() {
let _log = crate::tests::test_init_log();
let mapped = RequestedAddressFamily::new(AddressFamily::IPV4);
let raw: RawAttribute = mapped.to_raw();
let mut data: Vec<_> = raw.clone().into();
let len = data.len();
BigEndian::write_u16(&mut data[2..4], len as u16 - 4 - 1);
assert!(matches!(
RequestedAddressFamily::try_from(
&RawAttribute::from_bytes(data[..len - 1].as_ref()).unwrap()
),
Err(StunParseError::Truncated {
expected: _,
actual: _,
})
));
}
#[test]
fn requested_address_family_raw_wrong_type() {
let _log = crate::tests::test_init_log();
let mapped = RequestedAddressFamily::new(AddressFamily::IPV4);
let raw: RawAttribute = mapped.to_raw();
let mut data: Vec<_> = raw.clone().into();
BigEndian::write_u16(&mut data[0..2], 0);
assert!(matches!(
RequestedAddressFamily::try_from(&RawAttribute::from_bytes(data.as_ref()).unwrap()),
Err(StunParseError::WrongAttributeImplementation)
));
}
#[test]
fn requested_address_family_raw_wrong_family() {
let _log = crate::tests::test_init_log();
let mapped = RequestedAddressFamily::new(AddressFamily::IPV4);
let raw: RawAttribute = mapped.to_raw();
let mut data: Vec<_> = raw.clone().into();
data[4] = 3;
assert!(matches!(
RequestedAddressFamily::try_from(&RawAttribute::from_bytes(data.as_ref()).unwrap()),
Err(StunParseError::InvalidAttributeData)
));
}
#[test]
fn requested_address_family_write_into() {
let _log = crate::tests::test_init_log();
for family in [AddressFamily::IPV4, AddressFamily::IPV6] {
let mapped = RequestedAddressFamily::new(family);
assert_eq!(mapped.get_type(), RequestedAddressFamily::TYPE);
assert_eq!(mapped.family(), family);
let raw: RawAttribute = mapped.to_raw();
let mut dest = vec![0; raw.padded_len()];
mapped.write_into(&mut dest).unwrap();
let raw = RawAttribute::from_bytes(&dest).unwrap();
let mapped2 = RequestedAddressFamily::try_from(&raw).unwrap();
assert_eq!(mapped2.get_type(), RequestedAddressFamily::TYPE);
assert_eq!(mapped2.family(), family);
}
}
#[test]
#[should_panic = "out of bounds"]
fn requested_address_family_write_into_unchecked() {
let _log = crate::tests::test_init_log();
let mapped = RequestedAddressFamily::new(AddressFamily::IPV6);
let raw: RawAttribute = mapped.to_raw();
let mut dest = vec![0; raw.padded_len() - 1];
mapped.write_into_unchecked(&mut dest);
}
#[test]
fn additional_address_family_raw() {
let _log = crate::tests::test_init_log();
let mapped = AdditionalAddressFamily::new(AddressFamily::IPV6);
assert_eq!(mapped.get_type(), AdditionalAddressFamily::TYPE);
assert_eq!(mapped.family(), AddressFamily::IPV6);
let raw: RawAttribute = mapped.to_raw();
trace!("{}", raw);
assert_eq!(raw.get_type(), AdditionalAddressFamily::TYPE);
let mapped2 = AdditionalAddressFamily::try_from(&raw).unwrap();
assert_eq!(mapped2.get_type(), AdditionalAddressFamily::TYPE);
assert_eq!(mapped2.family(), AddressFamily::IPV6);
}
#[test]
fn additional_address_family_raw_short() {
let _log = crate::tests::test_init_log();
let mapped = AdditionalAddressFamily::new(AddressFamily::IPV6);
assert_eq!(mapped.get_type(), AdditionalAddressFamily::TYPE);
assert_eq!(mapped.family(), AddressFamily::IPV6);
let raw: RawAttribute = mapped.to_raw();
let mut data: Vec<_> = raw.clone().into();
let len = data.len();
BigEndian::write_u16(&mut data[2..4], len as u16 - 4 - 1);
assert!(matches!(
AdditionalAddressFamily::try_from(
&RawAttribute::from_bytes(data[..len - 1].as_ref()).unwrap()
),
Err(StunParseError::Truncated {
expected: _,
actual: _,
})
));
}
#[test]
fn additional_address_family_raw_wrong_type() {
let _log = crate::tests::test_init_log();
let mapped = AdditionalAddressFamily::new(AddressFamily::IPV6);
assert_eq!(mapped.get_type(), AdditionalAddressFamily::TYPE);
assert_eq!(mapped.family(), AddressFamily::IPV6);
let raw: RawAttribute = mapped.to_raw();
let mut data: Vec<_> = raw.clone().into();
BigEndian::write_u16(&mut data[0..2], 0);
assert!(matches!(
AdditionalAddressFamily::try_from(&RawAttribute::from_bytes(data.as_ref()).unwrap()),
Err(StunParseError::WrongAttributeImplementation)
));
}
#[test]
fn additional_address_family_raw_wrong_family() {
let _log = crate::tests::test_init_log();
let mapped = AdditionalAddressFamily::new(AddressFamily::IPV6);
assert_eq!(mapped.get_type(), AdditionalAddressFamily::TYPE);
assert_eq!(mapped.family(), AddressFamily::IPV6);
let raw: RawAttribute = mapped.to_raw();
let mut data: Vec<_> = raw.clone().into();
data[4] = 1;
assert!(matches!(
AdditionalAddressFamily::try_from(&RawAttribute::from_bytes(data.as_ref()).unwrap()),
Err(StunParseError::InvalidAttributeData)
));
}
#[test]
#[should_panic = "IPv4 is not supported"]
fn additional_address_family_ipv4_panic() {
let _log = crate::tests::test_init_log();
AdditionalAddressFamily::new(AddressFamily::IPV4);
}
#[test]
fn additional_address_family_write_into() {
let _log = crate::tests::test_init_log();
let family = AddressFamily::IPV6;
let mapped = AdditionalAddressFamily::new(family);
assert_eq!(mapped.get_type(), AdditionalAddressFamily::TYPE);
assert_eq!(mapped.family(), family);
let raw: RawAttribute = mapped.to_raw();
let mut dest = vec![0; raw.padded_len()];
mapped.write_into(&mut dest).unwrap();
let raw = RawAttribute::from_bytes(&dest).unwrap();
let mapped2 = AdditionalAddressFamily::try_from(&raw).unwrap();
assert_eq!(mapped2.get_type(), AdditionalAddressFamily::TYPE);
assert_eq!(mapped2.family(), family);
}
#[test]
#[should_panic = "out of bounds"]
fn additional_address_fmaily_write_into_unchecked() {
let _log = crate::tests::test_init_log();
let mapped = AdditionalAddressFamily::new(AddressFamily::IPV6);
let raw: RawAttribute = mapped.to_raw();
let mut dest = vec![0; raw.padded_len() - 1];
mapped.write_into_unchecked(&mut dest);
}
#[test]
fn address_error_code() {
let _log = crate::tests::test_init_log();
let error = ErrorCode::builder(ErrorCode::INSUFFICIENT_CAPACITY)
.build()
.unwrap();
for family in [AddressFamily::IPV4, AddressFamily::IPV6] {
let mapped = AddressErrorCode::new(family, error.clone());
assert_eq!(mapped.get_type(), AddressErrorCode::TYPE);
assert_eq!(mapped.family(), family);
assert_eq!(mapped.error(), &error);
let raw: RawAttribute = mapped.to_raw();
trace!("{}", raw);
assert_eq!(raw.get_type(), AddressErrorCode::TYPE);
let mapped2 = AddressErrorCode::try_from(&raw).unwrap();
assert_eq!(mapped2.get_type(), AddressErrorCode::TYPE);
assert_eq!(mapped2.family(), family);
assert_eq!(mapped2.error(), &error);
}
}
#[test]
fn address_error_code_raw_wrong_type() {
let _log = crate::tests::test_init_log();
let error = ErrorCode::builder(ErrorCode::INSUFFICIENT_CAPACITY)
.build()
.unwrap();
for family in [AddressFamily::IPV4, AddressFamily::IPV6] {
let mapped = AddressErrorCode::new(family, error.clone());
assert_eq!(mapped.get_type(), AddressErrorCode::TYPE);
assert_eq!(mapped.family(), family);
assert_eq!(mapped.error(), &error);
let raw: RawAttribute = mapped.to_raw();
let mut data: Vec<_> = raw.clone().into();
BigEndian::write_u16(&mut data[0..2], 0);
assert!(matches!(
AddressErrorCode::try_from(&RawAttribute::from_bytes(data.as_ref()).unwrap()),
Err(StunParseError::WrongAttributeImplementation)
));
}
}
#[test]
fn address_error_code_raw_wrong_family() {
let _log = crate::tests::test_init_log();
let error = ErrorCode::builder(ErrorCode::INSUFFICIENT_CAPACITY)
.build()
.unwrap();
for family in [AddressFamily::IPV4, AddressFamily::IPV6] {
let mapped = AddressErrorCode::new(family, error.clone());
assert_eq!(mapped.get_type(), AddressErrorCode::TYPE);
assert_eq!(mapped.family(), family);
assert_eq!(mapped.error(), &error);
let raw: RawAttribute = mapped.to_raw();
let mut data: Vec<_> = raw.clone().into();
data[4] = 3;
assert!(matches!(
AddressErrorCode::try_from(&RawAttribute::from_bytes(data.as_ref()).unwrap()),
Err(StunParseError::InvalidAttributeData)
));
}
}
#[test]
fn address_error_code_write_into() {
let _log = crate::tests::test_init_log();
let error = ErrorCode::builder(ErrorCode::INSUFFICIENT_CAPACITY)
.build()
.unwrap();
for family in [AddressFamily::IPV4, AddressFamily::IPV6] {
let mapped = AddressErrorCode::new(family, error.clone());
assert_eq!(mapped.get_type(), AddressErrorCode::TYPE);
assert_eq!(mapped.family(), family);
assert_eq!(mapped.error(), &error);
let raw: RawAttribute = mapped.to_raw();
let mut dest = vec![0; raw.padded_len()];
mapped.write_into(&mut dest).unwrap();
let raw = RawAttribute::from_bytes(&dest).unwrap();
let mapped2 = AddressErrorCode::try_from(&raw).unwrap();
assert_eq!(mapped2.get_type(), AddressErrorCode::TYPE);
assert_eq!(mapped2.family(), family);
assert_eq!(mapped.error(), &error);
}
}
#[test]
#[should_panic = "out of range"]
fn address_error_code_write_into_unchecked() {
let _log = crate::tests::test_init_log();
let error = ErrorCode::builder(ErrorCode::INSUFFICIENT_CAPACITY)
.build()
.unwrap();
let mapped = AddressErrorCode::new(AddressFamily::IPV6, error.clone());
let raw: RawAttribute = mapped.to_raw();
let mut dest = vec![0; raw.padded_len() - 1];
mapped.write_into_unchecked(&mut dest);
}
}