mirror of
https://github.com/n0mjs710/dmr-talkback.git
synced 2026-11-08 04:19:24 +00:00
Three changes, all driven by the same design conversation. GROUP CALLS ONLY. Private calls to the talkback's radio ID are now ignored. Unit routing draws on a globally administered namespace and is unbounded -- a private call to an unknown ID floods until located -- so reachability-by-ID would require a unique registered radio ID for every instance anyone ever deploys, for something that is neither a radio nor a repeater. BrandMeister can do it because it is the sole authority over its own namespace; these tools assume an internet of independent routers. Talkgroups are operator-scoped and bounded by the operator's own rules, so they cost nobody else anything. Consequence: the radio ID never needs to be reachable, so one ID an operator already owns serves every instance they run. PER-SLOT LANES. The previous version had a single global capture buffer, so two simultaneous callers -- one per timeslot, which the wire delivers routinely -- reset it on every interleaved packet and captured nothing. That is the same defect the 2019 Python playback.py had. Capture and replay are now per timeslot and fully independent. Within a lane, a second stream no longer supersedes unconditionally: first-come-wins unless the current capture has gone quiet, so interleaving can never thrash the buffer. One talkgroup per slot, deliberately: a slot carries one call at a time, so a list would advertise capacity that does not exist. N INSTANCES. One process now runs several independent connections, each with its own radio ID, server, and talkgroups. The purpose is one instance per HBlink3 *system*, so each system gets a private talkback without building a bridge to multiplex everyone into one engine. Bridging into a single instance remains supported. Two instances sharing a radio ID on the same server is rejected at startup. Adds toml_sections() to the vendored reader to discover [instance.<name>] sections, since it has no array-of-tables. Tests: rewrite conformance 566 checks; new test_lanes covers lane isolation, same-lane non-thrash, the ingress gate, and the capture ceiling. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
105 lines
3.5 KiB
Makefile
105 lines
3.5 KiB
Makefile
# dmr-talkback — DMR voice test / talkback endpoint
|
|
CC ?= cc
|
|
CFLAGS ?= -std=c11 -O2 -Wall -Wextra -D_DEFAULT_SOURCE
|
|
LDFLAGS ?= -lm
|
|
|
|
SRC_DIR := src
|
|
DMR_DIR := src/dmr
|
|
|
|
SOURCES := \
|
|
$(SRC_DIR)/main.c \
|
|
$(SRC_DIR)/config.c \
|
|
$(SRC_DIR)/toml.c \
|
|
$(SRC_DIR)/log.c \
|
|
$(SRC_DIR)/eventloop.c \
|
|
$(SRC_DIR)/net.c \
|
|
$(SRC_DIR)/crypto.c \
|
|
$(SRC_DIR)/hbp.c \
|
|
$(SRC_DIR)/capture.c \
|
|
$(SRC_DIR)/replay.c \
|
|
$(DMR_DIR)/dmr_bits.c \
|
|
$(DMR_DIR)/dmr_const.c \
|
|
$(DMR_DIR)/hamming.c \
|
|
$(DMR_DIR)/crc.c \
|
|
$(DMR_DIR)/rs129.c \
|
|
$(DMR_DIR)/golay.c \
|
|
$(DMR_DIR)/bptc.c \
|
|
$(DMR_DIR)/ambe.c
|
|
|
|
OBJECTS := $(SOURCES:.c=.o)
|
|
BIN := talkback
|
|
|
|
DMR_SOURCES := $(filter $(DMR_DIR)/%,$(SOURCES))
|
|
|
|
.PHONY: all clean test install uninstall
|
|
|
|
all: $(BIN)
|
|
|
|
$(BIN): $(OBJECTS)
|
|
$(CC) $(CFLAGS) -o $@ $(OBJECTS) $(LDFLAGS)
|
|
|
|
%.o: %.c
|
|
$(CC) $(CFLAGS) -c -o $@ $<
|
|
|
|
# FHS install (run as root: sudo make install)
|
|
# binary -> $(PREFIX)/bin/talkback (default /usr/local/bin)
|
|
# config -> $(SYSCONFDIR)/talkback/ (default /etc/talkback)
|
|
# unit -> $(UNITDIR)/talkback.service (default /lib/systemd/system)
|
|
# The live config is NEVER overwritten; the sample is always refreshed.
|
|
# install does NOT enable or start the service.
|
|
PREFIX ?= /usr/local
|
|
SYSCONFDIR ?= /etc
|
|
UNITDIR ?= /lib/systemd/system
|
|
CONFDIR := $(SYSCONFDIR)/talkback
|
|
UNIT := $(UNITDIR)/talkback.service
|
|
|
|
install: $(BIN)
|
|
install -d $(DESTDIR)$(PREFIX)/bin
|
|
install -m 0755 $(BIN) $(DESTDIR)$(PREFIX)/bin/talkback
|
|
install -d $(DESTDIR)$(CONFDIR)
|
|
install -m 0644 talkback.toml.sample $(DESTDIR)$(CONFDIR)/talkback.toml.sample
|
|
@if [ -f $(DESTDIR)$(CONFDIR)/talkback.toml ]; then \
|
|
echo "Preserving existing $(DESTDIR)$(CONFDIR)/talkback.toml (not overwritten)"; \
|
|
else \
|
|
install -m 0600 talkback.toml.sample $(DESTDIR)$(CONFDIR)/talkback.toml; \
|
|
echo "Installed fresh $(DESTDIR)$(CONFDIR)/talkback.toml — edit it before starting"; \
|
|
fi
|
|
install -d $(DESTDIR)$(UNITDIR)
|
|
install -m 0644 talkback.service $(DESTDIR)$(UNIT)
|
|
-systemctl daemon-reload
|
|
@echo
|
|
@echo "Installed. NOT enabled/started. Edit $(CONFDIR)/talkback.toml then:"
|
|
@echo " sudo systemctl enable --now talkback"
|
|
|
|
uninstall:
|
|
-systemctl disable --now talkback
|
|
-rm -f $(DESTDIR)$(PREFIX)/bin/talkback
|
|
-rm -f $(DESTDIR)$(UNIT)
|
|
-systemctl daemon-reload
|
|
@echo "Removed binary and unit. Left $(CONFDIR) intact (delete manually if desired)."
|
|
|
|
# Sources the tests link against (no main, no net). The HBP client is stubbed
|
|
# inside each test.
|
|
TEST_BASE := $(SRC_DIR)/log.c $(SRC_DIR)/eventloop.c $(DMR_SOURCES)
|
|
# test_rewrite stubs the instance accessors, so it links replay.c without capture.c.
|
|
TEST_REWRITE := $(SRC_DIR)/replay.c $(TEST_BASE)
|
|
# test_lanes drives the real capture path, so it needs both.
|
|
TEST_LANES := $(SRC_DIR)/capture.c $(SRC_DIR)/replay.c $(TEST_BASE)
|
|
|
|
# test_rewrite: the loopback-identity conformance vector — replayed AMBE is
|
|
# bit-identical to captured AMBE, headers are rewritten, and the LC in both
|
|
# carriers decodes back to the new addressing.
|
|
# test_lanes: the concurrency model — TS1 and TS2 capture independently and
|
|
# simultaneously, one lane never thrashes, and the ingress gate holds.
|
|
test: tests/test_rewrite.c tests/test_lanes.c $(TEST_LANES)
|
|
$(CC) $(CFLAGS) -I$(SRC_DIR) -o /tmp/talkback_test_rewrite \
|
|
tests/test_rewrite.c $(TEST_REWRITE) $(LDFLAGS)
|
|
/tmp/talkback_test_rewrite
|
|
@echo
|
|
$(CC) $(CFLAGS) -I$(SRC_DIR) -o /tmp/talkback_test_lanes \
|
|
tests/test_lanes.c $(TEST_LANES) $(LDFLAGS)
|
|
/tmp/talkback_test_lanes
|
|
|
|
clean:
|
|
rm -f $(OBJECTS) $(BIN)
|