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}