ndn_discovery/context.rs
1//! `DiscoveryContext` — narrow engine interface exposed to discovery protocols.
2//!
3//! Protocols call context methods to add/remove faces, install FIB routes, and
4//! update the neighbor table. They cannot access the engine directly, which
5//! keeps the protocol implementations portable and testable in isolation.
6
7use std::sync::Arc;
8use std::time::Instant;
9
10use bytes::Bytes;
11use ndn_packet::Name;
12use ndn_transport::{ErasedFace, FaceId};
13
14use crate::{MacAddr, NeighborEntry, NeighborUpdate, ProtocolId};
15
16/// Read-only view of the neighbor table, handed to protocols via the context.
17pub trait NeighborTableView: Send + Sync {
18 /// Look up an entry by node name.
19 fn get(&self, name: &Name) -> Option<NeighborEntry>;
20 /// Snapshot all entries.
21 fn all(&self) -> Vec<NeighborEntry>;
22 /// Find any existing face for this MAC + interface combination.
23 fn face_for_peer(&self, mac: &MacAddr, iface: &str) -> Option<FaceId>;
24}
25
26/// Narrow interface through which discovery protocols mutate engine state.
27///
28/// The engine implements this trait on a context struct that holds `Arc`
29/// references to the face table, FIB, and neighbor table. Protocol
30/// implementations only see this interface, making them easy to unit-test
31/// with a stub context.
32pub trait DiscoveryContext: Send + Sync {
33 // ── Face management ──────────────────────────────────────────────────────
34
35 /// Allocate a unique `FaceId` from the engine's face table.
36 ///
37 /// Discovery protocols call this before constructing a face object (e.g.
38 /// [`NamedEtherFace::new`]) that requires an ID at construction time.
39 fn alloc_face_id(&self) -> FaceId;
40
41 /// Add a dynamically created face to the engine.
42 ///
43 /// Returns the `FaceId` assigned by the face table. The engine spawns
44 /// recv/send tasks and begins forwarding through the face immediately.
45 fn add_face(&self, face: Arc<dyn ErasedFace>) -> FaceId;
46
47 /// Remove a face from the engine, stopping its tasks.
48 fn remove_face(&self, face_id: FaceId);
49
50 // ── FIB management ───────────────────────────────────────────────────────
51
52 /// Install a FIB route owned by `owner`.
53 ///
54 /// Routes tagged with a `ProtocolId` can be bulk-removed via
55 /// [`remove_fib_entries_by_owner`] when the protocol shuts down or
56 /// reconfigures.
57 fn add_fib_entry(&self, prefix: &Name, nexthop: FaceId, cost: u32, owner: ProtocolId);
58
59 /// Remove a single FIB nexthop.
60 fn remove_fib_entry(&self, prefix: &Name, nexthop: FaceId, owner: ProtocolId);
61
62 /// Remove every FIB route installed by `owner`.
63 fn remove_fib_entries_by_owner(&self, owner: ProtocolId);
64
65 // ── Neighbor table ───────────────────────────────────────────────────────
66
67 /// Read access to the engine-owned neighbor table.
68 fn neighbors(&self) -> Arc<dyn NeighborTableView>;
69
70 /// Apply a mutation to the engine-owned neighbor table.
71 fn update_neighbor(&self, update: NeighborUpdate);
72
73 // ── Packet I/O ───────────────────────────────────────────────────────────
74
75 /// Send raw bytes directly on a face, bypassing the pipeline.
76 ///
77 /// Used by discovery protocols to transmit hello packets and probes
78 /// without entering the forwarding plane.
79 fn send_on(&self, face_id: FaceId, pkt: Bytes);
80
81 // ── Time ─────────────────────────────────────────────────────────────────
82
83 /// Current monotonic time.
84 fn now(&self) -> Instant;
85}