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_raw<F>(
118 flav: F,
119 hdr: &CommonHeader,
120 key: Option<&Key>,
121 body: &[u8],
122) -> Result<F::Output, ()>
123where
124 F: ser_flavors::Flavor,
125{
126 let mut serializer = Serializer { output: flav };
127 hdr.serialize(&mut serializer).map_err(drop)?;
128
129 if let Some(key) = key {
130 serializer.output.try_extend(&key.0).map_err(drop)?;
131 }
132
133 serializer.output.try_extend(body).map_err(drop)?;
134 serializer.output.finalize().map_err(drop)
135}
136
137pub fn encode_frame_err<F>(flav: F, hdr: &CommonHeader, err: ProtocolError) -> Result<F::Output, ()>
138where
139 F: ser_flavors::Flavor,
140{
141 let mut serializer = Serializer { output: flav };
142 hdr.serialize(&mut serializer).map_err(drop)?;
143 err.serialize(&mut serializer).map_err(drop)?;
144 serializer.output.finalize().map_err(drop)
145}
146
147pub fn de_frame(remain: &[u8]) -> Option<BorrowedFrame<'_>> {
148 let res = decode_frame_partial(remain)?;
149
150 let app;
151 let body = match res.tail {
152 PartialDecodeTail::Specific(body) => {
153 app = None;
154 Ok(body)
155 }
156 PartialDecodeTail::AnyAll { apdx, body } => {
157 app = Some(apdx);
158 Ok(body)
159 }
160 PartialDecodeTail::Err(protocol_error) => {
161 app = None;
162 Err(protocol_error)
163 }
164 };
165
166 let CommonHeader {
167 src,
168 dst,
169 seq_no,
170 kind,
171 ttl,
172 } = res.hdr;
173
174 Some(BorrowedFrame {
175 hdr: HeaderSeq {
176 src,
177 dst,
178 seq_no,
179 any_all: app,
180 kind,
181 ttl,
182 },
183 body,
184 hdr_raw: res.hdr_raw,
185 })
186}
187
188pub struct BorrowedFrame<'a> {
189 pub hdr: HeaderSeq,
190 pub hdr_raw: &'a [u8],
191 pub body: Result<&'a [u8], ProtocolError>,
192}