- Fix a goroutine leak on the WHEP path: the backend→client reader was
being spawned on every inbound client packet (STUN keepalives + RTCP
feedback), leaking tens of thousands of goroutines under steady-state
load. Now spawned exactly once per connection via `sync.Once` on both
the RTC and SRT proxies. Listener and reader receive buffers are also
reused across iterations.
- Make the legacy SRS `/rtc/v1/play/` and `/rtc/v1/publish/` APIs work
end-to-end through the proxy. Those endpoints wrap the SDP in a JSON
envelope (`{"sdp":"v=0\r\n..."}` where `\r\n` is the literal 2-byte JSON
escape, not real CRLF), so ICE parsing previously absorbed the rest of
the body into the ufrag. Added `unwrapSDPEnvelope` for ICE extraction
and tightened `ParseIceUfragPwd`'s value class to stop at `\`. The bytes
forwarded to the client and the in-body candidate-port rewrite still
operate on the raw envelope.
- Enable `net/http/pprof` endpoints when `GO_PPROF` is set (blank import
in `internal/debug/pprof.go`) and add `docs/perf/proxy-whep.md` walking
through CPU/alloc/heap/goroutine/trace collection and `pprof -base`
before/after diffs for the WHEP workload (1 publisher + N players).
- Tighten `SRTHandshakePacket.UnmarshalBinary` to
`bytes.Clone(ExtraData)` so decoded handshakes kept on the connection
(`handshake0`, `handshake2`) stay valid once the receive buffer is
reused.
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
23 lines
414 B
Go
23 lines
414 B
Go
// Copyright (c) 2026 Winlin
|
|
//
|
|
// SPDX-License-Identifier: MIT
|
|
package debug
|
|
|
|
import (
|
|
"context"
|
|
"net/http"
|
|
_ "net/http/pprof"
|
|
|
|
"srsx/internal/env"
|
|
"srsx/internal/logger"
|
|
)
|
|
|
|
func HandleGoPprof(ctx context.Context, environment env.ProxyEnvironment) {
|
|
if addr := environment.GoPprof(); addr != "" {
|
|
go func() {
|
|
logger.Debug(ctx, "Start Go pprof at %v", addr)
|
|
http.ListenAndServe(addr, nil)
|
|
}()
|
|
}
|
|
}
|