16#include <netinet/in.h>
23#include <sys/socket.h>
26#include "safecomm/config/config.h"
27#include "safecomm/ale/ale.h"
29#include "rte/oal/netlink/rte_netlink.h"
30#include "rte/posix_osadapter/rte_posix_osadapter.h"
35#define CS_DRAIN_MAX 256U
37static volatile sig_atomic_t g_stop = 0;
38static bool g_trace =
false;
40static void on_signal(
int sig)
47static void trace_frame(
const char *dir,
const uint8_t *f,
size_t n)
49 if (!g_trace || (n < 4U))
53 (void)fprintf(stderr,
"commserver: TRACE %-12s kind=%3u train_id=%u nid_msg=%u\n",
54 dir, (
unsigned int)f[0], (
unsigned int)f[1], (
unsigned int)f[2]);
57static int tcp_listen(
const char *host, uint16_t port)
59 struct sockaddr_in addr;
63 fd = socket(AF_INET, SOCK_STREAM, 0);
68 (void)setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one,
sizeof(one));
70 (void)memset(&addr, 0,
sizeof(addr));
71 addr.sin_family = AF_INET;
72 addr.sin_port = htons(port);
73 if (inet_pton(AF_INET, host, &addr.sin_addr) != 1)
75 addr.sin_addr.s_addr = htonl(INADDR_ANY);
77 if ((bind(fd, (
const struct sockaddr *)&addr,
sizeof(addr)) != 0) || (listen(fd, 1) != 0))
85static rte_status_t netlink_connect(
const char *host, uint16_t port, uint16_t msg_size,
86 uint32_t timeout_ms, rte_netlink_storage_t *storage,
87 rte_netlink_handle_t *out)
89 rte_netlink_config_t nc;
91 (void)memset(&nc, 0,
sizeof(nc));
92 nc.role = RTE_NETLINK_ROLE_CONNECT;
95 nc.message_size = (size_t)msg_size;
96 nc.connect_timeout_ms = (rte_duration_ms_t)timeout_ms;
97 return rte_netlink_open(storage, &nc, out);
101static void serve_client(
int cfd,
const cs_cfg_t *cfg)
103 rte_netlink_storage_t west_storage;
104 rte_netlink_storage_t east_storage;
105 rte_netlink_handle_t west = NULL;
106 rte_netlink_handle_t east = NULL;
107 uint8_t up[CS_MSG_MAX];
108 uint8_t dn[CS_MSG_MAX];
110 const size_t msz = (size_t)cfg->message_size;
112 if (netlink_connect(cfg->west_host, cfg->west_port, cfg->message_size,
113 cfg->connect_timeout_ms, &west_storage, &west) != RTE_STATUS_OK)
115 (void)fprintf(stderr,
"commserver: WEST link (%s:%u) not established\n",
116 cfg->west_host, cfg->west_port);
119 if (netlink_connect(cfg->east_host, cfg->east_port, cfg->message_size,
120 cfg->connect_timeout_ms, &east_storage, &east) != RTE_STATUS_OK)
122 (void)fprintf(stderr,
"commserver: EAST link (%s:%u) not established\n",
123 cfg->east_host, cfg->east_port);
126 if ((west == NULL) && (east == NULL))
128 (void)fprintf(stderr,
"commserver: no RBC link — dropping train\n");
131 (void)fprintf(stderr,
"commserver: train connected; relaying (west=%s east=%s)\n",
132 (west != NULL) ?
"up" :
"down", (east != NULL) ?
"up" :
"down");
149 pr = poll(&pfd, 1U, 1);
163 ssize_t n = recv(cfd, &up[up_fill], msz - up_fill, MSG_DONTWAIT);
172 if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
183 up_fill += (size_t)n;
188 (void)rte_netlink_send(west, up, msz, 200U);
189 trace_frame(
"train->WEST", up, msz);
193 (void)rte_netlink_send(east, up, msz, 200U);
194 trace_frame(
"train->EAST", up, msz);
206 for (site = 0U; (site < 2U) && !closed; site++)
208 rte_netlink_handle_t h = (site == 0U) ? west : east;
219 if (rte_netlink_receive(h, dn, msz, 2U) != RTE_STATUS_OK)
223 trace_frame((site == 0U) ?
"WEST->train" :
"EAST->train", dn, msz);
224 if (write(cfd, dn, msz) != (ssize_t)msz)
239 (void)rte_netlink_close(west);
243 (void)rte_netlink_close(east);
245 (void)fprintf(stderr,
"commserver: train disconnected\n");
248int main(
int argc,
char **argv)
255 (void)fprintf(stderr,
"usage: %s <commserver.conf>\n", argv[0]);
263 (void)signal(SIGINT, on_signal);
264 (void)signal(SIGTERM, on_signal);
265 (void)signal(SIGPIPE, SIG_IGN);
267 g_trace = (getenv(
"COMMSERVER_TRACE") != NULL);
269 if (rte_posix_osadapter_register_all() != RTE_STATUS_OK)
271 (void)fprintf(stderr,
"commserver: rte_posix_osadapter_register_all failed\n");
275 lfd = tcp_listen(cfg.listen_host, cfg.listen_port);
278 (void)fprintf(stderr,
"commserver: cannot listen on %s:%u\n", cfg.listen_host, cfg.listen_port);
281 (void)fprintf(stderr,
"commserver: listening on %s:%u — RBC west %s:%u / east %s:%u — msg %u\n",
282 cfg.listen_host, cfg.listen_port, cfg.west_host, cfg.west_port,
283 cfg.east_host, cfg.east_port, cfg.message_size);
287 int cfd = accept(lfd, NULL, NULL);
297 serve_client(cfd, &cfg);
302 (void)fprintf(stderr,
"commserver: stopped\n");
int load_cfg(const char *path, cs_cfg_t *cfg)
Loads path into cfg, defaults first then overridden by whatever the file actually sets (out-of-range ...
CommServer's own config parsing (cs_cfg_t + load_cfg()), extracted from main.c (2026-09-24) purely fo...