fixed potentially skipping offer in PCTransport

this could explain the "missing" track problem when the server fails to send some tracks to some of the subscribers
This commit is contained in:
David Zhao
2021-06-09 16:06:10 -07:00
parent b10d903d3e
commit b3e6bd10cf
3 changed files with 60 additions and 17 deletions
+1 -1
View File
@@ -152,7 +152,7 @@ func checkUDPReadBuffer() (int, error) {
return 0, err
}
defer func() { _ = conn.Close() }()
_ = conn.SetReadBuffer(minUDPBufferSize)
_ = conn.SetReadBuffer(defaultUDPBufferSize)
fd, err := conn.File()
if err != nil {
return 0, nil
+7 -2
View File
@@ -144,8 +144,10 @@ func (t *PCTransport) SetRemoteDescription(sd webrtc.SessionDescription) error {
state := t.negotiationState
t.negotiationState = negotiationStateNone
if state == negotiationRetry {
// need to Negotiate again
t.Negotiate()
// need to Negotiate again, do it immediately
if err := t.CreateAndSendOffer(nil); err != nil {
logger.Errorw("could not negotiate", err)
}
}
return nil
@@ -199,6 +201,9 @@ func (t *PCTransport) CreateAndSendOffer(options *webrtc.OfferOptions) error {
t.negotiationState = negotiationRetry
return nil
}
} else if t.negotiationState == negotiationRetry {
// already set to retry, we can safely skip this attempt
return nil
}
offer, err := t.pc.CreateOffer(options)
+52 -14
View File
@@ -1,6 +1,7 @@
package rtc
import (
"sync/atomic"
"testing"
"github.com/livekit/livekit-server/pkg/testutils"
@@ -23,20 +24,8 @@ func TestMissingAnswerDuringICERestart(t *testing.T) {
require.NoError(t, err)
// exchange ICE
transportA.pc.OnICECandidate(func(candidate *webrtc.ICECandidate) {
if candidate == nil {
return
}
t.Logf("got ICE candidate from A: %v", candidate)
require.NoError(t, transportB.AddICECandidate(candidate.ToJSON()))
})
transportB.pc.OnICECandidate(func(candidate *webrtc.ICECandidate) {
if candidate == nil {
return
}
t.Logf("got ICE candidate from B: %v", candidate)
require.NoError(t, transportA.AddICECandidate(candidate.ToJSON()))
})
handleICEExchange(t, transportA, transportB)
// set offer/answer
handleOffer := handleOfferFunc(t, transportA, transportB)
transportA.OnOffer(handleOffer)
@@ -71,6 +60,38 @@ func TestMissingAnswerDuringICERestart(t *testing.T) {
})
}
func TestNegotiationTiming(t *testing.T) {
params := TransportParams{
Target: livekit.SignalTarget_SUBSCRIBER,
Config: &WebRTCConfig{},
Stats: nil,
}
transportA, err := NewPCTransport(params)
require.NoError(t, err)
_, err = transportA.pc.CreateDataChannel("test", nil)
require.NoError(t, err)
transportB, err := NewPCTransport(params)
require.NoError(t, err)
handleICEExchange(t, transportA, transportB)
offer := atomic.Value{}
transportA.OnOffer(func(sd webrtc.SessionDescription) {
offer.Store(sd)
})
// initial offer
require.NoError(t, transportA.CreateAndSendOffer(nil))
require.Equal(t, negotiationStateClient, transportA.negotiationState)
// second try, should've flipped transport status to retry
require.NoError(t, transportA.CreateAndSendOffer(nil))
require.Equal(t, negotiationRetry, transportA.negotiationState)
// third try, should've stayed at retry
require.NoError(t, transportA.CreateAndSendOffer(nil))
require.Equal(t, negotiationRetry, transportA.negotiationState)
}
func handleOfferFunc(t *testing.T, current, other *PCTransport) func(sd webrtc.SessionDescription) {
return func(sd webrtc.SessionDescription) {
t.Logf("handling offer")
@@ -84,3 +105,20 @@ func handleOfferFunc(t *testing.T, current, other *PCTransport) func(sd webrtc.S
require.NoError(t, current.SetRemoteDescription(answer))
}
}
func handleICEExchange(t *testing.T, a, b *PCTransport) {
a.pc.OnICECandidate(func(candidate *webrtc.ICECandidate) {
if candidate == nil {
return
}
t.Logf("got ICE candidate from A: %v", candidate)
require.NoError(t, b.AddICECandidate(candidate.ToJSON()))
})
b.pc.OnICECandidate(func(candidate *webrtc.ICECandidate) {
if candidate == nil {
return
}
t.Logf("got ICE candidate from B: %v", candidate)
require.NoError(t, a.AddICECandidate(candidate.ToJSON()))
})
}