mirror of
https://github.com/livekit/livekit.git
synced 2026-10-06 14:18:05 +00:00
fix: skip DTLS HelloVerifyRequest (#4937)
This commit is contained in:
@@ -421,6 +421,9 @@ func newPeerConnection(
|
||||
// As Firefox does not support migration, ICE Lite can be disabled.
|
||||
se.SetLite(false)
|
||||
}
|
||||
// ICE checks already prove the remote address, so the HelloVerifyRequest cookie only adds a round trip.
|
||||
// pion applies this only when this side ends up as the DTLS server.
|
||||
se.SetDTLSInsecureSkipHelloVerify(true)
|
||||
se.SetDTLSRetransmissionInterval(dtlsRetransmissionInterval)
|
||||
se.SetDTLSConnectContextMaker(func() (context.Context, func()) {
|
||||
return context.WithTimeout(context.Background(), dtlsHandshakeTimeout)
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/pion/dtls/v3/pkg/protocol/handshake"
|
||||
"github.com/pion/sdp/v3"
|
||||
"github.com/pion/webrtc/v4"
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -251,6 +252,78 @@ func TestFirstNegotiationUsesFastDebounce(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestDTLSHandshakeSkipsHelloVerify(t *testing.T) {
|
||||
// the SFU offers as on the subscriber connection, and a plain pion peer answers active like a browser,
|
||||
// so the SFU is the DTLS server and only the peer sends ClientHello
|
||||
handler := &transportfakes.FakeHandler{}
|
||||
sfu, err := NewPCTransport(TransportParams{Config: &WebRTCConfig{}, IsOfferer: true, Handler: handler})
|
||||
require.NoError(t, err)
|
||||
defer sfu.Close()
|
||||
_, err = sfu.pc.CreateDataChannel(ReliableDataChannel, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
var clientHellos atomic.Int32
|
||||
se := webrtc.SettingEngine{}
|
||||
require.NoError(t, se.SetAnsweringDTLSRole(webrtc.DTLSRoleClient))
|
||||
se.SetDTLSClientHelloMessageHook(func(m handshake.MessageClientHello) handshake.Message {
|
||||
clientHellos.Inc()
|
||||
return &m
|
||||
})
|
||||
client, err := webrtc.NewAPI(webrtc.WithSettingEngine(se)).NewPeerConnection(webrtc.Configuration{})
|
||||
require.NoError(t, err)
|
||||
defer client.Close()
|
||||
|
||||
var lock sync.Mutex
|
||||
var pending []webrtc.ICECandidateInit
|
||||
hasOffer := false
|
||||
handler.OnICECandidateCalls(func(c *webrtc.ICECandidate, _ livekit.SignalTarget) error {
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
if !hasOffer {
|
||||
pending = append(pending, c.ToJSON())
|
||||
return nil
|
||||
}
|
||||
return client.AddICECandidate(c.ToJSON())
|
||||
})
|
||||
client.OnICECandidate(func(c *webrtc.ICECandidate) {
|
||||
if c != nil {
|
||||
sfu.AddICECandidate(c.ToJSON())
|
||||
}
|
||||
})
|
||||
handler.OnOfferCalls(func(offer webrtc.SessionDescription, offerId uint32, _ map[string]string) error {
|
||||
lock.Lock()
|
||||
if err := client.SetRemoteDescription(offer); err != nil {
|
||||
lock.Unlock()
|
||||
return err
|
||||
}
|
||||
hasOffer = true
|
||||
for _, c := range pending {
|
||||
_ = client.AddICECandidate(c)
|
||||
}
|
||||
lock.Unlock()
|
||||
|
||||
answer, err := client.CreateAnswer(nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := client.SetLocalDescription(answer); err != nil {
|
||||
return err
|
||||
}
|
||||
return sfu.HandleRemoteDescription(answer, offerId)
|
||||
})
|
||||
sfu.Negotiate(true)
|
||||
|
||||
require.Eventually(t, func() bool {
|
||||
return sfu.IsEstablished() && client.ConnectionState() == webrtc.PeerConnectionStateConnected
|
||||
}, 10*time.Second, 10*time.Millisecond, "transports did not connect")
|
||||
|
||||
// a HelloVerifyRequest from the SFU makes the peer send its ClientHello a second time, with the cookie
|
||||
require.Equal(t, int32(1), clientHellos.Load())
|
||||
}
|
||||
|
||||
func TestFirstOfferMissedDuringICERestart(t *testing.T) {
|
||||
params := TransportParams{
|
||||
Config: &WebRTCConfig{},
|
||||
|
||||
Reference in New Issue
Block a user