File tree Expand file tree Collapse file tree 2 files changed +48
-10
lines changed Expand file tree Collapse file tree 2 files changed +48
-10
lines changed Original file line number Diff line number Diff line change @@ -291,6 +291,16 @@ func (pc *PeerConnection) onNegotiationNeeded() {
291291}
292292
293293func (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
Original file line number Diff line number Diff 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+ }
You can’t perform that action at this time.
0 commit comments