diff --git a/icetransport.go b/icetransport.go index 96e1dc3c575..177ad597082 100644 --- a/icetransport.go +++ b/icetransport.go @@ -244,7 +244,7 @@ func (t *ICETransport) SetRemoteCandidates(remoteCandidates []ICECandidate) erro } // AddRemoteCandidate adds a candidate associated with the remote ICETransport. -func (t *ICETransport) AddRemoteCandidate(remoteCandidate ICECandidate) error { +func (t *ICETransport) AddRemoteCandidate(remoteCandidate *ICECandidate) error { t.lock.RLock() defer t.lock.RUnlock() diff --git a/peerconnection.go b/peerconnection.go index dae2ff7b89f..1157ee7ee48 100644 --- a/peerconnection.go +++ b/peerconnection.go @@ -1053,8 +1053,8 @@ func (pc *PeerConnection) SetRemoteDescription(desc SessionDescription) error { } } - for _, c := range candidates { - if err = pc.iceTransport.AddRemoteCandidate(c); err != nil { + for i := range candidates { + if err = pc.iceTransport.AddRemoteCandidate(&candidates[i]); err != nil { return err } } @@ -1454,13 +1454,28 @@ func (pc *PeerConnection) RemoteDescription() *SessionDescription { } // AddICECandidate accepts an ICE candidate string and adds it -// to the existing set of candidates +// to the existing set of candidates. +// If ICE candidate string is empty, do not adds it to the existing +// set of candidates func (pc *PeerConnection) AddICECandidate(candidate ICECandidateInit) error { if pc.RemoteDescription() == nil { return &rtcerr.InvalidStateError{Err: ErrNoRemoteDescription} } candidateValue := strings.TrimPrefix(candidate.Candidate, "candidate:") + + if candidateValue == "" { + pc.iceTransport.lock.RLock() + defer pc.iceTransport.lock.RUnlock() + + agent := pc.iceTransport.gatherer.getAgent() + if agent == nil { + return fmt.Errorf("%w: unable to add remote candidates", errICEAgentNotExist) + } + + return agent.AddRemoteCandidate(nil) + } + c, err := ice.UnmarshalCandidate(candidateValue) if err != nil { return err @@ -1471,7 +1486,7 @@ func (pc *PeerConnection) AddICECandidate(candidate ICECandidateInit) error { return err } - return pc.iceTransport.AddRemoteCandidate(iceCandidate) + return pc.iceTransport.AddRemoteCandidate(&iceCandidate) } // ICEConnectionState returns the ICE connection state of the diff --git a/peerconnection_go_test.go b/peerconnection_go_test.go index 04f19c1d815..11d0249f0d8 100644 --- a/peerconnection_go_test.go +++ b/peerconnection_go_test.go @@ -1158,3 +1158,40 @@ func TestPeerConnection_MassiveTracks(t *testing.T) { assert.NoError(t, offerPC.Close()) assert.NoError(t, answerPC.Close()) } + +func TestEmptyCandidate(t *testing.T) { + testCases := []struct { + ICECandidate ICECandidateInit + expectError bool + }{ + {ICECandidateInit{"", nil, nil, nil}, false}, + {ICECandidateInit{ + "211962667 1 udp 2122194687 10.0.3.1 40864 typ host generation 0", + nil, nil, nil, + }, false}, + {ICECandidateInit{ + "1234567", + nil, nil, nil, + }, true}, + } + + for i, testCase := range testCases { + peerConn, err := NewPeerConnection(Configuration{}) + if err != nil { + t.Errorf("Case %d: got error: %v", i, err) + } + + err = peerConn.SetRemoteDescription(SessionDescription{Type: SDPTypeOffer, SDP: minimalOffer}) + if err != nil { + t.Errorf("Case %d: got error: %v", i, err) + } + + if testCase.expectError { + assert.Error(t, peerConn.AddICECandidate(testCase.ICECandidate)) + } else { + assert.NoError(t, peerConn.AddICECandidate(testCase.ICECandidate)) + } + + assert.NoError(t, peerConn.Close()) + } +}