fix(media-server): skip DTLS HelloVerify for inbound to accept Meta's first ClientHello
Inbound calls started failing DTLS again with state=failed ~2.5s after ICE connected. Keeping DTLSRoleServer (so Meta is the DTLS client and only starts ClientHello after it has our fingerprint) but adding SetDTLSInsecureSkipHelloVerify(true) — Meta's WhatsApp calling stack loses cookies between retransmits on occasion, and skipping HelloVerify lets pion accept the first ClientHello in one round-trip rather than rejecting the retry. 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
14869693d2
commit
07e8c8381c
@@ -48,14 +48,13 @@ func NewMetaPeer(cfg *config.Config, sdpOffer string, iceServers []webrtc.ICESer
|
||||
return nil, "", fmt.Errorf("set UDP port range: %w", err)
|
||||
}
|
||||
|
||||
// For inbound WhatsApp calls we answer Meta's offer. Meta doesn't know our
|
||||
// DTLS fingerprint until Rails delivers the answer via pre_accept_call /
|
||||
// accept_call, which happens ~1 second *after* pion is ready to handshake.
|
||||
// If we're the DTLS client (pion default when remote is actpass) we blast
|
||||
// ClientHello at Meta before Meta is listening for us; Meta responds with a
|
||||
// fatal alert and pion closes the PC. Flip the roles so *we* are the DTLS
|
||||
// server: Meta becomes the client and only starts ClientHello after it has
|
||||
// our fingerprint, so the handshake happens in the right order.
|
||||
// For inbound calls Meta doesn't know our DTLS fingerprint until Rails
|
||||
// delivers the SDP answer via pre_accept_call / accept_call — which runs
|
||||
// *after* create_session returns. If we're DTLS client (pion default when
|
||||
// remote is actpass) we'd send ClientHello before Meta is listening for
|
||||
// us and Meta would respond with a fatal alert. Answer as server so Meta
|
||||
// becomes the client and only starts ClientHello after it has our
|
||||
// fingerprint.
|
||||
if err := se.SetAnsweringDTLSRole(webrtc.DTLSRoleServer); err != nil {
|
||||
return nil, "", fmt.Errorf("set answering DTLS role: %w", err)
|
||||
}
|
||||
@@ -63,6 +62,11 @@ func NewMetaPeer(cfg *config.Config, sdpOffer string, iceServers []webrtc.ICESer
|
||||
return context.WithTimeout(context.Background(), 30*time.Second)
|
||||
})
|
||||
se.SetDTLSRetransmissionInterval(200 * time.Millisecond)
|
||||
// Skip the HelloVerify round-trip on the server side. Meta's WhatsApp
|
||||
// calling stack sometimes uses stateless retry which loses the pion
|
||||
// cookie between retransmits; skipping it makes the server accept the
|
||||
// ClientHello in one go.
|
||||
se.SetDTLSInsecureSkipHelloVerify(true)
|
||||
|
||||
// If a public IP is configured, use NAT1To1 so ICE candidates advertise
|
||||
// the correct address instead of a private Docker/container IP.
|
||||
|
||||
Reference in New Issue
Block a user