use super::bundle::*;
use super::crc::*;
use super::eid::*;
use derive_builder::Builder;
use serde::de::{SeqAccess, Visitor};
use serde::ser::{SerializeSeq, Serializer};
use serde::{de, Deserialize, Deserializer, Serialize};
use std::fmt;
pub type CanonicalBlockType = u64;
pub const PAYLOAD_BLOCK: CanonicalBlockType = 1;
pub const INTEGRITY_BLOCK: CanonicalBlockType = 2;
pub const CONFIDENTIALITY_BLOCK: CanonicalBlockType = 3;
pub const MANIFEST_BLOCK: CanonicalBlockType = 4;
pub const FLOW_LABEL_BLOCK: CanonicalBlockType = 6;
pub const PREVIOUS_NODE_BLOCK: CanonicalBlockType = 7;
pub const BUNDLE_AGE_BLOCK: CanonicalBlockType = 8;
pub const HOP_COUNT_BLOCK: CanonicalBlockType = 9;
#[derive(Debug, Clone, PartialEq, Builder)]
#[builder(default)]
pub struct CanonicalBlock {
pub block_type: CanonicalBlockType,
pub block_number: u64,
pub block_control_flags: BlockControlFlags,
pub crc_type: CRCType,
data: CanonicalData,
crc: ByteBuffer,
}
impl Serialize for CanonicalBlock {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let num_elems = if self.crc_type == CRC_NO { 5 } else { 6 };
let mut seq = serializer.serialize_seq(Some(num_elems))?;
seq.serialize_element(&self.block_type)?;
seq.serialize_element(&self.block_number)?;
seq.serialize_element(&self.block_control_flags)?;
seq.serialize_element(&self.crc_type)?;
seq.serialize_element(&self.data)?;
if self.crc_type != CRC_NO {
seq.serialize_element(&serde_bytes::Bytes::new(&self.crc))?;
}
seq.end()
}
}
impl<'de> Deserialize<'de> for CanonicalBlock {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct CanonicalBlockVisitor;
impl<'de> Visitor<'de> for CanonicalBlockVisitor {
type Value = CanonicalBlock;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("packet")
}
fn visit_seq<V>(self, mut seq: V) -> Result<Self::Value, V::Error>
where
V: SeqAccess<'de>,
{
let block_type: CanonicalBlockType = seq
.next_element()?
.ok_or_else(|| de::Error::invalid_length(0, &self))?;
let block_number: u64 = seq
.next_element()?
.ok_or_else(|| de::Error::invalid_length(1, &self))?;
let block_control_flags: BlockControlFlags = seq
.next_element()?
.ok_or_else(|| de::Error::invalid_length(2, &self))?;
let crc_type: CRCType = seq
.next_element()?
.ok_or_else(|| de::Error::invalid_length(3, &self))?;
let data = if block_type == PAYLOAD_BLOCK {
CanonicalData::Data(
seq.next_element::<serde_bytes::ByteBuf>()?
.ok_or_else(|| de::Error::invalid_length(4, &self))?
.into_vec(),
)
} else if block_type == BUNDLE_AGE_BLOCK {
CanonicalData::BundleAge(
seq.next_element::<u64>()?
.ok_or_else(|| de::Error::invalid_length(4, &self))?,
)
} else if block_type == HOP_COUNT_BLOCK {
let hc: (u32, u32) = seq
.next_element::<(u32, u32)>()?
.ok_or_else(|| de::Error::invalid_length(4, &self))?;
CanonicalData::HopCount(hc.0, hc.1)
} else if block_type == PREVIOUS_NODE_BLOCK {
CanonicalData::PreviousNode(
seq.next_element::<EndpointID>()?
.ok_or_else(|| de::Error::invalid_length(4, &self))?,
)
} else {
CanonicalData::DecodingError
};
let crc: ByteBuffer = if crc_type == CRC_NO {
Vec::new()
} else {
seq.next_element::<serde_bytes::ByteBuf>()?
.ok_or_else(|| de::Error::invalid_length(5, &self))?
.into_vec()
};
Ok(CanonicalBlock {
block_type,
block_number,
block_control_flags,
crc_type,
data,
crc,
})
}
}
deserializer.deserialize_any(CanonicalBlockVisitor)
}
}
impl Default for CanonicalBlock {
fn default() -> Self {
CanonicalBlock::new()
}
}
impl Block for CanonicalBlock {
fn has_crc(&self) -> bool {
self.crc_type != CRC_NO
}
fn crc(&self) -> &[u8] {
&self.crc
}
fn set_crc_type(&mut self, crc_type: CRCType) {
self.crc_type = crc_type;
}
fn crc_type(&self) -> CRCType {
self.crc_type
}
fn set_crc(&mut self, crc: ByteBuffer) {
self.crc = crc;
}
fn to_cbor(&self) -> ByteBuffer {
serde_cbor::to_vec(&self).unwrap()
}
}
pub fn new_canonical_block(
block_type: CanonicalBlockType,
block_number: u64,
block_control_flags: BlockControlFlags,
data: CanonicalData,
) -> CanonicalBlock {
CanonicalBlock {
block_type,
block_number,
block_control_flags,
crc_type: CRC_NO,
data,
crc: Vec::new(),
}
}
impl CanonicalBlock {
pub fn new() -> CanonicalBlock {
CanonicalBlock {
block_type: PAYLOAD_BLOCK,
block_number: 0,
block_control_flags: 0,
crc_type: CRC_NO,
data: CanonicalData::Data(Vec::new()),
crc: Vec::new(),
}
}
pub fn validation_errors(&self) -> Option<Bp7ErrorList> {
let mut errors: Bp7ErrorList = Vec::new();
if let Some(err) = self.block_control_flags.validation_error() {
errors.push(err);
}
if let Some(err) = self.extension_validation_error() {
errors.push(err);
}
if !errors.is_empty() {
return Some(errors);
}
None
}
pub fn extension_validation_error(&self) -> Option<Bp7Error> {
match &self.data {
CanonicalData::Data(_) => {
if self.block_type != PAYLOAD_BLOCK {
return Some(Bp7Error::CanonicalBlockError(
"Payload data not matching payload type".to_string(),
));
}
if self.block_number != 0 {
return Some(Bp7Error::CanonicalBlockError(
"Payload Block's block number is not zero".to_string(),
));
}
}
CanonicalData::BundleAge(_) => {
if self.block_type != BUNDLE_AGE_BLOCK {
return Some(Bp7Error::CanonicalBlockError(
"Payload data not matching payload type".to_string(),
));
}
}
CanonicalData::HopCount(_, _) => {
if self.block_type != HOP_COUNT_BLOCK {
return Some(Bp7Error::CanonicalBlockError(
"Payload data not matching payload type".to_string(),
));
}
}
CanonicalData::PreviousNode(prev_eid) => {
if self.block_type != PREVIOUS_NODE_BLOCK {
return Some(Bp7Error::CanonicalBlockError(
"Payload data not matching payload type".to_string(),
));
}
if let Some(err) = prev_eid.validation_error() {
return Some(err);
}
}
CanonicalData::DecodingError => {
return Some(Bp7Error::CanonicalBlockError("Unknown data".to_string()));
}
}
if (self.block_type > 9 && self.block_type < 192) || (self.block_type > 255) {
return Some(Bp7Error::CanonicalBlockError(
"Unknown block type".to_string(),
));
}
None
}
pub fn get_data(&self) -> &CanonicalData {
&self.data
}
pub fn set_data(&mut self, data: CanonicalData) {
self.data = data;
}
pub fn hop_count_get(&self) -> Option<(u32, u32)> {
if self.block_type == HOP_COUNT_BLOCK {
if let CanonicalData::HopCount(hc_limit, hc_count) = self.get_data() {
return Some((*hc_limit, *hc_count));
}
}
None
}
pub fn hop_count_increase(&mut self) -> bool {
if let Some((hc_limit, mut hc_count)) = self.hop_count_get() {
hc_count += 1;
self.set_data(CanonicalData::HopCount(hc_limit, hc_count));
return true;
}
false
}
pub fn hop_count_exceeded(&self) -> bool {
if self.block_type == HOP_COUNT_BLOCK {
if let CanonicalData::HopCount(hc_limit, hc_count) = self.get_data() {
if *hc_count > *hc_limit {
return true;
}
}
}
false
}
pub fn bundle_age_update(&mut self, age: u64) -> bool {
if self.bundle_age_get().is_some() {
self.set_data(CanonicalData::BundleAge(age));
return true;
}
false
}
pub fn bundle_age_get(&self) -> Option<u64> {
if self.block_type == BUNDLE_AGE_BLOCK {
if let CanonicalData::BundleAge(age) = self.get_data() {
return Some(*age);
}
}
None
}
pub fn previous_node_update(&mut self, nodeid: EndpointID) -> bool {
if self.previous_node_get().is_some() {
self.set_data(CanonicalData::PreviousNode(nodeid));
return true;
}
false
}
pub fn previous_node_get(&self) -> Option<&EndpointID> {
if self.block_type == PREVIOUS_NODE_BLOCK {
if let CanonicalData::PreviousNode(eid) = self.get_data() {
return Some(eid);
}
}
None
}
}
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
#[serde(untagged)]
pub enum CanonicalData {
HopCount(u32, u32),
Data(#[serde(with = "serde_bytes")] ByteBuffer),
BundleAge(u64),
PreviousNode(EndpointID),
DecodingError,
}
impl CanonicalData {
pub fn to_cbor(&self) -> ByteBuffer {
serde_cbor::to_vec(&self).expect("CanonicalData encoding error")
}
}
pub fn new_hop_count_block(
block_number: u64,
bcf: BlockControlFlags,
limit: u32,
) -> CanonicalBlock {
CanonicalBlockBuilder::default()
.block_type(HOP_COUNT_BLOCK)
.block_number(block_number)
.block_control_flags(bcf)
.data(CanonicalData::HopCount(limit, 0))
.build()
.unwrap()
}
pub fn new_payload_block(bcf: BlockControlFlags, data: ByteBuffer) -> CanonicalBlock {
CanonicalBlockBuilder::default()
.block_type(PAYLOAD_BLOCK)
.block_number(0)
.block_control_flags(bcf)
.data(CanonicalData::Data(data))
.build()
.unwrap()
}
pub fn new_previous_node_block(
block_number: u64,
bcf: BlockControlFlags,
prev: EndpointID,
) -> CanonicalBlock {
CanonicalBlockBuilder::default()
.block_type(PREVIOUS_NODE_BLOCK)
.block_number(block_number)
.block_control_flags(bcf)
.data(CanonicalData::PreviousNode(prev))
.build()
.unwrap()
}
pub fn new_bundle_age_block(
block_number: u64,
bcf: BlockControlFlags,
time: u64,
) -> CanonicalBlock {
CanonicalBlockBuilder::default()
.block_type(BUNDLE_AGE_BLOCK)
.block_number(block_number)
.block_control_flags(bcf)
.data(CanonicalData::BundleAge(time))
.build()
.unwrap()
}