package ice
import (
"fmt"
"sync/atomic"
"time"
"github.com/pion/stun/v3"
)
func newCandidatePair(local , remote Candidate , controlling bool ) *CandidatePair {
return &CandidatePair {
iceRoleControlling : controlling ,
Remote : remote ,
Local : local ,
state : CandidatePairStateWaiting ,
}
}
type CandidatePair struct {
iceRoleControlling bool
Remote Candidate
Local Candidate
bindingRequestCount uint16
state CandidatePairState
nominated bool
nominateOnBindingSuccess bool
currentRoundTripTime int64
totalRoundTripTime int64
requestsReceived uint64
requestsSent uint64
responsesReceived uint64
responsesSent uint64
firstRequestSentAt atomic .Value
lastRequestSentAt atomic .Value
firstReponseReceivedAt atomic .Value
lastResponseReceivedAt atomic .Value
firstRequestReceivedAt atomic .Value
lastRequestReceivedAt atomic .Value
}
func (p *CandidatePair ) String () string {
if p == nil {
return ""
}
return fmt .Sprintf (
"prio %d (local, prio %d) %s <-> %s (remote, prio %d), state: %s, nominated: %v, nominateOnBindingSuccess: %v" ,
p .priority (),
p .Local .Priority (),
p .Local ,
p .Remote ,
p .Remote .Priority (),
p .state ,
p .nominated ,
p .nominateOnBindingSuccess ,
)
}
func (p *CandidatePair ) equal (other *CandidatePair ) bool {
if p == nil && other == nil {
return true
}
if p == nil || other == nil {
return false
}
return p .Local .Equal (other .Local ) && p .Remote .Equal (other .Remote )
}
func (p *CandidatePair ) priority () uint64 {
var g , d uint32
if p .iceRoleControlling {
g = p .Local .Priority ()
d = p .Remote .Priority ()
} else {
g = p .Remote .Priority ()
d = p .Local .Priority ()
}
localMin := func (x , y uint32 ) uint64 {
if x < y {
return uint64 (x )
}
return uint64 (y )
}
localMax := func (x , y uint32 ) uint64 {
if x > y {
return uint64 (x )
}
return uint64 (y )
}
cmp := func (x , y uint32 ) uint64 {
if x > y {
return uint64 (1 )
}
return uint64 (0 )
}
return (1 <<32 -1 )*localMin (g , d ) + 2 *localMax (g , d ) + cmp (g , d )
}
func (p *CandidatePair ) Write (b []byte ) (int , error ) {
return p .Local .writeTo (b , p .Remote )
}
func (a *Agent ) sendSTUN (msg *stun .Message , local , remote Candidate ) {
_ , err := local .writeTo (msg .Raw , remote )
if err != nil {
a .log .Tracef ("Failed to send STUN message: %s" , err )
}
}
func (p *CandidatePair ) UpdateRoundTripTime (rtt time .Duration ) {
rttNs := rtt .Nanoseconds ()
atomic .StoreInt64 (&p .currentRoundTripTime , rttNs )
atomic .AddInt64 (&p .totalRoundTripTime , rttNs )
atomic .AddUint64 (&p .responsesReceived , 1 )
now := time .Now ()
p .firstReponseReceivedAt .CompareAndSwap (nil , now )
p .lastResponseReceivedAt .Store (now )
}
func (p *CandidatePair ) CurrentRoundTripTime () float64 {
return time .Duration (atomic .LoadInt64 (&p .currentRoundTripTime )).Seconds ()
}
func (p *CandidatePair ) TotalRoundTripTime () float64 {
return time .Duration (atomic .LoadInt64 (&p .totalRoundTripTime )).Seconds ()
}
func (p *CandidatePair ) RequestsReceived () uint64 {
return atomic .LoadUint64 (&p .requestsReceived )
}
func (p *CandidatePair ) RequestsSent () uint64 {
return atomic .LoadUint64 (&p .requestsSent )
}
func (p *CandidatePair ) ResponsesReceived () uint64 {
return atomic .LoadUint64 (&p .responsesReceived )
}
func (p *CandidatePair ) ResponsesSent () uint64 {
return atomic .LoadUint64 (&p .responsesSent )
}
func (p *CandidatePair ) FirstRequestSentAt () time .Time {
if v , ok := p .firstRequestSentAt .Load ().(time .Time ); ok {
return v
}
return time .Time {}
}
func (p *CandidatePair ) LastRequestSentAt () time .Time {
if v , ok := p .lastRequestSentAt .Load ().(time .Time ); ok {
return v
}
return time .Time {}
}
func (p *CandidatePair ) FirstReponseReceivedAt () time .Time {
if v , ok := p .firstReponseReceivedAt .Load ().(time .Time ); ok {
return v
}
return time .Time {}
}
func (p *CandidatePair ) LastResponseReceivedAt () time .Time {
if v , ok := p .lastResponseReceivedAt .Load ().(time .Time ); ok {
return v
}
return time .Time {}
}
func (p *CandidatePair ) FirstRequestReceivedAt () time .Time {
if v , ok := p .firstRequestReceivedAt .Load ().(time .Time ); ok {
return v
}
return time .Time {}
}
func (p *CandidatePair ) LastRequestReceivedAt () time .Time {
if v , ok := p .lastRequestReceivedAt .Load ().(time .Time ); ok {
return v
}
return time .Time {}
}
func (p *CandidatePair ) UpdateRequestSent () {
atomic .AddUint64 (&p .requestsSent , 1 )
now := time .Now ()
p .firstRequestSentAt .CompareAndSwap (nil , now )
p .lastRequestSentAt .Store (now )
}
func (p *CandidatePair ) UpdateResponseSent () {
atomic .AddUint64 (&p .responsesSent , 1 )
}
func (p *CandidatePair ) UpdateRequestReceived () {
atomic .AddUint64 (&p .requestsReceived , 1 )
now := time .Now ()
p .firstRequestReceivedAt .CompareAndSwap (nil , now )
p .lastRequestReceivedAt .Store (now )
}
The pages are generated with Golds v0.8.2 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .