rtp_relay: SIP→WebRTC transcoding regression tests (GH-3902)Feat/rtp relay tests - #33
Merged
Merged
Conversation
Add an rtp_relay test set covering OpenSIPS issue #3902: the callee/WebRTC profile (UDP/TLS/RTP/SAVPF + ICE=force) provisioned in a branch_route is not linked into sess->legs[CALLEE] before the offer, so rtp_relay asks rtpengine for plain RTP/AVP and a WebRTC UA replies 488. Four scenarios, each asserting via the rtpengine ng control stream (no live WebRTC UA needed) that the profile survives: 01.initial-offer-savpf initial SDP-in-INVITE offer 02.indialog-reinvite-hold-unhold in-dialog hold/unhold re-INVITE (issue title) 03.update-failover-reanchor rtp_relay_update node-failover re-anchor 04.late-negotiation no-SDP INVITE / delayed offer The checker (scripts/ng_checker.py) is dependency-free: it parses the libpcap capture and decodes the bencode ng messages with the standard library only. A host-networked capture sidecar sniffs the bridge so it sees the inter-container OpenSIPS<->rtpengine ng traffic. rtpengine runs from the official Debian rtpengine-daemon package (sipwise upstream, in Debian main) installed on a pinned debian:trixie-slim base at container start -- no third-party rtpengine image. It runs userspace-only (--table=-1, no kernel dkms, no NET_ADMIN). A Docker healthcheck on the ng socket lets dependents gate on `healthy: rtpengine` so the apt-install delay cannot race the proxy startup ping. Registered in run.yml. All required OpenSIPS modules (rtp_relay, rtpengine, mi_datagram, dialog, proto_udp) ship in the base opensips package, so no .opensips.modules change is needed. These are regression tests for the fixed behavior: RED on current master, GREEN once rtp_relay_reinvite_tag_v4 is merged and the image rebuilt.
- rtp_relay/config.yml and defines.yml are now symlinks to the suite-root files, matching every other test set. The set-specific extras moved up into the root: bridge device pins (config.yml) and the rtpengine/capture/ checker vars (defines.yml). - rtpengine image: drop the pinned digest, use plain debian:trixie-slim and run with default flags (no --log-level override). - widen the rtpengine readiness window (healthcheck retries 30->120, scenario timeout 90->300, and 360 for 03's MI re-anchor step) so the cold apt-install of rtpengine-daemon reliably completes on slower-apt hosts. Verified locally: rtp_relay 4/4 PASS against the fixed OpenSIPS image, and RED via the ng checker on the affected build (#3902).
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.
Summary
Adds a new
rtp_relaytest set — four sipssert scenarios that are regression tests for OpenSIPS issue #3902 ("rtp_relay: callee/WebRTC profile lost on the offer for a transcoding call").On a transcoding SIP → WebRTC call the caller leg is plain
RTP/AVP(set in the request route) and the callee/WebRTC leg (UDP/TLS/RTP/SAVPF,ICE=force) is provisioned in abranch_routevia$rtp_relay(...). On affected OpenSIPS the branch-provisioned callee leg is not linked intosess->legs[CALLEE]before the offer, sortp_relayasks rtpengine for plainRTP/AVP— the WebRTC transport-protocol and ICE are dropped and a real WebRTC UA replies 488 Not Acceptable Here.Changes
rtp_relay/test set (4 scenarios, see table below).run.yml— registers the set (- rtp_relay).config.yml— pins the bridge device names (device: osbr0/osbr1) so a host-networked capture sidecar cantcpdump -i osbr0. Inert for every other set.defines.yml— adds thertp_relayvars (rtpengine_ip,rtpengine_ng_port,rtpengine_image,capture_image,checker_image). Unused by the other sets.rtp_relay/config.ymlandrtp_relay/defines.ymlare symlinks to the suite root (../config.yml/../defines.yml), matchingdialog/,b2b/,auth/, and every other set.What the scenarios assert
01.initial-offer-savpf/UDP/TLS/RTP/SAVPF+ICE=force02.indialog-reinvite-hold-unhold/03.update-failover-reanchor/rtp_relay_update(MI) node-failover re-anchor04.late-negotiation/The assertion is made against the rtpengine
ngcontrol message (captured on the ng UDP port), not against media or a real endpoint — so no live DTLS/ICE peer is needed; the checker reads exactly what OpenSIPS asks rtpengine to do. The 488 is therefore inferred from the missing transport profile, not observed.scripts/ng_checker.py(one copy per test dir) is dependency-free — it parses the libpcap capture and decodes the bencodengmessages with the Python standard library only (no tshark/scapy/pip), so it runs in anypython3image.rtpengine service container
The suite has no rtpengine task yet, so this set adds one (
type: generic). Rather than depend on a third-party image (there is no official sipwise/rtpengine image), it installs the official Debianrtpengine-daemonpackage on a stockdebian:trixie-slimbase at container start, run with default values:rtpengine --table=-1 --interface={{ rtpengine_ip }} --listen-ng={{ rtpengine_ip }}:{{ rtpengine_ng_port }} --foreground --log-stderr
--table=-1⇒ pure userspace (no kernel module, noNET_ADMIN, no privileged). The cold apt-install pulls a sizeable ffmpeg/codec tree (~1–3 min on a cold cache), so dependents gate on a Dockerhealthcheck(retries: 120, ~4 min window) viarequire: { healthy: rtpengine }, and the per-scenariotimeoutis300s (360s for 03's MI re-anchor). If a prebuilt image is later preferred, pointrtpengine_imageat it and drop the apt-install from the task command.The checker needs the OpenSIPS↔rtpengine ng packets, which flow between two other containers, so each scenario runs a host-networked capture sidecar (
network: host) thattcpdump -i osbr0s the bridge device into a shared volumethe checker then reads.
Image modules — no
.opensips.moduleschangeEvery module these tests load (
rtp_relay.so,rtpengine.so,mi_datagram.so, plusdialog/tm/sl/rr/maxfwd/sipmsgops/proto_udp) ships in the baseopensipspackage —debian/controlhas no rtp/datagram split-out package, and the RPM spec lists them under the main%files. The stockghcr.io/opensips/opensips:sipssertimage already contains them.Validation
Run end-to-end through sipssert against two OpenSIPS images identical except for the
rtp_relay.so(#3902-fixed vs. stock), spinning up the full stack (OpenSIPS + rtpengine + sipp UAC/UAS + host-net ng-capture + checker, plus theopensips-midatagram task for 03):.so.soi.e. the tests catch the bug (pristine → all FAIL) and confirm the fix (all PASS) across all four paths.
Gaps / caveats
rtp_relay_updatere-anchors onto the same node (fired via MI, not a real watchdog node-down); still exercises the self-generated re-INVITE / profile-carry path, which is the defect.initial_cbbranches; 01–03 also pass with the narrower REQUEST_FWDED-only link.retries: 120,timeout300/360s) is sized for a cold apt-install on a slow-apt host; CI with a warm mirror finishes well inside it.nicolaka/netshoot) is a pragmatictcpdumpcarrier — trivially swappable viacapture_image.