1use crate::ValidStr;
10use packet::{
11 BufferView, BufferViewMut, FragmentedBytesMut, InnerPacketBuilder, NestablePacketBuilder,
12 PacketBuilder, PacketConstraints, ParsablePacket, ParseMetadata, SerializationContext,
13 SerializeTarget,
14};
15use std::num::NonZeroU16;
16use zerocopy::byteorder::little_endian::U32;
17use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, Ref, SplitByteSlice, Unaligned};
18
19pub const MULTICAST_PORT: NonZeroU16 = NonZeroU16::new(33337).unwrap();
20pub const ACK_PORT: NonZeroU16 = NonZeroU16::new(33338).unwrap();
21
22const MAGIC: u32 = 0xAEAE1123;
23const MAX_LOG_DATA: usize = 1216;
24const MAX_NODENAME_LENGTH: usize = 64;
25
26pub const ACK_SIZE: usize = std::mem::size_of::<PacketHead>();
27
28#[repr(C)]
29#[derive(KnownLayout, FromBytes, IntoBytes, Immutable, Unaligned)]
30pub struct PacketHead {
31 magic: U32,
32 seqno: U32,
33}
34
35pub struct DebugLogPacket<B> {
36 head: Ref<B, PacketHead>,
37 nodename: ValidStr<B>,
38 data: ValidStr<B>,
39}
40
41impl<B: SplitByteSlice> DebugLogPacket<B> {
42 pub fn seqno(&self) -> u32 {
43 self.head.seqno.get()
44 }
45
46 pub fn nodename(&self) -> &str {
47 self.nodename.as_str()
48 }
49
50 pub fn data(&self) -> &str {
51 self.data.as_str()
52 }
53}
54
55#[derive(Debug)]
56pub enum ParseError {
57 BadMagic,
58 Malformed,
59 Encoding(std::str::Utf8Error),
60}
61
62impl<B> ParsablePacket<B, ()> for DebugLogPacket<B>
63where
64 B: SplitByteSlice,
65{
66 type Error = ParseError;
67
68 fn parse<BV: BufferView<B>>(mut buffer: BV, _args: ()) -> Result<Self, Self::Error> {
69 let head = buffer.take_obj_front::<PacketHead>().ok_or(ParseError::Malformed)?;
70 if head.magic.get() != MAGIC {
71 return Err(ParseError::BadMagic);
72 }
73 let nodename = buffer.take_front(MAX_NODENAME_LENGTH).ok_or(ParseError::Malformed)?;
74 let nodename = ValidStr::new(nodename).map_err(ParseError::Encoding)?;
75 let (nodename, _rest) = nodename.truncate_null();
76 let data = ValidStr::new(buffer.into_rest()).map_err(ParseError::Encoding)?;
77
78 Ok(Self { head, nodename, data })
79 }
80
81 fn parse_metadata(&self) -> ParseMetadata {
82 unimplemented!()
84 }
85}
86
87#[derive(Debug)]
88pub struct AckPacketBuilder {
89 seqno: u32,
90}
91
92impl AckPacketBuilder {
93 pub fn new(seqno: u32) -> Self {
94 Self { seqno }
95 }
96}
97
98impl InnerPacketBuilder for AckPacketBuilder {
99 fn bytes_len(&self) -> usize {
100 std::mem::size_of::<PacketHead>()
101 }
102
103 fn serialize(&self, mut buffer: &mut [u8]) {
104 let mut bv = crate::as_buffer_view_mut(&mut buffer);
105 let mut head = bv.take_obj_front::<PacketHead>().unwrap();
106 head.magic.set(MAGIC);
107 head.seqno.set(self.seqno);
108 }
109}
110
111#[derive(Debug)]
112pub struct LogPacketBuilder<'a> {
113 seqno: u32,
114 nodename: &'a str,
115}
116
117impl<'a> LogPacketBuilder<'a> {
118 pub fn new(seqno: u32, nodename: &'a str) -> Option<Self> {
119 if nodename.len() <= MAX_NODENAME_LENGTH { Some(Self { seqno, nodename }) } else { None }
120 }
121}
122
123impl<'a> NestablePacketBuilder for LogPacketBuilder<'a> {
124 fn constraints(&self) -> PacketConstraints {
125 PacketConstraints::new(
126 std::mem::size_of::<PacketHead>() + MAX_NODENAME_LENGTH,
127 0,
128 0,
129 MAX_LOG_DATA,
130 )
131 }
132}
133
134impl<'a, C: SerializationContext> PacketBuilder<C> for LogPacketBuilder<'a> {
135 fn serialize(
136 &self,
137 _context: &mut C,
138 target: &mut SerializeTarget<'_>,
139 _body: FragmentedBytesMut<'_, '_>,
140 ) {
141 let mut bv = crate::as_buffer_view_mut(&mut target.header);
142 let mut head = bv.take_obj_front::<PacketHead>().unwrap();
143 head.magic.set(MAGIC);
144 head.seqno.set(self.seqno);
145 let nodename_bytes = self.nodename.as_bytes();
146 let nodename = bv.take_front_zero(MAX_NODENAME_LENGTH).unwrap();
147 let (nodename, _rest) = nodename.split_at_mut(nodename_bytes.len());
148 nodename.copy_from_slice(nodename_bytes);
149 }
150}
151
152#[cfg(test)]
153mod tests {
154 use super::*;
155 use packet::{NoOpSerializationContext, ParseBuffer as _, Serializer as _};
156
157 fn as_buffer_view<'a, B: packet::BufferView<&'a [u8]>>(
159 v: B,
160 ) -> impl packet::BufferView<&'a [u8]> {
161 v
162 }
163
164 #[test]
165 fn test_log_packet() {
166 const LOG_DATA: &'static str = "some log data";
167 const NODENAME: &'static str = "my node";
168 let mut log = LogPacketBuilder::new(3, NODENAME)
169 .unwrap()
170 .wrap_body(LOG_DATA.as_bytes().into_serializer())
171 .serialize_vec_outer(&mut NoOpSerializationContext)
172 .unwrap_or_else(|_| panic!("Failed to serialize"));
173 let packet = log.parse::<DebugLogPacket<_>>().expect("Failed to parse");
174 assert_eq!(packet.seqno(), 3);
175 assert_eq!(packet.nodename(), NODENAME);
176 assert_eq!(packet.data(), LOG_DATA);
177 }
178
179 #[test]
180 fn test_ack_packet() {
181 const SEQNO: u32 = 4;
182 let ack = AckPacketBuilder::new(SEQNO)
183 .into_serializer()
184 .serialize_vec_outer(&mut NoOpSerializationContext)
185 .unwrap_or_else(|_| panic!("Failed to serialize"));
186 let mut bv = ack.as_ref();
187 let head = as_buffer_view(&mut bv)
188 .take_obj_front::<PacketHead>()
189 .expect("failed to get serialized head");
190 assert_eq!(head.magic.get(), MAGIC);
191 assert_eq!(head.seqno.get(), SEQNO);
192 }
193}