1 //! UDP datagrams and binary encoding/decoding for client-reflector and reflector-reflector communication.
3 use crate::address
::Address
;
4 use crate::protocol
::LsfFrame
;
6 macro_rules
! define_message
{
7 ($t
:tt
, $sz
:tt
, $min_sz
:tt
, $magic
:tt
) => {
8 pub struct $
t(pub [u8; $sz
], pub usize);
11 pub fn new() -> Self {
12 let mut bytes
= [0u8; $sz
];
13 bytes
[0..4].copy_from_slice($magic
);
17 #[allow(clippy::double_comparisons)] // occurs in some macro invocations
18 #[allow(clippy::manual_range_contains)] // way more readable, good grief
19 pub fn from_bytes(b
: &[u8]) -> Option
<Self> {
21 if len
> $sz
|| len
< $min_sz
{
24 let mut s
= Self([0; $sz
], len
);
25 s
.0[0..len
].copy_from_slice(b
);
26 if !s
.verify_integrity() {
32 pub fn as_bytes(&self) -> &[u8] {
38 fn default() -> Self {
45 macro_rules
! impl_stream_id
{
46 ($t
:ty
, $from
:tt
) => {
48 pub fn stream_id(&self) -> u16 {
49 u16::from_be_bytes([self.0[$from
], self.0[$from
+ 1]])
52 pub fn set_stream_id(&mut self, id
: u16) {
53 let bytes
= id
.to_be_bytes();
54 self.0[$from
] = bytes
[0];
55 self.0[$from
+ 1] = bytes
[1];
56 self.recalculate_crc();
62 macro_rules
! impl_link_setup
{
63 ($t
:ty
, $from
:tt
) => {
65 pub fn link_setup_frame(&self) -> LsfFrame
{
66 let mut frame
= LsfFrame([0; 30]);
67 frame
.0[0..28].copy_from_slice(&self.0[$from
..($from
+ 28)]);
68 frame
.recalculate_crc();
72 pub fn set_link_setup_frame(&mut self, lsf
: &LsfFrame
) {
73 self.0[$from
..($from
+ 28)].copy_from_slice(&lsf
.0[0..28]);
74 self.recalculate_crc();
80 macro_rules
! impl_link_setup_frame
{
81 ($t
:ty
, $from
:tt
) => {
83 pub fn link_setup_frame(&self) -> LsfFrame
{
84 let mut frame
= LsfFrame([0; 30]);
85 frame
.0[..].copy_from_slice(&self.0[$from
..($from
+ 30)]);
89 pub fn set_link_setup_frame(&mut self, lsf
: &LsfFrame
) {
90 debug_assert_eq
!(lsf
.check_crc(), 0);
91 self.0[$from
..($from
+ 30)].copy_from_slice(&lsf
.0);
92 self.recalculate_crc();
98 macro_rules
! impl_frame_number
{
99 ($t
:ty
, $from
:tt
) => {
101 pub fn frame_number(&self) -> u16 {
102 let frame_num
= u16::from_be_bytes([self.0[$from
], self.0[$from
+ 1]]);
106 pub fn is_end_of_stream(&self) -> bool
{
107 let frame_num
= u16::from_be_bytes([self.0[$from
], self.0[$from
+ 1]]);
108 (frame_num
& 0x8000) > 0
111 pub fn set_frame_number(&mut self, number
: u16) {
112 let existing_eos
= u16::from_be_bytes([self.0[$from
], self.0[$from
+ 1]]) & 0x8000;
113 let new
= (existing_eos
| (number
& 0x7fff)).to_be_bytes();
114 self.0[$from
] = new
[0];
115 self.0[$from
+ 1] = new
[1];
116 self.recalculate_crc();
119 pub fn set_end_of_stream(&mut self, eos
: bool
) {
120 let existing_fn
= u16::from_be_bytes([self.0[$from
], self.0[$from
+ 1]]) & 0x7fff;
121 let new
= (existing_fn
| (if eos
{ 0x8000 } else { 0 })).to_be_bytes();
122 self.0[$from
] = new
[0];
123 self.0[$from
+ 1] = new
[1];
124 self.recalculate_crc();
130 macro_rules
! impl_payload
{
131 ($t
:ty
, $from
:tt
, $to
:tt
) => {
133 pub fn payload(&self) -> &[u8] {
137 pub fn set_payload(&mut self, bytes
: &[u8]) {
138 self.0[$from
..$to
].copy_from_slice(bytes
);
139 self.recalculate_crc();
145 macro_rules
! impl_modules
{
146 ($t
:ty
, $from
:tt
, $to
:tt
) => {
148 pub fn modules(&self) -> ModulesIterator
{
149 ModulesIterator
::new(&self.0[$from
..$to
])
152 pub fn set_modules(&mut self, list
: &str) {
153 debug_assert
!(list
.len() < 27);
155 for m
in list
.chars() {
156 self.0[idx
] = m
as u8;
160 self.recalculate_crc();
166 macro_rules
! impl_module
{
169 pub fn module(&self) -> char {
173 pub fn set_module(&mut self, m
: char) {
174 self.0[$at
] = m
as u8;
175 self.recalculate_crc();
181 macro_rules
! impl_address
{
182 ($t
:ty
, $from
:tt
) => {
184 pub fn address(&self) -> Address
{
185 crate::address
::decode_address(self.0[$from
..($from
+ 6)].try_into().unwrap
())
188 pub fn set_address(&mut self, address
: Address
) {
189 let encoded
= crate::address
::encode_address(&address
);
190 self.0[$from
..($from
+ 6)].copy_from_slice(&encoded
);
191 self.recalculate_crc();
197 macro_rules
! impl_trailing_crc_verify
{
200 pub fn verify_integrity(&self) -> bool
{
201 crate::crc
::m17_crc(&self.0) == 0
204 pub fn recalculate_crc(&mut self) {
205 let len
= self.0.len();
206 let start_crc
= crate::crc
::m17_crc(&self.0[0..(len
- 2)]).to_be_bytes();
207 self.0[len
- 2] = start_crc
[0];
208 self.0[len
- 1] = start_crc
[1];
209 debug_assert
!(self.verify_integrity());
215 macro_rules
! impl_internal_crc
{
216 ($t
:ty
, $from
:tt
, $to
:tt
) => {
218 pub fn verify_integrity(&self) -> bool
{
219 crate::crc
::m17_crc(&self.0[$from
..$to
]) == 0
222 pub fn recalculate_crc(&mut self) {
223 // assume the last two bytes of the range are the CRC
224 let start_crc
= crate::crc
::m17_crc(&self.0[$from
..($to
- 2)]).to_be_bytes();
225 self.0[$to
- 2] = start_crc
[0];
226 self.0[$to
- 1] = start_crc
[1];
227 debug_assert
!(self.verify_integrity());
233 macro_rules
! no_crc
{
236 pub fn verify_integrity(&self) -> bool
{
239 pub fn recalculate_crc(&mut self) {}
244 macro_rules
! impl_is_relayed
{
247 pub fn is_relayed(&self) -> bool
{
248 self.0[self.0.len() - 1] != 0
251 pub fn set_relayed(&mut self, relayed
: bool
) {
252 self.0[self.0.len() - 1] = if relayed
{ 1 } else { 0 };
253 self.recalculate_crc();
259 pub struct ModulesIterator
<'a
> {
264 impl<'a
> ModulesIterator
<'a
> {
265 fn new(modules
: &'a
[u8]) -> Self {
266 Self { modules
, idx
: 0 }
270 impl Iterator
for ModulesIterator
<'_
> {
273 fn next(&mut self) -> Option
<Self::Item
> {
274 if self.idx
< self.modules
.len() {
275 if self.modules
[self.idx
] == 0 {
279 return Some(self.modules
[self.idx
- 1] as char);
285 pub const MAGIC_VOICE
: &[u8] = b
"M17 ";
286 pub const MAGIC_VOICE_HEADER
: &[u8] = b
"M17H";
287 pub const MAGIC_VOICE_DATA
: &[u8] = b
"M17D";
288 pub const MAGIC_PACKET
: &[u8] = b
"M17P";
289 pub const MAGIC_ACKNOWLEDGE
: &[u8] = b
"ACKN";
290 pub const MAGIC_CONNECT
: &[u8] = b
"CONN";
291 pub const MAGIC_DISCONNECT
: &[u8] = b
"DISC";
292 pub const MAGIC_LISTEN
: &[u8] = b
"LSTN";
293 pub const MAGIC_NACK
: &[u8] = b
"NACK";
294 pub const MAGIC_PING
: &[u8] = b
"PING";
295 pub const MAGIC_PONG
: &[u8] = b
"PONG";
297 /// Messages sent from a station/client to a reflector
298 #[allow(clippy::large_enum_variant)]
299 pub enum ClientMessage
{
301 VoiceHeader(VoiceHeader
),
302 VoiceData(VoiceData
),
307 Disconnect(Disconnect
),
311 pub fn parse(bytes
: &[u8]) -> Option
<Self> {
316 MAGIC_VOICE
=> Some(Self::Voice(Voice
::from_bytes(bytes
)?
)),
317 MAGIC_VOICE_HEADER
=> Some(Self::VoiceHeader(VoiceHeader
::from_bytes(bytes
)?
)),
318 MAGIC_VOICE_DATA
=> Some(Self::VoiceData(VoiceData
::from_bytes(bytes
)?
)),
319 MAGIC_PACKET
=> Some(Self::Packet(Packet
::from_bytes(bytes
)?
)),
320 MAGIC_PONG
=> Some(Self::Pong(Pong
::from_bytes(bytes
)?
)),
321 MAGIC_CONNECT
=> Some(Self::Connect(Connect
::from_bytes(bytes
)?
)),
322 MAGIC_LISTEN
=> Some(Self::Listen(Listen
::from_bytes(bytes
)?
)),
323 MAGIC_DISCONNECT
=> Some(Self::Disconnect(Disconnect
::from_bytes(bytes
)?
)),
329 /// Messages sent from a reflector to a station/client
330 #[allow(clippy::large_enum_variant)]
331 pub enum ServerMessage
{
333 VoiceHeader(VoiceHeader
),
334 VoiceData(VoiceData
),
337 DisconnectAcknowledge(DisconnectAcknowledge
),
338 ForceDisconnect(ForceDisconnect
),
339 ConnectAcknowledge(ConnectAcknowledge
),
340 ConnectNack(ConnectNack
),
344 pub fn parse(bytes
: &[u8]) -> Option
<Self> {
349 MAGIC_VOICE
=> Some(Self::Voice(Voice
::from_bytes(bytes
)?
)),
350 MAGIC_VOICE_HEADER
=> Some(Self::VoiceHeader(VoiceHeader
::from_bytes(bytes
)?
)),
351 MAGIC_VOICE_DATA
=> Some(Self::VoiceData(VoiceData
::from_bytes(bytes
)?
)),
352 MAGIC_PACKET
=> Some(Self::Packet(Packet
::from_bytes(bytes
)?
)),
353 MAGIC_PING
=> Some(Self::Ping(Ping
::from_bytes(bytes
)?
)),
354 MAGIC_DISCONNECT
if bytes
.len() == 4 => Some(Self::DisconnectAcknowledge(
355 DisconnectAcknowledge
::from_bytes(bytes
)?
,
357 MAGIC_DISCONNECT
=> Some(Self::ForceDisconnect(ForceDisconnect
::from_bytes(bytes
)?
)),
358 MAGIC_ACKNOWLEDGE
=> Some(Self::ConnectAcknowledge(ConnectAcknowledge
::from_bytes(
361 MAGIC_NACK
=> Some(Self::ConnectNack(ConnectNack
::from_bytes(bytes
)?
)),
367 /// Messages sent and received between reflectors
368 #[allow(clippy::large_enum_variant)]
369 pub enum InterlinkMessage
{
370 VoiceInterlink(VoiceInterlink
),
371 VoiceHeaderInterlink(VoiceHeaderInterlink
),
372 VoiceDataInterlink(VoiceDataInterlink
),
373 PacketInterlink(PacketInterlink
),
375 ConnectInterlink(ConnectInterlink
),
376 ConnectInterlinkAcknowledge(ConnectInterlinkAcknowledge
),
377 ConnectNack(ConnectNack
),
378 DisconnectInterlink(DisconnectInterlink
),
381 impl InterlinkMessage
{
382 pub fn parse(bytes
: &[u8]) -> Option
<Self> {
387 MAGIC_VOICE
=> Some(Self::VoiceInterlink(VoiceInterlink
::from_bytes(bytes
)?
)),
388 MAGIC_VOICE_HEADER
=> Some(Self::VoiceHeaderInterlink(
389 VoiceHeaderInterlink
::from_bytes(bytes
)?
,
391 MAGIC_VOICE_DATA
=> Some(Self::VoiceDataInterlink(VoiceDataInterlink
::from_bytes(
394 MAGIC_PACKET
=> Some(Self::PacketInterlink(PacketInterlink
::from_bytes(bytes
)?
)),
395 MAGIC_PING
=> Some(Self::Ping(Ping
::from_bytes(bytes
)?
)),
396 MAGIC_CONNECT
=> Some(Self::ConnectInterlink(ConnectInterlink
::from_bytes(bytes
)?
)),
397 MAGIC_ACKNOWLEDGE
=> Some(Self::ConnectInterlinkAcknowledge(
398 ConnectInterlinkAcknowledge
::from_bytes(bytes
)?
,
400 MAGIC_NACK
=> Some(Self::ConnectNack(ConnectNack
::from_bytes(bytes
)?
)),
401 MAGIC_DISCONNECT
=> Some(Self::DisconnectInterlink(DisconnectInterlink
::from_bytes(
409 define_message
!(Voice
, 54, 54, MAGIC_VOICE
);
410 impl_stream_id
!(Voice
, 4);
411 impl_link_setup
!(Voice
, 6);
412 impl_frame_number
!(Voice
, 34);
413 impl_payload
!(Voice
, 36, 52);
414 impl_trailing_crc_verify
!(Voice
);
416 define_message
!(VoiceHeader
, 36, 36, MAGIC_VOICE_HEADER
);
417 impl_stream_id
!(VoiceHeader
, 4);
418 impl_link_setup
!(VoiceHeader
, 6);
419 impl_trailing_crc_verify
!(VoiceHeader
);
421 define_message
!(VoiceData
, 26, 26, MAGIC_VOICE_DATA
);
422 impl_stream_id
!(VoiceData
, 4);
423 impl_frame_number
!(VoiceData
, 6);
424 impl_payload
!(VoiceData
, 8, 24);
425 impl_trailing_crc_verify
!(VoiceData
);
427 define_message
!(Packet
, 859, 38, MAGIC_PACKET
);
428 impl_link_setup_frame
!(Packet
, 4);
431 pub fn payload(&self) -> &[u8] {
435 pub fn set_payload(&mut self, bytes
: &[u8]) {
436 let end
= 34 + bytes
.len();
437 self.0[34..end
].copy_from_slice(bytes
);
441 pub fn verify_integrity(&self) -> bool
{
442 self.link_setup_frame().check_crc() == 0
443 && self.payload().len() >= 4
444 && crate::crc
::m17_crc(self.payload()) == 0
447 pub fn recalculate_crc(&mut self) {
448 // LSF and payload should be confirmed valid before construction
452 define_message
!(Pong
, 10, 10, MAGIC_PONG
);
453 impl_address
!(Pong
, 4);
456 define_message
!(Connect
, 11, 11, MAGIC_CONNECT
);
457 impl_address
!(Connect
, 4);
458 impl_module
!(Connect
, 10);
461 define_message
!(Listen
, 11, 11, MAGIC_LISTEN
);
462 impl_address
!(Listen
, 4);
463 impl_module
!(Listen
, 10);
466 define_message
!(Disconnect
, 10, 10, MAGIC_DISCONNECT
);
467 impl_address
!(Disconnect
, 4);
470 define_message
!(Ping
, 10, 10, MAGIC_PING
);
471 impl_address
!(Ping
, 4);
474 define_message
!(DisconnectAcknowledge
, 4, 4, MAGIC_DISCONNECT
);
475 no_crc
!(DisconnectAcknowledge
);
477 define_message
!(ForceDisconnect
, 10, 10, MAGIC_DISCONNECT
);
478 impl_address
!(ForceDisconnect
, 4);
479 no_crc
!(ForceDisconnect
);
481 define_message
!(ConnectAcknowledge
, 4, 4, MAGIC_ACKNOWLEDGE
);
482 no_crc
!(ConnectAcknowledge
);
484 define_message
!(ConnectNack
, 4, 4, MAGIC_NACK
);
485 no_crc
!(ConnectNack
);
487 define_message
!(VoiceInterlink
, 55, 55, MAGIC_VOICE
);
488 impl_stream_id
!(VoiceInterlink
, 4);
489 impl_link_setup
!(VoiceInterlink
, 6);
490 impl_frame_number
!(VoiceInterlink
, 34);
491 impl_payload
!(VoiceInterlink
, 36, 52);
492 impl_internal_crc
!(VoiceInterlink
, 0, 54);
493 impl_is_relayed
!(VoiceInterlink
);
495 define_message
!(VoiceHeaderInterlink
, 37, 37, MAGIC_VOICE_HEADER
);
496 impl_stream_id
!(VoiceHeaderInterlink
, 4);
497 impl_link_setup
!(VoiceHeaderInterlink
, 6);
498 impl_internal_crc
!(VoiceHeaderInterlink
, 0, 36);
499 impl_is_relayed
!(VoiceHeaderInterlink
);
501 define_message
!(VoiceDataInterlink
, 27, 27, MAGIC_VOICE_DATA
);
502 impl_stream_id
!(VoiceDataInterlink
, 4);
503 impl_frame_number
!(VoiceDataInterlink
, 6);
504 impl_payload
!(VoiceDataInterlink
, 8, 24);
505 impl_internal_crc
!(VoiceDataInterlink
, 0, 24);
506 impl_is_relayed
!(VoiceDataInterlink
);
508 define_message
!(PacketInterlink
, 860, 39, MAGIC_PACKET
);
509 impl_link_setup_frame
!(PacketInterlink
, 4);
510 impl_is_relayed
!(PacketInterlink
);
512 impl PacketInterlink
{
513 pub fn payload(&self) -> &[u8] {
514 &self.0[34..(self.1 - 1)]
517 pub fn set_payload(&mut self, bytes
: &[u8]) {
518 let is_relayed
= self.is
_relayed
();
519 let end
= 34 + bytes
.len();
520 self.0[34..end
].copy_from_slice(bytes
);
522 self.set_relayed(is_relayed
);
525 pub fn verify_integrity(&self) -> bool
{
526 self.link_setup_frame().check_crc() == 0
527 && self.payload().len() >= 4
528 && crate::crc
::m17_crc(self.payload()) == 0
531 pub fn recalculate_crc(&mut self) {
532 // LSF and payload should be confirmed valid before construction
536 define_message
!(ConnectInterlink
, 37, 37, MAGIC_CONNECT
);
537 impl_address
!(ConnectInterlink
, 4);
538 impl_modules
!(ConnectInterlink
, 10, 37);
539 no_crc
!(ConnectInterlink
);
541 define_message
!(ConnectInterlinkAcknowledge
, 37, 37, MAGIC_ACKNOWLEDGE
);
542 impl_address
!(ConnectInterlinkAcknowledge
, 4);
543 impl_modules
!(ConnectInterlinkAcknowledge
, 10, 37);
544 no_crc
!(ConnectInterlinkAcknowledge
);
546 define_message
!(DisconnectInterlink
, 10, 10, MAGIC_DISCONNECT
);
547 impl_address
!(DisconnectInterlink
, 4);
548 no_crc
!(DisconnectInterlink
);