Proxy: Refactor for testability; add SRT/WHIP E2E and unit tests#4675
Merged
Conversation
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- New `proxy-e2e-srt-test.sh`: publishes SRT through the proxy and verifies SRT, RTMP, HTTP-FLV, and HLS playback (origin's `srt_to_rtmp` + HTTP remux + HLS). WebRTC WHEP is intentionally a placeholder. Pre-check requires an ffmpeg with libsrt and prints the exact homebrew-ffmpeg `--with-srt` recipe when missing, since the default `brew install ffmpeg` does not include SRT support. - `proxy-e2e-transmux-test.sh`: drop the srs-bench `srs_test` dependency and the `PROXY_TRANSMUX_TEST_RTC` env. WebRTC WHEP step becomes a placeholder, matching the SRT script style. Removes the now-unused Step 3 build of the WebRTC regression tool and renumbers the remaining steps. - `.openclaw/memory/srs-codebase-map.md`: register the new SRT script. - `.openclaw/skills/srs-develop/SKILL.md`: list the SRT script in the proxy verification flow and update the transmux description so it no longer mentions WebRTC verification or the dropped env var. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Randomize proxy E2E stream names to avoid stale shared state between runs, and make the WHIP HLS check skip the first possibly incomplete segment before requiring audio/video playback. Verified with the full srs-develop proxy script set: proxy unit coverage and all proxy E2E scripts passed. Co-authored-by: chatgpt-codex-connector[bot] <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com>
Create the origin load balancer in proxy bootstrap and pass it explicitly into protocol servers and system API handlers. Also keep load balancer implementations package-private and rename the default debugging origin helper. Co-authored-by: chatgpt-codex-connector[bot] <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com>
…bals. - Split OriginLoadBalancer into OriginService / HLSService / RTCService; the original interface now embeds the three role interfaces. Generate counterfeiter fakes for all four. - Extract internal/redisclient: RedisClient interface + New() factory. internal/lb/redis.go no longer imports github.com/go-redis/redis/v8. - Add unit tests for lb.go (OriginServer.ID/String/Format/NewOriginServer) and for the full memory + redis load balancers. - Replace package-level test seams (memoryKeepaliveInterval, newRedisClient, redisKeepaliveInterval, signal.signalNotify/osExit, rtmp.createBuffer) with per-instance struct fields so concurrent tests can't race on them. - Promote signal.InstallSignals / InstallForceQuit onto a new signal.Handler type; update bootstrap to construct one. - Move rtmp createBuffer onto amf0ObjectBase as bufFactory; the three AMF0 marshalers and their tests use the per-instance factory. - Make proxy test scripts locate the workspace by walking up to go.mod instead of brittle '../../../..' counting (symlink-aware). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Refactor internal/proxy/rtmp.go to expose functional-option seams (listen, newConnection, newHandshake, newProtocol, newBackend, dial) and widen the proxy server and connection to net.Listener / net.Conn so fakes can be injected. Tighten the identify switch in serve() to a real switch on CommandName. Add internal/proxy/rtmp_test.go covering rtmpProxyServer (constructor defaults, options, Close, listen error, endpoint normalization, accept-loop, graceful shutdown), rtmpConnection (defaults, serve handshake/protocol error paths, identify-loop branches, newBackend invocation contract), and rtmpClientToBackend (Close, Connect happy and error paths, publish, play). rtmp.go statement coverage rises to 76.9% with every function exercised.
Introduce listenUDP and backendURL functional-option seams on webRTCProxyServer and a dialBackendUDP seam on rtcConnection, mirroring the pattern already used by rtmpProxyServer. The seams default to the real net.ListenUDP / http URL builder / net.Dialer so production behavior is unchanged, but unit tests can now inject fakes. Cover webRTCProxyServer with focused tests: constructor defaults (including the three default-backendURL branches), Close with no listener, Run's listen error / endpoint normalization / graceful shutdown, HandleApiForWHIP and HandleApiForWHEP CORS preflight, Pick error, full happy-path against an httptest backend asserting SDP port rewrite and StoreWebRTC wiring, proxyApiToBackend error paths (backendURL error, non-2xx, malformed answer), and handleClientUDP's non-STUN, RTP-like, short-STUN, cached-username, LB-load, LB-error, and cached-address paths. internal/proxy package coverage rises from ~23% to 43.4%. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Mirror the listener and backend dial seams already in place on rtc.go so the SRT proxy is unit-testable without binding real UDP sockets: - srsSRTProxyServer.listener: *net.UDPConn -> net.PacketConn, with a new listenUDP factory injected via functional option. - SRTConnection.backendUDP: *net.UDPConn -> io.ReadWriteCloser, with a new dialBackendUDP factory; connectBackend uses it instead of building a net.UDPAddr and calling net.DialUDP directly. - handleClientUDP / HandlePacket / handleHandshake take net.Addr instead of *net.UDPAddr; writes go through PacketConn.WriteTo. - Fix a latent SA4001: v.handshake3 = &*handshake3p was no copy at all, so the subsequent SynCookie rewrite mutated the just-decoded backend packet. Replace with an explicit value copy. Adds internal/proxy/srt_test.go covering SRTHandshakePacket marshal roundtrip and stream-id parsing (100%), SRTConnection handshake-0, handshake-2 full replay, and connectBackend error paths, plus srsSRTProxyServer constructor/lifecycle and handleClientUDP routing. Reuses fakeBackendUDP / fakePacketConn / blockingUDPListener from rtc_test.go for consistency. Verified with proxy-utest.sh and the full proxy-e2e suite (rtmp, cluster, redis, transmux, srt, whip). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
winlinvip
added a commit
that referenced
this pull request
May 17, 2026
- Refactor the Go proxy for dependency injection: every proxy server, the bootstrap, the signal handler, the load balancers, and AMF0 now accept functional-option seams (factories/closures) so tests can inject fakes without binding real sockets, talking to real Redis, or racing on package globals. - Drop the package-global `lb.SrsLoadBalancer`. The bootstrap creates the LB locally and threads it through every proxy server constructor. Two old global indirections in `internal/signal` and `internal/rtmp/amf0` are likewise replaced by per-instance fields. - Rename `internal/server` → `internal/proxy` and rename the `lb` public surface for clarity: `SRSLoadBalancer` is split into `OriginService` / `HLSService` / `RTCService` and recomposed as `OriginLoadBalancer`; `SRSServer` → `OriginServer`; all proxy server types gain a `Proxy` qualifier (e.g. `RTMPServer` → `RTMPProxyServer`). - Extract the Redis client behind a new `internal/redisclient` package with a minimal `RedisClient` interface and a counterfeiter fake. - Add counterfeiter fakes (`proxyfakes`, `lbfakes`, `redisclientfakes`) and ~7.5k lines of unit tests covering bootstrap, memory + Redis LBs, all five proxy servers, the signal handler, and AMF0. - Add two new E2E flows — `proxy-e2e-srt-test.sh` (SRT publish through proxy, verify SRT/RTMP/HTTP-FLV/HLS playback) and `proxy-e2e-whip-test.sh` (WHIP publish, verify RTMP/HTTP-FLV/HLS via origin `rtc_to_rtmp`) — plus `setup-ffmpeg-with-whip.sh`, a macOS builder for an ffmpeg with openssl-DTLS WHIP and SRT support that the two scripts auto-invoke when needed. - Workspace reorg: move `memory/` and `skills/` to the repo root so all agent tools (Claude / Codex / Kiro / OpenClaw) share one source of truth via symlinks. Sync `docs/proxy/proxy-load-balancer.md` and `memory/srs-codebase-map.md` with the new names. No protocol, log, HTTP API, or wire-format changes. Refactor only — all externally observable proxy behavior is unchanged. --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: chatgpt-codex-connector[bot] <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com>
winlinvip
added a commit
that referenced
this pull request
May 17, 2026
…0.146 (#4675) - Refactor the Go proxy for dependency injection: every proxy server, the bootstrap, the signal handler, the load balancers, and AMF0 now accept functional-option seams (factories/closures) so tests can inject fakes without binding real sockets, talking to real Redis, or racing on package globals. - Drop the package-global `lb.SrsLoadBalancer`. The bootstrap creates the LB locally and threads it through every proxy server constructor. Two old global indirections in `internal/signal` and `internal/rtmp/amf0` are likewise replaced by per-instance fields. - Rename `internal/server` → `internal/proxy` and rename the `lb` public surface for clarity: `SRSLoadBalancer` is split into `OriginService` / `HLSService` / `RTCService` and recomposed as `OriginLoadBalancer`; `SRSServer` → `OriginServer`; all proxy server types gain a `Proxy` qualifier (e.g. `RTMPServer` → `RTMPProxyServer`). - Extract the Redis client behind a new `internal/redisclient` package with a minimal `RedisClient` interface and a counterfeiter fake. - Add counterfeiter fakes (`proxyfakes`, `lbfakes`, `redisclientfakes`) and ~7.5k lines of unit tests covering bootstrap, memory + Redis LBs, all five proxy servers, the signal handler, and AMF0. - Add two new E2E flows — `proxy-e2e-srt-test.sh` (SRT publish through proxy, verify SRT/RTMP/HTTP-FLV/HLS playback) and `proxy-e2e-whip-test.sh` (WHIP publish, verify RTMP/HTTP-FLV/HLS via origin `rtc_to_rtmp`) — plus `setup-ffmpeg-with-whip.sh`, a macOS builder for an ffmpeg with openssl-DTLS WHIP and SRT support that the two scripts auto-invoke when needed. - Workspace reorg: move `memory/` and `skills/` to the repo root so all agent tools (Claude / Codex / Kiro / OpenClaw) share one source of truth via symlinks. Sync `docs/proxy/proxy-load-balancer.md` and `memory/srs-codebase-map.md` with the new names. No protocol, log, HTTP API, or wire-format changes. Refactor only — all externally observable proxy behavior is unchanged. --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: chatgpt-codex-connector[bot] <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com>
winlinvip
added a commit
that referenced
this pull request
May 17, 2026
…0.148 (#4675) - Refactor the Go proxy for dependency injection: every proxy server, the bootstrap, the signal handler, the load balancers, and AMF0 now accept functional-option seams (factories/closures) so tests can inject fakes without binding real sockets, talking to real Redis, or racing on package globals. - Drop the package-global `lb.SrsLoadBalancer`. The bootstrap creates the LB locally and threads it through every proxy server constructor. Two old global indirections in `internal/signal` and `internal/rtmp/amf0` are likewise replaced by per-instance fields. - Rename `internal/server` → `internal/proxy` and rename the `lb` public surface for clarity: `SRSLoadBalancer` is split into `OriginService` / `HLSService` / `RTCService` and recomposed as `OriginLoadBalancer`; `SRSServer` → `OriginServer`; all proxy server types gain a `Proxy` qualifier (e.g. `RTMPServer` → `RTMPProxyServer`). - Extract the Redis client behind a new `internal/redisclient` package with a minimal `RedisClient` interface and a counterfeiter fake. - Add counterfeiter fakes (`proxyfakes`, `lbfakes`, `redisclientfakes`) and ~7.5k lines of unit tests covering bootstrap, memory + Redis LBs, all five proxy servers, the signal handler, and AMF0. - Add two new E2E flows — `proxy-e2e-srt-test.sh` (SRT publish through proxy, verify SRT/RTMP/HTTP-FLV/HLS playback) and `proxy-e2e-whip-test.sh` (WHIP publish, verify RTMP/HTTP-FLV/HLS via origin `rtc_to_rtmp`) — plus `setup-ffmpeg-with-whip.sh`, a macOS builder for an ffmpeg with openssl-DTLS WHIP and SRT support that the two scripts auto-invoke when needed. - Workspace reorg: move `memory/` and `skills/` to the repo root so all agent tools (Claude / Codex / Kiro / OpenClaw) share one source of truth via symlinks. Sync `docs/proxy/proxy-load-balancer.md` and `memory/srs-codebase-map.md` with the new names. No protocol, log, HTTP API, or wire-format changes. Refactor only — all externally observable proxy behavior is unchanged. --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: chatgpt-codex-connector[bot] <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com>
winlinvip
added a commit
that referenced
this pull request
May 17, 2026
…0.148 (#4675) - Refactor the Go proxy for dependency injection: every proxy server, the bootstrap, the signal handler, the load balancers, and AMF0 now accept functional-option seams (factories/closures) so tests can inject fakes without binding real sockets, talking to real Redis, or racing on package globals. - Drop the package-global `lb.SrsLoadBalancer`. The bootstrap creates the LB locally and threads it through every proxy server constructor. Two old global indirections in `internal/signal` and `internal/rtmp/amf0` are likewise replaced by per-instance fields. - Rename `internal/server` → `internal/proxy` and rename the `lb` public surface for clarity: `SRSLoadBalancer` is split into `OriginService` / `HLSService` / `RTCService` and recomposed as `OriginLoadBalancer`; `SRSServer` → `OriginServer`; all proxy server types gain a `Proxy` qualifier (e.g. `RTMPServer` → `RTMPProxyServer`). - Extract the Redis client behind a new `internal/redisclient` package with a minimal `RedisClient` interface and a counterfeiter fake. - Add counterfeiter fakes (`proxyfakes`, `lbfakes`, `redisclientfakes`) and ~7.5k lines of unit tests covering bootstrap, memory + Redis LBs, all five proxy servers, the signal handler, and AMF0. - Add two new E2E flows — `proxy-e2e-srt-test.sh` (SRT publish through proxy, verify SRT/RTMP/HTTP-FLV/HLS playback) and `proxy-e2e-whip-test.sh` (WHIP publish, verify RTMP/HTTP-FLV/HLS via origin `rtc_to_rtmp`) — plus `setup-ffmpeg-with-whip.sh`, a macOS builder for an ffmpeg with openssl-DTLS WHIP and SRT support that the two scripts auto-invoke when needed. - Workspace reorg: move `memory/` and `skills/` to the repo root so all agent tools (Claude / Codex / Kiro / OpenClaw) share one source of truth via symlinks. Sync `docs/proxy/proxy-load-balancer.md` and `memory/srs-codebase-map.md` with the new names. No protocol, log, HTTP API, or wire-format changes. Refactor only — all externally observable proxy behavior is unchanged. --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: chatgpt-codex-connector[bot] <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
bootstrap, the signal handler, the load balancers, and AMF0 now accept
functional-option seams (factories/closures) so tests can inject fakes
without binding real sockets, talking to real Redis, or racing on package
globals.
lb.SrsLoadBalancer. The bootstrap creates the LBlocally and threads it through every proxy server constructor. Two old
global indirections in
internal/signalandinternal/rtmp/amf0arelikewise replaced by per-instance fields.
internal/server→internal/proxyand rename thelbpublicsurface for clarity:
SRSLoadBalanceris split intoOriginService/HLSService/RTCServiceand recomposed asOriginLoadBalancer;SRSServer→OriginServer; all proxy server types gain aProxyqualifier (e.g.
RTMPServer→RTMPProxyServer).internal/redisclientpackage witha minimal
RedisClientinterface and a counterfeiter fake.proxyfakes,lbfakes,redisclientfakes) and~7.5k lines of unit tests covering bootstrap, memory + Redis LBs, all five
proxy servers, the signal handler, and AMF0.
proxy-e2e-srt-test.sh(SRT publish through proxy,verify SRT/RTMP/HTTP-FLV/HLS playback) and
proxy-e2e-whip-test.sh(WHIPpublish, verify RTMP/HTTP-FLV/HLS via origin
rtc_to_rtmp) — plussetup-ffmpeg-with-whip.sh, a macOS builder for an ffmpeg with openssl-DTLSWHIP and SRT support that the two scripts auto-invoke when needed.
memory/andskills/to the repo root so all agenttools (Claude / Codex / Kiro / OpenClaw) share one source of truth via
symlinks. Sync
docs/proxy/proxy-load-balancer.mdandmemory/srs-codebase-map.mdwith the new names.No protocol, log, HTTP API, or wire-format changes. Refactor only — all
externally observable proxy behavior is unchanged.