simple_stream/frame/
checksum32.rs

1// Copyright 2016 Nathan Sizemore <nathanrsizemore@gmail.com>
2//
3// This Source Code Form is subject to the terms of the
4// Mozilla Public License, v. 2.0. If a copy of the MPL was not
5// distributed with this file, You can obtain one at
6// http://mozilla.org/MPL/2.0/.
7
8
9//! Provides a simple framing pattern with a 32-bit checksum validation
10//! for each payload. This limits payload length to a max of `16,843,009` bytes.
11//!
12//! ```ignore
13//! 0                   1                   2                   3
14//! 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
15//! +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
16//! |                       Payload Length                          |
17//! +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
18//! |                        Payload Data                           |
19//! +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
20//! |                          Checksum                             |
21//! +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
22//!
23//! Payload Length    Signed 32-bit integer Network Byte Order.
24//! Payload Data      Payload Length bytes.
25//! CHecksum          Sum of all bytes contained in Payload Data
26//! ```
27//!
28//! [rfc-6455]: https://tools.ietf.org/html/rfc6455
29
30
31use std::mem;
32use std::default::Default;
33
34use super::Frame;
35use super::FrameBuilder;
36
37
38#[derive(Clone)]
39pub struct Checksum32Frame {
40    payload_len: usize,
41    payload: Vec<u8>,
42    checksum: u32
43}
44
45#[derive(Clone)]
46pub struct Checksum32FrameBuilder;
47impl FrameBuilder for Checksum32FrameBuilder {
48    fn from_bytes(buf: &mut Vec<u8>) -> Option<Box<dyn Frame>> {
49        if buf.len() < 9 {
50            return None;
51        }
52
53        let mut frame: Checksum32Frame = Default::default();
54
55        // Payload length
56        let mask = 0xFFFFFFFFu32;
57        let mut payload_len: u32 = 0;
58        payload_len |= ((buf[0] as u32) << 24) & mask;
59        payload_len |= ((buf[1] as u32) << 16) & mask;
60        payload_len |= ((buf[2] as u32) << 8) & mask;
61        payload_len |= buf[3] as u32;
62
63        let payload_len = payload_len as usize;
64        frame.payload_len = payload_len;
65
66        if buf.len() - 8 < payload_len {
67            return None;
68        }
69
70        trace!("Payload length: {}", payload_len);
71
72        let mut checksum: u32 = 0;
73        for x in 4..(payload_len + 4) {
74            let byte = buf[x];
75            frame.payload.push(byte);
76            checksum += byte as u32;
77        }
78
79        let mut maybe_checksum: u32 = 0;
80        maybe_checksum |= ((buf[payload_len + 4 + 0] as u32) << 24) & mask;
81        maybe_checksum |= ((buf[payload_len + 4 + 1] as u32) << 16) & mask;
82        maybe_checksum |= ((buf[payload_len + 4 + 2] as u32) << 8) & mask;
83        maybe_checksum |= buf[payload_len + 4 + 3] as u32;
84
85        if maybe_checksum != checksum {
86            error!("Checksum incorrect. Emptying passed buffer");
87            *buf = Vec::new();
88            return None;
89        }
90
91        frame.checksum = checksum;
92        let mut remainder = Vec::<u8>::with_capacity(buf.len() - frame.len_as_vec());
93        remainder.extend_from_slice(&buf[frame.len_as_vec()..buf.len()]);
94        mem::swap(buf, &mut remainder);
95
96        Some(Box::new(frame))
97    }
98}
99
100impl Checksum32Frame {
101    pub fn new(buf: &[u8]) -> Self {
102        let len = buf.len();
103        let mut checksum: u32 = 0;
104        let mut v = Vec::<u8>::with_capacity(len);
105
106        for x in 0..len {
107            let byte = buf[x];
108            v.push(byte);
109            checksum += byte as u32;
110        }
111
112        Checksum32Frame {
113            payload_len: len,
114            payload: v,
115            checksum: checksum
116        }
117    }
118}
119
120impl Frame for Checksum32Frame {
121    fn payload(&self) -> Vec<u8> {
122        self.payload.clone()
123    }
124
125    fn to_bytes(&self) -> Vec<u8> {
126        let mut buf = Vec::<u8>::with_capacity(self.len_as_vec());
127        buf.push((self.payload_len >> 24) as u8);
128        buf.push((self.payload_len >> 16) as u8);
129        buf.push((self.payload_len >> 8) as u8);
130        buf.push(self.payload_len as u8);
131        buf.extend_from_slice(&self.payload[..]);
132        buf.push((self.checksum >> 24) as u8);
133        buf.push((self.checksum >> 16) as u8);
134        buf.push((self.checksum >> 8) as u8);
135        buf.push(self.checksum as u8);
136
137        buf
138    }
139
140    fn len_as_vec(&self) -> usize {
141        self.payload_len + 8
142    }
143
144    fn as_mut_raw_erased(&self) -> *mut () {
145        let dup = Box::new(self.clone());
146        return Box::into_raw(dup) as *mut _ as *mut ();
147    }
148}
149
150impl Default for Checksum32Frame {
151    fn default() -> Checksum32Frame {
152        Checksum32Frame {
153            payload_len: 0,
154            payload: Vec::new(),
155            checksum: 0
156        }
157    }
158}