use crate::bytes::Reader;
use crate::error::{Error, Result};
pub const NAT_CONNECT: u16 = 0;
pub const NAT_SERVERINFO: u16 = 1;
pub const NAT_REQUEST: u16 = 2;
pub const NAT_RESPONSE: u16 = 3;
pub const NAT_REQUEST_MODELDEF: u16 = 4;
pub const NAT_MODELDEF: u16 = 5;
pub const NAT_REQUEST_FRAMEOFDATA: u16 = 6;
pub const NAT_FRAMEOFDATA: u16 = 7;
pub const NAT_MESSAGESTRING: u16 = 8;
pub const NAT_DISCONNECT: u16 = 9;
pub const NAT_KEEPALIVE: u16 = 10;
pub const NAT_DISCONNECTBYTIMEOUT: u16 = 11;
pub const NAT_ECHOREQUEST: u16 = 12;
pub const NAT_ECHORESPONSE: u16 = 13;
pub const NAT_DISCOVERY: u16 = 14;
pub const NAT_UNRECOGNIZED_REQUEST: u16 = 100;
pub const HEADER_LEN: usize = 4;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct MessageHeader {
pub message_id: u16,
pub declared_size: u16,
}
impl MessageHeader {
pub fn parse(data: &[u8]) -> Result<Self> {
let mut r = Reader::new(data);
Ok(Self {
message_id: r.u16()?,
declared_size: r.u16()?,
})
}
}
pub fn split(data: &[u8]) -> Result<(MessageHeader, &[u8])> {
let header = MessageHeader::parse(data)?;
Ok((header, &data[HEADER_LEN..]))
}
pub fn parse_message_string(datagram: &[u8]) -> Result<String> {
let payload = expect(datagram, NAT_MESSAGESTRING)?;
let end = payload
.iter()
.position(|&b| b == 0)
.unwrap_or(payload.len());
Ok(String::from_utf8_lossy(&payload[..end]).into_owned())
}
pub(crate) fn expect(data: &[u8], expected: u16) -> Result<&[u8]> {
let (header, payload) = split(data)?;
if header.message_id != expected {
return Err(Error::UnexpectedMessageId {
found: header.message_id,
expected,
});
}
Ok(payload)
}
pub(crate) fn frame(message_id: u16, payload: &[u8]) -> Vec<u8> {
let declared = u16::try_from(payload.len()).unwrap_or(u16::MAX);
frame_declared(message_id, declared, payload)
}
pub(crate) fn frame_checked(message_id: u16, payload: &[u8]) -> Result<Vec<u8>> {
let declared = u16::try_from(payload.len()).map_err(|_| Error::LengthOverflow {
field: "message payload size",
length: payload.len(),
max: usize::from(u16::MAX),
})?;
Ok(frame_declared(message_id, declared, payload))
}
fn frame_declared(message_id: u16, declared: u16, payload: &[u8]) -> Vec<u8> {
let mut out = Vec::with_capacity(HEADER_LEN + payload.len());
out.extend_from_slice(&message_id.to_le_bytes());
out.extend_from_slice(&declared.to_le_bytes());
out.extend_from_slice(payload);
out
}