use crate::operations::OpCode;
use crate::rtp::RtpPayload;
use crate::rtpcodec::CodecFlag;
use crate::session::SessionInfo;
use ascii;
#[derive(Copy, Clone)]
pub struct PacketNoPayload<'a> {
pub(crate) opcode: OpCode,
pub(crate) session: &'a SessionInfo<'a>,
}
#[derive(Clone)]
pub struct PacketWithPayload<'a> {
pub(crate) opcode: OpCode,
pub(crate) session: &'a SessionInfo<'a>,
pub(crate) codec: CodecFlag,
pub(crate) flags: u8,
pub(crate) samplecount: u32,
pub(crate) payload: RtpPayload,
}
pub trait Packet {
fn print(&self) -> Result<(), Box<dyn std::error::Error>>;
fn debug(&self);
fn to_bytes(&self) -> Result<Vec<u8>, Box<dyn std::error::Error>>;
}
#[derive(Debug, Clone)]
struct CallerIdLength;
impl std::fmt::Display for CallerIdLength {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "The Caller ID must be 13 characters or fewer")
}
}
impl std::error::Error for CallerIdLength {}
impl Packet for PacketNoPayload<'_> {
fn print(&self) -> Result<(), Box<dyn std::error::Error>> {
let callerid_ascii_result: Result<&ascii::AsciiStr, ascii::AsAsciiStrError> =
ascii::AsciiStr::from_ascii(self.session.callerid);
let callerid_ascii = match callerid_ascii_result {
Ok(cid_result) => cid_result,
Err(error) => return Err(Box::new(error)),
};
let mut callerid_bytes: [u8; 13] = [0; 13];
if callerid_ascii.len() > 13 {
return Err(Box::new(CallerIdLength));
}
for (i, b) in callerid_ascii.as_bytes().iter().enumerate() {
callerid_bytes[i] = *b;
}
println!("OpCode : {}", self.opcode);
println!("Channel Number : {}", self.session.channelnum);
println!("Host Serial : {:X}", self.session.hostserial);
println!("Caller ID Length : {}", self.session.callerid_len);
println!("Caller ID : {}", callerid_ascii);
println!("=====================");
Ok(())
}
fn debug(&self) {
log::debug!("OpCode : {}", self.opcode);
log::debug!("Channel Number : {}", self.session.channelnum);
log::debug!("Host Serial : {:X}", self.session.hostserial);
log::debug!("Caller ID Length : {}", self.session.callerid_len);
log::debug!("Caller ID : {}", self.session.callerid);
log::debug!("=====================");
}
fn to_bytes(&self) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
let mut value: Vec<u8> = Vec::new();
value.push(self.opcode.to_u8());
value.push(self.session.channelnum);
value.extend_from_slice(&transform_u32_to_u8_array(self.session.hostserial));
value.push(self.session.callerid_len);
let callerid_ascii_result: Result<&ascii::AsciiStr, ascii::AsAsciiStrError> =
ascii::AsciiStr::from_ascii(self.session.callerid);
let callerid_ascii = match callerid_ascii_result {
Ok(cid_result) => cid_result,
Err(error) => return Err(Box::new(error)),
};
let mut callerid_bytes: [u8; 13] = [0; 13];
if callerid_ascii.len() > 13 {
return Err(Box::new(CallerIdLength));
}
for (i, b) in callerid_ascii.as_bytes().iter().enumerate() {
callerid_bytes[i] = *b;
}
value.extend_from_slice(&callerid_bytes);
Ok(value)
}
}
impl Packet for PacketWithPayload<'_> {
fn print(&self) -> Result<(), Box<dyn std::error::Error>> {
let callerid_ascii_result: Result<&ascii::AsciiStr, ascii::AsAsciiStrError> =
ascii::AsciiStr::from_ascii(self.session.callerid);
let callerid_ascii = match callerid_ascii_result {
Ok(cid_result) => cid_result,
Err(error) => return Err(Box::new(error)),
};
let mut callerid_bytes: [u8; 13] = [0; 13];
if callerid_ascii.len() > 13 {
return Err(Box::new(CallerIdLength));
}
for (i, b) in callerid_ascii.as_bytes().iter().enumerate() {
callerid_bytes[i] = *b;
}
println!("OpCode : {}", self.opcode);
println!("Channel Number : {}", self.session.channelnum);
println!("Host Serial : {:X}", self.session.hostserial);
println!("Caller ID Length : {}", self.session.callerid_len);
println!("Caller ID : {}", self.session.callerid);
println!("Codec : {}", self.codec);
println!("Flags : {}", self.flags);
println!("Sample Count : {}", self.samplecount);
println!("Payload : {:X}", self.payload);
println!("=====================");
Ok(())
}
fn debug(&self) {
log::debug!("OpCode : {}", self.opcode);
log::debug!("Channel Number : {}", self.session.channelnum);
log::debug!("Host Serial : {:X}", self.session.hostserial);
log::debug!("Caller ID Length : {}", self.session.callerid_len);
log::debug!("Caller ID : {}", self.session.callerid);
log::debug!("Codec : {}", self.codec);
log::debug!("Flags : {}", self.flags);
log::debug!("Sample Count : {}", self.samplecount);
log::debug!("Payload : {:X}", self.payload);
log::debug!("=====================");
}
fn to_bytes(&self) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
let mut value: Vec<u8> = Vec::new();
value.push(self.opcode.to_u8());
value.push(self.session.channelnum);
value.extend_from_slice(&transform_u32_to_u8_array(self.session.hostserial));
value.push(self.session.callerid_len);
let callerid_ascii_result: Result<&ascii::AsciiStr, ascii::AsAsciiStrError> =
ascii::AsciiStr::from_ascii(self.session.callerid);
let callerid_ascii = match callerid_ascii_result {
Ok(cid_result) => cid_result,
Err(error) => return Err(Box::new(error)),
};
let mut callerid_bytes: [u8; 13] = [0; 13];
if callerid_ascii.len() > 13 {
return Err(Box::new(CallerIdLength));
}
for (i, b) in callerid_ascii.as_bytes().iter().enumerate() {
callerid_bytes[i] = *b;
}
value.extend_from_slice(&callerid_bytes);
value.push(self.codec.to_u8());
value.push(self.flags);
value.extend_from_slice(&transform_u32_to_u8_array(self.samplecount));
value.extend_from_slice(&self.payload.data);
Ok(value)
}
}
impl PacketWithPayload<'_> {
pub fn from_buffer<'a>(
session: &'a SessionInfo<'a>,
codec: CodecFlag,
flags: u8,
sample_count: &mut u32,
mut last_chunk: Vec<u8>,
buffer: &[u8],
) -> (Vec<u8>, PacketWithPayload<'a>) {
let payload_len = buffer.len();
let mut this_payload: Vec<u8> = Vec::new();
let mut packet_payload: Vec<u8> = Vec::new();
if !last_chunk.is_empty() {
this_payload.append(&mut last_chunk.clone());
};
last_chunk.truncate(0);
log::debug!("Payload Length: {payload_len}");
assert!(payload_len <= 80);
packet_payload.extend_from_slice(&buffer);
this_payload.extend_from_slice(&buffer);
last_chunk.extend_from_slice(&packet_payload);
let rtp_payload = RtpPayload {
data: this_payload.clone(),
};
*sample_count += 160u32;
let payload_packet = PacketWithPayload {
opcode: OpCode::Transmit,
session,
codec,
flags,
samplecount: *sample_count,
payload: rtp_payload,
};
(last_chunk, payload_packet)
}
}
fn transform_u32_to_u8_array(x: u32) -> [u8; 4] {
let b1: u8 = ((x >> 24) & 0xff) as u8;
let b2: u8 = ((x >> 16) & 0xff) as u8;
let b3: u8 = ((x >> 8) & 0xff) as u8;
let b4: u8 = (x & 0xff) as u8;
[b1, b2, b3, b4]
}
pub fn get_alert<'a>(session: &'a SessionInfo) -> PacketNoPayload<'a> {
PacketNoPayload {
opcode: OpCode::Alert,
session,
}
}
pub fn get_end<'a>(session: &'a SessionInfo) -> PacketNoPayload<'a> {
PacketNoPayload {
opcode: OpCode::End,
session,
}
}
pub fn get_payload<'a>(
session: &'a SessionInfo<'a>,
codec: CodecFlag,
flags: u8,
payload_bytes: &[u8],
) -> Vec<PacketWithPayload<'a>> {
let mut result: Vec<PacketWithPayload> = Vec::new();
let payload_len = payload_bytes.len();
let chunk_num = payload_len / 80;
log::debug!("Length: {}", payload_len);
log::debug!("Chunks: {}", chunk_num);
let mut last_chunk: Vec<u8> = Vec::new();
let mut sample_count = 0u32;
let mut this_payload: Vec<u8> = Vec::new();
let mut packet_payload: Vec<u8> = Vec::new();
for (n, this_byte) in payload_bytes.iter().enumerate().take(payload_len) {
if n % 80 == 0 {
if n != 0 {
this_payload.truncate(0);
if !last_chunk.is_empty() {
this_payload.append(&mut last_chunk);
};
this_payload.append(&mut packet_payload.clone());
last_chunk.truncate(0);
last_chunk.extend_from_slice(&packet_payload);
let rtp_payload = RtpPayload {
data: this_payload.clone(),
};
let payload_packet = PacketWithPayload {
opcode: OpCode::Transmit,
session,
codec,
flags,
samplecount: sample_count,
payload: rtp_payload,
};
result.push(payload_packet);
}
packet_payload.truncate(0);
sample_count += 160u32;
}
packet_payload.push(*this_byte);
}
result
}
pub fn get_payload_packets(
session: &SessionInfo,
codec: CodecFlag,
flags: u8,
data: &[u8],
) -> Result<Vec<Vec<u8>>, Box<dyn std::error::Error>> {
let mut result: Vec<Vec<u8>> = Vec::new();
let payload_packets: Vec<PacketWithPayload> = get_payload(session, codec, flags, data);
for packet_result in payload_packets {
result.push(packet_result.to_bytes()?);
}
Ok(result)
}
pub fn get_alert_packets(session: &SessionInfo) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
let alert: PacketNoPayload = get_alert(session);
alert.to_bytes()
}
pub fn get_end_packets(session: &SessionInfo) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
let end_packet: PacketNoPayload = get_end(session);
end_packet.to_bytes()
}
pub fn get_payload_packet(
session: &SessionInfo,
payload_chunk: &[u8; 80],
last_chunk: &[u8; 80],
codec: CodecFlag,
flags: u8,
sample_count: &mut u32,
) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
let mut result: Vec<PacketWithPayload> = Vec::new();
let mut this_payload: Vec<u8> = Vec::new();
let mut packet_payload: Vec<u8> = Vec::new();
let mut tmp_last_chunk: Vec<u8> = last_chunk.to_vec();
this_payload.append(&mut tmp_last_chunk);
this_payload.append(&mut packet_payload.clone());
let rtp_payload = RtpPayload {
data: this_payload.clone(),
};
*sample_count += 160u32;
let payload_packet = PacketWithPayload {
opcode: OpCode::Transmit,
session,
codec,
flags,
samplecount: *sample_count,
payload: rtp_payload,
};
result.push(payload_packet);
packet_payload.extend_from_slice(payload_chunk);
result[0].to_bytes()
}