Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 22 additions & 13 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@ require (
github.com/golang-jwt/jwt/v5 v5.3.0
github.com/google/uuid v1.6.0
github.com/oapi-codegen/runtime v1.6.0
github.com/pion/dtls/v3 v3.1.8
github.com/pion/ice/v4 v4.4.2
github.com/pion/interceptor v0.1.48
github.com/pion/dtls/v4 v4.0.0-rc.1
github.com/pion/ice/v4 v4.4.4
github.com/pion/interceptor v0.1.49
github.com/pion/logging v0.2.4
github.com/pion/rtcp v1.2.17
github.com/pion/rtcp v1.2.18
github.com/pion/rtp v1.10.5
github.com/pion/sdp/v3 v3.0.19
github.com/pion/transport/v4 v4.1.0
github.com/pion/webrtc/v4 v4.2.20
github.com/pion/sdp/v3 v3.0.20
github.com/pion/transport/v5 v5.1.1
github.com/pion/webrtc/v4 v4.2.22
github.com/sirupsen/logrus v1.9.3
github.com/stretchr/testify v1.12.1
github.com/thesyncim/gopus v0.1.1
Expand All @@ -32,17 +32,26 @@ require (
github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect
github.com/gobwas/httphead v0.1.0 // indirect
github.com/gobwas/pool v0.2.1 // indirect
github.com/pion/datachannel v1.6.2 // indirect
github.com/pion/mdns/v2 v2.2.0 // indirect
github.com/pion/datachannel v1.6.3 // indirect
github.com/pion/dtls/v3 v3.1.9 // indirect
github.com/pion/mdns/v2 v2.2.1 // indirect
github.com/pion/randutil v0.1.0 // indirect
github.com/pion/sctp v1.11.1 // indirect
github.com/pion/srtp/v3 v3.0.13 // indirect
github.com/pion/stun/v4 v4.0.0 // indirect
github.com/pion/turn/v5 v5.1.0 // indirect
github.com/pion/sctp v1.11.3 // indirect
github.com/pion/srtp/v3 v3.1.0 // indirect
github.com/pion/stun/v4 v4.0.1 // indirect
github.com/pion/turn/v5 v5.1.2 // indirect
github.com/wlynxg/anet v0.0.5 // indirect
go.yaml.in/yaml/v3 v3.0.5 // indirect
golang.org/x/crypto v0.48.0 // indirect
golang.org/x/net v0.50.0 // indirect
golang.org/x/sys v0.41.0 // indirect
golang.org/x/time v0.14.0 // indirect
)

replace github.com/pion/webrtc/v4 => github.com/GetStream/pion-webrtc/v4 v4.2.22-warp.3

replace github.com/pion/ice/v4 => github.com/GetStream/pion-ice/v4 v4.4.4-warp.3

replace github.com/pion/dtls/v4 => github.com/GetStream/pion-dtls/v4 v4.0.0-rc.1-warp.1

replace github.com/pion/sctp => github.com/GetStream/pion-sctp v1.11.3-warp.1
54 changes: 28 additions & 26 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
github.com/GetStream/getstream-go/v5 v5.2.0 h1:nrZkIL0mzHtByMeAeNFD4jpGIT5XPa0P3ItFL9bCIr8=
github.com/GetStream/getstream-go/v5 v5.2.0/go.mod h1:qnod4MVOSwxfpqtXLpxjbMo7lDcepOlg8X2GrpBs/cw=
github.com/GetStream/pion-dtls/v4 v4.0.0-rc.1-warp.1 h1:MpkUBXJU3E6JJ2SkxxxZtiFi3he11Dh1K6zKOz0yn/8=
github.com/GetStream/pion-dtls/v4 v4.0.0-rc.1-warp.1/go.mod h1:P8msRRyK3bGwG3aZccN0Vk8chAMp2nQiBR9O29b86Io=
github.com/GetStream/pion-ice/v4 v4.4.4-warp.3 h1:ptB/HQG0ZAwn8uE+ZihJGNdolGcp/mVjQWDysQyTr14=
github.com/GetStream/pion-ice/v4 v4.4.4-warp.3/go.mod h1:vkrbLwF98P/DJuCKoAmOQY4FJ7dJPI5VcBFOO3kyYx0=
github.com/GetStream/pion-sctp v1.11.3-warp.1 h1:/PcOWTVe1jATCPIz32EP3XmKkYOUE7mfZ4BJhEVDmh4=
github.com/GetStream/pion-sctp v1.11.3-warp.1/go.mod h1:7v/MXGBROc8fu9g2TVwCXRasPISCMd3j8wSH+o45uCI=
github.com/GetStream/pion-webrtc/v4 v4.2.22-warp.3 h1:VlwJR+ESym/KHUGnppmvWGRB21rcsN84s94M4bSuW0Q=
github.com/GetStream/pion-webrtc/v4 v4.2.22-warp.3/go.mod h1:SZqPA/FyKvBzjbV2FgTnJQZrcLmhTXgeXOG1dDbL8Ac=
github.com/GetStream/protocol v1.49.0 h1:AzTRH6+PRNHjFjBlcymbjZsVE+wZBp/wPG6w+/9FCw4=
github.com/GetStream/protocol v1.49.0/go.mod h1:jZALur2IoWnpcLnFzLtnFomgItt4SBHj+U1TjPYC114=
github.com/GetStream/protocol v1.50.0-3rtt.1 h1:kqsE1ZBf3gpO47lc2JLkyNVhVR9JNGFRYUtn83nLgIo=
Expand Down Expand Up @@ -31,38 +39,32 @@ github.com/oapi-codegen/nullable v1.1.0 h1:eAh8JVc5430VtYVnq00Hrbpag9PFRGWLjxR1/
github.com/oapi-codegen/nullable v1.1.0/go.mod h1:KUZ3vUzkmEKY90ksAmit2+5juDIhIZhfDl+0PwOQlFY=
github.com/oapi-codegen/runtime v1.6.0 h1:7Xx+GlueD6nRuyKoCPzL434Jfi3BetbiJOrzCHp/VPU=
github.com/oapi-codegen/runtime v1.6.0/go.mod h1:GwV7hC2hviaMzj+ITfHVRESK5J2W/GefVwIND/bMGvU=
github.com/pion/datachannel v1.6.2 h1:7EXQ8TH3vTouBUdRWYbcX2edSx9Yj6k5zl5P+qyxEPc=
github.com/pion/datachannel v1.6.2/go.mod h1:pzbdAZvyGtXbcHM1hBbsFaOTf40lZizU/dNlvVOak6E=
github.com/pion/dtls/v3 v3.1.8 h1:aLcgjZqzrYn5AbjSds4LvK2WI5VzJc1PencExyDjYis=
github.com/pion/dtls/v3 v3.1.8/go.mod h1:gz1K4jg6c+fq86oQMH4pilpCEOEPwmEr2jY+VcF/mkU=
github.com/pion/ice/v4 v4.4.2 h1:asS17nbHJrzlVQl8fiSJaipxrxSY3Dq6DWgmB+0VwpI=
github.com/pion/ice/v4 v4.4.2/go.mod h1:YZgNFOyJWXpLpLj0mb4ccqNAWRo9C2RtqKwuVTEz0Sc=
github.com/pion/interceptor v0.1.48 h1:FF4gZ6Yh+N75gKMYpC7rYR8DdkiMBFtA7V2OBUKo7XQ=
github.com/pion/interceptor v0.1.48/go.mod h1:5mg/N5xXMAa4codCUdrJYY9I1y4tVQhlpd7rfwAJpvI=
github.com/pion/datachannel v1.6.3 h1:HZAYLpunVI0xi057ZiANl558d0uSpomcWw4UEPz3qXs=
github.com/pion/datachannel v1.6.3/go.mod h1:oRmkXVVXxkUbqa8MatgdNHW29kvtQY3HUdjJQsfv2GE=
github.com/pion/dtls/v3 v3.1.9 h1:rpeycmLIkc4krpk1IxP7+39o11QdCXbmV9+FGi9yZJ8=
github.com/pion/dtls/v3 v3.1.9/go.mod h1:iKFQNYrjsN2TiA2YKKMqB9MOZaFpjFULBI/A4sW0eyc=
github.com/pion/interceptor v0.1.49 h1:iyBsNHRoLNNXZiJA/DdGvJgdyfS8YWDCzxIAlVjt5nY=
github.com/pion/interceptor v0.1.49/go.mod h1:MZ6PJkja/TCo350HAnBrs/rUIyad9mWjpcvytrf3ViQ=
github.com/pion/logging v0.2.4 h1:tTew+7cmQ+Mc1pTBLKH2puKsOvhm32dROumOZ655zB8=
github.com/pion/logging v0.2.4/go.mod h1:DffhXTKYdNZU+KtJ5pyQDjvOAh/GsNSyv1lbkFbe3so=
github.com/pion/mdns/v2 v2.2.0 h1:AlAZ9MTUKtWgO+4itk35JdNak4sk5k7G/X4xnIBWHyA=
github.com/pion/mdns/v2 v2.2.0/go.mod h1:IJddx58QMlojqhQYjHcOUmvuBQ5MnLNetkb80VMvk2Y=
github.com/pion/mdns/v2 v2.2.1 h1:lQPWv6Mo5jG1sKwqkYgfeXGX7/seban4x7/j0n485/M=
github.com/pion/mdns/v2 v2.2.1/go.mod h1:ZX5f0AAH1D6TOjdjvcBORZZHaZuG0t9+br78lHEwiJ4=
github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA=
github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8=
github.com/pion/rtcp v1.2.17 h1:PxiT6L79yPZKtXIsXdG1eakBl6dtBj4x+4oVEL0DlSw=
github.com/pion/rtcp v1.2.17/go.mod h1:7kBpuBJaWwax4hzc/pgexY8vkOpvh8atgYDbaKZq0iU=
github.com/pion/rtcp v1.2.18 h1:ZPgMZMCtBoReTixtFAyzcOkuJiebyB94qxtBAyvSooM=
github.com/pion/rtcp v1.2.18/go.mod h1:vX7Es6skWYm4oVvOSC5+4WHLYUTZHcbGNmk5wjzMGH4=
github.com/pion/rtp v1.10.5 h1:ip0HhO/wYZqQ4bKS+R99KnZh/GRCmIT0jDXikub7vlE=
github.com/pion/rtp v1.10.5/go.mod h1:Au8fc6cEByy8RLTwKTQTEeQqDB/SJDxwL4mZuxYA5Pk=
github.com/pion/sctp v1.11.1 h1:O4dIFyURw1KTST7w+gtD4gLeYXkhPa0xXLHMMoe/OSA=
github.com/pion/sctp v1.11.1/go.mod h1:7KFmTwLcoYgJs/Z+99nJvsWL0qDpuyloSI0RbAqlrz0=
github.com/pion/sdp/v3 v3.0.19 h1:1VMKs3gIkTQV5M3hNKfTAPrDXSNrYtOlmOD8+mSZUGQ=
github.com/pion/sdp/v3 v3.0.19/go.mod h1:dE5WOSlzXrtiE/iuZqe9n+AcEbOjtAd3k5m5NtlV/qU=
github.com/pion/srtp/v3 v3.0.13 h1:FmQaqgNbN1vUtMhEsmj8trldc3lNZr1xmN7nl8CyX+Q=
github.com/pion/srtp/v3 v3.0.13/go.mod h1:7qR3L69t8RX0EPVQwGNwCa1Gy9keKKNDpWwQzZbeXDY=
github.com/pion/stun/v4 v4.0.0 h1:UuQy2q6iZR4EnMl/+G8kAtaWhf7jx/u8ZyN9oD4+YEQ=
github.com/pion/stun/v4 v4.0.0/go.mod h1:JAojPsPtDH4iPeNQb7kvxBdzypmkWAROxy0coApKH2E=
github.com/pion/transport/v4 v4.1.0 h1:8S+nF2reM2cJuqC6g78OVy2BBgmbdns+acx3jA97BvQ=
github.com/pion/transport/v4 v4.1.0/go.mod h1:06hFI+jCFcok2X2MekVufNZ/uzNZXivGBPfviSVcjgM=
github.com/pion/turn/v5 v5.1.0 h1:OSzLub7q4GssG1P4BEVrz39MnnJlxLy1LOvEkP9f46o=
github.com/pion/turn/v5 v5.1.0/go.mod h1:6HJQO7UAe7pEPMrTtBrmj+tTfp+Ai8KAV2+GXHFi1nQ=
github.com/pion/webrtc/v4 v4.2.20 h1:NYiNhBTFArA8aoP18a30y4LN0dyqSrF65HxU7KnhNOo=
github.com/pion/webrtc/v4 v4.2.20/go.mod h1:aLGXbekuN0tHOu7IPX1o9Y/uN29Ovfjaaz4bL2P9ND8=
github.com/pion/sdp/v3 v3.0.20 h1:TS6DViqcmp+49f0+mjw9anbr9xY3vJtsZewxAvlMCRQ=
github.com/pion/sdp/v3 v3.0.20/go.mod h1:slIMXDK5OKj0nhISwjfeN18AzTBCt2LYZq9uPw0cU5Q=
github.com/pion/srtp/v3 v3.1.0 h1:keugrBOxtvAv5Urf4lBMfso8OCAX3mm7Brdl26JSvik=
github.com/pion/srtp/v3 v3.1.0/go.mod h1:RlTlj08MtRReQiVm/PMmMFUDNjZkoKuKJMHkl9+M7a8=
github.com/pion/stun/v4 v4.0.1 h1:S2ggK4hsUJJKoZfpL90uIqIRTj6xJ0NOIEkXgcpQif0=
github.com/pion/stun/v4 v4.0.1/go.mod h1:byktbPA8U7HjJ2H8w3moP7nzq0Q+kYNulvMLPaubQL4=
github.com/pion/transport/v5 v5.1.1 h1:Sauq8YJqRopgRfIgnpfKpdpKG14g0N4jWlRgpWsEfN8=
github.com/pion/transport/v5 v5.1.1/go.mod h1:Qxw6fCEjFWQkRDZOhS4Vf+neJBcihauvA3uyEa1J1F0=
github.com/pion/turn/v5 v5.1.2 h1:acEOO+D5txJ52vKfcilmSMItfP23Q9K6pJ1LM5P2VV0=
github.com/pion/turn/v5 v5.1.2/go.mod h1:57Oadc8fHnac15VFyCd6nEaBTVZBxQe2POUMD4lsHRA=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
Expand Down
2 changes: 1 addition & 1 deletion internal/netdelay/netdelay.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import (
"sync"
"time"

"github.com/pion/transport/v4/deadline"
"github.com/pion/transport/v5/deadline"
)

// DialFunc opens a network connection, like net.Dialer.DialContext.
Expand Down
4 changes: 2 additions & 2 deletions internal/netdelay/packet.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import (
"net"
"time"

"github.com/pion/transport/v4"
"github.com/pion/transport/v4/stdnet"
"github.com/pion/transport/v5"
"github.com/pion/transport/v5/stdnet"
)

// PacketConn is a datagram socket with delayed reads and writes.
Expand Down
2 changes: 1 addition & 1 deletion pc/hello_verify_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"testing"
"time"

"github.com/pion/dtls/v3/pkg/protocol/handshake"
"github.com/pion/dtls/v4/pkg/protocol/handshake"
"github.com/pion/webrtc/v4"
"github.com/stretchr/testify/require"
)
Expand Down
24 changes: 22 additions & 2 deletions pc/pc.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ import (
"time"

"github.com/GetStream/protocol/protobuf/video/sfu/models"
"github.com/pion/dtls/v3/pkg/crypto/elliptic"
"github.com/pion/dtls/v3/pkg/protocol/handshake"
"github.com/pion/dtls/v4/pkg/crypto/elliptic"
"github.com/pion/dtls/v4/pkg/protocol"
"github.com/pion/dtls/v4/pkg/protocol/handshake"
"github.com/pion/ice/v4"
"github.com/pion/interceptor"
"github.com/pion/rtcp"
Expand Down Expand Up @@ -230,6 +231,18 @@ func newPeerConnection(params TransportParams) (*webrtc.PeerConnection, error) {
// for, and browsers never send one either.
se.SetDTLSInsecureSkipHelloVerify(true)
se.SetICETimeouts(params.iceTimeouts())
// Offer the WARP connection setup (draft-uberti-tsvwg-warp) that the SFU negotiates in
// band: DTLS 1.3, and DTLS in the ICE checks (SPED). An SFU without them answers as
// before, so the connection falls back to DTLS 1.2 after ICE.
if err := se.SetDTLSVersionRange(protocol.Version1_2, protocol.Version1_3); err != nil {
return nil, xerr.Wrap(err)
}
se.EnableSped(true)
// On the subscriber, which the ICE-lite SFU offers, pion would answer passive and make
// the SFU the DTLS client, whose ClientHello can only ride our checks' responses, one
// datagram each. Answering active to an offer with SPED puts our one-datagram ClientHello
// in our first check, as browsers do.
se.SetAnsweringDTLSRoleWithSPED(webrtc.DTLSRoleClient)

// One line per handshake message we send pins down which direction a
// stalled handshake lost.
Expand Down Expand Up @@ -934,6 +947,13 @@ func (t *Transport) Timing() Timing {
// SelectedPairRTT is the round-trip time ICE measured on the selected candidate pair, or
// zero before it has one.
func (t *Transport) SelectedPairRTT() time.Duration {
// pion reads the ICE transport's gatherer without its lock, while ICETransport.Start
// sets it. With SPED, Start runs inside the DTLS start, concurrently with callers here,
// so wait until ICE has connected, which happens after Start.
switch t.PC.ICEConnectionState() {
case webrtc.ICEConnectionStateNew, webrtc.ICEConnectionStateChecking:
return 0
}
dtls := dtlsTransportOf(t.PC)
if dtls == nil || dtls.ICETransport() == nil {
return 0
Expand Down
135 changes: 135 additions & 0 deletions pc/warp_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
package pc

import (
"testing"
"time"

"github.com/pion/dtls/v4/pkg/protocol"
"github.com/pion/ice/v4"
"github.com/pion/webrtc/v4"
"github.com/stretchr/testify/require"

"github.com/GetStream/getstream-go-webrtc/logger"
"github.com/GetStream/protocol/protobuf/video/sfu/models"
)

// TestWARPNegotiation connects a publisher transport, which offers, to a pion peer
// configured like an SFU. A WARP SFU (DTLS 1.2 to 1.3, SPED, the DTLS server role when
// the offer has SPED) gets DTLS 1.3 and SPED; an SFU without WARP gets DTLS 1.2 without
// SPED, as before. The selected pair's RTT is read throughout, as the join trace does.
func TestWARPNegotiation(t *testing.T) {
for _, tc := range []struct {
name string
warp bool
wantVersion protocol.Version
}{
{name: "WARPSFU", warp: true, wantVersion: protocol.Version1_3},
{name: "LegacySFU", warp: false, wantVersion: protocol.Version1_2},
} {
t.Run(tc.name, func(t *testing.T) {
st := newPCTestWithTransportParams(t, TransportParams{
Transport: models.PeerType_PEER_TYPE_PUBLISHER_UNSPECIFIED,
Logger: logger.Noop{},
IsOfferer: true,
PeerConfig: newPCTestPeerConfig(t),
})

sfu := newPCTestPeerConfig(t)
sfu.SettingEngine.SetLite(true)
if tc.warp {
require.NoError(t, sfu.SettingEngine.SetDTLSVersionRange(protocol.Version1_2, protocol.Version1_3))
sfu.SettingEngine.EnableSped(true)
sfu.SettingEngine.SetAnsweringDTLSRoleWithSPED(webrtc.DTLSRoleServer)
}
remote := newRemotePeerWithConfig(t, st.tr, sfu)
st.handler.onICECandidateSender = remote.ICECandidateSender

done := make(chan struct{})
polled := make(chan struct{})
go func() {
defer close(polled)
for {
select {
case <-done:
return
default:
_ = st.tr.SelectedPairRTT()
}
}
}()
defer func() { close(done); <-polled }()

st.tr.Negotiate(true)
st.tr.HandleRemoteDescription(remote.Answer(st.waitForOffer()))
st.waitForPCState(webrtc.PeerConnectionStateConnected, 5*time.Second)

// The two ends finish the handshake one flight apart.
require.Eventually(t, func() bool {
return remote.PC.ConnectionState() == webrtc.PeerConnectionStateConnected
}, 5*time.Second, 10*time.Millisecond)
local, sfuState := st.tr.PC.WARPState(), remote.PC.WARPState()
require.Equal(t, tc.wantVersion, local.DTLSVersion)
require.Equal(t, tc.wantVersion, sfuState.DTLSVersion)
if !tc.warp {
require.Equal(t, ice.SPEDStateDisabled, local.SPED)
require.Equal(t, ice.SPEDStateDisabled, sfuState.SPED)
return
}
// SPED completes once everything sent is acknowledged or media arrives.
for _, state := range []ice.SPEDState{local.SPED, sfuState.SPED} {
require.Contains(t, []ice.SPEDState{ice.SPEDStatePending, ice.SPEDStateComplete}, state)
}
})
}
}

// TestWARPSubscriberAnswersActive has a pion peer configured like a WARP SFU (ICE-lite, DTLS
// 1.2 to 1.3, SPED) offer to a subscriber transport. The transport must answer active, so
// that it is the DTLS client and its ClientHello rides its first check, and get DTLS 1.3 with
// SPED.
func TestWARPSubscriberAnswersActive(t *testing.T) {
st := newPCTestWithTransportParams(t, TransportParams{
Transport: models.PeerType_PEER_TYPE_SUBSCRIBER,
Logger: logger.Noop{},
IsOfferer: false,
PeerConfig: newPCTestPeerConfig(t),
})

sfu := newPCTestPeerConfig(t)
sfu.SettingEngine.SetLite(true)
require.NoError(t, sfu.SettingEngine.SetDTLSVersionRange(protocol.Version1_2, protocol.Version1_3))
sfu.SettingEngine.EnableSped(true)
remote := newRemotePeerWithConfig(t, st.tr, sfu)
st.handler.onICECandidateSender = remote.ICECandidateSender
_, err := remote.PC.AddTransceiverFromKind(webrtc.RTPCodecTypeAudio, webrtc.RTPTransceiverInit{
Direction: webrtc.RTPTransceiverDirectionSendonly,
})
require.NoError(t, err)

offer, err := remote.PC.CreateOffer(nil)
require.NoError(t, err)
require.NoError(t, remote.PC.SetLocalDescription(offer))
st.tr.HandleRemoteDescription(*remote.PC.LocalDescription())
answer, _ := st.waitForAnswerWithID()
require.Contains(t, answer.SDP, "a=setup:active")
require.NoError(t, remote.PC.SetRemoteDescription(answer))
remote.mu.Lock()
remote.ready = true
pending := remote.pending
remote.pending = nil
remote.mu.Unlock()
for _, c := range pending {
require.NoError(t, remote.PC.AddICECandidate(c))
}

st.waitForPCState(webrtc.PeerConnectionStateConnected, 5*time.Second)
require.Eventually(t, func() bool {
return remote.PC.ConnectionState() == webrtc.PeerConnectionStateConnected
}, 5*time.Second, 10*time.Millisecond)
local, sfuState := st.tr.PC.WARPState(), remote.PC.WARPState()
require.Equal(t, protocol.Version1_3, local.DTLSVersion)
require.Equal(t, protocol.Version1_3, sfuState.DTLSVersion)
for _, state := range []ice.SPEDState{local.SPED, sfuState.SPED} {
require.Contains(t, []ice.SPEDState{ice.SPEDStatePending, ice.SPEDStateComplete}, state)
}
}
Loading