pub struct RouterApplicationPort { /* private fields */ }Expand description
The application entity of a running BACnetRouter as a
TransportPort (#1808): give it to a stack that runs on a transport,
such as bacnet-client’s BACnetClient, and the stack’s requests go
through the router’s table, and its replies come back from the router.
Made by StartedRouter::into_application_port, from the router’s own
local APDU receiver: the stack on the port gets every APDU the router
delivers to its application. StartedRouter::into_application_ports
makes two instead, for a client and a server (RouterApplicationPorts).
A remote device is addressed by its network and MAC, as a routed device
(with any MAC as the router’s; the table picks the next hop), whether its
network is directly attached or not. A device’s reply carries its network
and MAC as its source either way. The port has no local network, so a
send with no DNET, such as a local broadcast, is refused with
Error::Encoding, and so is a network message.
The stack’s answers to confirmed requests it receives, such as the acknowledgement of a confirmed COV notification, go back through the reply plan the router saved with each request, for up to 30 seconds and 64 requests at a time, as a server’s replies do. A send the router refuses there fails with the transport error the plan reports.
A refusal from BACnetRouter::originate fails the send:
OriginateError::TooLong as Error::SendTooLong, every other one
as Error::Transport carrying the OriginateFailure, which
OriginateFailure::from_error gets back. A network the table lacks
fails with OriginateError::NoRoute and starts a search for it, as
originate does; once the router has learned the route, a retry goes.
TransportPort::max_npdu reports the smallest NPDU limits among the
router’s ports as they are now, and TransportPort::max_npdu_changes
publishes each change once the port has started, such as a BACnet/SC
port’s on hub failover (#2070). TransportPort::egress_apdu_limit
follows them, so a stack that reads it for each request, as
BACnetClient does, builds the next request for the new limit.
TransportPort::local_receive_apdu_capacity is different: it is fixed
from the router ports’ limits when the port is made, and a later fall
leaves it alone (#2087). The port can’t know a future failover’s limit,
so there is nothing smaller to declare at creation, and the trait keeps
the declaration stable so the stacks above need not follow a moving one.
A stack may therefore advertise more, such as a server’s
Max_APDU_Length_Accepted, than a shrunken path carries back. The router
guards that path instead: a message routed onto it that is too long is
refused with reject reason 4 (message too long) to its source, and the
port’s own send that is too long for it fails with
Error::SendTooLong.
TransportPort::stop closes the port’s queue. Stopping the router
closes its local receiver, which closes the port’s queue too, and every
later send fails with OriginateFailure::Stopped.
let started = BACnetRouter::start(ports, RouterOptions::new()).await?;
let (router, port, _controls) = started.into_application_port();
// `BACnetClient::generic_builder().transport(port).build()` gives a
// client whose requests the router originates.Implementations§
Source§impl RouterApplicationPort
impl RouterApplicationPort
Sourcepub fn with_source(self, source: SourceSelection) -> Self
pub fn with_source(self, source: SourceSelection) -> Self
The router’s address each request names as its source, by default
SourceSelection::EgressPort: see Request::source.
Sourcepub fn with_max_npdu(self, max_npdu: NpduLimits) -> Self
pub fn with_max_npdu(self, max_npdu: NpduLimits) -> Self
Report at most max_npdu from TransportPort::max_npdu, below
the router ports’ smallest limits when those are larger. The router
still refuses a request too long for the port it leaves by.
Trait Implementations§
Source§impl Debug for RouterApplicationPort
impl Debug for RouterApplicationPort
Source§impl Drop for RouterApplicationPort
impl Drop for RouterApplicationPort
Source§impl TransportPort for RouterApplicationPort
impl TransportPort for RouterApplicationPort
Source§fn local_receive_apdu_capacity(&self) -> u16
fn local_receive_apdu_capacity(&self) -> u16
Fixed when the port is made: a declaration that limit changes leave
alone (#2087). After a router port’s limit falls, the router refuses
what no longer fits that path, with reject reason 4 for a routed
message and Error::SendTooLong for this port’s own send.
Source§async fn start(&mut self) -> Result<Receiver<ReceivedNpdu>, Error>
async fn start(&mut self) -> Result<Receiver<ReceivedNpdu>, Error>
Source§fn abort(&mut self)
fn abort(&mut self)
Source§async fn send_unicast(&self, npdu: &[u8], _mac: &[u8]) -> Result<(), Error>
async fn send_unicast(&self, npdu: &[u8], _mac: &[u8]) -> Result<(), Error>
Source§async fn send_broadcast(&self, npdu: &[u8]) -> Result<(), Error>
async fn send_broadcast(&self, npdu: &[u8]) -> Result<(), Error>
Error::SendTooLong, when returned, has the same meaning as in
Self::send_unicast.Source§fn egress_apdu_limit(&self) -> u16
fn egress_apdu_limit(&self) -> u16
Source§fn max_npdu(&self) -> NpduLimits
fn max_npdu(&self) -> NpduLimits
Source§fn max_npdu_changes(&self) -> Option<Receiver<NpduLimits>>
fn max_npdu_changes(&self) -> Option<Receiver<NpduLimits>>
Self::max_npdu while the transport runs, for a
link whose limit can change after start, or None, the default,
when it never does. Read moreSource§fn bip_broadcast_endpoint(&self) -> Option<SocketAddrV4>
fn bip_broadcast_endpoint(&self) -> Option<SocketAddrV4>
None means the link does not expose that capability. Wrappers must
forward the underlying value. After start, the port is the actual
bound UDP port, including when configuration requested port zero.Source§fn supports_local_nonrouter_number_controls(&self) -> bool
fn supports_local_nonrouter_number_controls(&self) -> bool
Source§fn bip_port(&self) -> Option<BipPort>
fn bip_port(&self) -> Option<BipPort>
Source§fn bip6_port(&self) -> Option<Bip6Port>
fn bip6_port(&self) -> Option<Bip6Port>
bip_port, under the same
contract. A transport should report at most one of the two; when
one reports both, registration takes the B/IP port and ignores this
one. The default refuses registration.Source§fn prepare_for_routing(&mut self)
fn prepare_for_routing(&mut self)
Source§fn send_unicast_with_data_attributes<'a>(
&'a self,
npdu: &'a [u8],
mac: &'a [u8],
_data_attributes: &'a [DataAttribute],
) -> impl Future<Output = Result<(), Error>> + Send + 'a
fn send_unicast_with_data_attributes<'a>( &'a self, npdu: &'a [u8], mac: &'a [u8], _data_attributes: &'a [DataAttribute], ) -> impl Future<Output = Result<(), Error>> + Send + 'a
Source§fn send_broadcast_with_data_attributes<'a>(
&'a self,
npdu: &'a [u8],
_data_attributes: &'a [DataAttribute],
) -> impl Future<Output = Result<(), Error>> + Send + 'a
fn send_broadcast_with_data_attributes<'a>( &'a self, npdu: &'a [u8], _data_attributes: &'a [DataAttribute], ) -> impl Future<Output = Result<(), Error>> + Send + 'a
Source§fn is_broadcast_mac(&self, _mac: &[u8]) -> bool
fn is_broadcast_mac(&self, _mac: &[u8]) -> bool
mac is this data link’s broadcast address. Read moreSource§fn is_group_destination(&self, mac: &[u8]) -> bool
fn is_group_destination(&self, mac: &[u8]) -> bool
mac with no DNET reaches a group of nodes rather
than one: this link’s broadcast MAC, or any other broadcast or
multicast address the medium carries, such as a B/IP limited
broadcast or an Ethernet multicast MAC (#1493). A B/IPv6 MAC is a
3-octet VMAC, which never names a group. Such a send is a local
broadcast, which may carry only an Unconfirmed-Request (Clause 6.3),
so a sender that takes a caller-chosen MAC refuses anything else to it
(#1479). The server binds
no device to one, and the confirmed requests it starts itself, to
event recipients, Channel and Command targets, audit recipients and
bound devices, never go to one (#1493). Its replies and COV
notifications go to the source a request came from, and the server,
the client and the endpoint ignore a confirmed request whose source
MAC is one (#1504), so those don’t go to a group on this link. A
routed request’s SADR names a node on another network, which this
link can’t judge: a reply to a group SADR is dropped only where the
final router is a BACnetRouter, which delivers only an
Unconfirmed-Request to a DADR that is a group on its delivery port,
as that port’s local broadcast when it is one of
Self::local_broadcast_destinations, and drops anything else,
network messages included. Read moreSource§fn group_destinations(&self) -> GroupDestinations
fn group_destinations(&self) -> GroupDestinations
Self::is_group_destination as an owned rule that a sender can keep
once the transport has moved into the task that runs it. The built-in
transports give their rule; the default is
GroupDestinations::unknown, which leaves the check to the send path.Source§fn local_broadcast_destinations(&self) -> GroupDestinations
fn local_broadcast_destinations(&self) -> GroupDestinations
NetworkLayer::send_apdu and BACnetRouter
send an Unconfirmed-Request for one through Self::send_broadcast
(#1677). It is a part of Self::group_destinations, and the default
is all of it. B/IP keeps the groups at the link’s own UDP port: one
at another port belongs to another B/IP network, so a send there is
refused, not turned into this one’s broadcast.