Skip to main content

ReinitializeHandler

Type Alias ReinitializeHandler 

Source
pub type ReinitializeHandler = Arc<dyn Fn(&ReinitializeContext, &mut ObjectDatabase) -> Result<(), Error> + Send + Sync>;
Expand description

Carries out a ReinitializeDevice request (Clause 16.4) on a full server or an endpoint session.

It is called only for a request that decoded, passed its password check and names a state the clause defines. Ok(()) sends the SimpleACK; an Err is sent in its place. The rules:

  • Reply first, restart later. The SimpleACK goes out only after the handler returns, so it must not restart the device inline. Accept or refuse, prepare, and schedule the restart (or the backup or restore step) to run after the reply: Clause 16.4.2 has the device acknowledge the request before it shuts down.
  • No reply signal yet. Nothing tells the application when the SimpleACK has left (#1565), so any delay before restarting is best effort, and on MS/TP it can need longer: a postponed reply waits for the token. BACnetServer::stop seals responses and aborts request tasks before joining them, so a restart path that stops the server before the reply has left drops the SimpleACK. On a full server, accepted WARMSTART/COLDSTART ends DISABLE_INITIATION immediately (Clause 16.1.2), cancels its timer and resumes held COV, even if the reply later fails.
  • Be quick. It runs synchronously on a runtime worker with the object database write-locked, so every other request waits for it. Hand slow work, such as writing backup files, to a task. On an endpoint session a blocking handler stalls the whole session.
  • Database edits are raw. On a full server, changes made through the &mut ObjectDatabase skip what BACnetServer::write_local adds around a write: the Object_Name uniqueness check, the COV fanout, the event pass, Schedule and Command follow-ups, and the Audit record. A change that needs them, as ACTIVATE_CHANGES work on Network Port or Device properties may, belongs in write_local, called after the reply from a task the handler schedules (for example by sending the change to the code that holds the server).
  • Gate the requester. Without reinit_password any peer reaches the handler. MutationPolicy and the mutation authorizer don’t cover ReinitializeDevice, so check the ReinitializeContext to restrict sources.
  • Refuse with Error::Protocol. Its class and code go back in an Error PDU, for example DEVICE / CONFIGURATION_IN_PROGRESS (Clause 16.4.1.3.1). Once the handler has run, the request may no longer be rejected (Clause 20.1.8), so an Error::Reject, or any error other than Protocol or Structured, is sent as SERVICES / OTHER. A panic is caught (with unwind builds) and also answered SERVICES / OTHER, since the handler may have partly acted.

Aliased Type§

pub struct ReinitializeHandler { /* private fields */ }