1package ice 2 3import ( 4 "fmt" 5 6 "github.com/pion/stun" 7) 8 9func newCandidatePair(local, remote Candidate, controlling bool) *candidatePair { 10 return &candidatePair{ 11 iceRoleControlling: controlling, 12 remote: remote, 13 local: local, 14 state: CandidatePairStateWaiting, 15 } 16} 17 18// candidatePair represents a combination of a local and remote candidate 19type candidatePair struct { 20 iceRoleControlling bool 21 remote Candidate 22 local Candidate 23 bindingRequestCount uint16 24 state CandidatePairState 25 nominated bool 26} 27 28func (p *candidatePair) String() string { 29 return fmt.Sprintf("prio %d (local, prio %d) %s <-> %s (remote, prio %d)", 30 p.Priority(), p.local.Priority(), p.local, p.remote, p.remote.Priority()) 31} 32 33func (p *candidatePair) Equal(other *candidatePair) bool { 34 if p == nil && other == nil { 35 return true 36 } 37 if p == nil || other == nil { 38 return false 39 } 40 return p.local.Equal(other.local) && p.remote.Equal(other.remote) 41} 42 43// RFC 5245 - 5.7.2. Computing Pair Priority and Ordering Pairs 44// Let G be the priority for the candidate provided by the controlling 45// agent. Let D be the priority for the candidate provided by the 46// controlled agent. 47// pair priority = 2^32*MIN(G,D) + 2*MAX(G,D) + (G>D?1:0) 48func (p *candidatePair) Priority() uint64 { 49 var g uint32 50 var d uint32 51 if p.iceRoleControlling { 52 g = p.local.Priority() 53 d = p.remote.Priority() 54 } else { 55 g = p.remote.Priority() 56 d = p.local.Priority() 57 } 58 59 // Just implement these here rather 60 // than fooling around with the math package 61 min := func(x, y uint32) uint64 { 62 if x < y { 63 return uint64(x) 64 } 65 return uint64(y) 66 } 67 max := func(x, y uint32) uint64 { 68 if x > y { 69 return uint64(x) 70 } 71 return uint64(y) 72 } 73 cmp := func(x, y uint32) uint64 { 74 if x > y { 75 return uint64(1) 76 } 77 return uint64(0) 78 } 79 80 // 1<<32 overflows uint32; and if both g && d are 81 // maxUint32, this result would overflow uint64 82 return (1<<32-1)*min(g, d) + 2*max(g, d) + cmp(g, d) 83} 84 85func (p *candidatePair) Write(b []byte) (int, error) { 86 return p.local.writeTo(b, p.remote) 87} 88 89func (a *Agent) sendSTUN(msg *stun.Message, local, remote Candidate) { 90 _, err := local.writeTo(msg.Raw, remote) 91 if err != nil { 92 a.log.Tracef("failed to send STUN message: %s", err) 93 } 94} 95