#![allow(dead_code)]
use core::net::{Ipv4Addr, SocketAddrV4};
use bacnet_bip_codec::{BvlcFunction, BvlcResultCode, Bvll, BvllFrame};
use bacnet_bip_core::node::{
Action, Addressed, Datagram, Foreign, Lease, Link, Mode, Node, Outgoing, Permissive, Policy,
Received, SendRefusal,
};
use bacnet_bip_core::port::Datagrams;
use bacnet_bip_core::{Duration, Instant, LocalSubnet};
pub const PORT: u16 = 0xBAC0;
pub const fn addr(a: u8, b: u8, c: u8, d: u8, port: u16) -> SocketAddrV4 {
SocketAddrV4::new(Ipv4Addr::new(a, b, c, d), port)
}
pub const OWN: SocketAddrV4 = addr(192, 168, 1, 10, PORT);
pub const BROADCAST: SocketAddrV4 = addr(192, 168, 1, 255, PORT);
pub const SUBNET: LocalSubnet = LocalSubnet::new(BROADCAST);
pub const PEER: SocketAddrV4 = addr(192, 168, 1, 20, PORT);
pub const BBMD: SocketAddrV4 = addr(10, 0, 0, 1, PORT);
pub const REMOTE: SocketAddrV4 = addr(172, 16, 0, 7, PORT);
pub const UNICAST: Addressed = Addressed {
node: true,
broadcast: false,
};
pub const TO_BROADCAST: Addressed = Addressed {
node: false,
broadcast: true,
};
pub fn link(mode: Mode) -> Link {
Link::new(OWN, SUBNET, mode).expect("valid link")
}
pub fn foreign() -> Foreign {
Foreign::new(BBMD, 60)
}
pub fn foreign_link(foreign: Foreign) -> Link {
link(Mode::Foreign(foreign))
}
pub fn wire(message: Bvll<'_>) -> Vec<u8> {
let mut out = vec![0; message.encoded_len().expect("encodable")];
message.encode_into(&mut out).expect("fits");
out
}
pub fn raw(function: u8, payload: &[u8]) -> Vec<u8> {
let length = u16::try_from(4 + payload.len()).expect("short");
let mut out = vec![0x81, function];
out.extend_from_slice(&length.to_be_bytes());
out.extend_from_slice(payload);
BvllFrame::decode(&out).expect("header checks out");
out
}
pub fn datagram(payload: &[u8], source: SocketAddrV4, to: Addressed) -> Datagram<'_> {
Datagram::new(payload, source, Some(to))
}
pub fn sent(outgoing: Outgoing<'_>) -> (SocketAddrV4, Bvll<'_>) {
(outgoing.to, outgoing.message)
}
pub fn span(lease: Lease) -> (Instant, Instant) {
(lease.since, lease.until)
}
pub fn with<T>(mut value: T, edit: impl FnOnce(&mut T)) -> T {
edit(&mut value);
value
}
pub fn receive<'d>(
link: &Link,
payload: &'d [u8],
source: SocketAddrV4,
to: Addressed,
) -> Received<'d> {
link.receive(
&datagram(payload, source, to),
Instant::ZERO,
&mut Permissive,
)
}
pub fn receive_datagram<'d>(link: &Link, datagram: &Datagram<'d>) -> Received<'d> {
link.receive(datagram, Instant::ZERO, &mut Permissive)
}
pub const fn at(millis: u64) -> Instant {
Instant::from_millis(millis)
}
pub const fn ms(millis: u64) -> Duration {
Duration::from_millis(millis)
}
pub fn result(code: BvlcResultCode) -> Vec<u8> {
wire(Bvll::BvlcResult(code))
}
pub const SUCCESS: BvlcResultCode = BvlcResultCode::SUCCESSFUL_COMPLETION;
pub fn drain<const X: usize>(node: &mut Node<X>) -> Vec<Action> {
let mut actions = Vec::new();
loop {
match node.poll_action() {
Action::Idle => return actions,
action => actions.push(action),
}
}
}
#[derive(Debug, Default)]
pub struct Recording {
pub admit: bool,
pub accept: bool,
pub asked: Vec<BvlcFunction>,
}
impl Recording {
pub fn new(admit: bool, accept: bool) -> Self {
Self {
admit,
accept,
asked: Vec::new(),
}
}
}
impl Policy for Recording {
fn admit_management(&mut self, _: SocketAddrV4, function: BvlcFunction, _: Instant) -> bool {
self.asked.push(function);
self.admit
}
fn accept_table(&mut self, ack: &Bvll<'_>) -> bool {
self.asked.push(ack.function());
self.accept
}
}
#[derive(Debug, Default)]
pub struct Socket {
pub sent: Vec<(SocketAddrV4, Vec<u8>)>,
pub calls: usize,
pub refuse: Option<SendRefusal>,
}
impl Datagrams for Socket {
fn send(&mut self, to: SocketAddrV4, message: &Bvll<'_>) -> Result<(), SendRefusal> {
self.calls += 1;
if let Some(why) = self.refuse {
return Err(why);
}
self.sent.push((to, wire(*message)));
Ok(())
}
}
impl Socket {
pub fn take(&mut self) -> Vec<(SocketAddrV4, Vec<u8>)> {
core::mem::take(&mut self.sent)
}
}