]>
code.octet-stream.net Git - m17rt/blob - m17core/src/protocol.rs
1 use crate::address
::Address
;
3 pub(crate) const LSF_SYNC
: [i8; 8] = [1, 1, 1, 1, -1, -1, 1, -1];
4 pub(crate) const BERT_SYNC
: [i8; 8] = [-1, 1, -1, -1, 1, 1, 1, 1];
5 pub(crate) const STREAM_SYNC
: [i8; 8] = [-1, -1, -1, -1, 1, 1, -1, 1];
6 pub(crate) const PACKET_SYNC
: [i8; 8] = [1, -1, 1, 1, -1, -1, -1, -1];
8 #[derive(Debug, Clone, PartialEq, Eq)]
13 #[derive(Debug, Clone, PartialEq, Eq)]
20 #[derive(Debug, Clone, PartialEq, Eq)]
21 pub enum EncryptionType
{
28 #[derive(Debug, Clone, PartialEq, Eq)]
36 #[derive(Debug, Clone, PartialEq, Eq)]
57 pub fn from_proto(buf
: &[u8]) -> Option
<(Self, usize)> {
60 .and_then(|chunk
| chunk
.valid().chars().next())
61 .map(|c
| match c
as u32 {
62 0x00 => (PacketType
::Raw
, 1),
63 0x01 => (PacketType
::Ax25
, 1),
64 0x02 => (PacketType
::Aprs
, 1),
65 0x03 => (PacketType
::SixLowPan
, 1),
66 0x04 => (PacketType
::Ipv4
, 1),
67 0x05 => (PacketType
::Sms
, 1),
68 0x06 => (PacketType
::Winlink
, 1),
69 _
=> (PacketType
::Other(c
), c
.len_utf8()),
73 pub fn as_proto(&self) -> ([u8; 4], usize) {
75 PacketType
::Raw
=> ([0, 0, 0, 0], 1),
76 PacketType
::Ax25
=> ([1, 0, 0, 0], 1),
77 PacketType
::Aprs
=> ([2, 0, 0, 0], 1),
78 PacketType
::SixLowPan
=> ([3, 0, 0, 0], 1),
79 PacketType
::Ipv4
=> ([4, 0, 0, 0], 1),
80 PacketType
::Sms
=> ([5, 0, 0, 0], 1),
81 PacketType
::Winlink
=> ([6, 0, 0, 0], 1),
82 PacketType
::Other(c
) => {
83 let mut buf
= [0u8; 4];
84 let s
= c
.encode_utf8(&mut buf
);
92 #[derive(Debug, Clone, PartialEq, Eq)]
93 pub struct LsfFrame(pub [u8; 30]);
96 pub fn crc(&self) -> u16 {
97 crate::crc
::m17_crc(&self.0)
100 pub fn destination(&self) -> Address
{
101 crate::address
::decode_address((&self.0[0..6]).try_into().unwrap
())
104 pub fn source(&self) -> Address
{
105 crate::address
::decode_address((&self.0[6..12]).try_into().unwrap
())
108 pub fn mode(&self) -> Mode
{
109 if self.0[12] & 0x01 > 0 {
116 pub fn data_type(&self) -> DataType
{
117 match (self.0[12] >> 1) & 0x03 {
118 0b00 => DataType
::Reserved
,
119 0b01 => DataType
::Data
,
120 0b10 => DataType
::Voice
,
121 0b11 => DataType
::VoiceAndData
,
126 pub fn encryption_type(&self) -> EncryptionType
{
127 match (self.0[12] >> 3) & 0x03 {
128 0b00 => EncryptionType
::None
,
129 0b01 => EncryptionType
::Scrambler
,
130 0b10 => EncryptionType
::Aes
,
131 0b11 => EncryptionType
::Other
,
136 // TODO: encryption sub-type
138 pub fn channel_access_number(&self) -> u8 {
139 (self.0[12] >> 7) & 0x0f
142 pub fn meta(&self) -> [u8; 14] {
143 self.0[14..28].try_into().unwrap
()
147 #[derive(Debug, Clone, PartialEq, Eq)]
148 pub struct StreamFrame
{
149 /// Which LICH segment is given in this frame, from 0 to 5 inclusive
151 /// Decoded LICH segment
152 pub lich_part
: [u8; 5],
153 /// Which frame in the transmission this is, starting from 0
154 pub frame_number
: u16,
155 /// Is this the last frame in the transmission?
156 pub end_of_stream
: bool
,
157 /// Raw application data in this frame
158 pub stream_data
: [u8; 16],
161 #[derive(Debug, Clone, PartialEq, Eq)]
162 pub struct PacketFrame
{
163 /// Application packet payload (chunk)
164 pub payload
: [u8; 25],
166 /// Frame counter, which provides different information depending on whether this is the last frame or not.
167 pub counter
: PacketFrameCounter
,
170 #[derive(Debug, Clone, PartialEq, Eq)]
171 pub enum PacketFrameCounter
{
172 /// Any packet frame that comes after the LSF and is not the final frame.
174 /// Which frame this is in the superframe, from 0 to 31 inclusive.
176 /// If a 33rd frame exists (index 32), it will be a `FinalFrame` instead.
178 /// All 25 bytes of of `payload` are filled and valid.
181 /// The final frame in the packet superframe.
183 /// The number of bytes in `payload` that are filled.
188 pub struct LichCollection([Option
<[u8; 5]>; 6]);
190 impl LichCollection
{
191 pub fn new() -> Self {
195 pub fn valid_segments(&self) -> usize {
196 self.0.iter
().filter
(|s
| s
.is
_some
()).count()
199 pub fn set_segment(&mut self, counter
: u8, part
: [u8; 5]) {
200 self.0[counter
as usize] = Some(part
);
203 pub fn try_assemble(&self) -> Option
<[u8; 30]> {
204 let mut out
= [0u8; 30];
205 for (i
, segment
) in self.0.iter
().enumerate() {
206 let Some(segment
) = segment
else {
209 for (j
, seg_val
) in segment
.iter
().enumerate() {
210 out
[i
* 5 + j
] = *seg_val
;
217 impl Default
for LichCollection
{
218 fn default() -> Self {