prns-runtime-embassy 0.3.6

Embassy host runtime for Personal Reticulum
Documentation
use crate::engine::test_support::{bytes_from_hex, routable_descriptor, RNS_1_4_2_ANNOUNCE};
use crate::engine::{Directive, EngineReaction, FanTarget, InstantMillis};
use crate::interfaces::{
    AnnounceBandwidthCap, BitrateBps, InterfaceDescriptor, InterfaceId, InterfaceIfac,
    InterfaceKind,
};
use crate::manifold::grant::{FrameTarget, GrantConsumer};
use crate::manifold::interface_seam::EMBEDDED_MAX_WIRE_FRAME_LEN;

use super::super::leaked_grant_lane;
use super::{
    enqueue_broadcast_for_wire, enqueue_for_wire, flush_due_pacers, route_reaction,
    soonest_pacer_release, EgressOutcome, InterfacePacer, ManifoldEgress, PooledEgress,
};

fn paced_descriptor(id: InterfaceId) -> InterfaceDescriptor {
    InterfaceDescriptor {
        bitrate: BitrateBps::guess(5_000),
        announce_bandwidth_cap: AnnounceBandwidthCap::RNS_DEFAULT,
        ..routable_descriptor(id)
    }
}

#[test]
fn pooled_egress_retag_relabels_a_lane_and_ignores_a_missing_id() {
    let old_id = InterfaceId::new([0x11; 8]);
    let new_id = InterfaceId::new([0x22; 8]);
    const FRAME: usize = EMBEDDED_MAX_WIRE_FRAME_LEN;
    let (producer, _consumer) = leaked_grant_lane::<FRAME>(2);
    let mut egress: PooledEgress<1> = PooledEgress::new();
    let _ = egress.push(
        old_id,
        std::boxed::Box::leak(std::boxed::Box::new(producer)),
    );

    egress.retag(old_id, new_id);
    assert_eq!(egress.lanes[0].0, new_id, "the lane carries the new id");
    egress.retag(old_id, new_id);
    assert_eq!(egress.lanes[0].0, new_id, "retagging a gone id is a no-op");
}

#[test]
fn pooled_egress_distinguishes_a_full_lane_from_missing_topology() {
    let id = InterfaceId::new([0x33; 8]);
    const FRAME: usize = EMBEDDED_MAX_WIRE_FRAME_LEN;
    let (producer, _consumer) = leaked_grant_lane::<FRAME>(1);
    let mut egress: PooledEgress<1> = PooledEgress::new();
    let _ = egress.push(id, std::boxed::Box::leak(std::boxed::Box::new(producer)));

    assert_eq!(egress.enqueue(id, b"first"), EgressOutcome::Enqueued);
    assert_eq!(
        egress.enqueue(id, b"second"),
        EgressOutcome::LaneFull { lane: id }
    );
    assert_eq!(
        egress.enqueue(InterfaceId::new([0x44; 8]), b"missing"),
        EgressOutcome::NoLane
    );
}

#[test]
fn a_fleet_lane_masks_direct_and_broadcast_frames_once() {
    use crate::interfaces::{IfacContext, IfacSize};

    let supervisor = InterfaceId::from_channel_tag(InterfaceKind::AutoWifi, b"private-fleet");
    let child = InterfaceId::from_channel_tag(InterfaceKind::WifiPeer, b"peer");
    const FRAME: usize = EMBEDDED_MAX_WIRE_FRAME_LEN;
    let (producer, mut consumer) = leaked_grant_lane::<FRAME>(2);
    let mut egress: PooledEgress<1> = PooledEgress::new();
    let _ = egress.push(
        supervisor,
        std::boxed::Box::leak(std::boxed::Box::new(producer)),
    );
    let network = IfacContext::derive(Some("fleet-net"), Some("secret"), IfacSize::NARROW).unwrap();
    let ifacs = [InterfaceIfac {
        id: supervisor,
        context: network.clone(),
    }];
    let clean = bytes_from_hex(RNS_1_4_2_ANNOUNCE);

    enqueue_for_wire(&mut egress, &ifacs, child, &clean);
    let direct = consumer.try_peek().unwrap();
    assert_eq!(direct.target, FrameTarget::Direct(child));
    let mut opened = [0u8; FRAME];
    let opened_len = network.unmask_inbound(direct.frame(), &mut opened).unwrap();
    assert_eq!(&opened[..opened_len], clean.as_slice());
    consumer.release();

    enqueue_broadcast_for_wire(
        &mut egress,
        &ifacs,
        InterfaceKind::AutoWifi,
        FanTarget::All,
        &clean,
    );
    let broadcast = consumer.try_peek().unwrap();
    assert_eq!(broadcast.target, FrameTarget::Fan(FanTarget::All));
    let opened_len = network
        .unmask_inbound(broadcast.frame(), &mut opened)
        .unwrap();
    assert_eq!(&opened[..opened_len], clean.as_slice());
    consumer.release();
}

#[test]
fn a_pacer_retains_back_to_back_announces_for_a_one_slot_direct_lane() {
    let id = InterfaceId::new([0x55; 8]);
    const FRAME: usize = EMBEDDED_MAX_WIRE_FRAME_LEN;
    let (producer, mut consumer) = leaked_grant_lane::<FRAME>(1);
    let mut egress: PooledEgress<1> = PooledEgress::new();
    let _ = egress.push(id, std::boxed::Box::leak(std::boxed::Box::new(producer)));
    let mut pacers = [InterfacePacer::from_descriptor(id, &paced_descriptor(id))];

    for bytes in [b"delivery".as_slice(), b"node"] {
        route_reaction(
            EngineReaction::Directive(Directive::SendAnnounce {
                target: id,
                bytes,
                hops: 0,
            }),
            &mut egress,
            &[],
            &mut pacers,
            InstantMillis(0),
            &mut |_| {},
        );
    }

    let first = consumer
        .try_peek()
        .expect("the first announce enters egress");
    assert_eq!(first.target, FrameTarget::Direct(id));
    assert_eq!(first.frame(), b"delivery");
    consumer.release();
    assert!(
        consumer.try_peek().is_none(),
        "the second announce waits in the pacer"
    );

    let due = soonest_pacer_release(&pacers).expect("the retained announce has a deadline");
    flush_due_pacers(&mut pacers, due, &mut egress, &[]);
    let second = consumer
        .try_peek()
        .expect("the retained announce enters the released lane");
    assert_eq!(second.target, FrameTarget::Direct(id));
    assert_eq!(second.frame(), b"node");
    consumer.release();
}

#[test]
fn a_pacer_retains_back_to_back_announces_for_a_one_slot_fleet_lane() {
    let supervisor = InterfaceId::from_channel_tag(InterfaceKind::BluetoothAuto, b"announce-fleet");
    let peer = InterfaceId::new([InterfaceKind::BluetoothPeer as u8, 0x66, 0, 0, 0, 0, 0, 0]);
    const FRAME: usize = EMBEDDED_MAX_WIRE_FRAME_LEN;
    let (producer, mut consumer) = leaked_grant_lane::<FRAME>(1);
    let mut egress: PooledEgress<1> = PooledEgress::new();
    let _ = egress.push(
        supervisor,
        std::boxed::Box::leak(std::boxed::Box::new(producer)),
    );
    let mut pacers = [InterfacePacer::from_descriptor(
        supervisor,
        &paced_descriptor(peer),
    )];

    for bytes in [b"delivery".as_slice(), b"node"] {
        route_reaction(
            EngineReaction::Directive(Directive::SendAnnounceToFleet {
                supervisor: InterfaceKind::BluetoothAuto,
                fan: FanTarget::All,
                bytes,
                hops: 0,
            }),
            &mut egress,
            &[],
            &mut pacers,
            InstantMillis(0),
            &mut |_| {},
        );
    }

    let first = consumer
        .try_peek()
        .expect("the first announce enters egress");
    assert_eq!(first.target, FrameTarget::Fan(FanTarget::All));
    assert_eq!(first.frame(), b"delivery");
    consumer.release();
    assert!(
        consumer.try_peek().is_none(),
        "the second fleet announce waits in the shared pacer"
    );

    let due = soonest_pacer_release(&pacers).expect("the retained announce has a deadline");
    flush_due_pacers(&mut pacers, due, &mut egress, &[]);
    let second = consumer
        .try_peek()
        .expect("the retained fleet announce enters the released lane");
    assert_eq!(second.target, FrameTarget::Fan(FanTarget::All));
    assert_eq!(second.frame(), b"node");
    consumer.release();
}