1use bytes::Bytes;
15use ndn_packet::{Name, NameComponent};
16use ndn_tlv::{TlvReader, TlvWriter};
17
18pub mod tlv {
21 pub const CONTROL_PARAMETERS: u64 = 0x68;
22 pub const FACE_ID: u64 = 0x69;
23 pub const COST: u64 = 0x6A;
24 pub const STRATEGY: u64 = 0x6B;
25 pub const FLAGS: u64 = 0x6C;
26 pub const EXPIRATION_PERIOD: u64 = 0x6D;
27 pub const ORIGIN: u64 = 0x6F;
28 pub const MASK: u64 = 0x70;
29 pub const URI: u64 = 0x72;
30 pub const LOCAL_URI: u64 = 0x81;
31 pub const CAPACITY: u64 = 0x83;
32 pub const COUNT: u64 = 0x84;
33 pub const FACE_PERSISTENCY: u64 = 0x85;
34 pub const BASE_CONG_INTERVAL: u64 = 0x87;
35 pub const DEF_CONG_THRESHOLD: u64 = 0x88;
36 pub const MTU: u64 = 0x89;
37
38 pub const NAME: u64 = 0x07;
40 pub const NAME_COMPONENT: u64 = 0x08;
41}
42
43pub mod origin {
45 pub const APP: u64 = 0;
46 pub const AUTOREG: u64 = 64;
47 pub const CLIENT: u64 = 65;
48 pub const AUTOCONF: u64 = 66;
49 pub const DVR: u64 = 127;
50 pub const NLSR: u64 = 128;
51 pub const PREFIX_ANN: u64 = 129;
52 pub const STATIC: u64 = 255;
53}
54
55pub mod route_flags {
57 pub const CHILD_INHERIT: u64 = 1;
58 pub const CAPTURE: u64 = 2;
59}
60
61#[derive(Debug, Clone, Default, PartialEq, Eq)]
65pub struct ControlParameters {
66 pub name: Option<Name>,
67 pub face_id: Option<u64>,
68 pub uri: Option<String>,
69 pub local_uri: Option<String>,
70 pub origin: Option<u64>,
71 pub cost: Option<u64>,
72 pub flags: Option<u64>,
73 pub mask: Option<u64>,
74 pub expiration_period: Option<u64>,
75 pub face_persistency: Option<u64>,
76 pub strategy: Option<Name>,
77 pub mtu: Option<u64>,
78 pub capacity: Option<u64>,
79 pub count: Option<u64>,
80}
81
82impl ControlParameters {
83 pub fn new() -> Self {
84 Self::default()
85 }
86
87 pub fn encode(&self) -> Bytes {
89 let mut w = TlvWriter::new();
90 w.write_nested(tlv::CONTROL_PARAMETERS, |w| {
91 self.encode_inner(w);
92 });
93 w.finish()
94 }
95
96 pub fn encode_value(&self) -> Bytes {
99 let mut w = TlvWriter::new();
100 self.encode_inner(&mut w);
101 w.finish()
102 }
103
104 fn encode_inner(&self, w: &mut TlvWriter) {
105 if let Some(ref name) = self.name {
106 encode_name(w, name);
107 }
108 if let Some(id) = self.face_id {
109 write_non_neg_int(w, tlv::FACE_ID, id);
110 }
111 if let Some(ref uri) = self.uri {
112 w.write_tlv(tlv::URI, uri.as_bytes());
113 }
114 if let Some(ref local_uri) = self.local_uri {
115 w.write_tlv(tlv::LOCAL_URI, local_uri.as_bytes());
116 }
117 if let Some(origin) = self.origin {
118 write_non_neg_int(w, tlv::ORIGIN, origin);
119 }
120 if let Some(cost) = self.cost {
121 write_non_neg_int(w, tlv::COST, cost);
122 }
123 if let Some(flags) = self.flags {
124 write_non_neg_int(w, tlv::FLAGS, flags);
125 }
126 if let Some(mask) = self.mask {
127 write_non_neg_int(w, tlv::MASK, mask);
128 }
129 if let Some(strategy) = self.strategy.as_ref() {
130 w.write_nested(tlv::STRATEGY, |w| {
131 encode_name(w, strategy);
132 });
133 }
134 if let Some(ep) = self.expiration_period {
135 write_non_neg_int(w, tlv::EXPIRATION_PERIOD, ep);
136 }
137 if let Some(fp) = self.face_persistency {
138 write_non_neg_int(w, tlv::FACE_PERSISTENCY, fp);
139 }
140 if let Some(mtu) = self.mtu {
141 write_non_neg_int(w, tlv::MTU, mtu);
142 }
143 if let Some(capacity) = self.capacity {
144 write_non_neg_int(w, tlv::CAPACITY, capacity);
145 }
146 if let Some(count) = self.count {
147 write_non_neg_int(w, tlv::COUNT, count);
148 }
149 }
150
151 pub fn decode(wire: Bytes) -> Result<Self, ControlParametersError> {
153 let mut r = TlvReader::new(wire);
154 let (typ, value) = r
155 .read_tlv()
156 .map_err(|_| ControlParametersError::MalformedTlv)?;
157 if typ != tlv::CONTROL_PARAMETERS {
158 return Err(ControlParametersError::WrongType(typ));
159 }
160 Self::decode_value(value)
161 }
162
163 pub fn decode_value(value: Bytes) -> Result<Self, ControlParametersError> {
165 let mut r = TlvReader::new(value);
166 let mut params = ControlParameters::default();
167
168 while !r.is_empty() {
169 let (typ, val) = r
170 .read_tlv()
171 .map_err(|_| ControlParametersError::MalformedTlv)?;
172 match typ {
173 tlv::NAME => {
174 params.name = Some(decode_name(val)?);
175 }
176 tlv::FACE_ID => {
177 params.face_id = Some(read_non_neg_int(&val)?);
178 }
179 tlv::URI => {
180 params.uri = Some(
181 std::str::from_utf8(&val)
182 .map_err(|_| ControlParametersError::InvalidUtf8)?
183 .to_owned(),
184 );
185 }
186 tlv::LOCAL_URI => {
187 params.local_uri = Some(
188 std::str::from_utf8(&val)
189 .map_err(|_| ControlParametersError::InvalidUtf8)?
190 .to_owned(),
191 );
192 }
193 tlv::ORIGIN => {
194 params.origin = Some(read_non_neg_int(&val)?);
195 }
196 tlv::COST => {
197 params.cost = Some(read_non_neg_int(&val)?);
198 }
199 tlv::FLAGS => {
200 params.flags = Some(read_non_neg_int(&val)?);
201 }
202 tlv::MASK => {
203 params.mask = Some(read_non_neg_int(&val)?);
204 }
205 tlv::STRATEGY => {
206 let mut inner = TlvReader::new(val);
207 let (t, v) = inner
208 .read_tlv()
209 .map_err(|_| ControlParametersError::MalformedTlv)?;
210 if t != tlv::NAME {
211 return Err(ControlParametersError::WrongType(t));
212 }
213 params.strategy = Some(decode_name(v)?);
214 }
215 tlv::EXPIRATION_PERIOD => {
216 params.expiration_period = Some(read_non_neg_int(&val)?);
217 }
218 tlv::FACE_PERSISTENCY => {
219 params.face_persistency = Some(read_non_neg_int(&val)?);
220 }
221 tlv::MTU => {
222 params.mtu = Some(read_non_neg_int(&val)?);
223 }
224 tlv::CAPACITY => {
225 params.capacity = Some(read_non_neg_int(&val)?);
226 }
227 tlv::COUNT => {
228 params.count = Some(read_non_neg_int(&val)?);
229 }
230 _ => {}
232 }
233 }
234
235 Ok(params)
236 }
237}
238
239#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
242pub enum ControlParametersError {
243 #[error("malformed TLV")]
244 MalformedTlv,
245 #[error("unexpected TLV type {0:#x}")]
246 WrongType(u64),
247 #[error("invalid NonNegativeInteger length")]
248 InvalidNonNegInt,
249 #[error("invalid UTF-8 in string field")]
250 InvalidUtf8,
251}
252
253fn encode_non_neg_int(value: u64) -> Vec<u8> {
257 if value <= 0xFF {
258 vec![value as u8]
259 } else if value <= 0xFFFF {
260 (value as u16).to_be_bytes().to_vec()
261 } else if value <= 0xFFFF_FFFF {
262 (value as u32).to_be_bytes().to_vec()
263 } else {
264 value.to_be_bytes().to_vec()
265 }
266}
267
268fn write_non_neg_int(w: &mut TlvWriter, typ: u64, value: u64) {
270 w.write_tlv(typ, &encode_non_neg_int(value));
271}
272
273fn read_non_neg_int(buf: &[u8]) -> Result<u64, ControlParametersError> {
275 match buf.len() {
276 1 => Ok(buf[0] as u64),
277 2 => Ok(u16::from_be_bytes([buf[0], buf[1]]) as u64),
278 4 => Ok(u32::from_be_bytes([buf[0], buf[1], buf[2], buf[3]]) as u64),
279 8 => Ok(u64::from_be_bytes([
280 buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7],
281 ])),
282 _ => Err(ControlParametersError::InvalidNonNegInt),
283 }
284}
285
286fn encode_name(w: &mut TlvWriter, name: &Name) {
289 w.write_nested(tlv::NAME, |w| {
290 for comp in name.components() {
291 w.write_tlv(comp.typ, &comp.value);
292 }
293 });
294}
295
296fn decode_name(value: Bytes) -> Result<Name, ControlParametersError> {
297 let mut r = TlvReader::new(value);
298 let mut components = Vec::new();
299 while !r.is_empty() {
300 let (typ, val) = r
301 .read_tlv()
302 .map_err(|_| ControlParametersError::MalformedTlv)?;
303 components.push(NameComponent { typ, value: val });
304 }
305 if components.is_empty() {
306 Ok(Name::root())
307 } else {
308 Ok(Name::from_components(components))
309 }
310}
311
312#[cfg(test)]
315mod tests {
316 use super::*;
317
318 fn name(components: &[&[u8]]) -> Name {
319 Name::from_components(
320 components
321 .iter()
322 .map(|c| NameComponent::generic(Bytes::copy_from_slice(c))),
323 )
324 }
325
326 #[test]
327 fn non_neg_int_encoding() {
328 assert_eq!(encode_non_neg_int(0), vec![0]);
329 assert_eq!(encode_non_neg_int(255), vec![255]);
330 assert_eq!(encode_non_neg_int(256), vec![1, 0]);
331 assert_eq!(encode_non_neg_int(0xFFFF), vec![0xFF, 0xFF]);
332 assert_eq!(encode_non_neg_int(0x10000), vec![0, 1, 0, 0]);
333 assert_eq!(
334 encode_non_neg_int(0x1_0000_0000),
335 vec![0, 0, 0, 1, 0, 0, 0, 0]
336 );
337 }
338
339 #[test]
340 fn non_neg_int_roundtrip() {
341 for v in [
342 0u64,
343 1,
344 255,
345 256,
346 0xFFFF,
347 0x10000,
348 0xFFFF_FFFF,
349 0x1_0000_0000,
350 u64::MAX,
351 ] {
352 let encoded = encode_non_neg_int(v);
353 let decoded = read_non_neg_int(&encoded).unwrap();
354 assert_eq!(decoded, v, "roundtrip failed for {v}");
355 }
356 }
357
358 #[test]
359 fn encode_decode_empty() {
360 let params = ControlParameters::new();
361 let wire = params.encode();
362 let decoded = ControlParameters::decode(wire).unwrap();
363 assert_eq!(decoded, params);
364 }
365
366 #[test]
367 fn encode_decode_rib_register() {
368 let params = ControlParameters {
369 name: Some(name(&[b"ndn", b"test"])),
370 face_id: Some(5),
371 origin: Some(origin::APP),
372 cost: Some(10),
373 flags: Some(route_flags::CHILD_INHERIT),
374 ..Default::default()
375 };
376 let wire = params.encode();
377 let decoded = ControlParameters::decode(wire).unwrap();
378 assert_eq!(decoded, params);
379 }
380
381 #[test]
382 fn encode_decode_faces_create() {
383 let params = ControlParameters {
384 uri: Some("shm://myapp".to_owned()),
385 face_persistency: Some(0), ..Default::default()
387 };
388 let wire = params.encode();
389 let decoded = ControlParameters::decode(wire).unwrap();
390 assert_eq!(decoded, params);
391 }
392
393 #[test]
394 fn encode_decode_with_strategy() {
395 let params = ControlParameters {
396 name: Some(name(&[b"test"])),
397 strategy: Some(name(&[b"ndn", b"strategy", b"best-route"])),
398 ..Default::default()
399 };
400 let wire = params.encode();
401 let decoded = ControlParameters::decode(wire).unwrap();
402 assert_eq!(decoded, params);
403 }
404
405 #[test]
406 fn encode_decode_all_fields() {
407 let params = ControlParameters {
408 name: Some(name(&[b"hello"])),
409 face_id: Some(42),
410 uri: Some("udp4://192.168.1.1:6363".to_owned()),
411 local_uri: Some("udp4://0.0.0.0:6363".to_owned()),
412 origin: Some(origin::STATIC),
413 cost: Some(100),
414 flags: Some(route_flags::CHILD_INHERIT | route_flags::CAPTURE),
415 mask: Some(3),
416 expiration_period: Some(30_000),
417 face_persistency: Some(1),
418 strategy: Some(name(&[b"ndn", b"strategy", b"multicast"])),
419 mtu: Some(8800),
420 capacity: Some(1024 * 1024),
421 count: Some(42),
422 };
423 let wire = params.encode();
424 let decoded = ControlParameters::decode(wire).unwrap();
425 assert_eq!(decoded, params);
426 }
427
428 #[test]
429 fn decode_value_works() {
430 let params = ControlParameters {
431 name: Some(name(&[b"test"])),
432 cost: Some(5),
433 ..Default::default()
434 };
435 let value = params.encode_value();
436 let decoded = ControlParameters::decode_value(value).unwrap();
437 assert_eq!(decoded, params);
438 }
439
440 #[test]
441 fn decode_wrong_type_errors() {
442 let mut w = TlvWriter::new();
444 w.write_nested(0x05, |_| {});
445 let result = ControlParameters::decode(w.finish());
446 assert!(matches!(
447 result,
448 Err(ControlParametersError::WrongType(0x05))
449 ));
450 }
451
452 #[test]
453 fn decode_ignores_unknown_types() {
454 let mut w = TlvWriter::new();
456 w.write_nested(tlv::CONTROL_PARAMETERS, |w| {
457 write_non_neg_int(w, tlv::COST, 10);
458 w.write_tlv(0xFE, b"unknown"); write_non_neg_int(w, tlv::FACE_ID, 3);
460 });
461 let decoded = ControlParameters::decode(w.finish()).unwrap();
462 assert_eq!(decoded.cost, Some(10));
463 assert_eq!(decoded.face_id, Some(3));
464 }
465}