]>
code.octet-stream.net Git - m17rt/blob - m17core/src/protocol.rs
1 use crate::address
::{encode_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];
7 pub(crate) const PREAMBLE
: [i8; 8] = [1, -1, 1, -1, 1, -1, 1, -1];
8 pub(crate) const END_OF_TRANSMISSION
: [i8; 8] = [1, 1, 1, 1, 1, 1, -1, 1];
10 #[derive(Debug, Clone, PartialEq, Eq, Copy)]
15 #[derive(Debug, Clone, PartialEq, Eq, Copy)]
22 #[derive(Debug, Clone, PartialEq, Eq, Copy)]
23 pub enum EncryptionType
{
30 #[derive(Debug, Clone, PartialEq, Eq)]
38 #[derive(Debug, Clone, PartialEq, Eq, Copy)]
59 pub fn from_proto(buf
: &[u8]) -> Option
<(Self, usize)> {
62 .and_then(|chunk
| chunk
.valid().chars().next())
63 .map(|c
| match c
as u32 {
64 0x00 => (PacketType
::Raw
, 1),
65 0x01 => (PacketType
::Ax25
, 1),
66 0x02 => (PacketType
::Aprs
, 1),
67 0x03 => (PacketType
::SixLowPan
, 1),
68 0x04 => (PacketType
::Ipv4
, 1),
69 0x05 => (PacketType
::Sms
, 1),
70 0x06 => (PacketType
::Winlink
, 1),
71 _
=> (PacketType
::Other(c
), c
.len_utf8()),
75 pub fn as_proto(&self) -> ([u8; 4], usize) {
77 PacketType
::Raw
=> ([0, 0, 0, 0], 1),
78 PacketType
::Ax25
=> ([1, 0, 0, 0], 1),
79 PacketType
::Aprs
=> ([2, 0, 0, 0], 1),
80 PacketType
::SixLowPan
=> ([3, 0, 0, 0], 1),
81 PacketType
::Ipv4
=> ([4, 0, 0, 0], 1),
82 PacketType
::Sms
=> ([5, 0, 0, 0], 1),
83 PacketType
::Winlink
=> ([6, 0, 0, 0], 1),
84 PacketType
::Other(c
) => {
85 let mut buf
= [0u8; 4];
86 let s
= c
.encode_utf8(&mut buf
);
94 #[derive(Debug, Clone, PartialEq, Eq)]
95 pub struct LsfFrame(pub [u8; 30]);
98 pub fn new_voice(source
: &Address
, destination
: &Address
) -> Self {
99 let mut out
= Self([0u8; 30]);
100 out
.set_source(source
);
101 out
.set_destination(destination
);
102 out
.set_mode(Mode
::Stream
);
103 out
.set_data_type(DataType
::Voice
);
104 out
.set_encryption_type(EncryptionType
::None
);
108 pub fn new_packet(source
: &Address
, destination
: &Address
) -> Self {
109 let mut out
= Self([0u8; 30]);
110 out
.set_source(source
);
111 out
.set_destination(destination
);
112 out
.set_mode(Mode
::Packet
);
113 out
.set_data_type(DataType
::Data
);
114 out
.set_encryption_type(EncryptionType
::None
);
118 /// Calculate crc of entire frame. If zero, it is a valid frame.
119 pub fn check_crc(&self) -> u16 {
120 crate::crc
::m17_crc(&self.0)
123 pub fn destination(&self) -> Address
{
124 crate::address
::decode_address((&self.0[0..6]).try_into().unwrap
())
127 pub fn source(&self) -> Address
{
128 crate::address
::decode_address((&self.0[6..12]).try_into().unwrap
())
131 pub fn mode(&self) -> Mode
{
132 if self.lsf_type() & 0x0001 > 0 {
139 pub fn data_type(&self) -> DataType
{
140 match (self.0[12] >> 1) & 0x03 {
141 0b00 => DataType
::Reserved
,
142 0b01 => DataType
::Data
,
143 0b10 => DataType
::Voice
,
144 0b11 => DataType
::VoiceAndData
,
149 pub fn encryption_type(&self) -> EncryptionType
{
150 match (self.lsf_type() >> 3) & 0x0003 {
151 0b00 => EncryptionType
::None
,
152 0b01 => EncryptionType
::Scrambler
,
153 0b10 => EncryptionType
::Aes
,
154 0b11 => EncryptionType
::Other
,
159 // TODO: encryption sub-type
161 pub fn channel_access_number(&self) -> u8 {
162 ((self.lsf_type() >> 7) & 0x000f) as u8
165 pub fn meta(&self) -> [u8; 14] {
166 self.0[14..28].try_into().unwrap
()
169 pub fn set_destination(&mut self, destination
: &Address
) {
170 self.0[0..6].copy_from_slice(&encode_address(&destination
));
171 self.recalculate_crc();
174 pub fn set_source(&mut self, source
: &Address
) {
175 self.0[6..12].copy_from_slice(&encode_address(&source
));
176 self.recalculate_crc();
179 pub fn set_mode(&mut self, mode
: Mode
) {
180 let existing_type
= self.lsf_type();
181 let new_type
= (existing_type
& !0x0001) | if mode
== Mode
::Stream
{ 1 } else { 0 };
182 self.0[12..14].copy_from_slice(&new_type
.to_be_bytes());
183 self.recalculate_crc();
186 pub fn set_data_type(&mut self, data_type
: DataType
) {
187 let type_part
= match data_type
{
188 DataType
::Reserved
=> 0b00 << 1,
189 DataType
::Data
=> 0b01 << 1,
190 DataType
::Voice
=> 0b10 << 1,
191 DataType
::VoiceAndData
=> 0b11 << 1,
193 let existing_type
= self.lsf_type();
194 let new_type
= (existing_type
& !0x0006) | type_part
;
195 self.0[12..14].copy_from_slice(&new_type
.to_be_bytes());
196 self.recalculate_crc();
199 pub fn set_encryption_type(&mut self, encryption_type
: EncryptionType
) {
200 let type_part
= match encryption_type
{
201 EncryptionType
::None
=> 0b00 << 3,
202 EncryptionType
::Scrambler
=> 0b01 << 3,
203 EncryptionType
::Aes
=> 0b10 << 3,
204 EncryptionType
::Other
=> 0b11 << 3,
206 let existing_type
= self.lsf_type();
207 let new_type
= (existing_type
& !0x0018) | type_part
;
208 self.0[12..14].copy_from_slice(&new_type
.to_be_bytes());
209 self.recalculate_crc();
212 fn recalculate_crc(&mut self) {
213 let new_crc
= crate::crc
::m17_crc(&self.0[0..28]);
214 self.0[28..30].copy_from_slice(&new_crc
.to_be_bytes());
215 debug_assert_eq
!(self.check_crc(), 0);
218 fn lsf_type(&self) -> u16 {
219 u16::from_be_bytes([self.0[12], self.0[13]])
223 #[derive(Debug, Clone, PartialEq, Eq, Default)]
224 pub struct StreamFrame
{
225 /// Which LICH segment is given in this frame, from 0 to 5 inclusive
227 /// Decoded LICH segment
228 pub lich_part
: [u8; 5],
229 /// Which frame in the transmission this is, starting from 0
230 pub frame_number
: u16,
231 /// Is this the last frame in the transmission?
232 pub end_of_stream
: bool
,
233 /// Raw application data in this frame
234 pub stream_data
: [u8; 16],
237 #[derive(Debug, Clone, PartialEq, Eq)]
238 pub struct PacketFrame
{
239 /// Application packet payload (chunk)
240 pub payload
: [u8; 25],
242 /// Frame counter, which provides different information depending on whether this is the last frame or not.
243 pub counter
: PacketFrameCounter
,
246 #[derive(Debug, Clone, PartialEq, Eq)]
247 pub enum PacketFrameCounter
{
248 /// Any packet frame that comes after the LSF and is not the final frame.
250 /// Which frame this is in the superframe, from 0 to 31 inclusive.
252 /// If a 33rd frame exists (index 32), it will be a `FinalFrame` instead.
254 /// All 25 bytes of of `payload` are filled and valid.
257 /// The final frame in the packet superframe.
259 /// The number of bytes in `payload` that are filled.
264 pub struct LichCollection([Option
<[u8; 5]>; 6]);
266 impl LichCollection
{
267 pub fn new() -> Self {
271 pub fn valid_segments(&self) -> usize {
272 self.0.iter
().filter
(|s
| s
.is
_some
()).count()
275 pub fn set_segment(&mut self, counter
: u8, part
: [u8; 5]) {
276 self.0[counter
as usize] = Some(part
);
279 pub fn try_assemble(&self) -> Option
<[u8; 30]> {
280 let mut out
= [0u8; 30];
281 for (i
, segment
) in self.0.iter
().enumerate() {
282 let Some(segment
) = segment
else {
285 for (j
, seg_val
) in segment
.iter
().enumerate() {
286 out
[i
* 5 + j
] = *seg_val
;
293 impl Default
for LichCollection
{
294 fn default() -> Self {