RTE RBC 2oo2 Reference Application 0.1.0 build 0006685
SIL 4 2oo2 Dual-Site Fault-Tolerant ERTMS Radio Block Centre Reference Architecture
Loading...
Searching...
No Matches
File List
Here is a list of all files with brief descriptions:
 
docs
 
interfaces
 src
  application
   AB
    common
     
app_main_common.c
See app_main_common.h
     
app_main_common.h
Process-wide runtime setup shared by every one of this example's binaries (main.c for A/B, main_c.c for C) - OSAdapter registration, checksum/watchdog/log init, signal handlers, and the REBOOT safe-state handler. Split out so this ~70-line sequence is written once instead of duplicated across both main() entry points now that C has its own binary (see CMakeLists.txt)
     
common_config.h
     
rbc_util_frame.h
ADR-038: the wire frame for the A/B<->C util side channel (RTE_EXAMPLE_RELAY_KIND_UTIL) and the C-side pub/sub broker
     
rbc_util_jru_payload.h
Wire payload for RBC_UTIL_TOPIC_JRU_LOG publishes: A/B forwarding one local log event to Gateway, for Gateway to hand to Platform_Protocol_JRU's rte_osadapter_log_t
     
rbc_util_km114_relay.h
Wire chunking for RBC_UTIL_TOPIC_KM114_FILE publishes: Gateway relays one opaque Subset-114 off-line KMC file's raw bytes to A/B, split across as many UTIL frames as needed. Gateway never interprets these bytes - see rbc_util_frame.h's own doc on this topic and Platform_Protocol_KM114/CLAUDE.md's "Consumption design" note
     
rbc_wire_types.h
The RBC Train/IL/CTC scenario's shared wire envelope (ADR-029) - one fixed-size struct/frame reused for every message kind exchanged between C and the Train/IL/CTC sims, AND between C and A/B (the same envelope end-to-end - see monitor_c.c's own header). Pure types, no I/O - encode/decode is owned per-domain by AB/train/ab_gp_train.c, AB/GA/il/ab_ga_il.c, and AB/GA/ctc/ab_ga_ctc.c (each a file-static codec over the kinds its own relay channel carries; no single shared codec file)
     
site_config.c
See site_config.h
     
site_config.h
West/East site identity and the per-site config derived from it (ports, container host lookup) - see common_config.h for the raw port bases/offsets this module turns into concrete per-site values
    GP
     com
      
ab_gp_channel.c
Channel A / channel B com layer using native RTE rte_channel_service
      
ab_gp_channel.h
      
ab_gp_channel_checkpoint.c
Checkpoint rte_channel OSAdapter adapter over the A<->B peer link
      
ab_gp_channel_checkpoint.h
Rte_channel_t OSAdapter for the built-in AppManager checkpoint (ADR-019 addendum, rewired onto rte_voter_t by ADR-025), wrapping the same peer link ab_gp_channel_io.c already uses. A single rte_channel_t is registered into a 1-channel NMR voter (quorum_size == 1) - the "channel" handle rte_channel hands back to these callbacks is a ab_gp_channel_context_t itself (see ab_gp_channel_context_t::checkpoint_channel_handle)
      
ab_gp_channel_crosscompare.c
A-vs-B cross-compare decision, routed through rte_cross_comparator (ADR-025) - see ab_gp_channel_crosscompare.h
      
ab_gp_channel_crosscompare.h
The actual A-vs-B cross-compare decision: does this cycle's own M24/M15 answer match what the peer independently decided? Reads this cycle's inputs from ctx->cyc_* (populated by ab_gp_channel.c's own ab_gp_channel_read_channels()/ ab_gp_channel_read_and_stash_peer_sample()); writes ctx->cyc_agree
      
ab_gp_channel_dual.c
This channel's own dual-transfer/role state - see ab_gp_channel_dual.h
      
ab_gp_channel_dual.h
Everything related to this channel's own "dual transfer" state: the single-mode degradation reaction when the A<->B peer stops answering at all, and this site's role-byte formatting helper. This site's live ONLINE/STANDBY/FAULTED role itself is now in-memory state (ctx->is_online/ctx->own_faulted), driven by the inter-site negotiate step in ab_gp_channel.c - see that file's own doc. Distinct from (and a legacy, hand-rolled precedent for) safeAPIFreamwork's own rte_dual framework module (ADR-020) - see that module's ADR for the reusable, generalized version of this same idea; this file is application-specific glue that predates it and is not retrofitted to use it in this pass (see ADR-020 section 4's own non-goals)
      
ab_gp_channel_negotiate.c
This channel's Site Role Client (ADR-040 step 2): the inter-site link, the ONLINE/STANDBY negotiation, partner supervision, takeover handling and warm-standby sync are Platform_RTE's rte_site_role service; this file supplies what is application specific and keeps GP's own entry points (ab_gp_channel_negotiate.h):
      
ab_gp_channel_negotiate.h
This channel's own West<->East inter-site negotiation link - see ab_gp_channel.c's file header for how this fits into the overall 6-container topology. Ported from the old standalone SITE role (SITE/site.c, now deleted): the same real rte_dual_channel_t + rte_dual_negotiator_t (ADR-020) startup tie-break and live promotion/demotion/deadlock rules, now driven once per A/B cycle (ab_gp_channel_read_channels()) instead of a standalone heartbeat timer, and mutating ctx->is_online/ctx->own_faulted directly instead of a shared NVM role region - see common_config.h's own doc on why no filesystem sharing is assumed between containers
      
ab_gp_channel_payload.c
Generic collector registry + AB_SAMPLE framing - see ab_gp_channel_payload.h
      
ab_gp_channel_payload.h
Generic, data-blind wire framing for the A<->B peer link's AB_SAMPLE frame (CRC-64-protected, ADR-029) and ab_gp_channel_negotiate.c's own state-transfer extra DATA payload. This file has no knowledge of what any collector's own data represents - each module that owns wire data (today: only AB/GP/train/ab_gp_train.c, via ab_gp_train_init()) registers its own whole-array encode/decode pair with ab_gp_channel_payload_register_collector() below, claiming a fixed byte range in registration order; this file only concatenates those ranges into one buffer and CRC-64-protects the result. Pure codec/framing functions - no ab_gp_channel_context_t, no I/O, no logging beyond the fail-safe cases documented below; see ab_gp_channel_io.c for the actual rte_netlink_send()/_receive() calls that move these bytes
      
ab_gp_channel_stage.c
Stage-then-commit output queue - see ab_gp_channel_stage.h
      
ab_gp_channel_stage.h
Stage-then-commit output queue for this cycle's own DECISION output (ADR-034): the peer AB_SAMPLE and the train/CTC/IL relay messages built from this cycle's own ma_logic result. Queued via ab_gp_channel_stage_peer()/_stage_relay() instead of sending immediately, then either transmitted (via the real ab_gp_channel_send_peer()/_send_relay()) or discarded once the cycle's own checkpoint rendezvous confirms - or fails to confirm
      
ab_gp_channel_types.h
Modular type definitions for AB channel components (Com, Train, DB, Redundancy)
      
ab_gp_channel_util.c
Ab_gp_channel_sleep_ms() - shared bounded-sleep helper used by ab_gp_channel.c (cycle-tick wait), ab_gp_channel_io.c (reconnect retry pacing), and ab_gp_channel_checkpoint.c (reply poll loop)
      
ab_gp_channel_util.h
Declares ab_gp_channel_sleep_ms() - see ab_gp_channel_types.h's own doc on why this tiny helper gets a dedicated translation unit instead of living inline in the shared types header
      
ab_gp_config.c
Zero-dependency, statically-allocated configuration parser for Role A/B
      
ab_gp_config.h
Zero-dependency, statically-allocated configuration parser for Role A/B
      
ab_gp_cycle_ticks.c
See ab_gp_cycle_ticks.h
      
ab_gp_cycle_ticks.h
A/B cycle tick count shared by the cycle timer callback and the cycle thread (ISS-051)
      
ab_gp_jru_forward.c
See ab_gp_jru_forward.h
      
ab_gp_jru_forward.h
A/B -> Gateway log-event forwarding (Platform_Protocol_JRU/CLAUDE.md's "Wiring" section). Installs an rte_osadapter_log_t that delegates every write() to the real local adapter (unchanged local stderr behaviour) and additionally, once a channel is attached, republishes INFO+ events to Gateway over RBC_UTIL_TOPIC_JRU_LOG - Gateway's status service forwards them on to Platform_Protocol_JRU
      
ab_gp_km114_client.c
See ab_gp_km114_client.h
      
ab_gp_km114_client.h
A/B-side Subset-114 KMC message decoder - step 2 of Platform_Protocol_KM114's "Consumption design" (see that product's own CLAUDE.md). Takes the raw bytes ab_gp_km114_relay.c reassembled from Gateway and does the actual decode/verify/decrypt this entity's own predefined key makes possible - Gateway never sees any of this, only opaque bytes
      
ab_gp_km114_relay.c
See ab_gp_km114_relay.h
      
ab_gp_km114_relay.h
A/B-side receiver for Gateway-relayed Subset-114 off-line KMC file bytes (RBC_UTIL_TOPIC_KM114_FILE, rbc_util_km114_relay.h). Reassembles the chunked transfer; does NOT decode it - see Platform_Protocol_KM114/CLAUDE.md's "Consumption design" note (actual km114_parse_*() decode/verify/decrypt and key installation is a separate, not-yet-implemented step - this module only gets the raw bytes back together and reports arrival)
      
ab_gp_saf_train.c
Train link SaF termination in A/B - see ab_gp_saf_train.h
      
ab_gp_saf_train.h
Train link safe communication (Subset-037 SaF) terminated inside A and B - REQ-SC-001, REQ-SC-003/004 (root docs/architecture/SAFE_COMM_INTEGRATION.dox, plan step 3)
      
ab_gp_sibling_state.c
See ab_gp_sibling_state.h
      
ab_gp_sibling_state.h
The A/B sibling's last site-state frame (PEER_MSG_KIND_SITE_STATE), kept raw and handed to Platform_RTE's rte_site_role through its sibling source (REQ-SITEROLE-016, ADR-040 step 5b). Pure, no I/O (the ab_gp_standby_policy pattern): the peer-link readers store the frame, the service takes it
      
ab_gp_site_status.c
See ab_gp_site_status.h
      
ab_gp_site_status.h
The site status monitor: collects, in one struct, the facts that decide and explain this channel's site role
      
ab_gp_standby_policy.c
See ab_gp_standby_policy.h
      
ab_gp_standby_policy.h
GP-specific standby and site-link constants, the session-adoption rule and the stall rule
      
ab_gp_startup_timestamp.c
See ab_gp_startup_timestamp.h
      
ab_gp_startup_timestamp.h
The site startup timestamp A and B agree over the A/B peer link (ADR-040 step 5a): the agreement rule and the codec of the PEER_MSG_KIND_STARTUP_TS payload. Pure, no I/O (the ab_gp_standby_policy pattern); the exchange itself is exchange_startup_timestamp() in ab_gp_channel_negotiate.c
      
ab_gp_status.c
See ab_gp_status.h
      
ab_gp_status.h
ADR-038: this A/B channel's periodic status - a self log line plus a PUBLISH(STATUS) rbc_util_frame_t out on the UTIL relay to the role-C status/broker service
      
ab_gp_takeover_key.c
See ab_gp_takeover_key.h
      
ab_gp_takeover_key.h
The site's takeover key and the token codec for the dispatcher takeover confirmation (ADR-040 step 4b)
      
ab_gp_util_link_gate.c
See ab_gp_util_link_gate.h
      
ab_gp_util_link_gate.h
Open gate of the UTIL relay link (ab-relay-util, ISS-020): bounds how often the A/B cycle thread may try the link's first open while the status service (rte_gateway_c_status) is unreachable
     db
      
ab_gp_db.c
Mechanical route<->train connect/disconnect - see ab_gp_db.h's own "Mechanical route<->train connect/disconnect" doc for why this logic lives here rather than in il/
      
ab_gp_db.h
A/B's own simplified Train/Route database - fixed-size arrays describing the domain objects logic/ (planned) will reason about when granting/extending a Movement Authority
     ertms
      train
       
ab_gp_ertms_train_interface.h
       
ab_gp_ertms_train_message_codec.c
ERTMS/ETCS Level 2 Message-Level Codec Implementation (GP)
       
ab_gp_ertms_train_message_codec.h
       
ab_gp_ertms_train_messages.h
       
ab_gp_ertms_train_packet_codec.c
ERTMS/ETCS Level 2 Packet-Level Codec Implementation (GP)
       
ab_gp_ertms_train_packet_codec.h
       
ab_gp_ertms_train_packets.h
      
ab_gp_ertms_types.h
     ertms_procedures
      
ab_gp_ertms_engine.c
Implementation of Unified ERTMS Subset-026 Chapter 5 Operational Procedure Orchestrator
      
ab_gp_ertms_engine.h
Unified ERTMS Subset-026 Chapter 5 Operational Procedure Orchestrator
      
ab_gp_ertms_types.h
ERTMS Subset-026 Chapter 5 Operational Procedure Data Types and Enums
      
ab_gp_proc_dispatch.c
See ab_gp_proc_dispatch.h
      
ab_gp_proc_dispatch.h
Glue between RBC_MSG_ERTMS_ENVELOPE wire frames and the real Subset-026 procedure engine (ab_gp_ertms_engine.h + the ab_gp_proc_*.c modules) - the missing piece that turns that already-built engine from ticking-but-unreachable scaffolding into something the live Train relay channel actually drives
      
ab_gp_proc_emergency_stop.c
Implementation of ERTMS Subset-026 §5.7 Emergency Stop Management
      
ab_gp_proc_emergency_stop.h
ERTMS Subset-026 §5.7 Emergency Stop Management Procedure
      
ab_gp_proc_eom.c
Implementation of ERTMS Subset-026 §5.9 End of Mission (EoM)
      
ab_gp_proc_eom.h
ERTMS Subset-026 §5.9 End of Mission (EoM) Procedure
      
ab_gp_proc_handover.c
ERTMS Subset-026 §5.11 RBC-to-RBC Handover Procedure (Packet 131) Implementation
      
ab_gp_proc_handover.h
ERTMS Subset-026 §5.11 RBC-to-RBC Handover Procedure (Packet 131)
      
ab_gp_proc_ma.c
Implementation of ERTMS Subset-026 §5.5 Movement Authority (MA) Management
      
ab_gp_proc_ma.h
ERTMS Subset-026 §5.5 Movement Authority (MA) Management Procedure
      
ab_gp_proc_position.c
Implementation of ERTMS Subset-026 §5.6 Supervised Location and Position Reporting
      
ab_gp_proc_position.h
ERTMS Subset-026 §5.6 Supervised Location and Position Reporting Procedure
      
ab_gp_proc_session.c
Implementation of ERTMS Subset-026 §5.3 Communication Session Management
      
ab_gp_proc_session.h
ERTMS Subset-026 §5.3 Communication Session Management Procedure
      
ab_gp_proc_shunting.c
Implementation of ERTMS Subset-026 5.6 Shunting initiated by driver
      
ab_gp_proc_shunting.h
ERTMS Subset-026 5.6 Shunting initiated by driver (Level 2)
      
ab_gp_proc_text_message.c
ERTMS Subset-026 §5.12 Plain Text Message to Driver (Packet 72) Procedure Implementation
      
ab_gp_proc_text_message.h
ERTMS Subset-026 §5.12 Plain Text Message to Driver (Packet 72) Procedure
      
ab_gp_proc_train_data.c
Implementation of ERTMS Subset-026 §5.4 Validated Train Data & Start of Mission
      
ab_gp_proc_train_data.h
ERTMS Subset-026 §5.4 & §5.2 Validated Train Data and Start of Mission Procedure
      
ab_gp_proc_tsr.c
ERTMS Subset-026 §5.10 Temporary Speed Restriction (TSR) Procedure Implementation
      
ab_gp_proc_tsr.h
ERTMS Subset-026 §5.10 Temporary Speed Restriction (TSR) Procedure
     ga_interface
      
ga_interface.h
THE single door GA (safeAPIRBC2oo2GA, a separate shared-library project) uses to reach GP - GP exports this header (GA reaches it header-only, via RTE_RBC2OO2GP_DIR, same sibling-source posture as common/) so GA's independent build can see every function signature it is allowed to call
     ma_logic
      
ab_gp_logic.c
Route<->train connect logic (GP) + its own GA callback registries - see ab_gp_logic.h
      
ab_gp_logic.h
A/B's own RBC decision logic - today's slice: connect a train's currently-reported route to that train, from the balise (NID_LRBG) it most recently reported in its Position Report
     main
      
ab_gp_channel_cycle_hooks.h
Shared declarations for the four rte_appmanager_operations_t cyclic-executive hooks this component's main.c registers - ab_gp_channel_pre_execute()/ab_gp_channel_execute()/ab_gp_channel_post_execute()/ ab_gp_channel_on_checkpoint_result() (ADR-034), each defined in its own file (pre_execute.c/execute.c/post_execute.c - the last hook lives in post_execute.c too, since it flushes/discards the very output post_execute() itself stages) as a short orchestrator over the named, single-purpose step functions AB/GP/com/ab_gp_channel.c exposes (see that file's own doc for the full phase breakdown). Declared here, not in AB/GP/com/ab_gp_channel.h, since these are implemented in this component's own main/ - not com/ - even though they take the same opaque ab_gp_channel_handle_t (cast from the rte_appmanager hook's own void *context) every other com/-facing call here does
      
ab_gp_ga_hooks.c
See ab_gp_ga_hooks.h and ga_interface.h's own "functions GP calls into GA with" section
      
ab_gp_ga_hooks.h
GP's own dispatch side of the "GP calls into GA" surface - see ga_interface.h's own "functions GP calls into GA with" section for the registration functions GA calls (ab_gp_register_il_envelope_handler()/_il_output_producer()/ _ctc_output_producer()) and the real storage/dispatch behind them (ab_gp_ga_hooks.c). The three functions below are what AB/GP/main/pre_execute.c and post_execute.c call INSTEAD of the old bare ab_ga_il_apply_envelope()/ab_ga_il_build_outputs()/ ab_ga_ctc_build_outputs() calls - each is a thin "is a handler registered? if so, call it; if not, no-op" wrapper, so a channel whose GA setup hasn't run yet (or failed) degrades to doing nothing here rather than crashing on a NULL function pointer
      
execute.c
Rte_appmanager_operations_t::execute for the AB channel
      
launcher_main.c
The rte_example EXECUTABLE target's own, entire body - a thin launcher over librte_gp (this project's own shared library, rte_gp_run() - see that function's own header, rte_gp_run.h). Exists so rte_example is a real shared-library dependent, not a monolithic executable - GP's own real logic became a .so/.dylib specifically so safeAPIRBC2oo2GA can link against it with genuinely bare C function calls both directions (symmetric dummy-then-real linking - see safeAPIRBC2oo2GA/CLAUDE.md's own doc for the full design and why the interface-pointer struct this project used before was replaced)
      
main.c
SafeAPIRBC2oo2: channel A/B binary, started as role A or B, for site WEST or EAST. C is a separate binary (C/main_c.c) - see app_main_common.c for the runtime setup shared by both. This file is the whole AB channel's own composition root: it owns both how the process starts up and how its cyclic executive is wired - deliberately kept that way so a reader can open just this file and see the whole story, rather than having to also read AB/GP/com/ab_gp_channel.c to find out how the process comes up or what each cycle does. AB/GP/com/ab_gp_channel.c is the channel factory and the real per-cycle implementation this file wires onto - see that file's own header for the mechanism; this one is the narrative
      
post_execute.c
Rte_appmanager_operations_t::post_execute for the AB channel
      
pre_execute.c
Rte_appmanager_operations_t::pre_execute for the AB channel
      
rte_gp_run.h
The one function librte_gp (this project's own shared library, see CMakeLists.txt's own doc on why rte_example is now a thin launcher over this library) exports - the old plain int main(int argc, char **argv) body, renamed and exported so launcher_main.c can call it. See main.c's own doc for what it actually does
     state_machines
      emergency_stop
       
ab_gp_emergency_stop_fsm.c
STUB - see ab_gp_emergency_stop_fsm.h
       
ab_gp_emergency_stop_fsm.h
STUB per-entity state machine for the EMERGENCY_STOP procedure
      eom
       
ab_gp_eom_fsm.c
STUB - see ab_gp_eom_fsm.h
       
ab_gp_eom_fsm.h
STUB per-entity state machine for the EOM procedure
      handover
       
ab_gp_handover_fsm.c
STUB - see ab_gp_handover_fsm.h
       
ab_gp_handover_fsm.h
STUB per-entity state machine for the HANDOVER procedure
      ma
       
ab_gp_ma_fsm.c
STUB - see ab_gp_ma_fsm.h
       
ab_gp_ma_fsm.h
STUB per-entity state machine for the MA procedure
      position
       
ab_gp_position_fsm.c
STUB - see ab_gp_position_fsm.h
       
ab_gp_position_fsm.h
STUB per-entity state machine for the POSITION procedure
      session
       
ab_gp_session_fsm.c
See ab_gp_session_fsm.h for this table's own design rationale
       
ab_gp_session_fsm.h
Event-driven legal-transition table for ab_gp_ertms_session_state_t (Subset-026 Chapter 5's various procedure states) - GP's first per-entity state machine under state_machines/ (one folder per entity: session/ here, train_data/ next; ma/, shunting/, emergency_stop/, route/, tsr/, boundary/ as they get the same treatment). All of them are fed by ab_gp_dispatch() (../ab_gp_dispatch.h) - a synchronous static event dispatcher whose one const subscription table says which FSM(s) react to each ab_gp_event_t (../ab_gp_event.h). A procedure raises an event through ab_gp_dispatch(); it never names an FSM
      shunting
       
ab_gp_shunting_fsm.c
STUB - see ab_gp_shunting_fsm.h
       
ab_gp_shunting_fsm.h
STUB per-entity state machine for the SHUNTING procedure
      text_message
       
ab_gp_text_message_fsm.c
STUB - see ab_gp_text_message_fsm.h
       
ab_gp_text_message_fsm.h
STUB per-entity state machine for the TEXT_MESSAGE procedure
      train_data
       
ab_gp_train_data_fsm.c
See ab_gp_train_data_fsm.h for this table's design rationale
       
ab_gp_train_data_fsm.h
(state, event) -> state table for ab_gp_train_data_state_t (Subset-026 §5.4 Validated Train Data acceptance) - GP's second per-entity procedure state machine under state_machines/, after session/
      tsr
       
ab_gp_tsr_fsm.c
STUB - see ab_gp_tsr_fsm.h
       
ab_gp_tsr_fsm.h
STUB per-entity state machine for the TSR procedure
      
ab_gp_dispatch.c
See ab_gp_dispatch.h. Holds the one subscription table
      
ab_gp_dispatch.h
Synchronous, statically-wired event dispatch for GP's per-entity procedure state machines (state_machines/)
      
ab_gp_event.h
The one shared event vocabulary for every GP procedure state machine under state_machines/
      
ab_gp_fsm_stub.c
See ab_gp_fsm_stub.h
      
ab_gp_fsm_stub.h
Shared "this per-entity FSM is a placeholder" handler
     train
      
ab_gp_train.c
Train lifecycle/find/getters/setters against db/'s runtime table, AND the Train-domain wire codec (train_wire_decode()/ _encode() below) - see ab_gp_train.h
      
ab_gp_train.h
A/B's own train lifecycle handling against db/'s runtime table
   C
    
gateway_c_common.c
Shared skeleton for the three Role C gateway service binaries - see gateway_c_common.h. Lifted verbatim from the old single gateway_c.c: only the "call all three handlers" sites became "call this service's one handler" (via gateway_c_service_def_t), and the version-banner / arg-parse from the old main_c.c folded into gateway_c_main()
    
gateway_c_common.h
Shared skeleton for the three Role C gateway service binaries (rte_gateway_c_train / _il / _ctc - ADR-037). Role C was one binary with three independent, zero-shared-state handlers (Train/IL/CTC relay); it is now three separate processes, one per client type, so the Train service can be the clean sole owner of per-train demux when ADR-036's multiplexing lands. Everything that was boilerplate in the old gateway_c.c - the appmanager ops, the cyclic timer + cycle_ticks pacing, the channel resolver, the channel-down self-reboot - lives here; each service supplies only a gateway_c_service_def_t naming its one handler
    
gateway_c_config.c
Lightweight JSON configuration parser for Role C Gateway
    
gateway_c_config.h
Configuration data structures and parser for Role C Gateway (JSON-based)
    
gateway_c_selfstatus.c
See gateway_c_selfstatus.h
    
gateway_c_selfstatus.h
ADR-038: a role-C gateway service's own periodic status - a self log line plus a PUBLISH(STATUS) rbc_util_frame_t to the C-side broker (rte_gateway_c_status). Wired in by gateway_c_common when a service's gateway_c_service_def_t sets broker_channel
    
gateway_c_train_handler.c
See gateway_c_train_handler.h. ADR-036: one multiplexed Train sim connection + one relay link per peer; frames forwarded verbatim, train_id never inspected here
    
gateway_c_train_handler.h
TrainHandler - Role C Gateway's TCP/IP server for the ONE multiplexed Train sim connection and the ONE dedicated relay link to/from each of A and B (ADR-036). Every train's traffic rides these single links, each envelope carrying its own train_id; this handler is a pure byte pipe - it forwards frames verbatim and never inspects train_id (that is A/B's job)
    
gateway_c_types.h
Shared wire-format constants and gateway_c_context_t
    
gateway_c_util.c
Gateway_c_sleep_ms() - shared bounded-sleep helper
    
gateway_c_util.h
Declares gateway_c_sleep_ms() - see gateway_c_types.h's own doc
    
main_c_train.c
SafeAPIRBC2oo2: Role C Gateway - Train service binary (rte_gateway_c_train). Relays every connected train's P0/M136/M146 to A/B and A/B's M24/M15/M3 back - see ADR-037 and gateway_c_train_handler.c