log non-trickle candidate in details (#2832)

* log non-trickle candidate in details

* fix test
This commit is contained in:
cnderrauber
2024-07-03 14:16:58 +08:00
committed by GitHub
parent e511464d3d
commit 7a5c90dc01
4 changed files with 105 additions and 28 deletions
+6
View File
@@ -1558,6 +1558,9 @@ func connectionDetailsFields(cds []*types.ICEConnectionDetails) []interface{} {
} else if c.Filtered {
cStr += "[filtered]"
}
if c.Trickle {
cStr += "[trickle]"
}
cStr += " " + c.Local.String()
candidates = append(candidates, cStr)
}
@@ -1568,6 +1571,9 @@ func connectionDetailsFields(cds []*types.ICEConnectionDetails) []interface{} {
} else if c.Filtered {
cStr += "[filtered]"
}
if c.Trickle {
cStr += "[trickle]"
}
cStr += " " + c.Remote.String()
candidates = append(candidates, cStr)
}
+21 -12
View File
@@ -1366,7 +1366,7 @@ func (t *PCTransport) handleLocalICECandidate(e event) error {
t.params.Logger.Debugw("filtering out local candidate", "candidate", c.String())
filtered = true
}
t.connectionDetails.AddLocalCandidate(c, filtered)
t.connectionDetails.AddLocalCandidate(c, filtered, true)
}
if filtered {
@@ -1395,7 +1395,7 @@ func (t *PCTransport) handleRemoteICECandidate(e event) error {
filtered = true
}
t.connectionDetails.AddRemoteCandidate(*c, filtered)
t.connectionDetails.AddRemoteCandidate(*c, filtered, true)
if filtered {
return nil
}
@@ -1422,7 +1422,7 @@ func (t *PCTransport) setNegotiationState(state transport.NegotiationState) {
}
}
func (t *PCTransport) filterCandidates(sd webrtc.SessionDescription, preferTCP bool) webrtc.SessionDescription {
func (t *PCTransport) filterCandidates(sd webrtc.SessionDescription, preferTCP, isLocal bool) webrtc.SessionDescription {
parsed, err := sd.Unmarshal()
if err != nil {
t.params.Logger.Warnw("could not unmarshal SDP to filter candidates", err)
@@ -1432,13 +1432,22 @@ func (t *PCTransport) filterCandidates(sd webrtc.SessionDescription, preferTCP b
filterAttributes := func(attrs []sdp.Attribute) []sdp.Attribute {
filteredAttrs := make([]sdp.Attribute, 0, len(attrs))
for _, a := range attrs {
if a.Key == sdp.AttrKeyCandidate {
if preferTCP {
if strings.Contains(a.Value, "tcp") {
filteredAttrs = append(filteredAttrs, a)
}
} else {
if a.IsICECandidate() {
c, err := ice.UnmarshalCandidate(a.Value)
if err != nil {
t.params.Logger.Errorw("failed to unmarshal candidate in sdp", err, "isLocal", isLocal, "sdp", sd.SDP)
filteredAttrs = append(filteredAttrs, a)
continue
}
excluded := preferTCP && !c.NetworkType().IsTCP()
if !excluded {
filteredAttrs = append(filteredAttrs, a)
}
if isLocal {
t.connectionDetails.AddLocalICECandidate(c, excluded, false)
} else {
t.connectionDetails.AddRemoteICECandidate(c, excluded, false)
}
} else {
filteredAttrs = append(filteredAttrs, a)
@@ -1566,7 +1575,7 @@ func (t *PCTransport) createAndSendOffer(options *webrtc.OfferOptions) error {
// Filtered offer is sent to remote so that remote does not
// see filtered candidates.
//
offer = t.filterCandidates(offer, preferTCP)
offer = t.filterCandidates(offer, preferTCP, true)
if preferTCP {
t.params.Logger.Debugw("local offer (filtered)", "sdp", offer.SDP)
}
@@ -1616,7 +1625,7 @@ func (t *PCTransport) setRemoteDescription(sd webrtc.SessionDescription) error {
if preferTCP {
t.params.Logger.Debugw("remote description (unfiltered)", "type", sd.Type, "sdp", sd.SDP)
}
sd = t.filterCandidates(sd, preferTCP)
sd = t.filterCandidates(sd, preferTCP, false)
if preferTCP {
t.params.Logger.Debugw("remote description (filtered)", "type", sd.Type, "sdp", sd.SDP)
}
@@ -1683,7 +1692,7 @@ func (t *PCTransport) createAndSendAnswer() error {
// Filtered answer is sent to remote so that remote does not
// see filtered candidates.
//
answer = t.filterCandidates(answer, preferTCP)
answer = t.filterCandidates(answer, preferTCP, true)
if preferTCP {
t.params.Logger.Debugw("local answer (filtered)", "sdp", answer.SDP)
}
+2 -2
View File
@@ -416,7 +416,7 @@ func TestFilteringCandidates(t *testing.T) {
// should not filter out UDP candidates if TCP is not preferred
offer = *transport.pc.LocalDescription()
filteredOffer := transport.filterCandidates(offer, false)
filteredOffer := transport.filterCandidates(offer, false, true)
require.EqualValues(t, offer.SDP, filteredOffer.SDP)
parsed, err := offer.Unmarshal()
@@ -494,7 +494,7 @@ func TestFilteringCandidates(t *testing.T) {
require.Equal(t, 2, tcp)
transport.SetPreferTCP(true)
filteredOffer = transport.filterCandidates(offer, true)
filteredOffer = transport.filterCandidates(offer, true, true)
parsed, err = filteredOffer.Unmarshal()
require.NoError(t, err)
udp, tcp = getNumTransportTypeCandidates(parsed)
+76 -14
View File
@@ -17,6 +17,7 @@
package types
import (
"fmt"
"strings"
"sync"
@@ -43,6 +44,7 @@ type ICECandidateExtended struct {
Remote ice.Candidate
Selected bool
Filtered bool
Trickle bool
}
type ICEConnectionDetails struct {
@@ -85,6 +87,7 @@ func (d *ICEConnectionDetails) Clone() *ICEConnectionDetails {
Local: c.Local,
Filtered: c.Filtered,
Selected: c.Selected,
Trickle: c.Trickle,
})
}
for _, c := range d.Remote {
@@ -92,32 +95,48 @@ func (d *ICEConnectionDetails) Clone() *ICEConnectionDetails {
Remote: c.Remote,
Filtered: c.Filtered,
Selected: c.Selected,
Trickle: c.Trickle,
})
}
return clone
}
func (d *ICEConnectionDetails) AddLocalCandidate(c *webrtc.ICECandidate, filtered bool) {
func (d *ICEConnectionDetails) AddLocalCandidate(c *webrtc.ICECandidate, filtered, trickle bool) {
d.lock.Lock()
defer d.lock.Unlock()
compFn := func(e *ICECandidateExtended) bool {
return isCandidateEqualTo(e.Local, c)
}
if slices.ContainsFunc[[]*ICECandidateExtended, *ICECandidateExtended](d.Local, compFn) {
if slices.ContainsFunc(d.Local, compFn) {
return
}
d.Local = append(d.Local, &ICECandidateExtended{
Local: c,
Filtered: filtered,
Trickle: trickle,
})
}
func (d *ICEConnectionDetails) AddRemoteCandidate(c webrtc.ICECandidateInit, filtered bool) {
func (d *ICEConnectionDetails) AddLocalICECandidate(c ice.Candidate, filtered, trickle bool) {
candidate, err := unmarshalCandidate(c)
if err != nil {
d.logger.Errorw("could not unmarshal ice candidate", err, "candidate", c)
return
}
d.AddLocalCandidate(candidate, filtered, trickle)
}
func (d *ICEConnectionDetails) AddRemoteCandidate(c webrtc.ICECandidateInit, filtered, trickle bool) {
candidate, err := unmarshalICECandidate(c)
if err != nil {
d.logger.Errorw("could not unmarshal candidate", err, "candidate", c)
return
}
d.AddRemoteICECandidate(candidate, filtered, trickle)
}
func (d *ICEConnectionDetails) AddRemoteICECandidate(candidate ice.Candidate, filtered, trickle bool) {
if candidate == nil {
// end-of-candidates candidate
return
@@ -126,14 +145,15 @@ func (d *ICEConnectionDetails) AddRemoteCandidate(c webrtc.ICECandidateInit, fil
d.lock.Lock()
defer d.lock.Unlock()
compFn := func(e *ICECandidateExtended) bool {
return isICECandidateEqualTo(e.Remote, *candidate)
return isICECandidateEqualTo(e.Remote, candidate)
}
if slices.ContainsFunc[[]*ICECandidateExtended, *ICECandidateExtended](d.Remote, compFn) {
if slices.ContainsFunc(d.Remote, compFn) {
return
}
d.Remote = append(d.Remote, &ICECandidateExtended{
Remote: *candidate,
Remote: candidate,
Filtered: filtered,
Trickle: trickle,
})
}
@@ -148,7 +168,7 @@ func (d *ICEConnectionDetails) Clear() {
func (d *ICEConnectionDetails) SetSelectedPair(pair *webrtc.ICECandidatePair) {
d.lock.Lock()
defer d.lock.Unlock()
remoteIdx := slices.IndexFunc[[]*ICECandidateExtended, *ICECandidateExtended](d.Remote, func(e *ICECandidateExtended) bool {
remoteIdx := slices.IndexFunc(d.Remote, func(e *ICECandidateExtended) bool {
return isICECandidateEqualToCandidate(e.Remote, pair.Remote)
})
if remoteIdx < 0 {
@@ -162,15 +182,16 @@ func (d *ICEConnectionDetails) SetSelectedPair(pair *webrtc.ICECandidatePair) {
return
}
d.Remote = append(d.Remote, &ICECandidateExtended{
Remote: *candidate,
Remote: candidate,
Filtered: false,
Trickle: true,
})
remoteIdx = len(d.Remote) - 1
}
remote := d.Remote[remoteIdx]
remote.Selected = true
localIdx := slices.IndexFunc[[]*ICECandidateExtended, *ICECandidateExtended](d.Local, func(e *ICECandidateExtended) bool {
localIdx := slices.IndexFunc(d.Local, func(e *ICECandidateExtended) bool {
return isCandidateEqualTo(e.Local, pair.Local)
})
if localIdx < 0 {
@@ -214,7 +235,6 @@ func isCandidateEqualTo(c1, c2 *webrtc.ICECandidate) bool {
c1.Protocol == c2.Protocol &&
c1.Address == c2.Address &&
c1.Port == c2.Port &&
c1.Component == c2.Component &&
c1.Foundation == c2.Foundation &&
c1.Priority == c2.Priority &&
c1.RelatedAddress == c2.RelatedAddress &&
@@ -233,7 +253,6 @@ func isICECandidateEqualTo(c1, c2 ice.Candidate) bool {
c1.NetworkType() == c2.NetworkType() &&
c1.Address() == c2.Address() &&
c1.Port() == c2.Port() &&
c1.Component() == c2.Component() &&
c1.Foundation() == c2.Foundation() &&
c1.Priority() == c2.Priority() &&
c1.RelatedAddress().Equal(c2.RelatedAddress()) &&
@@ -251,13 +270,12 @@ func isICECandidateEqualToCandidate(c1 ice.Candidate, c2 *webrtc.ICECandidate) b
c1.NetworkType().NetworkShort() == c2.Protocol.String() &&
c1.Address() == c2.Address &&
c1.Port() == int(c2.Port) &&
c1.Component() == c2.Component &&
c1.Foundation() == c2.Foundation &&
c1.Priority() == c2.Priority &&
c1.TCPType().String() == c2.TCPType
}
func unmarshalICECandidate(c webrtc.ICECandidateInit) (*ice.Candidate, error) {
func unmarshalICECandidate(c webrtc.ICECandidateInit) (ice.Candidate, error) {
candidateValue := strings.TrimPrefix(c.Candidate, "candidate:")
if candidateValue == "" {
return nil, nil
@@ -268,5 +286,49 @@ func unmarshalICECandidate(c webrtc.ICECandidateInit) (*ice.Candidate, error) {
return nil, err
}
return &candidate, nil
return candidate, nil
}
func unmarshalCandidate(i ice.Candidate) (*webrtc.ICECandidate, error) {
var typ webrtc.ICECandidateType
switch i.Type() {
case ice.CandidateTypeHost:
typ = webrtc.ICECandidateTypeHost
case ice.CandidateTypeServerReflexive:
typ = webrtc.ICECandidateTypeSrflx
case ice.CandidateTypePeerReflexive:
typ = webrtc.ICECandidateTypePrflx
case ice.CandidateTypeRelay:
typ = webrtc.ICECandidateTypeRelay
default:
return nil, fmt.Errorf("unknown candidate type: %s", i.Type())
}
var protocol webrtc.ICEProtocol
switch strings.ToLower(i.NetworkType().NetworkShort()) {
case "udp":
protocol = webrtc.ICEProtocolUDP
case "tcp":
protocol = webrtc.ICEProtocolTCP
default:
return nil, fmt.Errorf("unknown network type: %s", i.NetworkType())
}
c := webrtc.ICECandidate{
Foundation: i.Foundation(),
Priority: i.Priority(),
Address: i.Address(),
Protocol: protocol,
Port: uint16(i.Port()),
Component: i.Component(),
Typ: typ,
TCPType: i.TCPType().String(),
}
if i.RelatedAddress() != nil {
c.RelatedAddress = i.RelatedAddress().Address
c.RelatedPort = uint16(i.RelatedAddress().Port)
}
return &c, nil
}