candidatepair.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
  2. // SPDX-License-Identifier: MIT
  3. package ice
  4. import (
  5. "fmt"
  6. "github.com/pion/stun"
  7. )
  8. func newCandidatePair(local, remote Candidate, controlling bool) *CandidatePair {
  9. return &CandidatePair{
  10. iceRoleControlling: controlling,
  11. Remote: remote,
  12. Local: local,
  13. state: CandidatePairStateWaiting,
  14. }
  15. }
  16. // CandidatePair is a combination of a
  17. // local and remote candidate
  18. type CandidatePair struct {
  19. iceRoleControlling bool
  20. Remote Candidate
  21. Local Candidate
  22. bindingRequestCount uint16
  23. state CandidatePairState
  24. nominated bool
  25. nominateOnBindingSuccess bool
  26. }
  27. func (p *CandidatePair) String() string {
  28. if p == nil {
  29. return ""
  30. }
  31. return fmt.Sprintf("prio %d (local, prio %d) %s <-> %s (remote, prio %d)",
  32. p.priority(), p.Local.Priority(), p.Local, p.Remote, p.Remote.Priority())
  33. }
  34. func (p *CandidatePair) equal(other *CandidatePair) bool {
  35. if p == nil && other == nil {
  36. return true
  37. }
  38. if p == nil || other == nil {
  39. return false
  40. }
  41. return p.Local.Equal(other.Local) && p.Remote.Equal(other.Remote)
  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)
  48. func (p *CandidatePair) priority() uint64 {
  49. var g, d uint32
  50. if p.iceRoleControlling {
  51. g = p.Local.Priority()
  52. d = p.Remote.Priority()
  53. } else {
  54. g = p.Remote.Priority()
  55. d = p.Local.Priority()
  56. }
  57. // Just implement these here rather
  58. // than fooling around with the math package
  59. min := func(x, y uint32) uint64 {
  60. if x < y {
  61. return uint64(x)
  62. }
  63. return uint64(y)
  64. }
  65. max := func(x, y uint32) uint64 {
  66. if x > y {
  67. return uint64(x)
  68. }
  69. return uint64(y)
  70. }
  71. cmp := func(x, y uint32) uint64 {
  72. if x > y {
  73. return uint64(1)
  74. }
  75. return uint64(0)
  76. }
  77. // 1<<32 overflows uint32; and if both g && d are
  78. // maxUint32, this result would overflow uint64
  79. return (1<<32-1)*min(g, d) + 2*max(g, d) + cmp(g, d)
  80. }
  81. func (p *CandidatePair) Write(b []byte) (int, error) {
  82. return p.Local.writeTo(b, p.Remote)
  83. }
  84. func (a *Agent) sendSTUN(msg *stun.Message, local, remote Candidate) {
  85. _, err := local.writeTo(msg.Raw, remote)
  86. if err != nil {
  87. a.log.Tracef("failed to send STUN message: %s", err)
  88. }
  89. }