use alloc::vec::Vec;
use byteorder::{BigEndian, ByteOrder};
use core::net::SocketAddr;
use stun_types::message::Message;
use stun_types::message::MessageHeader;
use stun_types::message::MessageType;
use stun_types::message::MessageWriteMutSlice;
use stun_types::message::MessageWriteVec;
use stun_types::message::TransactionId;
use stun_types::prelude::AttributeExt;
use stun_types::prelude::MessageWrite;
use stun_types::prelude::MessageWriteExt;
use stun_proto::agent::Transmit;
use stun_types::TransportType;
use crate::attribute::Data as AData;
use crate::attribute::XorPeerAddress;
use crate::message::{DATA, SEND};
#[derive(Debug)]
pub struct TransmitBuild<T: DelayedTransmitBuild + core::fmt::Debug> {
pub data: T,
pub transport: TransportType,
pub from: SocketAddr,
pub to: SocketAddr,
}
impl<T: DelayedTransmitBuild + core::fmt::Debug> TransmitBuild<T> {
pub fn new(data: T, transport: TransportType, from: SocketAddr, to: SocketAddr) -> Self {
Self {
data,
transport,
from,
to,
}
}
pub fn build(self) -> Transmit<Vec<u8>> {
Transmit {
data: self.data.build(),
transport: self.transport,
from: self.from,
to: self.to,
}
}
pub fn write_into(self, dest: &mut [u8]) -> Transmit<&mut [u8]> {
let len = self.data.write_into(dest);
Transmit {
data: &mut dest[..len],
transport: self.transport,
from: self.from,
to: self.to,
}
}
}
pub trait DelayedTransmitBuild {
fn build(self) -> Vec<u8>;
fn len(&self) -> usize;
fn is_empty(&self) -> bool {
self.len() == 0
}
fn write_into(self, data: &mut [u8]) -> usize;
}
impl DelayedTransmitBuild for Vec<u8> {
fn len(&self) -> usize {
self.len()
}
fn build(self) -> Vec<u8> {
self
}
fn is_empty(&self) -> bool {
self.is_empty()
}
fn write_into(self, data: &mut [u8]) -> usize {
data[..self.len()].copy_from_slice(&self);
self.len()
}
}
impl DelayedTransmitBuild for &[u8] {
fn len(&self) -> usize {
(**self).len()
}
fn build(self) -> Vec<u8> {
self.to_vec()
}
fn is_empty(&self) -> bool {
(**self).is_empty()
}
fn write_into(self, data: &mut [u8]) -> usize {
data[..self.len()].copy_from_slice(self);
self.len()
}
}
#[derive(Debug)]
pub struct DelayedChannel<T: AsRef<[u8]> + core::fmt::Debug> {
data: T,
channel_id: u16,
}
impl<T: AsRef<[u8]> + core::fmt::Debug> DelayedChannel<T> {
pub fn new(channel_id: u16, data: T) -> Self {
Self { channel_id, data }
}
}
impl<T: AsRef<[u8]> + core::fmt::Debug> DelayedChannel<T> {
fn write_header_into(&self, len: u16, dest: &mut [u8]) {
BigEndian::write_u16(&mut dest[..2], self.channel_id);
BigEndian::write_u16(&mut dest[2..4], len);
}
}
impl<T: AsRef<[u8]> + core::fmt::Debug> DelayedTransmitBuild for DelayedChannel<T> {
fn len(&self) -> usize {
self.data.as_ref().len() + 4
}
fn build(self) -> Vec<u8> {
let data = self.data.as_ref();
let data_len = data.len();
let mut header = [0; 4];
self.write_header_into(data_len as u16, &mut header);
let mut out = Vec::with_capacity(4 + data_len);
out.extend(header.as_slice());
out.extend_from_slice(data);
out
}
fn write_into(self, dest: &mut [u8]) -> usize {
let data = self.data.as_ref();
let data_len = data.len();
self.write_header_into(data_len as u16, dest);
dest[4..4 + data_len].copy_from_slice(data);
data_len + 4
}
}
#[derive(Debug)]
pub struct DelayedMessage<T: AsRef<[u8]> + core::fmt::Debug> {
data: T,
peer_addr: SocketAddr,
for_client: bool,
}
impl<T: AsRef<[u8]> + core::fmt::Debug> DelayedMessage<T> {
pub fn for_client(peer_addr: SocketAddr, data: T) -> Self {
Self {
peer_addr,
data,
for_client: true,
}
}
pub fn for_server(peer_addr: SocketAddr, data: T) -> Self {
Self {
peer_addr,
data,
for_client: false,
}
}
}
impl<T: AsRef<[u8]> + core::fmt::Debug> DelayedTransmitBuild for DelayedMessage<T> {
fn len(&self) -> usize {
let xor_peer_addr = XorPeerAddress::new(self.peer_addr, 0.into());
let data = AData::new(self.data.as_ref());
MessageHeader::LENGTH + xor_peer_addr.padded_len() + data.padded_len()
}
fn build(self) -> Vec<u8> {
let transaction_id = TransactionId::generate();
let method = if self.for_client { DATA } else { SEND };
let mut msg = Message::builder(
MessageType::from_class_method(
stun_proto::types::message::MessageClass::Indication,
method,
),
transaction_id,
MessageWriteVec::with_capacity(self.len()),
);
let xor_peer_address = XorPeerAddress::new(self.peer_addr, transaction_id);
msg.add_attribute(&xor_peer_address).unwrap();
let data = AData::new(self.data.as_ref());
msg.add_attribute(&data).unwrap();
msg.finish()
}
fn write_into(self, dest: &mut [u8]) -> usize {
let transaction_id = TransactionId::generate();
let mut msg = Message::builder(
MessageType::from_class_method(
stun_proto::types::message::MessageClass::Indication,
SEND,
),
transaction_id,
MessageWriteMutSlice::new(dest),
);
let xor_peer_address = XorPeerAddress::new(self.peer_addr, transaction_id);
msg.add_attribute(&xor_peer_address).unwrap();
let data = AData::new(self.data.as_ref());
msg.add_attribute(&data).unwrap();
msg.finish()
}
}
#[cfg(test)]
mod tests {
use super::*;
use alloc::vec;
#[test]
fn test_delayed_vecu8() {
let data = vec![7; 7];
assert_eq!(DelayedTransmitBuild::len(&data), data.len());
assert_eq!(DelayedTransmitBuild::build(data.clone()), data);
assert!(!DelayedTransmitBuild::is_empty(&data));
assert!(DelayedTransmitBuild::is_empty(&Vec::new()));
let mut out = vec![0; 8];
assert_eq!(DelayedTransmitBuild::write_into(data.clone(), &mut out), 7);
}
#[test]
fn test_delayed_u8slice() {
let data = [7; 7];
assert_eq!(DelayedTransmitBuild::len(&data.as_slice()), data.len());
assert_eq!(DelayedTransmitBuild::build(data.as_slice()), data);
assert!(!DelayedTransmitBuild::is_empty(&data.as_slice()));
assert!(DelayedTransmitBuild::is_empty(&[].as_slice()));
let mut out = [0; 8];
assert_eq!(
DelayedTransmitBuild::write_into(data.as_slice(), &mut out),
7
);
}
}