Safe API Framework
Layered API framework for safety-related applications (ERTMS RBC reference targeting CENELEC EN 50128 SIL 4)
Loading...
Searching...
No Matches
sapi_dual_negotiator.h File Reference

Dual state negotiator of ADR-020: decides sapi_dual_state_t for both this instance and its peer, driven over an attached sapi_dual_channel_t's STATE-frame flow. More...

Include dependency graph for sapi_dual_negotiator.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  sapi_dual_negotiator_t
 One sapi_dual_negotiator_t instance's state. Caller-owned storage; every field is private - reach it only through the functions below. More...
struct  sapi_dual_negotiator_config_t
 Configuration for sapi_dual_negotiator_init(). More...

Typedefs

typedef void(*) sapi_dual_negotiator_state_change_callback_t(sapi_dual_state_t new_own_state, sapi_dual_state_t old_own_state, sapi_dual_state_t new_peer_state, sapi_dual_state_t old_peer_state, void *user_ctx)
 Optional callback invoked whenever either the own or the peer sapi_dual_state_t changes, from inside sapi_dual_negotiator_execute().

Functions

sapi_status_t sapi_dual_negotiator_init (sapi_dual_negotiator_t *negotiator, const sapi_dual_negotiator_config_t *config)
 Initializes a sapi_dual_negotiator_t. Captures this instance's own startup timestamp once (sapi_timer_now(), degrading to 0 if no timer backend is registered - same best-effort posture as sapi_log_write_event()'s Timestamp field) for use on every beacon this negotiator ever sends - see sapi_dual_state_frame_t's own doc on why this must stay fixed. Both own and peer state start at SAPI_DUAL_STATE_IDLE.
sapi_status_t sapi_dual_negotiator_execute (sapi_dual_negotiator_t *negotiator, sapi_duration_ms_t receive_timeout_ms)
 Drives one round of state negotiation: refreshes own_channel_degraded from the attached channel's current sapi_dual_channel_get_status(), sends this instance's own beacon, drains and processes every currently-pending inbound STATE frame, then recomputes both own and peer sapi_dual_state_t:
sapi_dual_state_t sapi_dual_negotiator_get_own_state (const sapi_dual_negotiator_t *negotiator)
 Returns this instance's own current sapi_dual_state_t.
sapi_dual_state_t sapi_dual_negotiator_get_peer_state (const sapi_dual_negotiator_t *negotiator)
 Returns this instance's last-known view of the peer's sapi_dual_state_t.

Detailed Description

Dual state negotiator of ADR-020: decides sapi_dual_state_t for both this instance and its peer, driven over an attached sapi_dual_channel_t's STATE-frame flow.

One-directional dependency (ADR-020 section 3): sapi_dual_negotiator_t depends on an already-initialized sapi_dual_channel_t (given to it at config time) and drives its own periodic beacon traffic through that channel's sapi_dual_channel_send_state_frame()/_receive_state_frame() pair; sapi_dual_channel_t itself has no knowledge of this module.

Intended call pattern: sapi_dual_negotiator_execute() once per application cycle (the same way sapi_channel_checkpoint() is driven today - ADR-017), after the application has already driven sapi_dual_channel_send()/_receive() for its own real payload traffic that cycle if it has any.

REQ-DUAL-NEGOTIATOR-001: no dynamic allocation; caller supplies storage and an already-initialized sapi_dual_channel_t. REQ-DUAL-NEGOTIATOR-002: sapi_dual_negotiator_execute() shall never call sapi_safestate_enter() itself - deciding what a sustained SAPI_DUAL_STATE_UNKNOWN means for safety stays an application policy decision (ADR-020 section 4's "no automatic safety reaction" non-goal). REQ-DUAL-NEGOTIATOR-003: the initial ONLINE-vs-STANDBY decision uses an older-startup-timestamp-wins rule, with own_id/peer_id as a deterministic fallback only on an exact timestamp tie. REQ-DUAL-NEGOTIATOR-004: whichever side is currently STANDBY has its HOT/COLD label derived from the ONLINE side's own channel-degradation bit - never from the STANDBY side's own self-report, and never from the ONLINE side's opinion of itself. REQ-DUAL-NEGOTIATOR-005: loss of peer contact past config->peer_lost_timeout_ms sets peer_state to UNKNOWN; own_state degrades to UNKNOWN too unless it was already ONLINE, which stays ONLINE.

Definition in file sapi_dual_negotiator.h.