use bytes::{Buf, BufMut, BytesMut};
use pim_core::{FrameCodec, NodeId, PimError};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct HeartbeatFrame {
pub sender_id: NodeId,
pub timestamp: u64,
pub gateway_hops: u8,
pub load: u8,
pub gw_x25519_pub: [u8; 32],
}
const SIZE: usize = 58;
impl FrameCodec for HeartbeatFrame {
fn encode(&self, buf: &mut BytesMut) {
buf.put_slice(self.sender_id.as_bytes());
buf.put_u64(self.timestamp);
buf.put_u8(self.gateway_hops);
buf.put_u8(self.load);
buf.put_slice(&self.gw_x25519_pub);
}
fn decode(buf: &mut BytesMut) -> Result<Self, PimError> {
if buf.len() < SIZE {
return Err(PimError::Protocol(format!(
"heartbeat frame too short: need {SIZE}, have {}",
buf.len()
)));
}
let mut id_bytes = [0u8; 16];
id_bytes.copy_from_slice(&buf[0..16]);
let sender_id = NodeId::from_bytes(id_bytes);
let timestamp = (&buf[16..24]).get_u64();
let gateway_hops = buf[24];
let load = buf[25];
let mut gw_x25519_pub = [0u8; 32];
gw_x25519_pub.copy_from_slice(&buf[26..58]);
buf.advance(SIZE);
Ok(HeartbeatFrame {
sender_id,
timestamp,
gateway_hops,
load,
gw_x25519_pub,
})
}
}
#[cfg(test)]
mod tests;