diff --git a/CHANGELOG.md b/CHANGELOG.md index e927915..53d0454 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,55 @@ # Datarhei — Dragon Fork +## v0.4.0-dragonfork (2026-05-10) + +Protocol polish milestone. Resolves issues #18, #19, #20, #21. + +### Added + +- **STAP-A IDR detection** (`core/webrtc/keyframecache.go`). The keyframe + cache's `isH264IDRStart` now handles all three H.264 RTP packetisation + modes: single-NAL (type 5), FU-A start fragment (type 28, start bit + + inner type 5), and STAP-A aggregate (type 24, first NAL header at byte 3, + inner type 5). Before this fix, an IDR delivered via STAP-A (common from + some encoders and relay chains) was not detected, so the cache was never + seeded and late-joining WHEP peers still waited a full GOP. Four new tests + cover STAP-A with and without truncated payloads. Closes #18. + +- **WHEP Link header — RFC 9429 §4.3** (`app/webrtc/handler.go`). + `POST /api/v3/whep/{id}` 201 responses now include one + `Link: ; rel="ice-server"` header per configured ICE server. + `Access-Control-Expose-Headers` updated to include `Link` so browser + fetch() can read the header cross-origin. `ICEServerURIs()` accessor added + to `Subsystem`. Two new tests verify the header and CORS exposure. Closes + #19. + +- **WHIP Link header — RFC 9261 §5.2** (`app/webrtc/whip_handler.go`). + `POST /api/v3/whip/{id}` 201 responses emit the same ICE server Link + headers as WHEP, allowing OBS, GStreamer, and browser-based publishers + to discover STUN/TURN without a separate signalling round-trip. Symmetric + implementation using the same `ICEServerURIs()` accessor. Closes #21 + (partial — see also trickle-ICE tests below). + +- **Multi-IP NAT1To1** (`core/webrtc/config.go`, `core/webrtc/ice.go`, + `app/webrtc/subsystem.go`). `Config` now carries `NAT1To1IPs []string` + alongside the legacy `PublicIP string`. `BuildICEConfig` passes the full + list to Pion's `SetNAT1To1IPs` when non-empty, falling back to + `[]string{PublicIP}` for backward compatibility. `Subsystem.New` builds + the merged list: `PublicIP` is prepended (deduplicated) then + `NAT1To1IPs` entries follow — enabling dual-homed servers (LAN + public + IP) to advertise host candidates on all interfaces simultaneously. Five + new tests cover multi-IP, fallback, precedence, and STUN-only mode. + Removes the old first-entry-only workaround comment. Closes #20. + +- **WHIP handler test suite** (`app/webrtc/whip_handler_test.go`). + Nine tests covering: `Publish` 404 on missing ingest, 400 on empty and + non-SDP body; `Unpublish` 204 idempotency, 400 on missing resource; + `TrickleIngest` 404 on unknown peer, 400 on missing resource; CORS + preflight Link/Location/ETag exposure; CORS headers present on error + responses. Closes #21 (trickle-ICE test coverage). + +--- + ## v0.3.0-dragonfork (2026-05-10) WebRTC ingest (WHIP) milestone. Browsers and OBS can now push a @@ -107,8 +157,7 @@ Resolves issues #11, #12, #13, #14. `ffmpeg_leg_failures_total`, `active_streams`, `active_peers`, `udp_ports_in_use`. Closes #11. -- **Grafana observability stack** in `deploy/truenas/core/`: - Prometheus v2.55 and Grafana OSS 11.3 containers on a `dragonfork-mon` +- **Grafana observability stack** in `deploy/truenas/core/`:\n Prometheus v2.55 and Grafana OSS 11.3 containers on a `dragonfork-mon` bridge network reaching Core via `host.docker.internal`. Pre-loaded WebRTC Health dashboard (5 rows: WHEP API, ICE, streams/peers, capacity, silent-degradation canary). Four pre-loaded Prometheus alert rules.