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_protocol_adapter_udp.c
Go to the documentation of this file.
1
9
12
13typedef struct rte_protocol_udp_state_s
14{
16 const rte_os_socket_ops_t *os_sockets;
18 bool is_connected;
19 bool peer_known;
20 char peer_host[RTE_PROTOCOL_ENDPOINT_STR_MAX];
21 uint16_t peer_port;
23
24static rte_status_t udp_adapter_open(void *storage, size_t storage_size,
25 const rte_protocol_config_t *config,
26 const rte_os_socket_ops_t *os_sockets,
27 rte_protocol_handle_t *out_handle)
28{
29 rte_protocol_udp_state_t *state = NULL;
30 const rte_os_socket_ops_t *ops = os_sockets;
31 rte_status_t status;
33
34 if ((storage == NULL) || (config == NULL) || (out_handle == NULL))
35 {
37 }
38 if (storage_size < sizeof(rte_protocol_udp_state_t))
39 {
41 }
42
43 if (ops == NULL)
44 {
46 }
47 if ((ops == NULL) || (ops->open == NULL) || (ops->close == NULL))
48 {
50 }
51
52 state = (rte_protocol_udp_state_t *)storage;
53 rte_mem_set(state, 0, sizeof(*state));
54 state->sock = RTE_OS_SOCKET_INVALID_HANDLE;
55 state->os_sockets = ops;
56 state->config = *config;
57
58 status = ops->open(RTE_OS_SOCKET_TYPE_UDP, &sock);
59 if (status != RTE_STATUS_OK)
60 {
61 return status;
62 }
63 state->sock = sock;
64
65 /* REQ-OAL-SOCKET-002: a refused non-blocking request releases the socket. A NULL slot is accepted, open()
66 * already delivers a non-blocking socket (REQ-OAL-SOCKET-001). */
67 if (ops->set_nonblocking != NULL)
68 {
69 status = ops->set_nonblocking(sock, true);
70 if (status != RTE_STATUS_OK)
71 {
72 (void)ops->close(sock);
73 state->sock = RTE_OS_SOCKET_INVALID_HANDLE;
74 return status;
75 }
76 }
77
78 if (config->role == RTE_PROTOCOL_ROLE_LISTEN)
79 {
80 if (ops->bind == NULL)
81 {
82 (void)ops->close(sock);
83 state->sock = RTE_OS_SOCKET_INVALID_HANDLE;
85 }
86 status = ops->bind(sock, config->host[0] != '\0' ? config->host : NULL, config->port);
87 if (status != RTE_STATUS_OK)
88 {
89 (void)ops->close(sock);
90 state->sock = RTE_OS_SOCKET_INVALID_HANDLE;
91 return status;
92 }
93 }
94 else if (config->role == RTE_PROTOCOL_ROLE_CONNECT)
95 {
96 if (ops->connect != NULL)
97 {
98 status = ops->connect(sock, config->host, config->port);
99 if (status == RTE_STATUS_OK)
100 {
101 state->is_connected = true;
102 }
103 }
104 /* Cache destination for sendto fallback */
105 rte_mem_copy(state->peer_host, config->host, sizeof(state->peer_host));
106 state->peer_port = config->port;
107 state->peer_known = true;
108 }
109 else
110 {
111 /* Peer endpoint specified in config */
112 rte_mem_copy(state->peer_host, config->host, sizeof(state->peer_host));
113 state->peer_port = config->port;
114 state->peer_known = (config->port > 0U);
115 }
116
117 *out_handle = (rte_protocol_handle_t)(void *)state;
118 return RTE_STATUS_OK;
119}
120
121static rte_status_t udp_adapter_send(rte_protocol_handle_t handle, const void *data,
122 size_t size, rte_duration_ms_t timeout_ms)
123{
124 rte_protocol_udp_state_t *state = (rte_protocol_udp_state_t *)(void *)handle;
125 const rte_os_socket_ops_t *ops;
126 rte_status_t status;
127 uint32_t revents = 0U;
128 size_t sent = 0U;
129
130 if ((state == NULL) || (data == NULL) || (size == 0U))
131 {
133 }
134 if (state->sock == RTE_OS_SOCKET_INVALID_HANDLE)
135 {
137 }
138
139 ops = state->os_sockets;
140 if (ops == NULL)
141 {
143 }
144
145 if (ops->poll != NULL)
146 {
147 status = ops->poll(state->sock, RTE_OS_SOCKET_EVENT_WRITE, timeout_ms, &revents);
148 if (status != RTE_STATUS_OK)
149 {
150 return status;
151 }
152 if ((revents & RTE_OS_SOCKET_EVENT_WRITE) == 0U)
153 {
154 return RTE_STATUS_TIMEOUT;
155 }
156 }
157
158 if (state->is_connected && (ops->send != NULL))
159 {
160 return ops->send(state->sock, data, size, &sent);
161 }
162 else if (state->peer_known && (ops->sendto != NULL))
163 {
164 return ops->sendto(state->sock, data, size, state->peer_host, state->peer_port, &sent);
165 }
166 else
167 {
169 }
170}
171
172static rte_status_t udp_adapter_receive(rte_protocol_handle_t handle, void *out_buf,
173 size_t buffer_size, rte_duration_ms_t timeout_ms)
174{
175 rte_protocol_udp_state_t *state = (rte_protocol_udp_state_t *)(void *)handle;
176 const rte_os_socket_ops_t *ops;
177 rte_status_t status;
178 uint32_t revents = 0U;
179 size_t recvd = 0U;
180
181 if ((state == NULL) || (out_buf == NULL) || (buffer_size == 0U))
182 {
184 }
185 if (state->sock == RTE_OS_SOCKET_INVALID_HANDLE)
186 {
188 }
189
190 ops = state->os_sockets;
191 if (ops == NULL)
192 {
194 }
195
196 if (ops->poll != NULL)
197 {
198 status = ops->poll(state->sock, RTE_OS_SOCKET_EVENT_READ, timeout_ms, &revents);
199 if (status != RTE_STATUS_OK)
200 {
201 return status;
202 }
203 if ((revents & RTE_OS_SOCKET_EVENT_READ) == 0U)
204 {
205 return RTE_STATUS_TIMEOUT;
206 }
207 }
208
209 if (state->is_connected && (ops->recv != NULL))
210 {
211 return ops->recv(state->sock, out_buf, buffer_size, &recvd);
212 }
213 else if (ops->recvfrom != NULL)
214 {
215 status = ops->recvfrom(state->sock, out_buf, buffer_size,
216 state->peer_host, sizeof(state->peer_host),
217 &state->peer_port, &recvd);
218 if (status == RTE_STATUS_OK)
219 {
220 state->peer_known = true;
221 }
222 return status;
223 }
224 else
225 {
227 }
228}
229
230static rte_status_t udp_adapter_close(rte_protocol_handle_t handle)
231{
232 rte_protocol_udp_state_t *state = (rte_protocol_udp_state_t *)(void *)handle;
233 if ((state == NULL) || (state->sock == RTE_OS_SOCKET_INVALID_HANDLE))
234 {
235 return RTE_STATUS_OK;
236 }
237 if ((state->os_sockets != NULL) && (state->os_sockets->close != NULL))
238 {
239 (void)state->os_sockets->close(state->sock);
240 }
241 state->sock = RTE_OS_SOCKET_INVALID_HANDLE;
242 state->is_connected = false;
243 return RTE_STATUS_OK;
244}
245
246static const rte_protocol_adapter_ops_t s_udp_ops = {
247 udp_adapter_open,
248 udp_adapter_send,
249 udp_adapter_receive,
250 udp_adapter_close
251};
252
254{
255 return &s_udp_ops;
256}
const rte_os_socket_ops_t * rte_osadapter_get_socket_ops(void)
Retrieves the active OSAdapter's raw socket operations.
intptr_t rte_os_socket_handle_t
Socket handle representation (pointer or file descriptor).
#define RTE_OS_SOCKET_INVALID_HANDLE
Invalid socket handle sentinel.
@ RTE_OS_SOCKET_TYPE_UDP
@ RTE_OS_SOCKET_EVENT_WRITE
@ RTE_OS_SOCKET_EVENT_READ
#define RTE_PROTOCOL_ENDPOINT_STR_MAX
Maximum length of host, topic, or endpoint string.
const rte_protocol_adapter_ops_t * rte_protocol_adapter_get_udp(void)
Returns the built-in raw UDP ProtocolAdapter vtable.
struct rte_protocol_impl_s * rte_protocol_handle_t
Opaque protocol handle pointer.
@ RTE_PROTOCOL_ROLE_CONNECT
@ RTE_PROTOCOL_ROLE_LISTEN
rte_status_t
Common result/status codes.
Definition rte_status.h:27
@ RTE_STATUS_INVALID_STATE
Definition rte_status.h:40
@ RTE_STATUS_OK
Definition rte_status.h:28
@ RTE_STATUS_INVALID_PARAM
Definition rte_status.h:29
@ RTE_STATUS_NOT_SUPPORTED
Definition rte_status.h:34
@ RTE_STATUS_NOT_INITIALIZED
Definition rte_status.h:30
@ RTE_STATUS_RESOURCE_EXHAUSTED
Definition rte_status.h:33
@ RTE_STATUS_TIMEOUT
Definition rte_status.h:32
uint32_t rte_duration_ms_t
Definition rte_types.h:27
Thin, MISRA-visible wrappers over the three raw memory-block primitives (fill/copy/compare) every oth...
static void rte_mem_copy(void *dest, const void *src, size_t count)
Copies count bytes from src to dest - the one sanctioned call site for libc memcpy() in this framewor...
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...
Communication Protocol Adapter Interface (UDP, TCP, DDS).
Vtable of low-level OS socket operations implemented by an OSAdapter.
rte_status_t(*) open(rte_os_socket_type_t type, rte_os_socket_handle_t *out_handle)
Creates a raw socket of the specified type, non-blocking from creation (REQ-OAL-SOCKET-001,...
rte_status_t(*) recv(rte_os_socket_handle_t handle, void *buf, size_t len, size_t *out_recv)
Receives data from a connected socket.
rte_status_t(*) sendto(rte_os_socket_handle_t handle, const void *buf, size_t len, const char *host, uint16_t port, size_t *out_sent)
Sends a datagram to a specific remote host and port.
rte_status_t(*) recvfrom(rte_os_socket_handle_t handle, void *buf, size_t len, char *out_host, size_t host_len, uint16_t *out_port, size_t *out_recv)
Receives a datagram and captures sender endpoint.
rte_status_t(*) set_nonblocking(rte_os_socket_handle_t handle, bool nonblocking)
Configures non-blocking mode on socket.
rte_status_t(*) connect(rte_os_socket_handle_t handle, const char *host, uint16_t port)
Connects a socket to a remote host and port.
rte_status_t(*) bind(rte_os_socket_handle_t handle, const char *host, uint16_t port)
Binds a socket to a local host and port.
rte_status_t(*) poll(rte_os_socket_handle_t handle, uint32_t events, rte_duration_ms_t timeout_ms, uint32_t *out_revents)
Polls a socket for I/O readiness with timeout.
rte_status_t(*) send(rte_os_socket_handle_t handle, const void *buf, size_t len, size_t *out_sent)
Sends data on a connected socket.
rte_status_t(*) close(rte_os_socket_handle_t handle)
Closes a socket handle.
Operations vtable implemented by a concrete ProtocolAdapter.
Configuration passed to open a protocol adapter instance.
uint16_t port
Port (UDP/TCP).
char host[RTE_PROTOCOL_ENDPOINT_STR_MAX]
Host address (UDP/TCP) or domain partition.