corevpn_protocol/
opcode.rs1use crate::{ProtocolError, Result};
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9#[repr(u8)]
10pub enum OpCode {
11 ControlV1 = 4,
13
14 AckV1 = 5,
16
17 DataV1 = 6,
19
20 HardResetClientV2 = 7,
22
23 HardResetServerV2 = 8,
25
26 SoftResetV1 = 3,
28
29 DataV2 = 9,
31
32 HardResetClientV3 = 10,
34
35 ControlWkcV1 = 11,
37}
38
39impl OpCode {
40 pub fn from_byte(byte: u8) -> Result<Self> {
42 let opcode = byte >> 3;
43 match opcode {
44 3 => Ok(OpCode::SoftResetV1),
45 4 => Ok(OpCode::ControlV1),
46 5 => Ok(OpCode::AckV1),
47 6 => Ok(OpCode::DataV1),
48 7 => Ok(OpCode::HardResetClientV2),
49 8 => Ok(OpCode::HardResetServerV2),
50 9 => Ok(OpCode::DataV2),
51 10 => Ok(OpCode::HardResetClientV3),
52 11 => Ok(OpCode::ControlWkcV1),
53 _ => Err(ProtocolError::UnknownOpcode(opcode)),
54 }
55 }
56
57 pub fn to_byte(self, key_id: KeyId) -> u8 {
59 ((self as u8) << 3) | (key_id.0 & 0x07)
60 }
61
62 pub fn is_control(&self) -> bool {
64 matches!(
65 self,
66 OpCode::ControlV1
67 | OpCode::AckV1
68 | OpCode::HardResetClientV2
69 | OpCode::HardResetServerV2
70 | OpCode::SoftResetV1
71 | OpCode::HardResetClientV3
72 | OpCode::ControlWkcV1
73 )
74 }
75
76 pub fn is_data(&self) -> bool {
78 matches!(self, OpCode::DataV1 | OpCode::DataV2)
79 }
80
81 pub fn is_hard_reset(&self) -> bool {
83 matches!(
84 self,
85 OpCode::HardResetClientV2 | OpCode::HardResetServerV2 | OpCode::HardResetClientV3
86 )
87 }
88}
89
90impl std::fmt::Display for OpCode {
91 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
92 match self {
93 OpCode::ControlV1 => write!(f, "P_CONTROL_V1"),
94 OpCode::AckV1 => write!(f, "P_ACK_V1"),
95 OpCode::DataV1 => write!(f, "P_DATA_V1"),
96 OpCode::HardResetClientV2 => write!(f, "P_CONTROL_HARD_RESET_CLIENT_V2"),
97 OpCode::HardResetServerV2 => write!(f, "P_CONTROL_HARD_RESET_SERVER_V2"),
98 OpCode::SoftResetV1 => write!(f, "P_CONTROL_SOFT_RESET_V1"),
99 OpCode::DataV2 => write!(f, "P_DATA_V2"),
100 OpCode::HardResetClientV3 => write!(f, "P_CONTROL_HARD_RESET_CLIENT_V3"),
101 OpCode::ControlWkcV1 => write!(f, "P_CONTROL_WKC_V1"),
102 }
103 }
104}
105
106#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
111pub struct KeyId(pub u8);
112
113impl KeyId {
114 pub fn new(id: u8) -> Self {
116 Self(id & 0x07)
117 }
118
119 pub fn from_byte(byte: u8) -> Self {
121 Self(byte & 0x07)
122 }
123
124 pub fn next(&self) -> Self {
126 Self((self.0 + 1) & 0x07)
127 }
128}
129
130#[cfg(test)]
131mod tests {
132 use super::*;
133
134 #[test]
135 fn test_opcode_roundtrip() {
136 let key_id = KeyId::new(3);
137
138 for opcode in [
139 OpCode::ControlV1,
140 OpCode::AckV1,
141 OpCode::DataV1,
142 OpCode::HardResetClientV2,
143 OpCode::HardResetServerV2,
144 OpCode::DataV2,
145 ] {
146 let byte = opcode.to_byte(key_id);
147 let parsed = OpCode::from_byte(byte).unwrap();
148 let parsed_key_id = KeyId::from_byte(byte);
149
150 assert_eq!(opcode, parsed);
151 assert_eq!(key_id, parsed_key_id);
152 }
153 }
154
155 #[test]
156 fn test_key_id_wrap() {
157 let key_id = KeyId::new(7);
158 assert_eq!(key_id.next(), KeyId::new(0));
159 }
160}