ergot_base/
wire_frames.rs1use log::warn;
2use postcard::{Serializer, ser_flavors};
3use serde::{Deserialize, Serialize};
4
5use crate::{Address, AnyAllAppendix, FrameKind, HeaderSeq, Key, ProtocolError, nash::NameHash};
6
7#[derive(Serialize, Deserialize, Debug)]
8pub struct CommonHeader {
9 pub src: Address,
10 pub dst: Address,
11 pub seq_no: u16,
12 pub kind: FrameKind,
13 pub ttl: u8,
14}
15
16pub enum PartialDecodeTail<'a> {
17 Specific(&'a [u8]),
18 AnyAll {
19 apdx: AnyAllAppendix,
20 body: &'a [u8],
21 },
22 Err(ProtocolError),
23}
24
25pub struct PartialDecode<'a> {
26 pub hdr: CommonHeader,
27 pub tail: PartialDecodeTail<'a>,
28 pub hdr_raw: &'a [u8],
31}
32
33pub(crate) fn decode_frame_partial(data: &[u8]) -> Option<PartialDecode<'_>> {
34 let (common, remain) = postcard::take_from_bytes::<CommonHeader>(data).ok()?;
35 let is_err = common.kind == FrameKind::PROTOCOL_ERROR;
36 let any_all = [0, 255].contains(&common.dst.port_id);
37
38 match (is_err, any_all) {
39 (true, true) => {
41 warn!("Rejecting any/all protocol error message");
42 None
43 }
44 (true, false) => {
45 let hdr_raw_len = data.len() - remain.len();
46 let hdr_raw = &data[..hdr_raw_len];
47 let (err, remain) = postcard::take_from_bytes::<ProtocolError>(remain).ok()?;
49 if !remain.is_empty() {
50 warn!("Excess data, rejecting");
51 return None;
52 }
53 Some(PartialDecode {
54 hdr: common,
55 tail: PartialDecodeTail::Err(err),
56 hdr_raw,
57 })
58 }
59 (false, true) => {
60 let (key, remain) = postcard::take_from_bytes::<Key>(remain).ok()?;
61 let (nash, remain) = postcard::take_from_bytes::<u32>(remain).ok()?;
62 let hdr_raw_len = data.len() - remain.len();
63 let hdr_raw = &data[..hdr_raw_len];
64
65 Some(PartialDecode {
66 hdr: common,
67 tail: PartialDecodeTail::AnyAll {
68 apdx: AnyAllAppendix {
69 key,
70 nash: NameHash::from_u32(nash),
71 },
72 body: remain,
73 },
74 hdr_raw,
75 })
76 }
77 (false, false) => {
78 let hdr_raw_len = data.len() - remain.len();
79 let hdr_raw = &data[..hdr_raw_len];
80
81 Some(PartialDecode {
82 hdr: common,
83 tail: PartialDecodeTail::Specific(remain),
84 hdr_raw,
85 })
86 }
87 }
88}
89
90pub fn encode_frame_ty<F, T>(
93 flav: F,
94 hdr: &CommonHeader,
95 apdx: Option<&AnyAllAppendix>,
96 body: &T,
97) -> Result<F::Output, ()>
98where
99 F: ser_flavors::Flavor,
100 T: Serialize,
101{
102 let mut serializer = Serializer { output: flav };
103 hdr.serialize(&mut serializer).map_err(drop)?;
104
105 if let Some(app) = apdx {
106 serializer.output.try_extend(&app.key.0).map_err(drop)?;
107 let val: u32 = app.nash.as_ref().map(NameHash::to_u32).unwrap_or(0);
108 val.serialize(&mut serializer).map_err(drop)?;
109 }
110
111 body.serialize(&mut serializer).map_err(drop)?;
112 serializer.output.finalize().map_err(drop)
113}
114
115pub fn encode_frame_err<F>(flav: F, hdr: &CommonHeader, err: ProtocolError) -> Result<F::Output, ()>
116where
117 F: ser_flavors::Flavor,
118{
119 let mut serializer = Serializer { output: flav };
120 hdr.serialize(&mut serializer).map_err(drop)?;
121 err.serialize(&mut serializer).map_err(drop)?;
122 serializer.output.finalize().map_err(drop)
123}
124
125pub fn de_frame(remain: &[u8]) -> Option<BorrowedFrame<'_>> {
126 let res = decode_frame_partial(remain)?;
127
128 let app;
129 let body = match res.tail {
130 PartialDecodeTail::Specific(body) => {
131 app = None;
132 Ok(body)
133 }
134 PartialDecodeTail::AnyAll { apdx, body } => {
135 app = Some(apdx);
136 Ok(body)
137 }
138 PartialDecodeTail::Err(protocol_error) => {
139 app = None;
140 Err(protocol_error)
141 }
142 };
143
144 let CommonHeader {
145 src,
146 dst,
147 seq_no,
148 kind,
149 ttl,
150 } = res.hdr;
151
152 Some(BorrowedFrame {
153 hdr: HeaderSeq {
154 src,
155 dst,
156 seq_no,
157 any_all: app,
158 kind,
159 ttl,
160 },
161 body,
162 hdr_raw: res.hdr_raw,
163 })
164}
165
166pub struct BorrowedFrame<'a> {
167 pub hdr: HeaderSeq,
168 pub hdr_raw: &'a [u8],
169 pub body: Result<&'a [u8], ProtocolError>,
170}