aethersdr / aethersdr/AetherSDR
D-STAR/smartsdr-dsp vendored tree: adopt-and-shrink strategy (upstream dead) — Phases 2–5
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 221
- Forks
- 117
- Avg merge
- 2d 7h
- Merged PRs (30d)
- 299
Description
Tracking issue for the post-merge strategy on the vendored D-STAR / smartsdr-dsp
tree introduced by #3956. Phase 1 (below) is already done on that PR; this issue
covers Phases 2–5.
Context & decision
- Upstream is dead.
github.com/n5ac/smartsdr-dsp— last code push 2019-08-09; thedevelopdefault branch's last real commit is 2016. We imported the tip ofthumbDV_support(762297a, © FlexRadio 2012–2014), so there is nothing newer to re-sync to. The "vendored snapshot we can re-sync" model is fiction. - We own it either way. With upstream abandoned, we are the de-facto maintainer whether we keep the C or rewrite it — so re-sync value is ~zero and is not a reason to keep or to rewrite.
- Licensing is settled and unchanged by any of this. smartsdr-dsp is GPL-3.0; AetherSDR is GPL-3.0 — same-license vendoring is the easy case. A C→C++ port that reads the source is a derivative work and stays GPL; "just credit them" (attribution-only) is not legally sufficient for a GPL derivative. So there is no licensing benefit to a rewrite (and the project is already GPL). Only a true clean-room escapes the original copyright, and it buys nothing here.
- Subprocess isolation is a design strength. The C network/serial parsers (VITA-49, discovery, ThumbDV) run in a separate process, containing their C-isms and any parser bug outside the C++ address space. Keep it.
Direction: adopt as a frozen, owned, isolated, sandboxed fork — then shrink it. Do NOT rewrite now. A full rewrite only wins if a product constraint the C can't meet appears (see Phase 5).
Phase 1 — Ship + must-fixes ✅ (done on #3956)
-
fix(dstar): stop the local helper on app shutdown— closeEvent no longer orphans the helper subprocess. -
build(dstar): gate the helper behind ENABLE_DSTAR— matches ENABLE_RADE/SPECBLEACH/DFNR; opt-out for packagers / GUI-only CI; a helper build break no longer fails the whole build.
Phase 2 — Adopt as an owned fork (docs/policy) — effort: S, risk: none
- Re-frame
third_party/smartsdr-dsp/AETHERSDR-PATCHES.md: header goes from "patches to re-apply on re-sync" → "Adopted fork. Upstream abandoned (last push 2019-08-09; imported atthumbDV_supporttip762297a). Maintained in-tree; git history is the change log." - Keep it under
third_party/(preserves the GPL license/attribution boundary — do not move intosrc/). - GPL compliance audit for a maintained fork: LICENSE retained; FlexRadio/n5ac copyright headers intact on every file; provenance line in
THIRD_PARTY_LICENSES; GPL §5 modified-file change notices satisfied (git history + a short CHANGES note per changed file/area). - Acceptance: a reviewer can trace provenance and every local modification from the repo alone; docs reflect the owned-fork posture, not a re-syncable snapshot.
Phase 3 — Prune to the used subset (high value, low risk) — effort: M, risk: low
- Measure what the
aether-dstar-waveformtarget actually compiles + links vs the full vendored tree; identify dead files and unused code paths (leftover vendor/vocoder/discovery/Windows branches; FTDI is already gone). - Delete unreferenced source files and dead
#ifdefbranches; keep the helper building and theaether_dstar_waveform_no_argssmoke test passing after each removal. - Report before/after line count (goal: ~9k → the actually-used subset; realistic target likely 3–5k).
- Acceptance: helper builds + tests pass on the pruned tree; a note records what was removed and why. This is the single biggest reduction in the surface we own, and it's near-zero-risk (deleting unreferenced code, guarded by build + smoke test).
Phase 4 — De-risk the untrusted-input surface (the real safety win) — effort: L, risk: medium
- Replace
target_compile_options(aether-dstar-waveform PRIVATE -w)with targeted-Wno-*for the specific classes the vendored code trips; fix warnings that indicate real defects (uninitialized, format, sign-compare). - Add a test/fuzz harness for the untrusted parsers — VITA-49 (
hal_listener.c),discovery_client.c, ThumbDV serial framing (thumbDV.c): feed malformed/oversized/underflow inputs, assert no OOB/crash (libFuzzer or a targeted unit harness). - Fix the concrete shim robustness bugs from the #3956 review:
aether_serial_compat.cpartial-write handling (shortwrite(2)currently treated as fatal),aether_sem_compat.cfixedregistry[128]with no reclamation (exhaustion on repeated sem create/destroy, macOS). - Harden the subprocess sandbox — run the helper with dropped capabilities / a seccomp filter / namespace isolation so a parser compromise stays contained; document the trust boundary in
docs/architecture/dstar-thumbdv-waveform.md. (Cheap because it's already a separate process — no DSP changes needed.) - Acceptance: parsers survive a fuzz corpus; sandbox profile applied + documented;
-wgone; shim bugs fixed.
Phase 5 — Incremental C++ modernization (ONLY on a product trigger) — effort: XL, risk: high
Do not start speculatively. Trigger only if one of:
-
First-class Windows support is needed (the POSIX/termios shims don't port), or
-
In-process / low-latency integration is required (removing the subprocess — accept the trade-off against isolation), or
-
After Phase 3–4, the pruned parser layer proves cheaper to reimplement than to keep testing.
-
Rewrite the thin glue only — serial/audio I/O, config, the app-facing IPC — in modern C++ (RAII,
std::span, bounds-checked containers). -
Leave the AMBE vocoder framing / GMSK modem / D-STAR protocol math as-is (highest risk, least benefit to touch).
-
Result stays GPL-3.0 (derivative); attribution retained.
-
Acceptance: parity with the C helper on a real D-STAR QSO test; no regressions.
Non-goals
- A full clean-room or full C++ rewrite now — no licensing benefit (project is already GPL), large regression risk on working, field-tested DSP, and the C is already contained by subprocess isolation.
Sequencing
Phase 2 → 3 → 4 are each independently shippable; do 3 before 4 (pruning shrinks what must be tested/hardened). Phase 5 is gated behind a product decision and should not begin until 3–4 have shrunk and de-risked the surface.
Refs: #3956 (introduces the vendored tree + Phase 1 fixes).
🤖 Generated with Claude Code
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with third_party/smartsdr-dsp/AETHERSDR-PATCHES.md and the Phase 2 provenance requirements, then inspect the aether-dstar-waveform target and aether_dstar_waveform_no_args smoke test before pruning. Review hal_listener.c, discovery_client.c, thumbDV.c, aether_serial_compat.c, and aether_sem_compat.c for the Phase 4 work. Done requires the staged acceptance checks: documented ownership, a passing pruned helper and smoke test, parser robustness, fixed shims, and a documented sandbox.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- c, cmake, cpp
- Domain
- build-system, documentation, security, testing
- Issue type
- Refactor
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100