Skip to content

Commit ca05618

Browse files
edanielsSean-Der
authored andcommitted
Reset state machine after negotiationNeededOp
- Fixes #2774
1 parent 09461d5 commit ca05618

File tree

2 files changed

+48
-10
lines changed

2 files changed

+48
-10
lines changed

peerconnection.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,16 @@ func (pc *PeerConnection) onNegotiationNeeded() {
291291
}
292292

293293
func (pc *PeerConnection) negotiationNeededOp() {
294+
// non-canon, reset needed state machine and run again if there was a request
295+
defer func() {
296+
pc.mu.Lock()
297+
defer pc.mu.Unlock()
298+
if pc.negotiationNeededState == negotiationNeededStateQueue {
299+
defer pc.onNegotiationNeeded()
300+
}
301+
pc.negotiationNeededState = negotiationNeededStateEmpty
302+
}()
303+
294304
// Don't run NegotiatedNeeded checks if OnNegotiationNeeded is not set
295305
if handler, ok := pc.onNegotiationNeededHandler.Load().(func()); !ok || handler == nil {
296306
return
@@ -307,16 +317,6 @@ func (pc *PeerConnection) negotiationNeededOp() {
307317
return
308318
}
309319

310-
// non-canon, run again if there was a request
311-
defer func() {
312-
pc.mu.Lock()
313-
defer pc.mu.Unlock()
314-
if pc.negotiationNeededState == negotiationNeededStateQueue {
315-
defer pc.onNegotiationNeeded()
316-
}
317-
pc.negotiationNeededState = negotiationNeededStateEmpty
318-
}()
319-
320320
// Step 2.3
321321
if pc.SignalingState() != SignalingStateStable {
322322
return

peerconnection_go_test.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1606,3 +1606,41 @@ func TestPeerConnectionState(t *testing.T) {
16061606
assert.NoError(t, pc.Close())
16071607
assert.Equal(t, PeerConnectionStateClosed, pc.ConnectionState())
16081608
}
1609+
1610+
// See https://github.com/pion/webrtc/issues/2774
1611+
func TestNegotiationNeededAddedAfterOpQueueDone(t *testing.T) {
1612+
lim := test.TimeOut(time.Second * 30)
1613+
defer lim.Stop()
1614+
1615+
report := test.CheckRoutines(t)
1616+
defer report()
1617+
1618+
pc, err := NewPeerConnection(Configuration{})
1619+
if err != nil {
1620+
t.Error(err.Error())
1621+
}
1622+
1623+
var wg sync.WaitGroup
1624+
wg.Add(1)
1625+
1626+
_, err = pc.CreateDataChannel("initial_data_channel", nil)
1627+
assert.NoError(t, err)
1628+
1629+
// after there are no ops left in the queue, a previously faulty version
1630+
// of negotiationNeededOp would keep the negotiation needed state in
1631+
// negotiationNeededStateQueue which will cause all subsequent
1632+
// onNegotiationNeeded calls to never queue again, only if
1633+
// OnNegotiationNeeded has not been set yet.
1634+
for !pc.ops.IsEmpty() {
1635+
time.Sleep(time.Millisecond)
1636+
}
1637+
1638+
pc.OnNegotiationNeeded(wg.Done)
1639+
1640+
_, err = pc.CreateDataChannel("another_data_channel", nil)
1641+
assert.NoError(t, err)
1642+
1643+
wg.Wait()
1644+
1645+
assert.NoError(t, pc.Close())
1646+
}

0 commit comments

Comments
 (0)