Skip to content

fix(call): resolve T103 timeout in 1:1 audio calls#202

Merged
EdamAme-x merged 1 commit into
mainfrom
fix/call-t103-timeout-1to1
Jul 7, 2026
Merged

fix(call): resolve T103 timeout in 1:1 audio calls#202
EdamAme-x merged 1 commit into
mainfrom
fix/call-t103-timeout-1to1

Conversation

@EdamAme-x

@EdamAme-x EdamAme-x commented Jul 7, 2026

Copy link
Copy Markdown
Member

Summary

Fixes the T103 timeout (CONN_REQ_FAIL.timeout, relCode=511) in 1:1 audio calls, where the responder tears down the call ~10s after answering.

Root cause diagnosed by @botnick in #198 (with full native app wire captures + Frida instrumentation):

  • Channel ID mismatch: conn_rsp body advertised mChanId=X but cc-header used srcChanId=Y. The native app keeps these identical. The responder couldn't correlate our MC messages with the conn handshake.
  • Missing BEPI/MC handshake: After answer, the peer drives a media-channel negotiation (join_req, change_req) that linejs never answered. Without responses, the peer never considers the connection established.
  • Missing DATA channel SRTP: The peer's data stream (pt=98) failed SRTP auth because linejs only derived DATA keying for group calls.

Changes

  1. localMediaChanId = srcChanId for 1:1 calls — conn_rsp body and cc-header now use the same channel ID
  2. DATA SRTP recv context derived in #configureMedia for 1:1 calls
  3. MC JOIN_REQJOIN_RSP (0x3285) handler
  4. MC CHANGE_REQCHANGE_RSP (0x3286) handler
  5. MC CHECK_RPT (0x3287) sent after join
  6. bepi_channel_open (0x1102) SC-layer message sent after join_rsp
  7. Refactored defaultOneToOneDataSessionPayload to reuse shared stream spec

Replaces the closed #199 which took a wrong approach (UPD_RSP keepalive).

Ref: #198

Test plan

  • deno check passes
  • deno fmt passes
  • Existing planet tests pass (52/52, 2 skipped due to net permissions)
  • Manual test: place 1:1 AUDIO call from linejs to mobile device, verify no T103 timeout and call stays up >10s
  • Verify responder stops re-issuing conn_req after our conn_rsp

Root cause diagnosed by @botnick in #198: the responder never
considers its conn_req satisfied because linejs was missing the
BEPI/MC media-channel handshake and had inconsistent channel IDs.

Changes:

1. Channel ID consistency: for 1:1 calls, set localMediaChanId equal
   to srcChanId so the conn_rsp body mChanId and cc-header srcChanId
   match (the native app keeps them identical).

2. DATA channel SRTP: derive a recv SRTP context for the peer's DATA
   stream (pt=98) in 1:1 calls, not just group calls.  Without this,
   inbound data-channel packets fail auth tag verification.

3. MC JOIN_REQ / CHANGE_REQ handlers: the peer drives a BEPI media
   handshake after answer (join_req, change_req) that linejs never
   answered.  Added handlers that respond with join_rsp (0x3285),
   change_rsp (0x3286), and check_rpt (0x3287).

4. bepi_channel_open (0x1102): send the SC-layer channel-open message
   after join_rsp, matching the native app's post-answer sequence.

5. Refactored defaultOneToOneDataSessionPayload to share stream spec
   with the new MC response handlers.
@EdamAme-x EdamAme-x merged commit 58deecb into main Jul 7, 2026
4 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.

1 participant