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
Go to the documentation of this file.
1
42
43#include <string.h>
44
48
49/* Only the fields ensure_open() needs to rebuild a rte_flow_config_t are
50 * stored (not the whole struct) - this OSAdapter's storage must fit inside
51 * rte_channel_service_storage_t's 128-byte reserved size alongside
52 * rte_flow_storage_t (64 bytes) itself. */
53typedef struct
54{
55 rte_flow_storage_t flow_storage;
56 rte_flow_handle_t flow_handle;
57 uint32_t oflags;
58 size_t message_size;
59 char name_buf[RTE_CHANNEL_SERVICE_NAME_SIZE];
60 rte_duration_ms_t default_timeout_ms;
61 bool resolved;
62 bool opened;
64
65typedef char flow_channel_state_fits_[(sizeof(flow_channel_state_t) <=
66 sizeof(rte_channel_service_storage_t)) ? 1 : -1];
67
69static void *s_resolver_context;
70
71static flow_channel_state_t *channel_state(rte_channel_service_storage_t *storage)
72{
73 return (flow_channel_state_t *)(void *)storage;
74}
75
81{
82 return (role == RTE_NETLINK_ROLE_CONNECT) ? (uint32_t)RTE_FLOW_O_PUBLISHER
83 : (uint32_t)RTE_FLOW_O_SUBSCRIBER;
84}
85
86static rte_status_t osadapter_setup(rte_channel_service_storage_t *storage, const char *channel_name)
87{
89 rte_netlink_config_t resolved;
90 rte_status_t status;
91
92 if ((storage == NULL) || (channel_name == NULL))
93 {
95 }
96 state = channel_state(storage);
97 rte_mem_set(state, 0, sizeof(*state));
98
99 rte_mem_set(&resolved, 0, sizeof(resolved));
100 if (s_resolver != NULL)
101 {
102 status = s_resolver(channel_name, &resolved, s_resolver_context);
103 if (status != RTE_STATUS_OK)
104 {
105 return status;
106 }
107 }
108 else
109 {
112 if (active == NULL)
113 {
115 }
116 status = rte_redundancy_config_find_channel_by_name(active, channel_name, &def);
117 if (status != RTE_STATUS_OK)
118 {
119 return status;
120 }
121 resolved.role = (def.role == RTE_CHANNEL_ROLE_CONNECT) ? RTE_NETLINK_ROLE_CONNECT : RTE_NETLINK_ROLE_LISTEN;
122 resolved.host = (def.host[0] != '\0') ? def.host : NULL;
123 resolved.port = def.port;
124 resolved.message_size = def.message_size;
125 resolved.connect_timeout_ms = def.connect_timeout_ms;
126 /* Copied for a complete resolved config only: not applied, see the
127 * file comment (socket buffer sizes). */
128 resolved.rcvbuf_bytes = def.rcvbuf_bytes;
129 resolved.sndbuf_bytes = def.sndbuf_bytes;
130 }
131
132 (void)strncpy(state->name_buf, channel_name, sizeof(state->name_buf) - 1U);
133 state->oflags = oflags_for_role(resolved.role);
134 state->message_size = resolved.message_size;
135 state->default_timeout_ms = resolved.connect_timeout_ms;
136 state->resolved = true;
137 state->opened = false;
138 return RTE_STATUS_OK;
139}
140
156{
157 rte_flow_config_t flow_cfg;
158 rte_status_t status;
159
160 if (state->opened)
161 {
162 return RTE_STATUS_OK;
163 }
164 rte_mem_set(&flow_cfg, 0, sizeof(flow_cfg));
165 flow_cfg.name = state->name_buf;
166 flow_cfg.oflags = state->oflags;
167 flow_cfg.message_size = state->message_size;
168 flow_cfg.open_timeout_ms = (open_timeout_ms > 0U) ? open_timeout_ms : state->default_timeout_ms;
169 status = rte_flow_open(&state->flow_storage, &flow_cfg, &state->flow_handle);
170 if (status == RTE_STATUS_OK)
171 {
172 state->opened = true;
173 }
174 return status;
175}
176
177static rte_status_t osadapter_read(rte_channel_service_storage_t *storage, void *data, size_t data_size,
178 rte_duration_ms_t timeout_ms)
179{
181 rte_status_t status;
182
183 if ((storage == NULL) || (data == NULL) || (data_size == 0U))
184 {
186 }
187 state = channel_state(storage);
188 if (!state->resolved)
189 {
191 }
192 status = ensure_open(state, timeout_ms);
193 if (status != RTE_STATUS_OK)
194 {
195 return status;
196 }
197 return rte_flow_receive(state->flow_handle, data, data_size, NULL, timeout_ms);
198}
199
200static rte_status_t backend_send(rte_channel_service_storage_t *storage, const void *data, size_t data_size,
201 rte_duration_ms_t timeout_ms)
202{
204 rte_status_t status;
205
206 if ((storage == NULL) || (data == NULL) || (data_size == 0U))
207 {
209 }
210 state = channel_state(storage);
211 if (!state->resolved)
212 {
214 }
215 status = ensure_open(state, timeout_ms);
216 if (status != RTE_STATUS_OK)
217 {
218 return status;
219 }
220 return rte_flow_send(state->flow_handle, data, data_size, RTE_FLOW_CHANNEL_USER, timeout_ms);
221}
222
223static rte_status_t osadapter_close(rte_channel_service_storage_t *storage)
224{
226 rte_status_t status;
227
228 if (storage == NULL)
229 {
231 }
232 state = channel_state(storage);
233 if (!state->opened)
234 {
235 state->resolved = false;
236 return RTE_STATUS_OK;
237 }
238 status = rte_flow_close(state->flow_handle);
239 state->opened = false;
240 state->resolved = false;
241 return status;
242}
243
244static const rte_osadapter_channel_service_t g_flow_osadapter = {
245 osadapter_setup,
246 osadapter_read,
247 backend_send,
248 osadapter_close,
249 NULL /* read_ex: not implemented here, rte_channel_service_read_ex() falls back to read() */
250};
251
253 void *context)
254{
255 if (resolver == NULL)
256 {
258 }
259 s_resolver = resolver;
260 s_resolver_context = context;
261 /* Mirrors safeAPIBackendPosix's rte_posix_osadapter_channel_service_register_resolver()'s
262 * own convention exactly - registering the resolver AND activating this
263 * OSAdapter in one call - so an integrator's call site is a one-line swap
264 * between the two OSAdapters (see ab_gp_channel.c). */
265 return rte_osadapter_channel_service_register(&g_flow_osadapter);
266}
267
269{
270 return &g_flow_osadapter;
271}
rte_status_t rte_flow_send(rte_flow_handle_t handle, const void *data, size_t data_size, rte_flow_channel_t channel, rte_duration_ms_t timeout_ms)
Sends one fixed-size message on the given channel, blocking at most timeout_ms.
Definition rte_flow.c:86
rte_status_t rte_flow_close(rte_flow_handle_t handle)
Closes (leaves/unregisters/unsubscribes from) a Flow.
Definition rte_flow.c:132
rte_status_t rte_flow_receive(rte_flow_handle_t handle, void *out_data, size_t buffer_size, rte_flow_channel_t *out_channel, rte_duration_ms_t timeout_ms)
Receives one fixed-size message, blocking at most timeout_ms.
Definition rte_flow.c:111
rte_status_t rte_flow_open(rte_flow_storage_t *storage, const rte_flow_config_t *config, rte_flow_handle_t *out_handle)
Opens (joins/registers/subscribes to, per OCORA's own fl_open() doc) a named Flow.
Definition rte_flow.c:58
struct rte_flow_impl_s * rte_flow_handle_t
Opaque handle to an opened Flow, returned by rte_flow_open().
Definition rte_flow.h:71
@ RTE_FLOW_CHANNEL_USER
Definition rte_flow.h:98
@ RTE_FLOW_O_SUBSCRIBER
Definition rte_flow.h:84
@ RTE_FLOW_O_PUBLISHER
Definition rte_flow.h:83
rte_status_t
Common result/status codes.
Definition rte_status.h:27
@ RTE_STATUS_OK
Definition rte_status.h:28
@ RTE_STATUS_INVALID_PARAM
Definition rte_status.h:29
@ RTE_STATUS_NOT_INITIALIZED
Definition rte_status.h:30
uint32_t rte_duration_ms_t
Definition rte_types.h:27
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(...
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/mes...
rte_status_t(*) rte_channel_service_flow_resolve_fn(const char *channel_name, rte_netlink_config_t *out_config, void *context)
const rte_redundancy_config_t * rte_redundancy_config_get_active(void)
Get the currently active loaded redundancy/channel configuration (if any).
rte_status_t rte_redundancy_config_find_channel_by_name(const rte_redundancy_config_t *config, const char *name, rte_channel_def_t *out_channel)
Find channel definition by name in the given configuration.
rte_status_t rte_osadapter_channel_service_register(const rte_osadapter_channel_service_t *osadapter)
Registers the OSAdapter that implements named channels (ADR-005).
static uint32_t oflags_for_role(rte_netlink_role_t role)
static rte_status_t ensure_open(flow_channel_state_t *state, rte_duration_ms_t open_timeout_ms)
rte_osadapter_channel_service_t implementation over rte_flow.
OS Abstraction Layer - OCORA PI-API-compatible Flow service.
Thin, MISRA-visible wrappers over the three raw memory-block primitives (fill/copy/compare) every oth...
static void rte_mem_set(void *dest, int value, size_t count)
Fills count bytes starting at dest with value - the one sanctioned call site for libc memset() in thi...
Application-level redundancy topology configuration (2oo2 / 2oo2 with redundancy / 2oo3 / NMR),...
Caller-owned storage for one named channel service instance.
Configuration for rte_flow_open().
Definition rte_flow.h:119
const char * name
Definition rte_flow.h:124
rte_duration_ms_t open_timeout_ms
Definition rte_flow.h:131
size_t message_size
Definition rte_flow.h:129
uint32_t oflags
Definition rte_flow.h:127
OSAdapter implementation for named channel operations.