Safe API Framework 0.1.0 build 384e6ae
Layered API framework for safety-related applications (ERTMS RBC reference targeting CENELEC EN 50128 SIL 4)
Loading...
Searching...
No Matches
rte_channel_service_flow_osadapter.c File Reference

See rte_channel_service_flow_osadapter.h. More...

Include dependency graph for rte_channel_service_flow_osadapter.c:

Go to the source code of this file.

Data Structures

struct  flow_channel_state_t

Typedefs

typedef char flow_channel_state_fits_[(sizeof(flow_channel_state_t)<=sizeof(rte_channel_service_storage_t)) ? 1 :-1]

Functions

static flow_channel_state_t * channel_state (rte_channel_service_storage_t *storage)
static uint32_t oflags_for_role (rte_netlink_role_t role)
static rte_status_t osadapter_setup (rte_channel_service_storage_t *storage, const char *channel_name)
static rte_status_t ensure_open (flow_channel_state_t *state, rte_duration_ms_t open_timeout_ms)
static rte_status_t osadapter_read (rte_channel_service_storage_t *storage, void *data, size_t data_size, rte_duration_ms_t timeout_ms)
static rte_status_t backend_send (rte_channel_service_storage_t *storage, const void *data, size_t data_size, rte_duration_ms_t timeout_ms)
static rte_status_t osadapter_close (rte_channel_service_storage_t *storage)
rte_status_t rte_channel_service_flow_osadapter_register_resolver (rte_channel_service_flow_resolve_fn resolver, void *context)
 Registers the resolver this OSAdapter calls from setup() to learn a channel name's role/host/port/message_size.
const rte_osadapter_channel_service_t * rte_channel_service_flow_osadapter (void)
 Returns the rte_osadapter_channel_service_t vtable to pass to rte_osadapter_channel_service_register().

Variables

static rte_channel_service_flow_resolve_fn s_resolver
static void * s_resolver_context
static const rte_osadapter_channel_service_t g_flow_osadapter

Detailed Description

See rte_channel_service_flow_osadapter.h.

Lazy open, not eager (found live, not designed up front - see the RCA/OCORA Phase 4 verification history in root TODO.md): rte_flow_open() blocks synchronously for its peer's handshake, up to config->open_timeout_ms (REQ-OAL-FLOW-002) - a real behavioral difference from safeAPIBackendPosix's own rte_posix_osadapter_channel_service, whose osadapter_setup() fires the connect/HELLO (or binds, for LISTEN) and returns immediately, deferring the actual peer handshake to the first osadapter_read() call, retried indefinitely and silently in the background from then on. That difference matters for real: an integrator (e.g. safeAPIRBC2oo2GP) may legitimately set up a channel whose peer is not running yet, or never runs in a given deployment (e.g. an optional service) - the POSIX OSAdapter tolerates that gracefully (setup() never blocks on it), this OSAdapter's naive first version did not (setup() would block for the full open_timeout_ms, then FAIL setup() outright, taking down the whole integrator process even though the missing peer was expected and harmless). Fixed by matching the POSIX OSAdapter's own lazy-connect shape: osadapter_setup() only resolves and stores configuration; the actual rte_flow_open() call happens lazily, on the first osadapter_read()/backend_send(), using a bounded 0ms probe timeout so a still-absent peer returns RTE_STATUS_TIMEOUT immediately rather than blocking that cycle's I/O - the caller's own retry loop (e.g. safeAPIRBC2oo2GP's channel_service_setup_with_retry(), or simply calling read()/send() again next cycle) is what re-attempts the open, exactly the same shape the POSIX OSAdapter's own osadapter_read() reconnect-on-demand logic already has.

Socket buffer sizes are not applied here. The resolved rte_netlink_config_t carries rcvbuf_bytes / sndbuf_bytes (from a resolver, or from rte_channel_def_t's "rcvbuf_bytes" / "sndbuf_bytes" keys, REQ-REDCFG-001), but rte_flow_config_t has no buffer fields, so this flow-backed channel service drops them and the flow OSAdapter keeps the OS default. The POSIX channel service (Platform_OS_POSIX; RBC_GP's Gateway registers it through its resolver) applies them (REQ-OAL-NETLINK-015); RBC_GP's A/B register this flow-backed one, so for them the sizes take effect only once the flow path down to rte_netlink_open() carries them (rte_flow_config_t, or the flow OSAdapter's own route).

Definition in file rte_channel_service_flow_osadapter.c.

Typedef Documentation

◆ flow_channel_state_fits_

typedef char flow_channel_state_fits_[(sizeof(flow_channel_state_t)<= sizeof(rte_channel_service_storage_t)) ? 1 :-1]

Definition at line 65 of file rte_channel_service_flow_osadapter.c.

Function Documentation

◆ channel_state()

flow_channel_state_t * channel_state ( rte_channel_service_storage_t * storage)
static

Definition at line 71 of file rte_channel_service_flow_osadapter.c.

◆ oflags_for_role()

uint32_t oflags_for_role ( rte_netlink_role_t role)
static

CONNECT->PUBLISHER, LISTEN->SUBSCRIBER, matching safeAPIFlowBackendDDS's own oflags->netlink-role mapping in reverse (see that project's file header comment) - kept here, not there, since this module must not depend on any concrete rte_osadapter_flow_t implementation.

Definition at line 80 of file rte_channel_service_flow_osadapter.c.

◆ osadapter_setup()

rte_status_t osadapter_setup ( rte_channel_service_storage_t * storage,
const char * channel_name )
static

Definition at line 86 of file rte_channel_service_flow_osadapter.c.

◆ ensure_open()

rte_status_t ensure_open ( flow_channel_state_t * state,
rte_duration_ms_t open_timeout_ms )
static

Attempts the deferred rte_flow_open() exactly once, bounded by open_timeout_ms - the SAME timeout_ms the caller passed to THIS read()/send() call, matching safeAPIBackendPosix's own osadapter_read() reconnect-on-demand logic exactly (it hands the caller's own read timeout to its ACK-consumption poll(), not a separate hardcoded value - see that file's osadapter_read()). A caller sees RTE_STATUS_TIMEOUT (or another rte_flow_open() failure) as an ordinary per-call read()/send() failure, not a setup()-time one. Using the caller's own timeout (not a hardcoded 0) matters for real: a genuinely-present peer (e.g. a loopback peer that is also just starting up) needs a real, non-zero window to complete its handshake - 0 would starve it just as thoroughly as an absent peer, found live against a real GP process (ab-peer briefly failing the same way ab-relay-util legitimately does) before this was corrected - see root TODO.md's Phase 4 entry.

Definition at line 155 of file rte_channel_service_flow_osadapter.c.

◆ osadapter_read()

rte_status_t osadapter_read ( rte_channel_service_storage_t * storage,
void * data,
size_t data_size,
rte_duration_ms_t timeout_ms )
static

Definition at line 177 of file rte_channel_service_flow_osadapter.c.

◆ backend_send()

rte_status_t backend_send ( rte_channel_service_storage_t * storage,
const void * data,
size_t data_size,
rte_duration_ms_t timeout_ms )
static

Definition at line 200 of file rte_channel_service_flow_osadapter.c.

◆ osadapter_close()

rte_status_t osadapter_close ( rte_channel_service_storage_t * storage)
static

Definition at line 223 of file rte_channel_service_flow_osadapter.c.

Variable Documentation

◆ s_resolver

Definition at line 68 of file rte_channel_service_flow_osadapter.c.

◆ s_resolver_context

void* s_resolver_context
static

Definition at line 69 of file rte_channel_service_flow_osadapter.c.

◆ g_flow_osadapter

const rte_osadapter_channel_service_t g_flow_osadapter
static
Initial value:
= {
osadapter_setup,
osadapter_read,
backend_send,
osadapter_close,
NULL
}

Definition at line 244 of file rte_channel_service_flow_osadapter.c.