Skip to content

Add late SDP answer support for inbound calls. - #820

Open
alexfish8 wants to merge 9 commits into
mainfrom
afish/late-offer-inbound
Open

Add late SDP answer support for inbound calls.#820
alexfish8 wants to merge 9 commits into
mainfrom
afish/late-offer-inbound

Conversation

@alexfish8

@alexfish8 alexfish8 commented Aug 29, 2026

Copy link
Copy Markdown
Contributor
  • Whenever we don't receive an offer with the initial invite, we respond with a 200 and an SDP offer, and we expect an ACK to eventually arrive with an answer
    • In the event that we are waiting for a late answer, do not proceed with the call until we receive an ACK (previously, this logic was solely gated on some experimental flag being set)
    • Note: this is is gated by a feature-flag currently
  • Small refactor of acceptCall function variable (defined in handleInvite)
    • Move logic out of function variable into three top-level functions: acceptCallAndWaitForMedia, acceptCall, and waitForMedia
  • Reinvite handling for late offers
    • Reply with the negotiated SDP (rather than the offer we sent in response to the offerless INVITE)
  • Tests

@alexfish8
alexfish8 requested a review from a team as a code owner August 29, 2026 01:19

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note

This report is out of date. Scroll down for Devin Review's latest report on this PR.

Devin Review found 1 potential issue.

1 flag not posted on this PR by your GitHub settings — view it in Devin Review. (Configure)

Devin Review

Comment thread pkg/sip/inbound.go Outdated
// Encryption is picked here, before the room is selected.
answerData, err = c.negotiateMedia(rawSDP)
var sdpResponseBody []byte
expectingLateAnswer := len(rawSDP) == 0

@devin-ai-integration devin-ai-integration Bot Aug 29, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Non-SDP invitations miss late negotiation

When an offerless invitation carries another body type, expectingLateAnswer treats it as an SDP offer. Negotiation rejects the valid call.

Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Base automatically changed from tel-886/media-port to main August 31, 2026 15:54

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note

This report is out of date. Scroll down for Devin Review's latest report on this PR.

Devin Review found 2 new potential issues.

2 flags not posted on this PR by your GitHub settings — view them in Devin Review. (Configure)

Devin Review

Comment thread pkg/sip/inbound.go
Comment thread pkg/sip/outbound.go Outdated
@alexlivekit
alexlivekit force-pushed the afish/late-offer-inbound branch from 109daae to dde2f94 Compare September 2, 2026 15:12

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 new potential issue.

2 flags not posted on this PR by your GitHub settings — view them in Devin Review. (Configure)

Devin Review

Comment thread pkg/sip/inbound.go

@alexlivekit alexlivekit left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice. Mostly a bunch of nits, but one concern to map out.

Comment thread pkg/sip/inbound.go
Comment on lines +1316 to +1318
if c.media.NegotiatedAudio() != nil {
return nil
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Highly unexpected, no?
Can this happen on a re-invite?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, this seems pretty unlikely and would involve a re-invite. We'd need to see a sequence like:

  1. INVITE comes in without an offer. handleInvite sends an offer and waits for an ACK
  2. A second INVITE comes with both an offer and a higher cseq than the first invite, and so updateRemoteFromSDP is invoked, which sets up media.
  3. ACK comes in for the first invite, negotiateMediaForLateAnswer is eventually invoked, and this branch is hit.

Per spec, I think it's illegal for a client to send a second, new invite while the first invite's transaction hasn't closed, but, this is still probably something we should guard against. This would also affect initial INVITEs with offers, too. Given that this is a pre-existing thing, maybe we add guards against this in a follow-up PR?

Comment thread pkg/sip/inbound.go Outdated
Comment thread pkg/sip/inbound.go Outdated
Comment thread pkg/sip/inbound.go Outdated
Comment thread pkg/sip/inbound.go Outdated

@alexfish8 alexfish8 left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for the review!

Comment thread pkg/sip/inbound.go Outdated
Comment thread pkg/sip/inbound.go Outdated
Comment thread pkg/sip/inbound.go Outdated
Comment thread pkg/sip/inbound.go Outdated
Comment thread pkg/sip/inbound.go
Comment on lines +1316 to +1318
if c.media.NegotiatedAudio() != nil {
return nil
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, this seems pretty unlikely and would involve a re-invite. We'd need to see a sequence like:

  1. INVITE comes in without an offer. handleInvite sends an offer and waits for an ACK
  2. A second INVITE comes with both an offer and a higher cseq than the first invite, and so updateRemoteFromSDP is invoked, which sets up media.
  3. ACK comes in for the first invite, negotiateMediaForLateAnswer is eventually invoked, and this branch is hit.

Per spec, I think it's illegal for a client to send a second, new invite while the first invite's transaction hasn't closed, but, this is still probably something we should guard against. This would also affect initial INVITEs with offers, too. Given that this is a pre-existing thing, maybe we add guards against this in a follow-up PR?

@alexfish8

Copy link
Copy Markdown
Contributor Author

Still need to write tests and handle the ACK issue.

@alexfish8

Copy link
Copy Markdown
Contributor Author

PR updates:

  1. Add tests
  2. Gate late offer support on a feature flag (there's additional codec changes that will be deployed to cloud-sip, and so as to minimize the risk of breaking anything by deploying yet more changes, we'll feature gate this for now)
  3. Make code more robust to reinvites (ignore reinvites requests if we're waiting for a late answer in an ACK for a previous invite)
  4. Ensure that, if a reinvite request comes in, we reply with the negotiated SDP (rather than the offer we sent in response to the offerless invite).

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