1
Fork 0

COBS encode checksum.

https://github.com/fluffysquirrels/framed-rs/issues/30
This commit is contained in:
Alex Helfet 2019-04-13 16:15:09 +01:00
parent 8e9fe0e182
commit 18c295391a
5 changed files with 54 additions and 74 deletions

6
Cargo.lock generated
View file

@ -97,7 +97,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "framed" name = "framed"
version = "0.4.1" version = "0.4.2"
dependencies = [ dependencies = [
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"cobs 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "cobs 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
@ -115,7 +115,7 @@ dependencies = [
"clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
"csv 1.0.0-beta.5 (registry+https://github.com/rust-lang/crates.io-index)", "csv 1.0.0-beta.5 (registry+https://github.com/rust-lang/crates.io-index)",
"derive-error 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "derive-error 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"framed 0.4.1", "framed 0.4.2",
"serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -123,7 +123,7 @@ dependencies = [
name = "framed_test_type" name = "framed_test_type"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"framed 0.4.1", "framed 0.4.2",
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
] ]

View file

@ -1,6 +1,6 @@
[package] [package]
name = "framed" name = "framed"
version = "0.4.1" version = "0.4.2"
description = "Send and receive data over lossy streams of bytes." description = "Send and receive data over lossy streams of bytes."
authors = ["Alex Helfet <alex.helfet@gmail.com>"] authors = ["Alex Helfet <alex.helfet@gmail.com>"]
categories = ["no-std", "embedded", "encoding", "network-programming"] categories = ["no-std", "embedded", "encoding", "network-programming"]

View file

@ -156,27 +156,17 @@ impl Config {
} }
} }
const MAX_HEADER_LEN: usize = 0; const MAX_FRAMING_LEN: usize = MAX_CHECKSUM_LEN + 1;
const MAX_FOOTER_LEN: usize = MAX_CHECKSUM_LEN + 1;
const MAX_FRAMING_LEN: usize = MAX_HEADER_LEN + MAX_FOOTER_LEN;
impl Codec { impl Codec {
fn checksum(&self) -> &Checksum { fn checksum(&self) -> &Checksum {
&self.config.checksum &self.config.checksum
} }
fn header_len(&self) -> usize { fn min_frame_len(&self) -> usize {
0 0 // payload length
} + self.checksum().len()
+ 1 // sentinel length
fn footer_len(&self) -> usize {
1 + self.checksum().len()
}
fn framing_len(&self) -> usize {
self.header_len() + self.footer_len()
} }
/// Encode the supplied payload data as a frame at the beginning of /// Encode the supplied payload data as a frame at the beginning of
@ -198,30 +188,25 @@ impl Codec {
println!("framed::encode: Payload = {:?}", p); println!("framed::encode: Payload = {:?}", p);
} }
let cobs_len = cobs::encode(&p, &mut dest[self.header_len()..]); let checksum_type = self.checksum();
let checksum = self.checksum(); let checksum_value = checksum_type.calculate(p);
let checksum_value = checksum.calculate(p);
let checksum_len = checksum.len();
{ let cobs_len = {
let mut _header = &mut dest[0..self.header_len()]; let mut cobs_enc = cobs::CobsEncoder::new(dest);
cobs_enc.push(p)
.map_err(|_| Error::CobsEncodeFailed)?;
if checksum_value.len() > 0 {
cobs_enc.push(&*checksum_value)
.map_err(|_| Error::CobsEncodeFailed)?;
}
let cobs_len = cobs_enc.finalize()
.map_err(|_| Error::CobsEncodeFailed)?;
cobs_len
};
dest[cobs_len] = FRAME_END_SYMBOL;
#[cfg(feature = "trace")] { // len is cobs_len + len(FRAME_END_SYMBOL)
println!("framed::encode: Header = {:?}", _header); let len = cobs_len + 1;
}
}
{
let footer = &mut dest[
(self.header_len() + cobs_len)
..
(self.header_len() + cobs_len + self.footer_len())];
footer[0..checksum_len].copy_from_slice(&*checksum_value);
footer[checksum_len] = FRAME_END_SYMBOL;
#[cfg(feature = "trace")] {
println!("framed::encode: Footer = {:?}", footer);
}
}
let len = self.header_len() + cobs_len + self.footer_len();
#[cfg(feature = "trace")] { #[cfg(feature = "trace")] {
println!("framed::encode: Frame = {:?}", &dest[0..len]); println!("framed::encode: Frame = {:?}", &dest[0..len]);
} }
@ -287,7 +272,7 @@ impl Codec {
return Err(Error::EofBeforeFrame); return Err(Error::EofBeforeFrame);
} }
if e.len() < self.framing_len() { if e.len() < self.min_frame_len() {
return Err(Error::EofDuringFrame); return Err(Error::EofDuringFrame);
} }
@ -298,47 +283,39 @@ impl Codec {
assert!(dest.len() >= max_decoded_len(e.len())); assert!(dest.len() >= max_decoded_len(e.len()));
assert_eq!(e[e.len() - 1], FRAME_END_SYMBOL); assert_eq!(e[e.len() - 1], FRAME_END_SYMBOL);
let _header = &e[0..self.header_len()]; let cobs_payload = &e[0..e.len() - 1];
let body = &e[self.header_len()..(e.len() - self.footer_len())]; let cobs_decoded_len =
let footer = &e[(e.len() - self.footer_len())..e.len()]; if cobs_payload.len() == 0 {
#[cfg(feature = "trace")] {
println!("framed::decode: header = {:?}\n\
framed::decode: body = {:?}\n\
framed::decode: footer = {:?}",
_header, body, footer);
}
let decoded_len =
if body.len() == 0 {
0 0
} else { } else {
cobs::decode(body, dest) cobs::decode(cobs_payload, dest)
.map_err(|_| Error::CobsDecodeFailed)? .map_err(|_| Error::CobsDecodeFailed)?
}; };
let cobs_decoded = &dest[0..cobs_decoded_len];
let decoded = &dest[0..decoded_len]; let payload = &cobs_decoded[0..cobs_decoded_len - self.checksum().len()];
#[cfg(feature = "trace")] { #[cfg(feature = "trace")] {
println!("framed::decode: cobs_decoded = {:?}",
cobs_decoded);
println!("framed::decode: payload = {:?}", println!("framed::decode: payload = {:?}",
decoded); payload);
} }
let checksum = self.checksum(); let checksum = self.checksum();
let calc_checksum = checksum.calculate(decoded); let calc_checksum = checksum.calculate(payload);
let received_checksum = &footer[0..checksum.len()]; let recv_checksum = &cobs_decoded[payload.len() .. payload.len() + checksum.len()];
#[cfg(feature = "trace")] { #[cfg(feature = "trace")] {
println!("framed::decode: calc checksum = {:?}\n\ println!("framed::decode: calc_checksum = {:?}\n\
framed::decode: recv checksum = {:?}", framed::decode: recv_checksum = {:?}",
calc_checksum, received_checksum); calc_checksum, recv_checksum);
} }
if &*calc_checksum != received_checksum { if &*calc_checksum != recv_checksum {
return Err(Error::ChecksumError); return Err(Error::ChecksumError);
} }
Ok(decoded_len) Ok(payload.len())
} }
/// Decode the supplied encoded frame, returning the payload on the heap. /// Decode the supplied encoded frame, returning the payload on the heap.
@ -634,7 +611,7 @@ mod tests {
#[cfg(feature = "use_std")] #[cfg(feature = "use_std")]
fn decode_to_slice_encoded_too_short() { fn decode_to_slice_encoded_too_short() {
let mut c = codec(); let mut c = codec();
let encoded = vec![FRAME_END_SYMBOL; c.framing_len() - 1]; let encoded = vec![FRAME_END_SYMBOL; c.min_frame_len() - 1];
let mut decoded_buf = []; let mut decoded_buf = [];
let res = c.decode_to_slice(&*encoded, &mut decoded_buf); let res = c.decode_to_slice(&*encoded, &mut decoded_buf);
@ -663,7 +640,7 @@ mod tests {
let mut c = codec(); let mut c = codec();
let encoded = c.encode_to_box(&PAYLOAD).unwrap(); let encoded = c.encode_to_box(&PAYLOAD).unwrap();
let mut encoded = Vec::from(&*encoded); let mut encoded = Vec::from(&*encoded);
let checksum_offset = encoded.len() - c.footer_len(); let checksum_offset = encoded.len() - c.checksum().len() - 1;
{ {
let checksum = let checksum =

View file

@ -19,6 +19,9 @@ pub enum Error {
/// COBS decode failed /// COBS decode failed
CobsDecodeFailed, CobsDecodeFailed,
/// COBS encode failed
CobsEncodeFailed,
/// Checksum error: the received frame was corrupted. /// Checksum error: the received frame was corrupted.
ChecksumError, ChecksumError,

View file

@ -22,11 +22,11 @@
//! //!
//! Currently the encoding is: //! Currently the encoding is:
//! //!
//! * Header: //! * Frame [COBS]-encoded to remove bytes equal to zero
//! * Nothing here yet. //! * Payload: supplied by user
//! * Body: payload [COBS]-encoded to remove bytes equal to zero
//! * Footer: //! * Footer:
//! * A variable length checksum, depending on configuration in `framed::bytes::Config`. //! * A checksum computed over the payload. The type of checksum depends
//! on the configuration in `framed::bytes::Config`.
//! * A terminating zero byte. //! * A terminating zero byte.
//! //!
//! [COBS]: https://en.wikipedia.org/wiki/Consistent_Overhead_Byte_Stuffing //! [COBS]: https://en.wikipedia.org/wiki/Consistent_Overhead_Byte_Stuffing