mirror of
https://github.com/livekit/livekit.git
synced 2026-05-14 14:05:18 +00:00
log non-trickle candidate in details (#2832)
* log non-trickle candidate in details * fix test
This commit is contained in:
@@ -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
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user