1use std::sync::Arc;
21
22use bytes::Bytes;
23use tokio::sync::Mutex;
24
25use ndn_config::{
26 ControlParameters, ControlResponse,
27 nfd_command::{command_name, dataset_name, module, verb},
28};
29use ndn_faces::local::IpcFace;
30use ndn_packet::{Name, encode::InterestBuilder};
31use ndn_transport::{Face, FaceId};
32
33use crate::forwarder_client::ForwarderError;
34
35pub struct MgmtClient {
43 face: Arc<IpcFace>,
44 recv_lock: Mutex<()>,
45}
46
47impl MgmtClient {
48 pub async fn connect(face_socket: impl AsRef<str>) -> Result<Self, ForwarderError> {
54 let face =
55 Arc::new(ndn_faces::local::ipc_face_connect(FaceId(0), face_socket.as_ref()).await?);
56 Ok(Self {
57 face,
58 recv_lock: Mutex::new(()),
59 })
60 }
61
62 pub fn from_face(face: Arc<IpcFace>) -> Self {
64 Self {
65 face,
66 recv_lock: Mutex::new(()),
67 }
68 }
69
70 pub async fn route_add(
79 &self,
80 prefix: &Name,
81 face_id: Option<u64>,
82 cost: u64,
83 ) -> Result<ControlParameters, ForwarderError> {
84 let params = ControlParameters {
85 name: Some(prefix.clone()),
86 face_id,
87 cost: Some(cost),
88 ..Default::default()
89 };
90 self.command(module::RIB, verb::REGISTER, ¶ms).await
91 }
92
93 pub async fn route_remove(
97 &self,
98 prefix: &Name,
99 face_id: Option<u64>,
100 ) -> Result<ControlParameters, ForwarderError> {
101 let params = ControlParameters {
102 name: Some(prefix.clone()),
103 face_id,
104 ..Default::default()
105 };
106 self.command(module::RIB, verb::UNREGISTER, ¶ms).await
107 }
108
109 pub async fn route_list(&self) -> Result<Vec<ndn_config::FibEntry>, ForwarderError> {
113 let bytes = self.dataset_raw(module::FIB, verb::LIST).await?;
114 Ok(ndn_config::FibEntry::decode_all(&bytes))
115 }
116
117 pub async fn rib_list(&self) -> Result<Vec<ndn_config::RibEntry>, ForwarderError> {
121 let bytes = self.dataset_raw(module::RIB, verb::LIST).await?;
122 Ok(ndn_config::RibEntry::decode_all(&bytes))
123 }
124
125 pub async fn face_create(&self, uri: &str) -> Result<ControlParameters, ForwarderError> {
129 self.face_create_with_mtu(uri, None).await
130 }
131
132 pub async fn face_create_with_mtu(
138 &self,
139 uri: &str,
140 mtu: Option<u64>,
141 ) -> Result<ControlParameters, ForwarderError> {
142 let params = ControlParameters {
143 uri: Some(uri.to_owned()),
144 mtu,
145 ..Default::default()
146 };
147 self.command(module::FACES, verb::CREATE, ¶ms).await
148 }
149
150 pub async fn face_destroy(&self, face_id: u64) -> Result<ControlParameters, ForwarderError> {
152 let params = ControlParameters {
153 face_id: Some(face_id),
154 ..Default::default()
155 };
156 self.command(module::FACES, verb::DESTROY, ¶ms).await
157 }
158
159 pub async fn face_list(&self) -> Result<Vec<ndn_config::FaceStatus>, ForwarderError> {
163 let bytes = self.dataset_raw(module::FACES, verb::LIST).await?;
164 Ok(ndn_config::FaceStatus::decode_all(&bytes))
165 }
166
167 pub async fn strategy_set(
171 &self,
172 prefix: &Name,
173 strategy: &Name,
174 ) -> Result<ControlParameters, ForwarderError> {
175 let params = ControlParameters {
176 name: Some(prefix.clone()),
177 strategy: Some(strategy.clone()),
178 ..Default::default()
179 };
180 self.command(module::STRATEGY, verb::SET, ¶ms).await
181 }
182
183 pub async fn strategy_unset(&self, prefix: &Name) -> Result<ControlParameters, ForwarderError> {
185 let params = ControlParameters {
186 name: Some(prefix.clone()),
187 ..Default::default()
188 };
189 self.command(module::STRATEGY, verb::UNSET, ¶ms).await
190 }
191
192 pub async fn strategy_list(&self) -> Result<Vec<ndn_config::StrategyChoice>, ForwarderError> {
196 let bytes = self.dataset_raw(module::STRATEGY, verb::LIST).await?;
197 Ok(ndn_config::StrategyChoice::decode_all(&bytes))
198 }
199
200 pub async fn cs_info(&self) -> Result<ControlResponse, ForwarderError> {
204 self.dataset(module::CS, verb::INFO).await
205 }
206
207 pub async fn cs_config(
212 &self,
213 capacity: Option<u64>,
214 ) -> Result<ControlParameters, ForwarderError> {
215 let params = ControlParameters {
216 capacity,
217 ..Default::default()
218 };
219 self.command(module::CS, verb::CONFIG, ¶ms).await
220 }
221
222 pub async fn cs_erase(
227 &self,
228 prefix: &ndn_packet::Name,
229 count: Option<u64>,
230 ) -> Result<ControlParameters, ForwarderError> {
231 let params = ControlParameters {
232 name: Some(prefix.clone()),
233 count,
234 ..Default::default()
235 };
236 self.command(module::CS, verb::ERASE, ¶ms).await
237 }
238
239 pub async fn neighbors_list(&self) -> Result<ControlResponse, ForwarderError> {
243 self.dataset(module::NEIGHBORS, verb::LIST).await
244 }
245
246 pub async fn service_list(&self) -> Result<ControlResponse, ForwarderError> {
250 self.dataset(module::SERVICE, verb::LIST).await
251 }
252
253 pub async fn service_announce(
255 &self,
256 prefix: &Name,
257 ) -> Result<ControlParameters, ForwarderError> {
258 let params = ControlParameters {
259 name: Some(prefix.clone()),
260 ..Default::default()
261 };
262 self.command(module::SERVICE, verb::ANNOUNCE, ¶ms).await
263 }
264
265 pub async fn service_withdraw(
267 &self,
268 prefix: &Name,
269 ) -> Result<ControlParameters, ForwarderError> {
270 let params = ControlParameters {
271 name: Some(prefix.clone()),
272 ..Default::default()
273 };
274 self.command(module::SERVICE, verb::WITHDRAW, ¶ms).await
275 }
276
277 pub async fn service_browse(
282 &self,
283 prefix: Option<&Name>,
284 ) -> Result<ControlResponse, ForwarderError> {
285 let name = match prefix {
286 None => dataset_name(module::SERVICE, verb::BROWSE),
287 Some(p) => {
288 let params = ControlParameters {
289 name: Some(p.clone()),
290 ..Default::default()
291 };
292 command_name(module::SERVICE, verb::BROWSE, ¶ms)
293 }
294 };
295 self.send_interest(name).await
296 }
297
298 pub async fn status(&self) -> Result<ControlResponse, ForwarderError> {
302 self.dataset(module::STATUS, b"general").await
303 }
304
305 pub async fn shutdown(&self) -> Result<ControlResponse, ForwarderError> {
307 self.dataset(module::STATUS, b"shutdown").await
308 }
309
310 pub async fn config_get(&self) -> Result<ControlResponse, ForwarderError> {
314 self.dataset(module::CONFIG, verb::GET).await
315 }
316
317 pub async fn face_counters(&self) -> Result<ControlResponse, ForwarderError> {
321 self.dataset(module::FACES, verb::COUNTERS).await
322 }
323
324 pub async fn measurements_list(&self) -> Result<ControlResponse, ForwarderError> {
328 self.dataset(module::MEASUREMENTS, verb::LIST).await
329 }
330
331 pub async fn security_identity_list(&self) -> Result<ControlResponse, ForwarderError> {
335 self.dataset(module::SECURITY, verb::IDENTITY_LIST).await
336 }
337
338 pub async fn security_identity_status(&self) -> Result<ControlResponse, ForwarderError> {
344 self.dataset(module::SECURITY, verb::IDENTITY_STATUS).await
345 }
346
347 pub async fn security_identity_generate(
349 &self,
350 name: &Name,
351 ) -> Result<ControlParameters, ForwarderError> {
352 let params = ControlParameters {
353 name: Some(name.clone()),
354 ..Default::default()
355 };
356 self.command(module::SECURITY, verb::IDENTITY_GENERATE, ¶ms)
357 .await
358 }
359
360 pub async fn security_anchor_list(&self) -> Result<ControlResponse, ForwarderError> {
362 self.dataset(module::SECURITY, verb::ANCHOR_LIST).await
363 }
364
365 pub async fn security_key_delete(
367 &self,
368 name: &Name,
369 ) -> Result<ControlParameters, ForwarderError> {
370 let params = ControlParameters {
371 name: Some(name.clone()),
372 ..Default::default()
373 };
374 self.command(module::SECURITY, verb::KEY_DELETE, ¶ms)
375 .await
376 }
377
378 pub async fn security_identity_did(
382 &self,
383 name: &Name,
384 ) -> Result<ControlResponse, ForwarderError> {
385 let params = ControlParameters {
386 name: Some(name.clone()),
387 ..Default::default()
388 };
389 let name = command_name(module::SECURITY, verb::IDENTITY_DID, ¶ms);
390 self.send_interest(name).await
391 }
392
393 pub async fn security_ca_info(&self) -> Result<ControlResponse, ForwarderError> {
397 self.dataset(module::SECURITY, verb::CA_INFO).await
398 }
399
400 pub async fn security_ca_enroll(
411 &self,
412 ca_prefix: &Name,
413 challenge_type: &str,
414 challenge_param: &str,
415 ) -> Result<ControlParameters, ForwarderError> {
416 let params = ControlParameters {
417 name: Some(ca_prefix.clone()),
418 uri: Some(format!("{challenge_type}:{challenge_param}")),
419 ..Default::default()
420 };
421 self.command(module::SECURITY, verb::CA_ENROLL, ¶ms)
422 .await
423 }
424
425 pub async fn security_ca_token_add(
429 &self,
430 description: &str,
431 ) -> Result<ControlParameters, ForwarderError> {
432 let params = ControlParameters {
433 uri: Some(description.to_owned()),
434 ..Default::default()
435 };
436 self.command(module::SECURITY, verb::CA_TOKEN_ADD, ¶ms)
437 .await
438 }
439
440 pub async fn security_ca_requests(&self) -> Result<ControlResponse, ForwarderError> {
442 self.dataset(module::SECURITY, verb::CA_REQUESTS).await
443 }
444
445 pub async fn security_yubikey_detect(&self) -> Result<ControlResponse, ForwarderError> {
450 self.dataset(module::SECURITY, verb::YUBIKEY_DETECT).await
451 }
452
453 pub async fn security_yubikey_generate(
458 &self,
459 name: &Name,
460 ) -> Result<ControlParameters, ForwarderError> {
461 let params = ControlParameters {
462 name: Some(name.clone()),
463 ..Default::default()
464 };
465 self.command(module::SECURITY, verb::YUBIKEY_GENERATE, ¶ms)
466 .await
467 }
468
469 pub async fn security_schema_list(&self) -> Result<ControlResponse, ForwarderError> {
476 self.dataset(module::SECURITY, verb::SCHEMA_LIST).await
477 }
478
479 pub async fn security_schema_rule_add(
484 &self,
485 rule: &str,
486 ) -> Result<ControlResponse, ForwarderError> {
487 let params = ControlParameters {
488 uri: Some(rule.to_owned()),
489 ..Default::default()
490 };
491 let name = ndn_config::command_name(module::SECURITY, verb::SCHEMA_RULE_ADD, ¶ms);
492 self.send_interest(name).await
493 }
494
495 pub async fn security_schema_rule_remove(
499 &self,
500 index: u64,
501 ) -> Result<ControlResponse, ForwarderError> {
502 let params = ControlParameters {
503 count: Some(index),
504 ..Default::default()
505 };
506 let name = ndn_config::command_name(module::SECURITY, verb::SCHEMA_RULE_REMOVE, ¶ms);
507 self.send_interest(name).await
508 }
509
510 pub async fn security_schema_set(
516 &self,
517 rules: &str,
518 ) -> Result<ControlResponse, ForwarderError> {
519 let params = ControlParameters {
520 uri: Some(rules.to_owned()),
521 ..Default::default()
522 };
523 let name = ndn_config::command_name(module::SECURITY, verb::SCHEMA_SET, ¶ms);
524 self.send_interest(name).await
525 }
526
527 pub async fn discovery_status(&self) -> Result<ControlResponse, ForwarderError> {
531 self.dataset(module::DISCOVERY, b"status").await
532 }
533
534 pub async fn discovery_config_set(
544 &self,
545 params: &str,
546 ) -> Result<ControlResponse, ForwarderError> {
547 let cp = ControlParameters {
548 uri: Some(params.to_owned()),
549 ..Default::default()
550 };
551 let name = command_name(module::DISCOVERY, verb::CONFIG, &cp);
552 self.send_interest(name).await
553 }
554
555 pub async fn routing_dvr_status(&self) -> Result<ControlResponse, ForwarderError> {
557 self.dataset(module::ROUTING, verb::DVR_STATUS).await
558 }
559
560 pub async fn routing_dvr_config_set(
565 &self,
566 params: &str,
567 ) -> Result<ControlResponse, ForwarderError> {
568 let cp = ControlParameters {
569 uri: Some(params.to_owned()),
570 ..Default::default()
571 };
572 let name = command_name(module::ROUTING, verb::DVR_CONFIG, &cp);
573 self.send_interest(name).await
574 }
575
576 pub async fn log_get_filter(&self) -> Result<ControlResponse, ForwarderError> {
580 self.dataset(module::LOG, verb::GET_FILTER).await
581 }
582
583 pub async fn log_get_recent(&self, after_seq: u64) -> Result<ControlResponse, ForwarderError> {
592 let params = ControlParameters {
593 count: Some(after_seq),
594 ..Default::default()
595 };
596 let name = command_name(module::LOG, verb::GET_RECENT, ¶ms);
597 self.send_interest(name).await
598 }
599
600 pub async fn log_set_filter(&self, filter: &str) -> Result<ControlResponse, ForwarderError> {
605 let params = ControlParameters {
606 uri: Some(filter.to_owned()),
607 ..Default::default()
608 };
609 let name = command_name(module::LOG, verb::SET_FILTER, ¶ms);
610 self.send_interest(name).await
611 }
612
613 async fn command(
617 &self,
618 module_name: &[u8],
619 verb_name: &[u8],
620 params: &ControlParameters,
621 ) -> Result<ControlParameters, ForwarderError> {
622 let name = command_name(module_name, verb_name, params);
623 let resp = self.send_interest(name).await?;
624
625 if !resp.is_ok() {
626 return Err(ForwarderError::Command {
627 code: resp.status_code,
628 text: resp.status_text,
629 });
630 }
631
632 Ok(resp.body.unwrap_or_default())
633 }
634
635 async fn dataset_raw(
641 &self,
642 module_name: &[u8],
643 verb_name: &[u8],
644 ) -> Result<Bytes, ForwarderError> {
645 let name = dataset_name(module_name, verb_name);
646 let interest_wire = InterestBuilder::new(name).build();
647 self.send_content_bytes(interest_wire).await
648 }
649
650 async fn send_content_bytes(&self, interest_wire: Bytes) -> Result<Bytes, ForwarderError> {
652 let _guard = self.recv_lock.lock().await;
653
654 self.face
655 .send(ndn_packet::lp::encode_lp_packet(&interest_wire))
656 .await?;
657
658 let data_wire = self
659 .face
660 .recv()
661 .await
662 .map(crate::forwarder_client::strip_lp)?;
663 let data =
664 ndn_packet::Data::decode(data_wire).map_err(|_| ForwarderError::MalformedResponse)?;
665
666 let content = data.content().ok_or(ForwarderError::MalformedResponse)?;
667 Ok(Bytes::copy_from_slice(content))
668 }
669
670 async fn dataset(
676 &self,
677 module_name: &[u8],
678 verb_name: &[u8],
679 ) -> Result<ControlResponse, ForwarderError> {
680 let name = dataset_name(module_name, verb_name);
681 self.send_unsigned_interest(name).await
682 }
683
684 async fn send_unsigned_interest(&self, name: Name) -> Result<ControlResponse, ForwarderError> {
691 let interest_wire = InterestBuilder::new(name).build();
692 self.send_raw(interest_wire).await
693 }
694
695 async fn send_interest(&self, name: Name) -> Result<ControlResponse, ForwarderError> {
703 let interest_wire = InterestBuilder::new(name).sign_digest_sha256();
704 self.send_raw(interest_wire).await
705 }
706
707 async fn send_raw(&self, interest_wire: Bytes) -> Result<ControlResponse, ForwarderError> {
709 let interest_wire = interest_wire;
710
711 let _guard = self.recv_lock.lock().await;
713
714 self.face
715 .send(ndn_packet::lp::encode_lp_packet(&interest_wire))
716 .await?;
717
718 let data_wire = self
719 .face
720 .recv()
721 .await
722 .map(crate::forwarder_client::strip_lp)?;
723 let data =
724 ndn_packet::Data::decode(data_wire).map_err(|_| ForwarderError::MalformedResponse)?;
725
726 let content = data.content().ok_or(ForwarderError::MalformedResponse)?;
727
728 ControlResponse::decode(Bytes::copy_from_slice(content))
729 .map_err(|_| ForwarderError::MalformedResponse)
730 }
731}