diff options
| author | info@mode42.com <info@mode42.com> | 2026-08-08 03:54:55 +0000 |
|---|---|---|
| committer | info@mode42.com <info@mode42.com> | 2026-08-08 03:54:55 +0000 |
| commit | 20cb29c2f8c5c87bc590896854a20b1473ceb358 (patch) | |
| tree | 2857f41513a56ad41af97b57362639298aa7f033 /src/core/circuit_bridge.c | |
#2
Diffstat (limited to 'src/core/circuit_bridge.c')
| -rw-r--r-- | src/core/circuit_bridge.c | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/src/core/circuit_bridge.c b/src/core/circuit_bridge.c new file mode 100644 index 0000000..af3bde4 --- /dev/null +++ b/src/core/circuit_bridge.c @@ -0,0 +1,175 @@ +#include "hybbx/circuit_bridge.h" +#include "hybbx/util.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +typedef struct bridge_load_ctx { + hybbx_circuit_bridge_registry_t *reg; + const hybbx_config_t *reg_config; +} bridge_load_ctx_t; + +static int bridge_section_is_numbered_transport(const char *section, + const char *plugin) +{ + char prefix[64]; + size_t prefix_len; + const char *suffix; + + if (section == NULL || plugin == NULL) { + return 0; + } + + snprintf(prefix, sizeof(prefix), "transport.%s", plugin); + prefix_len = strlen(prefix); + if (strncmp(section, prefix, prefix_len) != 0) { + return 0; + } + + suffix = section + prefix_len; + if (suffix[0] == '\0') { + return 0; + } + + while (*suffix != '\0') { + if (*suffix < '0' || *suffix > '9') { + return 0; + } + suffix++; + } + + return 1; +} + +static int bridge_section_is_numbered_packet_radio(const char *section) +{ + return bridge_section_is_numbered_transport(section, "packet_radio"); +} + +static int bridge_section_is_numbered_ardop(const char *section) +{ + return bridge_section_is_numbered_transport(section, "ardop"); +} + +static int bridge_section_is_numbered_crdop(const char *section) +{ + return bridge_section_is_numbered_transport(section, "crdop"); +} + +static int bridge_section_is_numbered_baycom(const char *section) +{ + return bridge_section_is_numbered_transport(section, "baycom"); +} + +static void bridge_load_section(const char *section, void *userdata) +{ + bridge_load_ctx_t *ctx = (bridge_load_ctx_t *)userdata; + hybbx_circuit_bridge_entry_t *entry; + const char *value; + unsigned i; + + if (ctx == NULL || ctx->reg == NULL || section == NULL) { + return; + } + + if (!bridge_section_is_numbered_packet_radio(section) && + !bridge_section_is_numbered_ardop(section) && + !bridge_section_is_numbered_crdop(section) && + !bridge_section_is_numbered_baycom(section) && + !bridge_section_is_numbered_transport(section, "mains_proxy")) { + return; + } + + if (ctx->reg->count >= HYBBX_CIRCUIT_MAX_LINKS) { + return; + } + + entry = &ctx->reg->entries[ctx->reg->count]; + memset(entry, 0, sizeof(*entry)); + + value = hybbx_config_get(ctx->reg_config, section, "link_id", NULL); + if (value == NULL || value[0] == '\0') { + return; + } + hybbx_strlcpy(entry->link_id, value, sizeof(entry->link_id)); + + for (i = 0; i < ctx->reg->count; i++) { + if (strcmp(ctx->reg->entries[i].link_id, entry->link_id) == 0) { + fprintf(stderr, + "[circuit] bridge: duplicate link_id=%s in [%s] — skipped\n", + entry->link_id, section); + return; + } + } + + value = hybbx_config_get(ctx->reg_config, section, "link_password", NULL); + if (value != NULL && value[0] != '\0') { + hybbx_strlcpy(entry->link_password, value, sizeof(entry->link_password)); + } + + value = hybbx_config_get(ctx->reg_config, section, "link_role", NULL); + if (value != NULL && value[0] != '\0') { + hybbx_strlcpy(entry->link_role, value, sizeof(entry->link_role)); + } else if (bridge_section_is_numbered_transport(section, "mains_proxy")) { + hybbx_strlcpy(entry->link_role, "proxy", sizeof(entry->link_role)); + } else { + hybbx_strlcpy(entry->link_role, "link", sizeof(entry->link_role)); + } + + value = hybbx_config_get(ctx->reg_config, section, "frequency_mhz", NULL); + if (value == NULL || value[0] == '\0') { + value = hybbx_config_get(ctx->reg_config, section, "frequency", NULL); + } + if (value != NULL && value[0] != '\0') { + double mhz = strtod(value, NULL); + + if (mhz > 0.0) { + entry->frequency_mhz = mhz; + } + } + + ctx->reg->count++; +} + +void hybbx_circuit_bridge_clear(hybbx_circuit_bridge_registry_t *reg) +{ + if (reg == NULL) { + return; + } + memset(reg, 0, sizeof(*reg)); +} + +hybbx_result_t hybbx_circuit_bridge_load(hybbx_circuit_bridge_registry_t *reg, + const hybbx_config_t *config) +{ + bridge_load_ctx_t ctx; + + if (reg == NULL || config == NULL) { + return HYBBX_ERR_INVALID; + } + + hybbx_circuit_bridge_clear(reg); + ctx.reg = reg; + ctx.reg_config = config; + hybbx_config_foreach_section(config, bridge_load_section, &ctx); + return HYBBX_OK; +} + +const hybbx_circuit_bridge_entry_t *hybbx_circuit_bridge_find( + const hybbx_circuit_bridge_registry_t *reg, const char *link_id) +{ + unsigned i; + + if (reg == NULL || link_id == NULL || link_id[0] == '\0') { + return NULL; + } + + for (i = 0; i < reg->count; i++) { + if (strcmp(reg->entries[i].link_id, link_id) == 0) { + return ®->entries[i]; + } + } + + return NULL; +} |
