Safe API Framework
0.1.0 build 384e6ae
Layered API framework for safety-related applications (ERTMS RBC reference targeting CENELEC EN 50128 SIL 4)
Toggle main menu visibility
Loading...
Searching...
No Matches
main.c
Go to the documentation of this file.
1
22
23
#include <stdio.h>
24
#include <stdlib.h>
25
#include <string.h>
26
#include <unistd.h>
27
28
#include <sys/neutrino.h>
29
#include <sys/netmgr.h>
30
#include <sys/siginfo.h>
31
32
#include "rte/status.h"
33
#include "rte/types.h"
34
#include "rte/log.h"
35
#include "rte/safestate.h"
36
37
/* ============================================================================
38
* QNX Configuration
39
* ========================================================================== */
40
41
#define SERVER_NAME "railway-server"
42
#define CHANNEL_NAME "/railway/cmd"
43
#define MESSAGE_BUFFER_SIZE 256
44
45
/* Application state */
46
typedef
enum
{
47
STATE_INIT = 0,
48
STATE_LISTENING = 1,
49
STATE_PROCESSING = 2,
50
STATE_ERROR = 3,
51
STATE_SHUTDOWN = 4
52
} app_state_t;
53
54
typedef
struct
{
55
int
chid;
/* Channel ID for message passing */
56
int
coid;
/* Connection ID */
57
app_state_t state;
58
uint32_t messages_received;
59
uint32_t messages_processed;
60
uint32_t errors;
61
volatile
int
running;
62
}
app_context_t
;
63
64
static
app_context_t
g_app = {
65
.chid = -1,
66
.coid = -1,
67
.state = STATE_INIT,
68
.messages_received = 0,
69
.messages_processed = 0,
70
.errors = 0,
71
.running = 1
72
};
73
74
/* Message types */
75
typedef
enum
{
76
MSG_TYPE_PING = 1,
77
MSG_TYPE_TRAIN_UPDATE = 2,
78
MSG_TYPE_SIGNAL_QUERY = 3,
79
MSG_TYPE_SHUTDOWN = 99
80
} msg_type_t;
81
82
/* Message structure */
83
typedef
struct
{
84
uint32_t type;
85
uint32_t train_id;
86
uint32_t position;
87
uint8_t data[MESSAGE_BUFFER_SIZE - 12];
88
}
train_message_t
;
89
90
/* Reply structure */
91
typedef
struct
{
92
rte_status_t
status;
93
uint32_t signal_state;
94
uint32_t track_speed_limit;
95
}
cmd_reply_t
;
96
97
/* ============================================================================
98
* QNX Message Handling
99
* ========================================================================== */
100
104
static
rte_status_t
qnx_init_channel
(
void
)
105
{
106
/* Create a channel for receiving messages */
107
g_app.chid = ChannelCreate(0);
108
if
(g_app.chid == -1) {
109
RTE_LOG_ERROR(
"Failed to create QNX channel: %d"
, errno);
110
return
RTE_STATUS_ERROR;
111
}
112
113
RTE_LOG_INFO(
"QNX channel created: %d"
, g_app.chid);
114
115
/* Register the channel in the name space */
116
/* In production, would attach to well-known name */
117
RTE_LOG_INFO(
"Message channel ready (PID=%d, CHID=%d)"
, getpid(), g_app.chid);
118
119
return
RTE_STATUS_OK
;
120
}
121
125
static
rte_status_t
process_train_update
(
const
train_message_t
*msg,
126
cmd_reply_t
*reply)
127
{
128
RTE_ASSERT
(msg != NULL);
129
RTE_ASSERT
(reply != NULL);
130
131
RTE_LOG_DEBUG(
"Train update: ID=%u, Position=%u"
, msg->train_id, msg->position);
132
133
/* Validate train position */
134
if
(msg->position > 10000) {
135
RTE_LOG_WARN(
"Train position out of valid range: %u"
, msg->position);
136
reply->status = RTE_STATUS_ERROR;
137
reply->signal_state = 0;
/* Red signal - stop */
138
return
RTE_STATUS_ERROR;
139
}
140
141
/* Determine signal state based on position */
142
if
(msg->position < 1000) {
143
reply->signal_state = 1;
/* Green - go */
144
reply->track_speed_limit = 80;
145
}
else
if
(msg->position < 5000) {
146
reply->signal_state = 2;
/* Yellow - caution */
147
reply->track_speed_limit = 40;
148
}
else
{
149
reply->signal_state = 0;
/* Red - stop */
150
reply->track_speed_limit = 0;
151
}
152
153
reply->status =
RTE_STATUS_OK
;
154
155
RTE_LOG_INFO(
"Train %u: signal=%u, speed_limit=%u"
,
156
msg->train_id,
157
reply->signal_state,
158
reply->track_speed_limit);
159
160
g_app.messages_processed++;
161
return
RTE_STATUS_OK
;
162
}
163
167
static
rte_status_t
handle_message
(
train_message_t
*msg,
int
rcvid)
168
{
169
cmd_reply_t
reply = {
170
.status =
RTE_STATUS_OK
,
171
.signal_state = 0,
172
.track_speed_limit = 0
173
};
174
175
g_app.messages_received++;
176
177
/* Dispatch based on message type */
178
switch
(msg->type) {
179
case
MSG_TYPE_PING:
180
RTE_LOG_DEBUG(
"Received PING from client"
);
181
reply.status =
RTE_STATUS_OK
;
182
break
;
183
184
case
MSG_TYPE_TRAIN_UPDATE:
185
RTE_LOG_DEBUG(
"Processing TRAIN_UPDATE message"
);
186
process_train_update
(msg, &reply);
187
break
;
188
189
case
MSG_TYPE_SIGNAL_QUERY:
190
RTE_LOG_DEBUG(
"Received SIGNAL_QUERY"
);
191
reply.signal_state = 1;
/* Default: green */
192
reply.track_speed_limit = 80;
193
reply.status =
RTE_STATUS_OK
;
194
break
;
195
196
case
MSG_TYPE_SHUTDOWN:
197
RTE_LOG_INFO(
"Received SHUTDOWN request"
);
198
g_app.running = 0;
199
reply.status =
RTE_STATUS_OK
;
200
break
;
201
202
default
:
203
RTE_LOG_WARN(
"Unknown message type: %u"
, msg->type);
204
reply.status = RTE_STATUS_ERROR;
205
break
;
206
}
207
208
/* Send reply back to client */
209
MsgReply(rcvid, EOK, &reply,
sizeof
(reply));
210
211
return
reply.status;
212
}
213
217
static
rte_status_t
server_loop
(
void
)
218
{
219
int
rcvid;
220
train_message_t
msg;
221
int
rc;
222
223
RTE_LOG_INFO(
"Starting QNX server loop"
);
224
g_app.state = STATE_LISTENING;
225
226
while
(g_app.running) {
227
/* Block waiting for a message */
228
rcvid = MsgReceive(g_app.chid, &msg,
sizeof
(msg), NULL);
229
230
if
(rcvid == -1) {
231
/* Error receiving message */
232
RTE_LOG_ERROR(
"MsgReceive failed: %d"
, errno);
233
g_app.errors++;
234
continue
;
235
}
236
237
if
(rcvid == 0) {
238
/* Pulse or special case */
239
RTE_LOG_DEBUG(
"Received pulse or special message"
);
240
continue
;
241
}
242
243
/* Process the message */
244
g_app.state = STATE_PROCESSING;
245
rc =
handle_message
(&msg, rcvid);
246
g_app.state = STATE_LISTENING;
247
248
if
(rc !=
RTE_STATUS_OK
) {
249
g_app.errors++;
250
}
251
252
/* Log statistics every 10 messages */
253
if
((g_app.messages_received % 10) == 0) {
254
RTE_LOG_INFO(
"Stats: received=%u, processed=%u, errors=%u"
,
255
g_app.messages_received,
256
g_app.messages_processed,
257
g_app.errors);
258
}
259
}
260
261
return
RTE_STATUS_OK
;
262
}
263
267
static
rte_status_t
app_shutdown
(
void
)
268
{
269
RTE_LOG_INFO(
"Shutting down railway server"
);
270
271
g_app.state = STATE_SHUTDOWN;
272
273
/* Destroy channel */
274
if
(g_app.chid != -1) {
275
ChannelDestroy(g_app.chid);
276
g_app.chid = -1;
277
}
278
279
return
RTE_STATUS_OK
;
280
}
281
282
/* ============================================================================
283
* Main Entry Point
284
* ========================================================================== */
285
286
int
main(
int
argc,
char
*argv[])
287
{
288
(void)argc;
289
(void)argv;
290
291
rte_status_t
status;
292
293
printf(
"\n"
);
294
printf(
"═══════════════════════════════════════════════════════════════\n"
);
295
printf(
"Railway Control Server (QNX RTOS)\n"
);
296
printf(
"═══════════════════════════════════════════════════════════════\n"
);
297
printf(
"PID: %d\n"
, getpid());
298
299
/* Initialize logging */
300
status = rte_log_initialize();
301
if
(status !=
RTE_STATUS_OK
) {
302
fprintf(stderr,
"Failed to initialize logging\n"
);
303
return
EXIT_FAILURE;
304
}
305
306
RTE_LOG_INFO(
"Railway Control Server starting (QNX RTOS)"
);
307
308
/* Initialize QNX message channel */
309
status =
qnx_init_channel
();
310
if
(status !=
RTE_STATUS_OK
) {
311
RTE_LOG_ERROR(
"Failed to initialize QNX channel"
);
312
return
EXIT_FAILURE;
313
}
314
315
/* Run server loop */
316
status =
server_loop
();
317
if
(status !=
RTE_STATUS_OK
) {
318
RTE_LOG_ERROR(
"Server loop exited with error: %d"
, status);
319
}
320
321
/* Shutdown */
322
app_shutdown
();
323
324
/* Print summary */
325
printf(
"\n"
);
326
printf(
"═══════════════════════════════════════════════════════════════\n"
);
327
printf(
"Railway Server Summary\n"
);
328
printf(
"═══════════════════════════════════════════════════════════════\n"
);
329
printf(
"Messages received: %u\n"
, g_app.messages_received);
330
printf(
"Messages processed: %u\n"
, g_app.messages_processed);
331
printf(
"Errors: %u\n"
, g_app.errors);
332
printf(
"═══════════════════════════════════════════════════════════════\n"
);
333
printf(
"\n"
);
334
335
rte_log_shutdown();
336
return
EXIT_SUCCESS;
337
}
RTE_ASSERT
#define RTE_ASSERT(cond)
Checked assertion. Always active in every build configuration, including production (ADR-004 section ...
Definition
rte_safestate.h:156
rte_status_t
rte_status_t
Common result/status codes.
Definition
rte_status.h:27
RTE_STATUS_OK
@ RTE_STATUS_OK
Definition
rte_status.h:28
handle_message
static rte_status_t handle_message(train_message_t *msg, int rcvid)
Handle incoming message.
Definition
main.c:167
qnx_init_channel
static rte_status_t qnx_init_channel(void)
Initialize QNX message channel.
Definition
main.c:104
app_shutdown
static rte_status_t app_shutdown(void)
Shutdown application.
Definition
main.c:267
server_loop
static rte_status_t server_loop(void)
Main server loop.
Definition
main.c:217
process_train_update
static rte_status_t process_train_update(const train_message_t *msg, cmd_reply_t *reply)
Process train update message.
Definition
main.c:125
app_context_t
Definition
channel_callbacks_example.c:59
cmd_reply_t
Definition
main.c:91
train_message_t
Definition
main.c:83
examples
qnx-rtos-app
main.c
Generated by
1.18.0