dstar_gateway_core/codec/dextra/
consts.rs

1//! `DExtra` wire-format constants.
2//!
3//! Every magic byte and every duration here is annotated with the
4//! exact line in the GPL reference implementation it was derived from.
5
6use std::time::Duration;
7
8/// Default UDP port for `DExtra` reflectors.
9///
10/// Reference: `ircDDBGateway/Common/DStarDefines.h:116` (`DEXTRA_PORT = 30001U`).
11pub const DEFAULT_PORT: u16 = 30001;
12
13/// `DExtra` keepalive interval.
14///
15/// Reference: `ircDDBGateway/Common/DExtraHandler.cpp:51`
16/// (`m_pollTimer(1000U, 10U)` = 10 seconds).
17pub const KEEPALIVE_INTERVAL: Duration = Duration::from_secs(10);
18
19/// `DExtra` keepalive inactivity timeout.
20///
21/// Reference: `ircDDBGateway/Common/DExtraHandler.cpp:52`
22/// (`m_pollInactivityTimer(1000U, 60U)` = 60 seconds).
23pub const KEEPALIVE_INACTIVITY_TIMEOUT: Duration = Duration::from_secs(60);
24
25/// `DExtra` voice inactivity timeout — synthesize `VoiceEnd` after this.
26pub const VOICE_INACTIVITY_TIMEOUT: Duration = Duration::from_secs(2);
27
28/// `DExtra` disconnect ACK timeout — give up waiting for unlink reply.
29pub const DISCONNECT_TIMEOUT: Duration = Duration::from_secs(2);
30
31/// Number of times the connect packet is retransmitted.
32pub const CONNECT_RETX: u8 = 2;
33
34/// Number of times the voice header is retransmitted.
35pub const HEADER_RETX: u8 = 5;
36
37/// DSVT magic at offsets `[0..4]` of every `DExtra` voice packet.
38///
39/// **Note**: unlike `DPlus`, `DExtra` has NO 2-byte length prefix —
40/// DSVT magic is at offset 0, not offset 2.
41pub const DSVT_MAGIC: [u8; 4] = *b"DSVT";
42
43/// Connect (LINK/UNLINK) packet length (11 bytes).
44///
45/// Reference: `ircDDBGateway/Common/ConnectData.cpp:283-300` (return 11U).
46pub const CONNECT_LEN: usize = 11;
47
48/// Connect reply length (14 bytes: 11 + 3 tag).
49///
50/// Reference: `ircDDBGateway/Common/ConnectData.cpp:302-316` (return 14U).
51pub const CONNECT_REPLY_LEN: usize = 14;
52
53/// Poll packet length (9 bytes).
54///
55/// Reference: `ircDDBGateway/Common/PollData.cpp:155-168` (return 9U).
56pub const POLL_LEN: usize = 9;
57
58/// Voice header length (56 bytes).
59///
60/// Reference: `ircDDBGateway/Common/HeaderData.cpp:590-635` (return 56U).
61pub const VOICE_HEADER_LEN: usize = 56;
62
63/// Voice data length (27 bytes).
64///
65/// Reference: `ircDDBGateway/Common/AMBEData.cpp:317-345` (return 15+12).
66pub const VOICE_DATA_LEN: usize = 27;
67
68/// Voice EOT length (27 bytes, same as data but seq has 0x40 bit).
69pub const VOICE_EOT_LEN: usize = 27;
70
71/// ACK tag at offsets `[10..13]` of a 14-byte connect reply,
72/// followed by `0x00` at byte `[13]`.
73///
74/// Reference: `ircDDBGateway/Common/ConnectData.cpp:302-308`
75/// (`data[LONG_CALLSIGN_LENGTH + 2U] = 'A';` — i.e. `data[10]`).
76pub const CONNECT_ACK_TAG: [u8; 3] = *b"ACK";
77
78/// NAK tag at offsets `[10..13]` of a 14-byte connect reply,
79/// followed by `0x00` at byte `[13]`.
80///
81/// Reference: `ircDDBGateway/Common/ConnectData.cpp:310-316`.
82pub const CONNECT_NAK_TAG: [u8; 3] = *b"NAK";
83
84#[cfg(test)]
85mod tests {
86    use super::*;
87
88    #[test]
89    fn keepalive_interval_is_ten_seconds() {
90        assert_eq!(KEEPALIVE_INTERVAL, Duration::from_secs(10));
91    }
92
93    #[test]
94    fn default_port_is_30001() {
95        assert_eq!(DEFAULT_PORT, 30001);
96    }
97
98    #[test]
99    fn voice_header_is_56_bytes() {
100        assert_eq!(VOICE_HEADER_LEN, 56);
101    }
102
103    #[test]
104    fn voice_data_is_27_bytes() {
105        assert_eq!(VOICE_DATA_LEN, 27);
106    }
107
108    #[test]
109    fn ack_tag_is_ack() {
110        assert_eq!(&CONNECT_ACK_TAG, b"ACK");
111    }
112
113    #[test]
114    fn nak_tag_is_nak() {
115        assert_eq!(&CONNECT_NAK_TAG, b"NAK");
116    }
117}