]>
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)]
56 pub fn as_proto(&self) -> ([u8; 4], usize) {
58 PacketType
::Raw
=> ([0, 0, 0, 0], 1),
59 PacketType
::Ax25
=> ([1, 0, 0, 0], 1),
60 PacketType
::Aprs
=> ([2, 0, 0, 0], 1),
61 PacketType
::SixLowPan
=> ([3, 0, 0, 0], 1),
62 PacketType
::Ipv4
=> ([4, 0, 0, 0], 1),
63 PacketType
::Sms
=> ([5, 0, 0, 0], 1),
64 PacketType
::Winlink
=> ([6, 0, 0, 0], 1),
65 PacketType
::Other(c
) => {
66 let mut buf
= [0u8; 4];
67 let s
= c
.encode_utf8(&mut buf
);
74 pub fn from_proto(&self, buf
: &[u8]) -> Option
<PacketType
> {
77 .and_then(|chunk
| chunk
.valid().chars().next())
78 .map(|c
| match c
as u32 {
79 0x00 => PacketType
::Raw
,
80 0x01 => PacketType
::Ax25
,
81 0x02 => PacketType
::Aprs
,
82 0x03 => PacketType
::SixLowPan
,
83 0x04 => PacketType
::Ipv4
,
84 0x05 => PacketType
::Sms
,
85 0x06 => PacketType
::Winlink
,
86 _
=> PacketType
::Other(c
),
91 #[derive(Debug, Clone, PartialEq, Eq)]
92 pub struct LsfFrame(pub [u8; 30]);
95 pub fn crc(&self) -> u16 {
96 crate::crc
::m17_crc(&self.0)
99 pub fn destination(&self) -> Address
{
100 crate::address
::decode_address((&self.0[0..6]).try_into().unwrap
())
103 pub fn source(&self) -> Address
{
104 crate::address
::decode_address((&self.0[6..12]).try_into().unwrap
())
107 pub fn mode(&self) -> Mode
{
108 if self.0[12] & 0x01 > 0 {
115 pub fn data_type(&self) -> DataType
{
116 match (self.0[12] >> 1) & 0x03 {
117 0b00 => DataType
::Reserved
,
118 0b01 => DataType
::Data
,
119 0b10 => DataType
::Voice
,
120 0b11 => DataType
::VoiceAndData
,
125 pub fn encryption_type(&self) -> EncryptionType
{
126 match (self.0[12] >> 3) & 0x03 {
127 0b00 => EncryptionType
::None
,
128 0b01 => EncryptionType
::Scrambler
,
129 0b10 => EncryptionType
::Aes
,
130 0b11 => EncryptionType
::Other
,
135 pub fn channel_access_number(&self) -> u8 {
136 (self.0[12] >> 7) & 0x0f
139 pub fn meta(&self) -> [u8; 14] {
140 self.0[14..28].try_into().unwrap
()
144 #[derive(Debug, Clone, PartialEq, Eq)]
145 pub struct StreamFrame
{
146 /// Which LICH segment is given in this frame, from 0 to 5 inclusive
148 /// Decoded LICH segment
149 pub lich_part
: [u8; 5],
150 /// Which frame in the transmission this is, starting from 0
151 pub frame_number
: u16,
152 /// Is this the last frame in the transmission?
153 pub end_of_stream
: bool
,
154 /// Raw application data in this frame
155 pub stream_data
: [u8; 16],
158 pub struct LichCollection([Option
<[u8; 5]>; 6]);
160 impl LichCollection
{
161 pub fn new() -> Self {
165 pub fn valid_segments(&self) -> usize {
166 self.0.iter
().filter
(|s
| s
.is
_some
()).count()
169 pub fn set_segment(&mut self, counter
: u8, part
: [u8; 5]) {
170 self.0[counter
as usize] = Some(part
);
173 pub fn try_assemble(&self) -> Option
<[u8; 30]> {
174 let mut out
= [0u8; 30];
175 for (i
, segment
) in self.0.iter
().enumerate() {
176 let Some(segment
) = segment
else {
179 for (j
, seg_val
) in segment
.iter
().enumerate() {
180 out
[i
* 5 + j
] = *seg_val
;
187 impl Default
for LichCollection
{
188 fn default() -> Self {