Skip to main content

RouterApplicationPort

Struct RouterApplicationPort 

Source
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

Source

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.

Source

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

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Drop for RouterApplicationPort

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

fn pin_drop(self: Pin<&mut Self>)

🔬This is a nightly-only experimental API. (pin_ergonomics)
Execute the destructor for this type, but different to Drop::drop, it requires self to be pinned. Read more
Source§

impl TransportPort for RouterApplicationPort

Source§

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>

Start the transport. Returns a receiver for incoming NPDUs. Read more
Source§

async fn stop(&mut self) -> Result<(), Error>

Stop the transport and clean up resources.
Source§

fn abort(&mut self)

Synchronously abort background work and release owned transport resources. Read more
Source§

async fn send_unicast(&self, npdu: &[u8], _mac: &[u8]) -> Result<(), Error>

Send NPDU bytes to a specific MAC address (unicast). Read more
Source§

async fn send_broadcast(&self, npdu: &[u8]) -> Result<(), Error>

Broadcast NPDU bytes on the local network. Error::SendTooLong, when returned, has the same meaning as in Self::send_unicast.
Source§

fn local_mac(&self) -> &[u8] ⓘ

This transport’s local MAC address.
Source§

fn egress_apdu_limit(&self) -> u16

Current outgoing APDU limit for the transport’s ordinary send path. This may change as a connection negotiates remote receive limits.
Source§

fn max_npdu(&self) -> NpduLimits

The longest NPDU this link sends, to one node and to every node. Read more
Source§

fn max_npdu_changes(&self) -> Option<Receiver<NpduLimits>>

The changes to 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 more
Source§

fn bip_broadcast_endpoint(&self) -> Option<SocketAddrV4>

Configured broadcast endpoint when this link uses IPv4 BACnet/IP. 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

Opt in to the existing single-link nonrouter Network Number owner. Read more
Source§

fn bip_port(&self) -> Option<BipPort>

Explicit capability for registration as one IPv4 Network Port, with the B/IP mode the port reports (Clause 12.56.21). Read more
Source§

fn bip6_port(&self) -> Option<Bip6Port>

Explicit capability for registration as one IPv6 Network Port, with the B/IPv6 mode the port reports (Clause 12.56.39): the B/IPv6 counterpart of 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)

Prepare the transport to be a port of a router, before it starts. Read more
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

Send NPDU bytes with data attributes to a specific MAC address. Read more
Source§

fn send_broadcast_with_data_attributes<'a>( &'a self, npdu: &'a [u8], _data_attributes: &'a [DataAttribute], ) -> impl Future<Output = Result<(), Error>> + Send + 'a

Broadcast NPDU bytes with data attributes on the local network. Read more
Source§

fn is_broadcast_mac(&self, _mac: &[u8]) -> bool

Whether mac is this data link’s broadcast address. Read more
Source§

fn is_group_destination(&self, mac: &[u8]) -> bool

Whether a send to 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 more
Source§

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

The group destinations a send with no DNET may reach as this link’s local broadcast instead: 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.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more