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_tcp.c
Go to the documentation of this file.
1
9
12
13typedef struct rte_protocol_tcp_state_s
14{
16 const rte_os_socket_ops_t *os_sockets;
18 bool is_connected;
20
21static rte_status_t tcp_adapter_open(void *storage, size_t storage_size,
22 const rte_protocol_config_t *config,
23 const rte_os_socket_ops_t *os_sockets,
24 rte_protocol_handle_t *out_handle)
25{
26 rte_protocol_tcp_state_t *state = NULL;
27 const rte_os_socket_ops_t *ops = os_sockets;
28 rte_status_t status;
30
31 if ((storage == NULL) || (config == NULL) || (out_handle == NULL))
32 {
34 }
35 if (storage_size < sizeof(rte_protocol_tcp_state_t))
36 {
38 }
39
40 if (ops == NULL)
41 {
43 }
44 if ((ops == NULL) || (ops->open == NULL) || (ops->close == NULL))
45 {
47 }
48
49 state = (rte_protocol_tcp_state_t *)storage;
50 rte_mem_set(state, 0, sizeof(*state));
51 state->sock = RTE_OS_SOCKET_INVALID_HANDLE;
52 state->os_sockets = ops;
53 state->config = *config;
54
55 status = ops->open(RTE_OS_SOCKET_TYPE_TCP, &sock);
56 if (status != RTE_STATUS_OK)
57 {
58 return status;
59 }
60 state->sock = sock;
61
62 /* REQ-OAL-SOCKET-002: a refused non-blocking request releases the socket. A NULL slot is accepted, open()
63 * already delivers a non-blocking socket (REQ-OAL-SOCKET-001). */
64 if (ops->set_nonblocking != NULL)
65 {
66 status = ops->set_nonblocking(sock, true);
67 if (status != RTE_STATUS_OK)
68 {
69 (void)ops->close(sock);
70 state->sock = RTE_OS_SOCKET_INVALID_HANDLE;
71 return status;
72 }
73 }
74
75 if (config->role == RTE_PROTOCOL_ROLE_LISTEN)
76 {
77 if (ops->bind == NULL)
78 {
79 (void)ops->close(sock);
80 state->sock = RTE_OS_SOCKET_INVALID_HANDLE;
82 }
83 status = ops->bind(sock, config->host[0] != '\0' ? config->host : NULL, config->port);
84 if (status != RTE_STATUS_OK)
85 {
86 (void)ops->close(sock);
87 state->sock = RTE_OS_SOCKET_INVALID_HANDLE;
88 return status;
89 }
90 }
91 else if (config->role == RTE_PROTOCOL_ROLE_CONNECT)
92 {
93 if (ops->connect == NULL)
94 {
95 (void)ops->close(sock);
96 state->sock = RTE_OS_SOCKET_INVALID_HANDLE;
98 }
99 status = ops->connect(sock, config->host, config->port);
100 if (status == RTE_STATUS_OK)
101 {
102 state->is_connected = true;
103 }
104 }
105
106 *out_handle = (rte_protocol_handle_t)(void *)state;
107 return RTE_STATUS_OK;
108}
109
110static rte_status_t tcp_adapter_send(rte_protocol_handle_t handle, const void *data,
111 size_t size, rte_duration_ms_t timeout_ms)
112{
113 rte_protocol_tcp_state_t *state = (rte_protocol_tcp_state_t *)(void *)handle;
114 const rte_os_socket_ops_t *ops;
115 rte_status_t status;
116 uint32_t revents = 0U;
117 size_t sent = 0U;
118
119 if ((state == NULL) || (data == NULL) || (size == 0U))
120 {
122 }
123 if (state->sock == RTE_OS_SOCKET_INVALID_HANDLE)
124 {
126 }
127
128 ops = state->os_sockets;
129 if ((ops == NULL) || (ops->send == NULL))
130 {
132 }
133
134 if (ops->poll != NULL)
135 {
136 status = ops->poll(state->sock, RTE_OS_SOCKET_EVENT_WRITE, timeout_ms, &revents);
137 if (status != RTE_STATUS_OK)
138 {
139 return status;
140 }
141 if ((revents & RTE_OS_SOCKET_EVENT_WRITE) == 0U)
142 {
143 return RTE_STATUS_TIMEOUT;
144 }
145 }
146
147 return ops->send(state->sock, data, size, &sent);
148}
149
150static rte_status_t tcp_adapter_receive(rte_protocol_handle_t handle, void *out_buf,
151 size_t buffer_size, rte_duration_ms_t timeout_ms)
152{
153 rte_protocol_tcp_state_t *state = (rte_protocol_tcp_state_t *)(void *)handle;
154 const rte_os_socket_ops_t *ops;
155 rte_status_t status;
156 uint32_t revents = 0U;
157 size_t recvd = 0U;
158
159 if ((state == NULL) || (out_buf == NULL) || (buffer_size == 0U))
160 {
162 }
163 if (state->sock == RTE_OS_SOCKET_INVALID_HANDLE)
164 {
166 }
167
168 ops = state->os_sockets;
169 if ((ops == NULL) || (ops->recv == NULL))
170 {
172 }
173
174 if (ops->poll != NULL)
175 {
176 status = ops->poll(state->sock, RTE_OS_SOCKET_EVENT_READ, timeout_ms, &revents);
177 if (status != RTE_STATUS_OK)
178 {
179 return status;
180 }
181 if ((revents & RTE_OS_SOCKET_EVENT_READ) == 0U)
182 {
183 return RTE_STATUS_TIMEOUT;
184 }
185 }
186
187 return ops->recv(state->sock, out_buf, buffer_size, &recvd);
188}
189
190static rte_status_t tcp_adapter_close(rte_protocol_handle_t handle)
191{
192 rte_protocol_tcp_state_t *state = (rte_protocol_tcp_state_t *)(void *)handle;
193 if ((state == NULL) || (state->sock == RTE_OS_SOCKET_INVALID_HANDLE))
194 {
195 return RTE_STATUS_OK;
196 }
197 if ((state->os_sockets != NULL) && (state->os_sockets->close != NULL))
198 {
199 (void)state->os_sockets->close(state->sock);
200 }
201 state->sock = RTE_OS_SOCKET_INVALID_HANDLE;
202 state->is_connected = false;
203 return RTE_STATUS_OK;
204}
205
206static const rte_protocol_adapter_ops_t s_tcp_ops = {
207 tcp_adapter_open,
208 tcp_adapter_send,
209 tcp_adapter_receive,
210 tcp_adapter_close
211};
212
214{
215 return &s_tcp_ops;
216}
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_TCP
@ RTE_OS_SOCKET_EVENT_WRITE
@ RTE_OS_SOCKET_EVENT_READ
const rte_protocol_adapter_ops_t * rte_protocol_adapter_get_tcp(void)
Returns the built-in raw TCP 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_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(*) 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.