fix(media-server): fall back to sole agent peer when peer_id missing
Rails' /agent_answer forwards only the SDP answer to the media server; it
doesn't persist or echo the peer_id returned from /agent-offer. The
AgentAnswer handler required peer_id and 400'd on every Rails call, so
Peer B never completed its handshake. With no agent remote track, the
bridge delivered nothing to Meta, and Meta tore the call down after ~20s
with error 138021 ("WhatsApp client terminated the call due to not
receiving any media").
Add Session.SoleAgentPeerID and have the handler use it when peer_id is
absent. Single-agent sessions now complete negotiation without extra
Rails plumbing. Multi-agent sessions still require an explicit peer_id.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
83f32cddac
commit
02279d4e15
@@ -297,9 +297,16 @@ func (h *Handlers) AgentAnswer(w http.ResponseWriter, r *http.Request) {
|
||||
writeError(w, http.StatusBadRequest, "sdp_answer is required")
|
||||
return
|
||||
}
|
||||
// When peer_id is omitted (single-agent sessions), fall back to the only
|
||||
// agent peer attached to the session. Rails doesn't currently surface
|
||||
// peer_id through ActionCable, so browsers just send the SDP answer.
|
||||
if req.PeerID == "" {
|
||||
writeError(w, http.StatusBadRequest, "peer_id is required")
|
||||
return
|
||||
if only, ok := sess.SoleAgentPeerID(); ok {
|
||||
req.PeerID = only
|
||||
} else {
|
||||
writeError(w, http.StatusBadRequest, "peer_id is required (session has multiple agent peers)")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if err := sess.SetAgentAnswer(req.PeerID, req.SDPAnswer); err != nil {
|
||||
|
||||
@@ -204,6 +204,22 @@ func (s *Session) CreateAgentPeer(peerID string, role peer.PeerRole, iceServers
|
||||
return sdpOffer, nil
|
||||
}
|
||||
|
||||
// SoleAgentPeerID returns the peer_id when the session has exactly one agent
|
||||
// peer. Used by the agent-answer handler as a fallback for clients that don't
|
||||
// track peer ids.
|
||||
func (s *Session) SoleAgentPeerID() (string, bool) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
if len(s.AgentPeers) != 1 {
|
||||
return "", false
|
||||
}
|
||||
for id := range s.AgentPeers {
|
||||
return id, true
|
||||
}
|
||||
return "", false
|
||||
}
|
||||
|
||||
// SetAgentAnswer sets the agent browser's SDP answer on the specified agent
|
||||
// peer, completing the WebRTC handshake.
|
||||
func (s *Session) SetAgentAnswer(peerID, sdpAnswer string) error {
|
||||
|
||||
Reference in New Issue
Block a user