Skip to content

pjmedia/pjsua: add on-demand stream keep-alive API - #15

Merged
darshan-verkada merged 2 commits into
intercom/release-2-15from
dev/darshan/intercom-sip-keepalive-uaf-fix
Jun 17, 2026
Merged

pjmedia/pjsua: add on-demand stream keep-alive API#15
darshan-verkada merged 2 commits into
intercom/release-2-15from
dev/darshan/intercom-sip-keepalive-uaf-fix

Conversation

@darshan-verkada

@darshan-verkada darshan-verkada commented Jun 11, 2026

Copy link
Copy Markdown

Crash signature

Operating system: Linux
                  0.0.0 Linux 4.14.183-kenobi-secure #1 SMP PREEMPT Thu Jul 14 23:55:20 UTC 2022 aarch64
Crash reason:  SIGSEGV /SEGV_MAPERR
Crash address: 0x20

Thread 14 (crashed)
 0  libpjmedia.so.2!put_frame_imp [codec.h : 1094 + 0x4]
    Found by: given as instruction pointer in context
 1  libpjmedia.so.2!put_frame [stream.c : 1733 + 0x8]
    Found by: call frame info

Summary

  • Adds pjmedia_stream_send_keep_alive() — a build-flag-independent public API that sends an empty RTP packet + RTCP to keep the media path / NAT binding alive when put_frame() is not driving the stream (e.g. local audio device disconnected but SIP session must stay up).
  • Adds pjsua_call_send_stream_keep_alive(call_id, med_idx) — a pjsua-level wrapper that acquires PJSUA_LOCK before touching the stream, making it mutually exclusive with pjmedia_channel_deinit(). This prevents a use-after-free where the caller's thread could race stream teardown.
  • Adds Call::sendStreamKeepAlive(med_idx) pjsua2 C++ binding.

Test plan

Make intercom call using command, make sure it switches to livekit. check SIP audio threads are closed, but call is still active for 2 minutes.

🤖 Generated with Claude Code

Add pjmedia_stream_send_keep_alive(), pjsua_call_send_stream_keep_alive()
and pjsua2 Call::sendStreamKeepAlive() to send an empty RTP + RTCP keep-alive
on demand, independent of PJMEDIA_STREAM_ENABLE_KA (whose auto-KA only fires
from within put_frame()).

This lets an application keep the media path / NAT binding alive when the
local sound device has been disconnected from the stream (parked audio) but
the SIP/media session must stay up, without reaching into the raw pjmedia
stream port and calling put_frame() from an app thread. The pjsua-lib entry
point sends under PJSUA_LOCK and revalidates the stream, so it is mutually
exclusive with pjsua_media_channel_deinit() and cannot use-after-free the
stream during call teardown.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Comment thread pjmedia/src/pjmedia/stream.c Outdated
Per review feedback: since PJMEDIA_STREAM_ENABLE_KA=1 in Verkada builds,
send_keep_alive_packet is always compiled in. Replace the duplicated logic
in pjmedia_stream_send_keep_alive with a direct call-through; return
PJ_ENOTSUP as a fallback for builds with KA disabled.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@darshan-verkada
darshan-verkada merged commit b3f126f into intercom/release-2-15 Jun 17, 2026
20 of 31 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants