volt_ws_protocol/
binary_message.rs

1use crate::{
2    constant::{PAYLOAD_TYPE_KEY_EXCHANGE, PAYLOAD_VERSION},
3    log,
4};
5
6/**
7 * Sends a binary message to the Volt websocket server.
8 * The websocket protocol is binary, and the message is a binary buffer that contains the following:
9 *
10 * - 1 byte for the protocol version
11 * - 2 bytes for the length of the JSON metadata (might be 0 if there is no metadata)
12 * - N bytes for the JSON metadata
13 * - 8 bytes for the method id
14 * - 1 byte for the length of the iv
15 * - N bytes for the iv
16 * - 1 byte for the length of the token signature (might be 0 if there is no token)
17 * - N bytes for the token signature
18 * - 2 bytes for the length of the token payload (omit if there is no token)
19 * - N bytes for the token payload
20 * - 2 bytes for the length of the public key (might be 0 if there is no public key)
21 * - N bytes for the public key
22 * - N bytes for the binary payload
23 *
24 * All multi-byte values are in big-endian byte order.
25 *
26 */
27
28pub struct BinaryMessage {
29    pub version: u8,
30    pub payload_type: u8,
31    pub meta: Vec<u8>,
32    pub method_id: u64,
33    pub iv: Vec<u8>,
34    pub signature: Vec<u8>,
35    pub token: Vec<u8>,
36    pub payload: Vec<u8>,
37    pub public_key: Vec<u8>,
38    pub nonce: Vec<u8>,
39    pub public_key_signature: Vec<u8>,
40}
41
42impl BinaryMessage {
43    pub fn new_key_exchange(
44        method_id: u64,
45        meta: Vec<u8>,
46        signature: Vec<u8>,
47        token: Vec<u8>,
48    ) -> Self {
49        Self {
50            version: PAYLOAD_VERSION.clone(),
51            payload_type: PAYLOAD_TYPE_KEY_EXCHANGE.clone(),
52            meta,
53            method_id,
54            iv: Vec::<u8>::new(),
55            signature,
56            token,
57            payload: Vec::<u8>::new(),
58            public_key: Vec::<u8>::new(),
59            nonce: Vec::<u8>::new(),
60            public_key_signature: Vec::<u8>::new(),
61        }
62    }
63
64    pub fn new_payload(
65        payload_type: &u8,
66        method_id: u64,
67        meta: Vec<u8>,
68        iv: Vec<u8>,
69        payload: Vec<u8>,
70    ) -> Self {
71        Self {
72            version: PAYLOAD_VERSION.clone(),
73            payload_type: payload_type.clone(),
74            meta,
75            method_id,
76            iv,
77            signature: Vec::<u8>::new(),
78            token: Vec::<u8>::new(),
79            payload,
80            public_key: Vec::<u8>::new(),
81            nonce: Vec::<u8>::new(),
82            public_key_signature: Vec::<u8>::new(),
83        }
84    }
85
86    pub fn from_bytes(bytes: &[u8]) -> Self {
87        let mut offset = 0;
88        let version = bytes[offset];
89        offset += 1;
90
91        let payload_type = bytes[offset];
92        offset += 1;
93
94        let mut method_id_bytes = [0; 8];
95        method_id_bytes.copy_from_slice(&bytes[offset..offset + 8]);
96        let method_id = u64::from_be_bytes(method_id_bytes);
97        offset += 8;
98
99        match &payload_type {
100            PAYLOAD_TYPE_KEY_EXCHANGE => {
101                log("parsing key exchange message");
102
103                let public_key_len_bytes = bytes[offset];
104                offset += 1;
105
106                let public_key = bytes[offset..offset + public_key_len_bytes as usize].to_vec();
107                offset += public_key_len_bytes as usize;
108
109                let nonce_len = bytes[offset];
110                offset += 1;
111
112                let nonce = bytes[offset..offset + nonce_len as usize].to_vec();
113                offset += nonce_len as usize;
114
115                let signature_len = bytes[offset];
116                offset += 1;
117
118                let signature = bytes[offset..offset + signature_len as usize].to_vec();
119
120                Self {
121                    version,
122                    payload_type,
123                    meta: Vec::<u8>::new(),
124                    method_id,
125                    iv: Vec::<u8>::new(),
126                    signature: Vec::<u8>::new(),
127                    token: Vec::<u8>::new(),
128                    payload: Vec::<u8>::new(),
129                    public_key,
130                    nonce,
131                    public_key_signature: signature,
132                }
133            }
134            _ => {
135                log("parsing invoke or payload message");
136
137                let meta_len_bytes = [bytes[offset], bytes[offset + 1]];
138                let meta_len = u16::from_be_bytes(meta_len_bytes);
139                offset += 2;
140
141                let meta = bytes[offset..offset + meta_len as usize].to_vec();
142                offset += meta_len as usize;
143
144                let iv_len = bytes[offset];
145                offset += 1;
146
147                let iv = bytes[offset..offset + iv_len as usize].to_vec();
148                offset += iv_len as usize;
149
150                let payload = bytes[offset..].to_vec();
151
152                log(&format!("parsed payload length: {:?}", payload.len()));
153
154                Self {
155                    version,
156                    payload_type,
157                    meta,
158                    method_id,
159                    iv,
160                    signature: Vec::<u8>::new(),
161                    token: Vec::<u8>::new(),
162                    payload,
163                    public_key: Vec::<u8>::new(),
164                    nonce: Vec::<u8>::new(),
165                    public_key_signature: Vec::<u8>::new(),
166                }
167            }
168        }
169    }
170
171    pub fn to_bytes(&self) -> Vec<u8> {
172        let mut bytes = Vec::new();
173        bytes.push(self.version);
174        bytes.push(self.payload_type);
175        bytes.extend_from_slice(&self.method_id.to_be_bytes());
176
177        let meta_len = self.meta.len() as u16;
178        bytes.extend_from_slice(&meta_len.to_be_bytes());
179        bytes.extend_from_slice(&self.meta);
180
181        match &self.payload_type {
182            PAYLOAD_TYPE_KEY_EXCHANGE => {
183                let signature_len = self.signature.len() as u8;
184                bytes.push(signature_len);
185                bytes.extend_from_slice(&self.signature);
186
187                let token_len = self.token.len() as u16;
188                bytes.extend_from_slice(&token_len.to_be_bytes());
189                bytes.extend_from_slice(&self.token);
190            }
191            _ => {
192                let iv_len = self.iv.len() as u8;
193                bytes.push(iv_len);
194                bytes.extend_from_slice(&self.iv);
195                bytes.extend_from_slice(&self.payload);
196            }
197        }
198
199        bytes
200    }
201}