From 606792825ed2ac21496365864f2eba5f18d5eeac Mon Sep 17 00:00:00 2001 From: Hoan Luu Huu <110280845+xquanluu@users.noreply.github.com> Date: Mon, 20 Jul 2026 18:24:14 +0700 Subject: [PATCH] feat: honor X-Jambonz-SRTP header for forwarded sip URI calls (#230) The feature-server sets X-Jambonz-SRTP (from the dial verb's srtpEncryption option) to request encrypted media on a per-call basis. Previously SRTP on a forwarded sip URI could only be enabled globally via JAMBONES_SIPS_FORWARD_SRTP + a sips: scheme; now an application can opt in per call. The env var remains as a global fallback. The internal header is stripped before the INVITE is sent to the target. Co-authored-by: Claude Opus 4.8 (1M context) --- lib/call-session.js | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/lib/call-session.js b/lib/call-session.js index 255aae4..c58c924 100644 --- a/lib/call-session.js +++ b/lib/call-session.js @@ -237,7 +237,20 @@ class CallSession extends Emitter { this.logger.info(`sending call to registered user ${destUri}`); } else if (this.req.locals.target === 'forward') { - if (process.env.JAMBONES_SIPS_FORWARD_SRTP && this.req.uri.startsWith('sips:')) { + /* the feature-server sets X-Jambonz-SRTP (from the dial verb's srtpEncryption + option) to request encrypted media on a per-call basis */ + const srtpMode = this.req.get('X-Jambonz-SRTP'); + if (srtpMode) { + /* SDES (RTP/SAVP): pass teams=true to select the SDES srtp profile, matching + the proven carrier tls/srtp path above. This offers a=crypto to the target + (what SIP endpoints such as LiveKit expect), not DTLS-SRTP. */ + this.logger.info({uri: this.req.uri, srtpMode}, + 'using SRTP (SDES) for forwarded call per X-Jambonz-SRTP'); + this.rtpEngineOpts = makeRtpEngineOpts(this.req, false, true, false, true); + encryptedMedia = true; + } + else if (process.env.JAMBONES_SIPS_FORWARD_SRTP && this.req.uri.startsWith('sips:')) { + /* legacy global opt-in for sips: forwards (uses the DTLS srtp profile) */ this.logger.info({uri: this.req.uri}, 'using SRTP/TLS for forwarded sips: call'); this.rtpEngineOpts = makeRtpEngineOpts(this.req, false, true, false, false); encryptedMedia = true; @@ -531,6 +544,7 @@ class CallSession extends Emitter { '-X-Preferred-From-Host', '-X-Jambonz-FS-UUID', '-X-Voip-Carrier-Sid', + '-X-Jambonz-SRTP', '-X-SIP-Proxy' ], proxyResponseHeaders: [