aethersdr / aethersdr/AetherSDR

D-STAR/smartsdr-dsp vendored tree: adopt-and-shrink strategy (upstream dead) — Phases 2–5

Open
#3,963 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement external devices maintainer-review protocol
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; the develop default branch's last real commit is 2016. We imported the tip of thumbDV_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 at thumbDV_support tip 762297a). Maintained in-tree; git history is the change log."
  • Keep it under third_party/ (preserves the GPL license/attribution boundary — do not move into src/).
  • 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-waveform target 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 #ifdef branches; keep the helper building and the aether_dstar_waveform_no_args smoke 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.c partial-write handling (short write(2) currently treated as fatal), aether_sem_compat.c fixed registry[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; -w gone; 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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.