]> code.octet-stream.net Git - m17rt/blob - m17core/src/protocol.rs
Add metadata to m17rt-mod Cargo.toml
[m17rt] / m17core / src / protocol.rs
1 use crate::address::{encode_address, Address};
2
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];
7
8 #[derive(Debug, Clone, PartialEq, Eq, Copy)]
9 pub enum Mode {
10 Packet,
11 Stream,
12 }
13 #[derive(Debug, Clone, PartialEq, Eq, Copy)]
14 pub enum DataType {
15 Reserved,
16 Data,
17 Voice,
18 VoiceAndData,
19 }
20 #[derive(Debug, Clone, PartialEq, Eq, Copy)]
21 pub enum EncryptionType {
22 None,
23 Scrambler,
24 Aes,
25 Other,
26 }
27
28 #[derive(Debug, Clone, PartialEq, Eq)]
29 pub enum Frame {
30 Lsf(LsfFrame),
31 Stream(StreamFrame),
32 Packet(PacketFrame),
33 // BERT
34 }
35
36 #[derive(Debug, Clone, PartialEq, Eq, Copy)]
37 pub enum PacketType {
38 /// RAW
39 Raw,
40 /// AX.25
41 Ax25,
42 /// APRS
43 Aprs,
44 /// 6LoWPAN
45 SixLowPan,
46 /// IPv4
47 Ipv4,
48 /// SMS
49 Sms,
50 /// Winlink
51 Winlink,
52 /// Custom identifier
53 Other(char),
54 }
55
56 impl PacketType {
57 pub fn from_proto(buf: &[u8]) -> Option<(Self, usize)> {
58 buf.utf8_chunks()
59 .next()
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()),
70 })
71 }
72
73 pub fn as_proto(&self) -> ([u8; 4], usize) {
74 match self {
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);
85 let len = s.len();
86 (buf, len)
87 }
88 }
89 }
90 }
91
92 #[derive(Debug, Clone, PartialEq, Eq)]
93 pub struct LsfFrame(pub [u8; 30]);
94
95 impl LsfFrame {
96 pub fn new_voice(source: &Address, destination: &Address) -> Self {
97 let mut out = Self([0u8; 30]);
98 out.set_source(source);
99 out.set_destination(destination);
100 out.set_mode(Mode::Stream);
101 out.set_data_type(DataType::Voice);
102 out.set_encryption_type(EncryptionType::None);
103 out
104 }
105
106 pub fn new_packet(source: &Address, destination: &Address) -> Self {
107 let mut out = Self([0u8; 30]);
108 out.set_source(source);
109 out.set_destination(destination);
110 out.set_mode(Mode::Packet);
111 out.set_data_type(DataType::Data);
112 out.set_encryption_type(EncryptionType::None);
113 out
114 }
115
116 /// Calculate crc of entire frame. If zero, it is a valid frame.
117 pub fn check_crc(&self) -> u16 {
118 crate::crc::m17_crc(&self.0)
119 }
120
121 pub fn destination(&self) -> Address {
122 crate::address::decode_address((&self.0[0..6]).try_into().unwrap())
123 }
124
125 pub fn source(&self) -> Address {
126 crate::address::decode_address((&self.0[6..12]).try_into().unwrap())
127 }
128
129 pub fn mode(&self) -> Mode {
130 if self.lsf_type() & 0x0001 > 0 {
131 Mode::Stream
132 } else {
133 Mode::Packet
134 }
135 }
136
137 pub fn data_type(&self) -> DataType {
138 match (self.0[12] >> 1) & 0x03 {
139 0b00 => DataType::Reserved,
140 0b01 => DataType::Data,
141 0b10 => DataType::Voice,
142 0b11 => DataType::VoiceAndData,
143 _ => unreachable!(),
144 }
145 }
146
147 pub fn encryption_type(&self) -> EncryptionType {
148 match (self.lsf_type() >> 3) & 0x0003 {
149 0b00 => EncryptionType::None,
150 0b01 => EncryptionType::Scrambler,
151 0b10 => EncryptionType::Aes,
152 0b11 => EncryptionType::Other,
153 _ => unreachable!(),
154 }
155 }
156
157 // TODO: encryption sub-type
158
159 pub fn channel_access_number(&self) -> u8 {
160 ((self.lsf_type() >> 7) & 0x000f) as u8
161 }
162
163 pub fn meta(&self) -> [u8; 14] {
164 self.0[14..28].try_into().unwrap()
165 }
166
167 pub fn set_destination(&mut self, destination: &Address) {
168 self.0[0..6].copy_from_slice(&encode_address(&destination));
169 self.recalculate_crc();
170 }
171
172 pub fn set_source(&mut self, source: &Address) {
173 self.0[6..12].copy_from_slice(&encode_address(&source));
174 self.recalculate_crc();
175 }
176
177 pub fn set_mode(&mut self, mode: Mode) {
178 let existing_type = self.lsf_type();
179 let new_type = (existing_type & !0x0001) | if mode == Mode::Stream { 1 } else { 0 };
180 self.0[12..14].copy_from_slice(&new_type.to_be_bytes());
181 self.recalculate_crc();
182 }
183
184 pub fn set_data_type(&mut self, data_type: DataType) {
185 let type_part = match data_type {
186 DataType::Reserved => 0b00 << 1,
187 DataType::Data => 0b01 << 1,
188 DataType::Voice => 0b10 << 1,
189 DataType::VoiceAndData => 0b11 << 1,
190 };
191 let existing_type = self.lsf_type();
192 let new_type = (existing_type & !0x0006) | type_part;
193 self.0[12..14].copy_from_slice(&new_type.to_be_bytes());
194 self.recalculate_crc();
195 }
196
197 pub fn set_encryption_type(&mut self, encryption_type: EncryptionType) {
198 let type_part = match encryption_type {
199 EncryptionType::None => 0b00 << 3,
200 EncryptionType::Scrambler => 0b01 << 3,
201 EncryptionType::Aes => 0b10 << 3,
202 EncryptionType::Other => 0b11 << 3,
203 };
204 let existing_type = self.lsf_type();
205 let new_type = (existing_type & !0x0018) | type_part;
206 self.0[12..14].copy_from_slice(&new_type.to_be_bytes());
207 self.recalculate_crc();
208 }
209
210 fn recalculate_crc(&mut self) {
211 let new_crc = crate::crc::m17_crc(&self.0[0..28]);
212 self.0[28..30].copy_from_slice(&new_crc.to_be_bytes());
213 debug_assert_eq!(self.check_crc(), 0);
214 }
215
216 fn lsf_type(&self) -> u16 {
217 u16::from_be_bytes([self.0[12], self.0[13]])
218 }
219 }
220
221 #[derive(Debug, Clone, PartialEq, Eq, Default)]
222 pub struct StreamFrame {
223 /// Which LICH segment is given in this frame, from 0 to 5 inclusive
224 pub lich_idx: u8,
225 /// Decoded LICH segment
226 pub lich_part: [u8; 5],
227 /// Which frame in the transmission this is, starting from 0
228 pub frame_number: u16,
229 /// Is this the last frame in the transmission?
230 pub end_of_stream: bool,
231 /// Raw application data in this frame
232 pub stream_data: [u8; 16],
233 }
234
235 #[derive(Debug, Clone, PartialEq, Eq)]
236 pub struct PacketFrame {
237 /// Application packet payload (chunk)
238 pub payload: [u8; 25],
239
240 /// Frame counter, which provides different information depending on whether this is the last frame or not.
241 pub counter: PacketFrameCounter,
242 }
243
244 #[derive(Debug, Clone, PartialEq, Eq)]
245 pub enum PacketFrameCounter {
246 /// Any packet frame that comes after the LSF and is not the final frame.
247 Frame {
248 /// Which frame this is in the superframe, from 0 to 31 inclusive.
249 ///
250 /// If a 33rd frame exists (index 32), it will be a `FinalFrame` instead.
251 ///
252 /// All 25 bytes of of `payload` are filled and valid.
253 index: usize,
254 },
255 /// The final frame in the packet superframe.
256 FinalFrame {
257 /// The number of bytes in `payload` that are filled.
258 payload_len: usize,
259 },
260 }
261
262 pub struct LichCollection([Option<[u8; 5]>; 6]);
263
264 impl LichCollection {
265 pub fn new() -> Self {
266 Self([None; 6])
267 }
268
269 pub fn valid_segments(&self) -> usize {
270 self.0.iter().filter(|s| s.is_some()).count()
271 }
272
273 pub fn set_segment(&mut self, counter: u8, part: [u8; 5]) {
274 self.0[counter as usize] = Some(part);
275 }
276
277 pub fn try_assemble(&self) -> Option<[u8; 30]> {
278 let mut out = [0u8; 30];
279 for (i, segment) in self.0.iter().enumerate() {
280 let Some(segment) = segment else {
281 return None;
282 };
283 for (j, seg_val) in segment.iter().enumerate() {
284 out[i * 5 + j] = *seg_val;
285 }
286 }
287 Some(out)
288 }
289 }
290
291 impl Default for LichCollection {
292 fn default() -> Self {
293 Self::new()
294 }
295 }