Skip to content

Commit

Permalink
Add round trip time measurement to candidate pair
Browse files Browse the repository at this point in the history
Use the round trip time measurement to populate RTT fields in
CandidatePairStats.
  • Loading branch information
boks1971 committed Sep 16, 2024
1 parent 277014e commit 6977e58
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 8 deletions.
6 changes: 3 additions & 3 deletions agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -973,16 +973,16 @@ func (a *Agent) invalidatePendingBindingRequests(filterTime time.Time) {

// Assert that the passed TransactionID is in our pendingBindingRequests and returns the destination
// If the bindingRequest was valid remove it from our pending cache
func (a *Agent) handleInboundBindingSuccess(id [stun.TransactionIDSize]byte) (bool, *bindingRequest) {
func (a *Agent) handleInboundBindingSuccess(id [stun.TransactionIDSize]byte) (bool, *bindingRequest, time.Duration) {

Check warning on line 976 in agent.go

View check run for this annotation

Codecov / codecov/patch

agent.go#L976

Added line #L976 was not covered by tests
a.invalidatePendingBindingRequests(time.Now())
for i := range a.pendingBindingRequests {
if a.pendingBindingRequests[i].transactionID == id {
validBindingRequest := a.pendingBindingRequests[i]
a.pendingBindingRequests = append(a.pendingBindingRequests[:i], a.pendingBindingRequests[i+1:]...)
return true, &validBindingRequest
return true, &validBindingRequest, time.Since(validBindingRequest.timestamp)

Check warning on line 982 in agent.go

View check run for this annotation

Codecov / codecov/patch

agent.go#L982

Added line #L982 was not covered by tests
}
}
return false, nil
return false, nil, 0

Check warning on line 985 in agent.go

View check run for this annotation

Codecov / codecov/patch

agent.go#L985

Added line #L985 was not covered by tests
}

// handleInbound processes STUN traffic from a remote candidate
Expand Down
6 changes: 3 additions & 3 deletions agent_stats.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,14 @@ func (a *Agent) GetCandidatePairsStats() []CandidatePairStats {
// FirstRequestTimestamp time.Time
// LastRequestTimestamp time.Time
// LastResponseTimestamp time.Time
// TotalRoundTripTime float64
// CurrentRoundTripTime float64
TotalRoundTripTime: cp.TotalRoundTripTime(),
CurrentRoundTripTime: cp.CurrentRoundTripTime(),

Check warning on line 33 in agent_stats.go

View check run for this annotation

Codecov / codecov/patch

agent_stats.go#L32-L33

Added lines #L32 - L33 were not covered by tests
// AvailableOutgoingBitrate float64
// AvailableIncomingBitrate float64
// CircuitBreakerTriggerCount uint32
// RequestsReceived uint64
// RequestsSent uint64
// ResponsesReceived uint64
ResponsesReceived: cp.ResponsesReceived(),

Check warning on line 39 in agent_stats.go

View check run for this annotation

Codecov / codecov/patch

agent_stats.go#L39

Added line #L39 was not covered by tests
// ResponsesSent uint64
// RetransmissionsReceived uint64
// RetransmissionsSent uint64
Expand Down
46 changes: 46 additions & 0 deletions candidatepair.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ package ice

import (
"fmt"
"sync"
"time"

"github.com/pion/stun/v3"
)
Expand All @@ -28,6 +30,12 @@ type CandidatePair struct {
state CandidatePairState
nominated bool
nominateOnBindingSuccess bool

// stats
statsMu sync.RWMutex
currentRoundTripTime time.Duration
totalRoundTripTime time.Duration
responsesReceived uint64
}

func (p *CandidatePair) String() string {
Expand Down Expand Up @@ -100,3 +108,41 @@ func (a *Agent) sendSTUN(msg *stun.Message, local, remote Candidate) {
a.log.Tracef("Failed to send STUN message: %s", err)
}
}

// UpdateRoundTripTime sets the current round time of this pair and
// accumulates total round trip time and responses received
func (p *CandidatePair) UpdateRoundTripTime(rtt time.Duration) {
p.statsMu.Lock()
defer p.statsMu.Unlock()

Check warning on line 116 in candidatepair.go

View check run for this annotation

Codecov / codecov/patch

candidatepair.go#L114-L116

Added lines #L114 - L116 were not covered by tests

p.currentRoundTripTime = rtt
p.totalRoundTripTime += rtt
p.responsesReceived++

Check warning on line 120 in candidatepair.go

View check run for this annotation

Codecov / codecov/patch

candidatepair.go#L118-L120

Added lines #L118 - L120 were not covered by tests
}

// CurrentRoundTripTime returns the current round trip time in seconds
// https://www.w3.org/TR/webrtc-stats/#dom-rtcicecandidatepairstats-currentroundtriptime
func (p *CandidatePair) CurrentRoundTripTime() float64 {
p.statsMu.RLock()
defer p.statsMu.RUnlock()

Check warning on line 127 in candidatepair.go

View check run for this annotation

Codecov / codecov/patch

candidatepair.go#L125-L127

Added lines #L125 - L127 were not covered by tests

return p.currentRoundTripTime.Seconds()

Check warning on line 129 in candidatepair.go

View check run for this annotation

Codecov / codecov/patch

candidatepair.go#L129

Added line #L129 was not covered by tests
}

// TotalRoundTripTime returns the current round trip time in seconds
// https://www.w3.org/TR/webrtc-stats/#dom-rtcicecandidatepairstats-totalroundtriptime
func (p *CandidatePair) TotalRoundTripTime() float64 {
p.statsMu.RLock()
defer p.statsMu.RUnlock()

Check warning on line 136 in candidatepair.go

View check run for this annotation

Codecov / codecov/patch

candidatepair.go#L134-L136

Added lines #L134 - L136 were not covered by tests

return p.totalRoundTripTime.Seconds()

Check warning on line 138 in candidatepair.go

View check run for this annotation

Codecov / codecov/patch

candidatepair.go#L138

Added line #L138 was not covered by tests
}

// ResponsesReceived returns the total number of connectivity responses received
// https://www.w3.org/TR/webrtc-stats/#dom-rtcicecandidatepairstats-responsesreceived
func (p *CandidatePair) ResponsesReceived() uint64 {
p.statsMu.RLock()
defer p.statsMu.RUnlock()

Check warning on line 145 in candidatepair.go

View check run for this annotation

Codecov / codecov/patch

candidatepair.go#L143-L145

Added lines #L143 - L145 were not covered by tests

return p.responsesReceived

Check warning on line 147 in candidatepair.go

View check run for this annotation

Codecov / codecov/patch

candidatepair.go#L147

Added line #L147 was not covered by tests
}
8 changes: 6 additions & 2 deletions selection.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ func (s *controllingSelector) HandleBindingRequest(m *stun.Message, local, remot
}

func (s *controllingSelector) HandleSuccessResponse(m *stun.Message, local, remote Candidate, remoteAddr net.Addr) {
ok, pendingRequest := s.agent.handleInboundBindingSuccess(m.TransactionID)
ok, pendingRequest, rtt := s.agent.handleInboundBindingSuccess(m.TransactionID)

Check warning on line 123 in selection.go

View check run for this annotation

Codecov / codecov/patch

selection.go#L123

Added line #L123 was not covered by tests
if !ok {
s.log.Warnf("Discard message from (%s), unknown TransactionID 0x%x", remote, m.TransactionID)
return
Expand Down Expand Up @@ -149,6 +149,8 @@ func (s *controllingSelector) HandleSuccessResponse(m *stun.Message, local, remo
if pendingRequest.isUseCandidate && s.agent.getSelectedPair() == nil {
s.agent.setSelectedPair(p)
}

p.UpdateRoundTripTime(rtt)

Check warning on line 153 in selection.go

View check run for this annotation

Codecov / codecov/patch

selection.go#L153

Added line #L153 was not covered by tests
}

func (s *controllingSelector) PingCandidate(local, remote Candidate) {
Expand Down Expand Up @@ -211,7 +213,7 @@ func (s *controlledSelector) HandleSuccessResponse(m *stun.Message, local, remot
// request with an appropriate error code response (e.g., 400)
// [RFC5389].

ok, pendingRequest := s.agent.handleInboundBindingSuccess(m.TransactionID)
ok, pendingRequest, rtt := s.agent.handleInboundBindingSuccess(m.TransactionID)

Check warning on line 216 in selection.go

View check run for this annotation

Codecov / codecov/patch

selection.go#L216

Added line #L216 was not covered by tests
if !ok {
s.log.Warnf("Discard message from (%s), unknown TransactionID 0x%x", remote, m.TransactionID)
return
Expand Down Expand Up @@ -245,6 +247,8 @@ func (s *controlledSelector) HandleSuccessResponse(m *stun.Message, local, remot
s.log.Tracef("Ignore nominate new pair %s, already nominated pair %s", p, selectedPair)
}
}

p.UpdateRoundTripTime(rtt)

Check warning on line 251 in selection.go

View check run for this annotation

Codecov / codecov/patch

selection.go#L251

Added line #L251 was not covered by tests
}

func (s *controlledSelector) HandleBindingRequest(m *stun.Message, local, remote Candidate) {
Expand Down

0 comments on commit 6977e58

Please sign in to comment.