ratman_netmod/
seq.rs

1//! Sequence handling module
2
3use crate::{Error, Frame, Recipient};
4use identity::Identity;
5use {
6    std::hash::{BuildHasher, Hasher},
7    twox_hash::{RandomXxHashBuilder64 as RXHash64, XxHash64},
8};
9
10/// A unique identifier to represents a sequence of frames
11pub type SeqId = Identity;
12
13/// An XxHash signature and initialisation seed
14#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
15pub struct XxSignature {
16    sig: u64,
17    seed: u64,
18}
19
20impl XxSignature {
21    fn new(data: &Vec<u8>) -> Self {
22        let mut hasher = RXHash64::default().build_hasher();
23        hasher.write(data);
24        Self {
25            sig: hasher.finish(),
26            seed: hasher.seed(),
27        }
28    }
29
30    fn verify(&self, data: &Vec<u8>) -> bool {
31        let mut hasher = XxHash64::with_seed(self.seed);
32        hasher.write(data);
33        hasher.finish() == self.sig
34    }
35}
36
37/// Encoded signature information related to a data sequence
38///
39/// When a large chunk of data is split across a `Frame` set,
40/// signature hashes are used to verify data integrity, as well as
41/// sequence ordering.  The "Sequence ID" itself can be used to
42/// re-order frames received out of order, as well as verifying that a
43/// `Frame` was transmitted without error.
44///
45/// Check the crate documentation for more details.
46#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
47pub struct SeqData {
48    /// Frame number in sequence
49    pub num: u32,
50    /// A hash signature of the payload
51    pub sig: XxSignature,
52    /// Global frame sequence ID
53    pub seqid: SeqId,
54    /// Next sequenced Frame SIG
55    pub next: Option<u64>,
56}
57
58/// Utility wrapping around `Vec<Frame>` with `SeqId` initialisation.
59///
60/// This type implements a builder, which is initialised with header
61/// data, then filled with various sliced payloads, and then made into
62/// a frame sequence, as outlined in the root netmod docs.
63pub struct SeqBuilder {
64    #[doc(hidden)]
65    pub seqid: SeqId,
66    #[doc(hidden)]
67    pub sender: Identity,
68    #[doc(hidden)]
69    pub recp: Recipient,
70    #[doc(hidden)]
71    pub data: Vec<Vec<u8>>,
72}
73
74impl SeqBuilder {
75    /// Initialise a Sequence builder
76    pub fn new(sender: Identity, recp: Recipient, seqid: SeqId) -> Self {
77        Self {
78            sender,
79            recp,
80            seqid,
81            data: vec![],
82        }
83    }
84
85    /// Add a slice of payload to the sequence set
86    pub fn add(mut self, data: Vec<u8>) -> Self {
87        self.data.push(data);
88        self
89    }
90
91    /// Consume the builder into a set of frames
92    pub fn build(self) -> Vec<Frame> {
93        let seqid = self.seqid;
94        let sender = self.sender;
95        let recipient = self.recp;
96        let signed = self
97            .data
98            .into_iter()
99            .map(|d| (XxSignature::new(&d), d))
100            .collect::<Vec<_>>();
101
102        (0..signed.len())
103            .enumerate()
104            .map(|(num, i)| match (signed.get(i), signed.get(i + 1)) {
105                (
106                    Some((ref sig, data)),
107                    Some((
108                        XxSignature {
109                            sig: ref next,
110                            seed: _,
111                        },
112                        _,
113                    )),
114                ) => (
115                    SeqData {
116                        num: num as u32,
117                        seqid,
118                        sig: *sig,
119                        next: Some(*next),
120                    },
121                    data,
122                ),
123                (Some((ref sig, data)), None) => (
124                    SeqData {
125                        num: num as u32,
126                        seqid,
127                        sig: *sig,
128                        next: None,
129                    },
130                    data,
131                ),
132                _ => unreachable!(),
133            })
134            .map(|(seq, data)| Frame {
135                sender,
136                recipient,
137                seq,
138                payload: data.to_vec(),
139            })
140            .collect()
141    }
142
143    /// Take a sequence of frames and turn it into a complete payload
144    ///
145    /// This function assumes a complete set of frame that has
146    /// previously been sorted along the `seq.num` metric.
147    pub fn restore(buf: &mut Vec<Frame>) -> Vec<u8> {
148        // FIXME: `windows` are weird when there's less than n Items.
149        // This hack just pretends that there are two.  We also
150        // communicate to the fold that we should drop the last frame
151        // in the set again.  A much better approach would be to use a
152        // windowing iterator that doesn't need to copy and can handle
153        // this situation more gracefully
154        //
155        // ~k
156        let fake = if buf.len() == 1 {
157            buf.push(buf.get(0).unwrap().clone());
158            true
159        } else {
160            false
161        };
162
163        let wins = buf.windows(2);
164        let len = wins.len();
165
166        let r: Result<Vec<u8>, Error> = wins.enumerate().into_iter().fold(
167            Ok(Vec::with_capacity(buf.len())),
168            |mut res, (i, win)| {
169                let last = i == (len - 1);
170                let a = &win[0];
171                let seqa = &a.seq;
172                let b = &win[1];
173                let seqb = &b.seq;
174
175                if !seqa.sig.verify(&a.payload) {
176                    res = Err(Error::DesequenceFault);
177                }
178
179                if last && !seqb.sig.verify(&b.payload) {
180                    res = Err(Error::DesequenceFault);
181                }
182
183                fn append(vec: &mut Vec<u8>, other: &Vec<u8>) {
184                    let mut f = other.clone();
185                    vec.append(&mut f);
186                }
187
188                match (res, last) {
189                    (Ok(mut vec), false) => {
190                        append(&mut vec, &a.payload);
191                        Ok(vec)
192                    }
193                    (Ok(mut vec), true) => {
194                        append(&mut vec, &a.payload);
195
196                        if !fake {
197                            append(&mut vec, &b.payload);
198                        }
199                        Ok(vec)
200                    }
201                    _ => Err(Error::DesequenceFault),
202                }
203            },
204        );
205
206        r.expect("SeqBuilder::restore failed with invalid inputs!")
207    }
208
209    /// Read the sequence ID back from the builder
210    pub fn seqid(&self) -> &SeqId {
211        &self.seqid
212    }
213
214    /// Read the sender back from the builder
215    pub fn sender(&self) -> Identity {
216        self.sender
217    }
218
219    /// Read the recipient back from the builder
220    pub fn recp(&self) -> Recipient {
221        self.recp
222    }
223
224    /// Read the payload data set back from the builder
225    pub fn data(&self) -> Vec<u8> {
226        self.data.get(0).unwrap().clone()
227    }
228}
229
230#[cfg(test)]
231fn setup() -> Vec<Frame> {
232    let sender = Identity::with_digest(&vec![1]);
233    let recp = Identity::with_digest(&vec![2]);
234    SeqBuilder::new(sender, Recipient::User(recp), Identity::random())
235        .add(vec![42])
236        .add(vec![13, 12])
237        .add(vec![13, 37])
238        .build()
239}
240
241#[test]
242fn simple() {
243    let seq = setup();
244    assert!(seq.len() == 3);
245    assert!(seq.get(0).unwrap().seq.next == Some(seq.get(1).unwrap().seq.sig.sig));
246}
247
248/// A simple test to see if the sequence numbers are ok
249#[test]
250fn seq_num() {
251    let seq = setup();
252    assert_eq!(seq[0].seq.num, 0);
253    assert_eq!(seq[1].seq.num, 1);
254    assert_eq!(seq[2].seq.num, 2);
255}
256
257/// Hash sequence test
258#[test]
259fn hash_seq() {
260    let seq = setup();
261    assert_eq!(seq[0].seq.next, Some(seq[1].seq.sig.sig));
262    assert_eq!(seq[1].seq.next, Some(seq[2].seq.sig.sig));
263    assert_eq!(seq[2].seq.next, None);
264}