Some applications buffer events in external storage (database, queue, file) upstream of the DNP3 stack and feed them into the library's in-memory event buffers in batches via transaction. In that architecture, the stack's view of "are there pending class N events" is incomplete — it only knows about events already pushed in.
That breaks down with masters that read a clear CLASS_n_EVENTS IIN bit on an integrity-poll response as "outstation has nothing more to report" and tear down the connection until the next scheduled poll. We've seen field deployments where the master disconnects after each integrity poll that drains the in-memory buffer and then waits hours before re-polling, even when the application has a backlog ready to push in.
The application needs a way to tell the stack "I have class N events you don't know about yet" so the IIN bits on outgoing responses reflect the full system state, not just the in-memory buffer.
This is a niche feature. Most applications push events directly into the DNP3 buffer via transaction and should ignore it — the buffer-derived IIN bits are correct for them.
Proposal: add class_1_events / class_2_events / class_3_events boolean fields to ApplicationIin. They get OR'd with the buffer-derived bits in get_response_iin, so false is a no-op and true asserts the bit even when the in-memory buffer is empty. The override cannot clear a bit the buffer says should be set, and it doesn't touch the unsolicited path or the internal unwritten_classes bookkeeping. The application is responsible for clearing the override once its external queue drains.
Field doc:
Set this only if your application maintains an event queue upstream of the DNP3 event buffer and there are pending class-N events not yet pushed in via transaction. Most applications should leave this false and let the in-memory buffer state speak for itself.
Compatibility: Rust callers using ..Default::default() are unaffected; positional struct literals break. The FFI no-arg ApplicationIin() constructor is unchanged (the new fields default to false in the schema initializer); the all-fields constructor goes from 4-arg to 7-arg. Every shipped binding example uses the no-arg form, so the breakage is narrow. Lands in 1.7.0-RC2 with the constructor change called out in the changelog.
Longer term (#315), ApplicationIin should become a builder along with the other small return-value structs so additive fields stop being API breakage events. This change is the expedient until that 2.0 sweep.
Some applications buffer events in external storage (database, queue, file) upstream of the DNP3 stack and feed them into the library's in-memory event buffers in batches via
transaction. In that architecture, the stack's view of "are there pending class N events" is incomplete — it only knows about events already pushed in.That breaks down with masters that read a clear
CLASS_n_EVENTSIIN bit on an integrity-poll response as "outstation has nothing more to report" and tear down the connection until the next scheduled poll. We've seen field deployments where the master disconnects after each integrity poll that drains the in-memory buffer and then waits hours before re-polling, even when the application has a backlog ready to push in.The application needs a way to tell the stack "I have class N events you don't know about yet" so the IIN bits on outgoing responses reflect the full system state, not just the in-memory buffer.
This is a niche feature. Most applications push events directly into the DNP3 buffer via
transactionand should ignore it — the buffer-derived IIN bits are correct for them.Proposal: add
class_1_events/class_2_events/class_3_eventsboolean fields toApplicationIin. They get OR'd with the buffer-derived bits inget_response_iin, sofalseis a no-op andtrueasserts the bit even when the in-memory buffer is empty. The override cannot clear a bit the buffer says should be set, and it doesn't touch the unsolicited path or the internalunwritten_classesbookkeeping. The application is responsible for clearing the override once its external queue drains.Field doc:
Compatibility: Rust callers using
..Default::default()are unaffected; positional struct literals break. The FFI no-argApplicationIin()constructor is unchanged (the new fields default tofalsein the schema initializer); the all-fields constructor goes from 4-arg to 7-arg. Every shipped binding example uses the no-arg form, so the breakage is narrow. Lands in 1.7.0-RC2 with the constructor change called out in the changelog.Longer term (#315),
ApplicationIinshould become a builder along with the other small return-value structs so additive fields stop being API breakage events. This change is the expedient until that 2.0 sweep.