1use crate::{Commit, Error, Result, BETA_VERSION, CURRENT_VERSION};
4use bramble_crypto::PublicKey;
5use bramble_data::{custom::array_as_bytes, Deserializer, Object, ObjectSerializer, Serializer};
6use serde::{de, Deserialize, Serialize};
7use std::{
8 convert::{TryFrom, TryInto},
9 io::{Cursor, Read, Write},
10 result, slice,
11};
12
13#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
15#[serde(into = "PayloadSerial", try_from = "PayloadSerial")]
16pub struct Payload {
17 commit: Commit,
18 transports: Vec<Descriptor>,
19}
20
21#[derive(Serialize, Deserialize)]
22#[serde(transparent)]
23struct PayloadSerial(Vec<PayloadEntry>);
24
25#[derive(Serialize, Deserialize)]
26#[serde(untagged)]
27enum PayloadEntry {
28 Commit(Commit),
29 Transport(Descriptor),
30}
31
32impl From<Payload> for PayloadSerial {
33 fn from(p: Payload) -> Self {
34 let mut v = vec![PayloadEntry::Commit(p.commit)];
35 v.extend(p.transports.into_iter().map(PayloadEntry::Transport));
36 Self(v)
37 }
38}
39
40impl TryFrom<PayloadSerial> for Payload {
41 type Error = Error;
42
43 fn try_from(p: PayloadSerial) -> Result<Self> {
44 let mut iter = p.0.into_iter();
45 let commit = match iter.next() {
46 Some(PayloadEntry::Commit(commit)) => commit,
47 Some(_) => return Err(Error::InvalidCommitment),
48 None => return Err(Error::EmptyPayload),
49 };
50 let transports = iter
51 .map(|e| match e {
52 PayloadEntry::Transport(d) => Ok(d),
53 _ => Err(Error::InvalidTransport),
54 })
55 .collect::<Result<_>>()?;
56 Ok(Self { commit, transports })
57 }
58}
59
60impl Payload {
61 pub fn new(pk: &PublicKey, transports: Vec<Descriptor>) -> Self {
63 let commit = Commit::derive(pk);
64 Self { commit, transports }
65 }
66
67 pub fn read_from<R: Read>(r: &mut R) -> Result<Self> {
69 let mut version = 0;
70 r.read_exact(slice::from_mut(&mut version))?;
71 if version == BETA_VERSION {
72 return Err(Error::BetaVersion);
73 }
74 if version < CURRENT_VERSION {
75 return Err(Error::OlderVersion);
76 }
77 if version > CURRENT_VERSION {
78 return Err(Error::NewerVersion);
79 }
80 let mut de = Deserializer::new(r);
81 let value = Self::deserialize(&mut de)?;
82 de.end()?;
83 Ok(value)
84 }
85
86 pub fn from_bytes(mut slice: &[u8]) -> Result<Self> {
88 Self::read_from(&mut slice)
89 }
90
91 pub fn write_to<W: Write>(&self, w: &mut W) -> Result<()> {
93 w.write_all(&[CURRENT_VERSION])?;
94 let mut ser = Serializer::new(w);
95 self.serialize(&mut ser)?;
96 Ok(())
97 }
98
99 pub fn to_bytes(&self) -> Vec<u8> {
101 let mut c = Cursor::new(vec![]);
102 self.write_to(&mut c).expect("writing to vec failed");
103 c.into_inner()
104 }
105
106 pub fn commit(&self) -> Commit {
108 self.commit
109 }
110
111 pub fn transports(&self) -> &[Descriptor] {
113 &self.transports
114 }
115}
116
117#[derive(Clone, Debug, PartialEq, Serialize)]
119#[serde(untagged)]
120pub enum Descriptor {
121 Bluetooth(BluetoothDescriptor),
123 Lan(LanDescriptor),
125 Unknown(UnknownDescriptor),
127}
128
129impl Descriptor {
130 pub fn bluetooth() -> Self {
132 Self::Bluetooth(BluetoothDescriptor::new())
133 }
134
135 pub fn bluetooth_address(address: [u8; BLUETOOTH_ADDRESS_LEN]) -> Self {
137 Self::Bluetooth(BluetoothDescriptor::with_address(address))
138 }
139
140 pub fn lan(address: [u8; IPV4_ADDRESS_LEN], port: u16) -> Self {
142 Self::Lan(LanDescriptor::new(address, port))
143 }
144
145 pub fn unknown(id: i64, data: Vec<Object>) -> Self {
147 Self::Unknown(UnknownDescriptor::new(id, data))
148 }
149}
150
151#[derive(Clone, Default, Debug, PartialEq, Eq, Serialize, Deserialize)]
153#[serde(into = "UnknownDescriptor", try_from = "UnknownDescriptor")]
154pub struct BluetoothDescriptor {
155 address: Option<[u8; BLUETOOTH_ADDRESS_LEN]>,
156}
157
158impl BluetoothDescriptor {
159 pub fn new() -> Self {
161 Self { address: None }
162 }
163
164 pub fn with_address(address: [u8; BLUETOOTH_ADDRESS_LEN]) -> Self {
166 Self {
167 address: Some(address),
168 }
169 }
170
171 pub fn address(&self) -> Option<[u8; BLUETOOTH_ADDRESS_LEN]> {
173 self.address
174 }
175}
176
177impl From<BluetoothDescriptor> for UnknownDescriptor {
178 fn from(d: BluetoothDescriptor) -> Self {
179 match d.address {
180 Some(address) => {
181 let address_obj = array_as_bytes::serialize(&address, ObjectSerializer)
182 .expect("failed to convert bluetooth address to object");
183 Self::new(BLUETOOTH_ID, vec![address_obj])
184 }
185 None => Self::new(BLUETOOTH_ID, vec![]),
186 }
187 }
188}
189
190impl TryFrom<UnknownDescriptor> for BluetoothDescriptor {
191 type Error = Error;
192
193 fn try_from(d: UnknownDescriptor) -> Result<Self> {
194 if d.id != BLUETOOTH_ID {
195 return Err(Error::InvalidTransport);
196 }
197
198 match d.data {
199 Object::List(l) if l.is_empty() => Ok(Self::new()),
200 Object::List(mut l) if l.len() == 1 => Ok(Self::with_address(
201 array_as_bytes::deserialize(l.remove(0))?,
202 )),
203 _ => Err(Error::InvalidTransport),
204 }
205 }
206}
207
208#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
210#[serde(into = "UnknownDescriptor", try_from = "UnknownDescriptor")]
211pub struct LanDescriptor {
212 id: i64,
213 address: [u8; IPV4_ADDRESS_LEN],
214 port: u16,
215}
216
217impl LanDescriptor {
218 pub fn new(address: [u8; IPV4_ADDRESS_LEN], port: u16) -> Self {
220 Self {
221 id: LAN_ID,
222 address,
223 port,
224 }
225 }
226
227 pub fn address(&self) -> [u8; IPV4_ADDRESS_LEN] {
229 self.address
230 }
231
232 pub fn port(&self) -> u16 {
234 self.port
235 }
236}
237
238impl From<LanDescriptor> for UnknownDescriptor {
239 fn from(d: LanDescriptor) -> Self {
240 let address_obj = array_as_bytes::serialize(&d.address, ObjectSerializer)
241 .expect("failed to convert IPv4 address to object");
242 let port_obj = d
243 .port
244 .serialize(ObjectSerializer)
245 .expect("failed to convert IPv4 address to object");
246 Self::new(LAN_ID, vec![address_obj, port_obj])
247 }
248}
249
250impl TryFrom<UnknownDescriptor> for LanDescriptor {
251 type Error = Error;
252
253 fn try_from(d: UnknownDescriptor) -> Result<Self> {
254 if d.id != LAN_ID {
255 return Err(Error::InvalidTransport);
256 }
257
258 let mut list = d.data.to_list()?;
259 if list.len() != 2 {
260 return Err(Error::InvalidTransport);
261 }
262 let port_obj = list.remove(1);
263 let address_obj = list.remove(0);
264 Ok(Self {
265 id: LAN_ID,
266 address: array_as_bytes::deserialize(address_obj)?,
267 port: u16::deserialize(port_obj)?,
268 })
269 }
270}
271
272#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
274#[serde(into = "UnknownDescriptorSerial", try_from = "UnknownDescriptorSerial")]
275pub struct UnknownDescriptor {
276 id: i64,
277 data: Object,
278}
279
280impl UnknownDescriptor {
281 pub fn new(id: i64, data: Vec<Object>) -> Self {
283 Self {
284 id,
285 data: Object::List(data),
286 }
287 }
288
289 pub fn id(&self) -> i64 {
291 self.id
292 }
293
294 pub fn data(&self) -> &Object {
296 &self.data
297 }
298}
299
300#[derive(Serialize, Deserialize)]
301#[serde(transparent)]
302struct UnknownDescriptorSerial(Vec<Object>);
303
304impl From<UnknownDescriptor> for UnknownDescriptorSerial {
305 fn from(d: UnknownDescriptor) -> Self {
306 let mut v = vec![Object::Integer(d.id)];
307 match d.data {
308 Object::List(l) => v.extend(l.into_iter()),
309 _ => unreachable!(),
310 }
311 Self(v)
312 }
313}
314
315impl TryFrom<UnknownDescriptorSerial> for UnknownDescriptor {
316 type Error = Error;
317
318 fn try_from(mut d: UnknownDescriptorSerial) -> Result<Self> {
319 let id = d.0.remove(0).to_integer()?;
320 Ok(Self {
321 id,
322 data: Object::List(d.0),
323 })
324 }
325}
326
327impl<'de> Deserialize<'de> for Descriptor {
328 fn deserialize<D>(de: D) -> result::Result<Self, D::Error>
329 where
330 D: de::Deserializer<'de>,
331 {
332 let error_map =
333 |_| de::Error::invalid_type(de::Unexpected::Other("not bluetooth"), &"bluetooth");
334 let unknown = UnknownDescriptor::deserialize(de)?;
335 Ok(match unknown.id {
336 BLUETOOTH_ID => Descriptor::Bluetooth(unknown.try_into().map_err(error_map)?),
337 LAN_ID => Descriptor::Lan(unknown.try_into().map_err(error_map)?),
338 _ => Descriptor::Unknown(unknown),
339 })
340 }
341}
342
343const BLUETOOTH_ID: i64 = 0;
344const LAN_ID: i64 = 1;
345
346const BLUETOOTH_ADDRESS_LEN: usize = 6;
347const IPV4_ADDRESS_LEN: usize = 4;
348
349#[cfg(test)]
350mod test {
351 use super::*;
352 use bramble_data::{from_object, to_object};
353 use hex_literal::hex;
354
355 #[test]
356 fn payload_read_rejects_older_versions() {
357 let mut buf: &[u8] = &hex!("03");
358 let e = Payload::read_from(&mut buf);
359 assert!(e.is_err());
360 let e = e.unwrap_err();
361 assert!(matches!(e, Error::OlderVersion));
362 }
363
364 #[test]
365 fn payload_read_rejects_beta_version() {
366 let mut buf: &[u8] = &hex!("59");
367 let e = Payload::read_from(&mut buf);
368 assert!(e.is_err());
369 let e = e.unwrap_err();
370 assert!(matches!(e, Error::BetaVersion));
371 }
372
373 #[test]
374 fn payload_read_rejects_newer_version() {
375 let mut buf: &[u8] = &hex!("05");
376 let e = Payload::read_from(&mut buf);
377 assert!(e.is_err());
378 let e = e.unwrap_err();
379 assert!(matches!(e, Error::NewerVersion));
380 }
381
382 #[test]
383 fn payload_read_rejects_non_list() {
384 let mut buf: &[u8] = &hex!("04 2180");
385 let e = Payload::read_from(&mut buf);
386 assert!(e.is_err());
387 }
388
389 #[test]
390 fn payload_read_rejects_empty_list() {
391 let mut buf: &[u8] = &hex!("04 6080");
392 let e = Payload::read_from(&mut buf);
393 assert!(e.is_err());
394 }
395
396 #[test]
397 fn payload_read_rejects_data_after_list() {
398 let mut buf: &[u8] = &hex!("04 60 5110000102030405060708090A0B0C0D0E0F 60 21FF 80 80 00");
399 let e = Payload::read_from(&mut buf);
400 assert!(e.is_err());
401 }
402
403 #[test]
404 fn payload_read_rejects_short_commit() {
405 let mut buf: &[u8] = &hex!("04 60 510F000102030405060708090A0B0C0D0E 60 21FF 80 80");
406 let e = Payload::read_from(&mut buf);
407 assert!(e.is_err());
408 }
409
410 #[test]
411 fn payload_read_rejects_long_commit() {
412 let mut buf: &[u8] = &hex!("04 60 5111000102030405060708090A0B0C0D0E0F10 60 21FF 80 80");
413 let e = Payload::read_from(&mut buf);
414 assert!(e.is_err());
415 }
416
417 #[test]
418 fn payload_read_accepts_without_transports() {
419 let expected = Commit::from(hex!("000102030405060708090A0B0C0D0E0F"));
420 let mut buf: &[u8] = &hex!("04 60 5110000102030405060708090A0B0C0D0E0F 80");
421 let p = Payload::read_from(&mut buf);
422 assert!(p.is_ok());
423 let p = p.unwrap();
424 assert_eq!(p.commit(), expected);
425 assert!(p.transports().is_empty());
426 }
427
428 #[test]
429 fn payload_read_rejects_bluetooth_with_bad_address() {
430 let mut buf: &[u8] =
431 &hex!("04 60 5110000102030405060708090A0B0C0D0E0F 60 2100 220101 80 80");
432 let e = Payload::read_from(&mut buf);
433 assert!(e.is_err());
434 }
435
436 #[test]
437 fn payload_read_accepts_bluetooth_without_address() {
438 let expected = Commit::from(hex!("000102030405060708090A0B0C0D0E0F"));
439 let mut buf: &[u8] = &hex!("04 60 5110000102030405060708090A0B0C0D0E0F 60 2100 80 80");
440 let p = Payload::read_from(&mut buf);
441 assert!(p.is_ok());
442 let p = p.unwrap();
443 assert_eq!(p.commit(), expected);
444 assert_eq!(p.transports().len(), 1);
445 assert_eq!(p.transports()[0], Descriptor::bluetooth());
446 }
447
448 #[test]
449 fn payload_read_accepts_bluetooth_with_address() {
450 let expected = Commit::from(hex!("000102030405060708090A0B0C0D0E0F"));
451 let mut buf: &[u8] =
452 &hex!("04 60 5110000102030405060708090A0B0C0D0E0F 60 2100 5106000102030405 80 80");
453 let p = Payload::read_from(&mut buf);
454 assert!(p.is_ok());
455 let p = p.unwrap();
456 assert_eq!(p.commit(), expected);
457 assert_eq!(p.transports().len(), 1);
458 assert_eq!(
459 p.transports()[0],
460 Descriptor::bluetooth_address([0, 1, 2, 3, 4, 5])
461 );
462 }
463
464 #[test]
465 fn payload_read_rejects_lan_with_bad_address() {
466 let mut buf: &[u8] =
467 &hex!("04 60 5110000102030405060708090A0B0C0D0E0F 60 2101 220101 80 80");
468 let e = Payload::read_from(&mut buf);
469 assert!(e.is_err());
470 }
471
472 #[test]
473 fn payload_read_rejects_lan_without_address() {
474 let mut buf: &[u8] = &hex!("04 60 5110000102030405060708090A0B0C0D0E0F 60 2101 80 80");
475 let e = Payload::read_from(&mut buf);
476 assert!(e.is_err());
477 }
478
479 #[test]
480 fn payload_read_rejects_lan_without_port() {
481 let mut buf: &[u8] =
482 &hex!("04 60 5110000102030405060708090A0B0C0D0E0F 60 2101 510401020304 80 80");
483 let e = Payload::read_from(&mut buf);
484 assert!(e.is_err());
485 }
486
487 #[test]
488 fn payload_read_accepts_lan_with_address_and_port() {
489 let expected = Commit::from(hex!("000102030405060708090A0B0C0D0E0F"));
490 let mut buf: &[u8] =
491 &hex!("04 60 5110000102030405060708090A0B0C0D0E0F 60 2101 510401020304 221020 80 80");
492 let p = Payload::read_from(&mut buf);
493 assert!(p.is_ok());
494 let p = p.unwrap();
495 assert_eq!(p.commit(), expected);
496 assert_eq!(p.transports().len(), 1);
497 assert_eq!(p.transports()[0], Descriptor::lan([1, 2, 3, 4], 4128));
498 }
499
500 #[test]
501 fn payload_read_accepts_unknown_transports() {
502 let expected = Commit::from(hex!("000102030405060708090A0B0C0D0E0F"));
503 let mut buf: &[u8] =
504 &hex!("04 60 5110000102030405060708090A0B0C0D0E0F 60 2159 2101 2102 80 80");
505 let p = Payload::read_from(&mut buf);
506 assert!(p.is_ok());
507 let p = p.unwrap();
508 assert_eq!(p.commit(), expected);
509 assert_eq!(p.transports().len(), 1);
510 assert_eq!(
511 p.transports()[0],
512 Descriptor::unknown(89, vec![Object::Integer(1), Object::Integer(2)])
513 );
514 }
515
516 #[test]
517 fn payload_read_accepts_multiple_transports() {
518 let expected = Commit::from(hex!("000102030405060708090A0B0C0D0E0F"));
519 let mut buf: &[u8] =
520 &hex!("04 60 5110000102030405060708090A0B0C0D0E0F 60 2101 510401020304 221020 80 60 2100 80 60 2159 220000 80 80");
521 let p = Payload::read_from(&mut buf);
522 assert!(p.is_ok());
523 let p = p.unwrap();
524 assert_eq!(p.commit(), expected);
525 assert_eq!(p.transports().len(), 3);
526 assert_eq!(p.transports()[0], Descriptor::lan([1, 2, 3, 4], 4128));
527 assert_eq!(p.transports()[1], Descriptor::bluetooth());
528 assert_eq!(
529 p.transports()[2],
530 Descriptor::unknown(89, vec![Object::Integer(0)])
531 );
532 }
533
534 #[test]
535 fn payload_to_bytes() {
536 let p = Payload {
537 commit: Commit::from(hex!("000102030405060708090A0B0C0D0E0F")),
538 transports: vec![
539 Descriptor::lan([1, 2, 3, 4], 4128),
540 Descriptor::bluetooth(),
541 Descriptor::bluetooth_address([1, 2, 3, 4, 5, 6]),
542 Descriptor::unknown(89, vec![Object::Integer(17)]),
543 ],
544 };
545 let expected = hex!("04 60 5110000102030405060708090A0B0C0D0E0F 60 2101 510401020304 221020 80 60 2100 80 60 2100 5106010203040506 80 60 2159 2111 80 80");
546 assert_eq!(p.to_bytes(), expected);
547 }
548
549 #[test]
550 fn payload_roundtrips() {
551 let input = Payload {
552 commit: Commit::from(hex!("000102030405060708090A0B0C0D0E0F")),
553 transports: vec![
554 Descriptor::lan([1, 2, 3, 4], 4128),
555 Descriptor::bluetooth(),
556 Descriptor::bluetooth_address([1, 2, 3, 4, 5, 6]),
557 Descriptor::unknown(89, vec![Object::Integer(17)]),
558 ],
559 };
560 let obj = to_object(input.clone()).unwrap();
561 let output = from_object(obj).unwrap();
562
563 assert_eq!(input, output);
564 }
565}
566
567