COBS encode checksum.
https://github.com/fluffysquirrels/framed-rs/issues/30
This commit is contained in:
parent
8e9fe0e182
commit
18c295391a
5 changed files with 54 additions and 74 deletions
6
Cargo.lock
generated
6
Cargo.lock
generated
|
@ -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)",
|
||||||
]
|
]
|
||||||
|
|
|
@ -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"]
|
||||||
|
|
|
@ -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 =
|
||||||
|
|
|
@ -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,
|
||||||
|
|
||||||
|
|
|
@ -22,12 +22,12 @@
|
||||||
//!
|
//!
|
||||||
//! 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 checksum computed over the payload. The type of checksum depends
|
||||||
//! * A variable length checksum, depending on configuration in `framed::bytes::Config`.
|
//! 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
|
||||||
//!
|
//!
|
||||||
|
|
Loading…
Reference in a new issue