addr.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
  2. // SPDX-License-Identifier: MIT
  3. package stun
  4. import (
  5. "fmt"
  6. "io"
  7. "net"
  8. "strconv"
  9. )
  10. // MappedAddress represents MAPPED-ADDRESS attribute.
  11. //
  12. // This attribute is used only by servers for achieving backwards
  13. // compatibility with RFC 3489 clients.
  14. //
  15. // RFC 5389 Section 15.1
  16. type MappedAddress struct {
  17. IP net.IP
  18. Port int
  19. }
  20. // AlternateServer represents ALTERNATE-SERVER attribute.
  21. //
  22. // RFC 5389 Section 15.11
  23. type AlternateServer struct {
  24. IP net.IP
  25. Port int
  26. }
  27. // ResponseOrigin represents RESPONSE-ORIGIN attribute.
  28. //
  29. // RFC 5780 Section 7.3
  30. type ResponseOrigin struct {
  31. IP net.IP
  32. Port int
  33. }
  34. // OtherAddress represents OTHER-ADDRESS attribute.
  35. //
  36. // RFC 5780 Section 7.4
  37. type OtherAddress struct {
  38. IP net.IP
  39. Port int
  40. }
  41. // AddTo adds ALTERNATE-SERVER attribute to message.
  42. func (s *AlternateServer) AddTo(m *Message) error {
  43. a := (*MappedAddress)(s)
  44. return a.AddToAs(m, AttrAlternateServer)
  45. }
  46. // GetFrom decodes ALTERNATE-SERVER from message.
  47. func (s *AlternateServer) GetFrom(m *Message) error {
  48. a := (*MappedAddress)(s)
  49. return a.GetFromAs(m, AttrAlternateServer)
  50. }
  51. func (a MappedAddress) String() string {
  52. return net.JoinHostPort(a.IP.String(), strconv.Itoa(a.Port))
  53. }
  54. // GetFromAs decodes MAPPED-ADDRESS value in message m as an attribute of type t.
  55. func (a *MappedAddress) GetFromAs(m *Message, t AttrType) error {
  56. v, err := m.Get(t)
  57. if err != nil {
  58. return err
  59. }
  60. if len(v) <= 4 {
  61. return io.ErrUnexpectedEOF
  62. }
  63. family := bin.Uint16(v[0:2])
  64. if family != familyIPv6 && family != familyIPv4 {
  65. return newDecodeErr("xor-mapped address", "family",
  66. fmt.Sprintf("bad value %d", family),
  67. )
  68. }
  69. ipLen := net.IPv4len
  70. if family == familyIPv6 {
  71. ipLen = net.IPv6len
  72. }
  73. // Ensuring len(a.IP) == ipLen and reusing a.IP.
  74. if len(a.IP) < ipLen {
  75. a.IP = a.IP[:cap(a.IP)]
  76. for len(a.IP) < ipLen {
  77. a.IP = append(a.IP, 0)
  78. }
  79. }
  80. a.IP = a.IP[:ipLen]
  81. for i := range a.IP {
  82. a.IP[i] = 0
  83. }
  84. a.Port = int(bin.Uint16(v[2:4]))
  85. copy(a.IP, v[4:])
  86. return nil
  87. }
  88. // AddToAs adds MAPPED-ADDRESS value to m as t attribute.
  89. func (a *MappedAddress) AddToAs(m *Message, t AttrType) error {
  90. var (
  91. family = familyIPv4
  92. ip = a.IP
  93. )
  94. if len(a.IP) == net.IPv6len {
  95. if isIPv4(ip) {
  96. ip = ip[12:16] // like in ip.To4()
  97. } else {
  98. family = familyIPv6
  99. }
  100. } else if len(ip) != net.IPv4len {
  101. return ErrBadIPLength
  102. }
  103. value := make([]byte, 128)
  104. value[0] = 0 // first 8 bits are zeroes
  105. bin.PutUint16(value[0:2], family)
  106. bin.PutUint16(value[2:4], uint16(a.Port))
  107. copy(value[4:], ip)
  108. m.Add(t, value[:4+len(ip)])
  109. return nil
  110. }
  111. // AddTo adds MAPPED-ADDRESS to message.
  112. func (a *MappedAddress) AddTo(m *Message) error {
  113. return a.AddToAs(m, AttrMappedAddress)
  114. }
  115. // GetFrom decodes MAPPED-ADDRESS from message.
  116. func (a *MappedAddress) GetFrom(m *Message) error {
  117. return a.GetFromAs(m, AttrMappedAddress)
  118. }
  119. // AddTo adds OTHER-ADDRESS attribute to message.
  120. func (o *OtherAddress) AddTo(m *Message) error {
  121. a := (*MappedAddress)(o)
  122. return a.AddToAs(m, AttrOtherAddress)
  123. }
  124. // GetFrom decodes OTHER-ADDRESS from message.
  125. func (o *OtherAddress) GetFrom(m *Message) error {
  126. a := (*MappedAddress)(o)
  127. return a.GetFromAs(m, AttrOtherAddress)
  128. }
  129. func (o OtherAddress) String() string {
  130. return net.JoinHostPort(o.IP.String(), strconv.Itoa(o.Port))
  131. }
  132. // AddTo adds RESPONSE-ORIGIN attribute to message.
  133. func (o *ResponseOrigin) AddTo(m *Message) error {
  134. a := (*MappedAddress)(o)
  135. return a.AddToAs(m, AttrResponseOrigin)
  136. }
  137. // GetFrom decodes RESPONSE-ORIGIN from message.
  138. func (o *ResponseOrigin) GetFrom(m *Message) error {
  139. a := (*MappedAddress)(o)
  140. return a.GetFromAs(m, AttrResponseOrigin)
  141. }
  142. func (o ResponseOrigin) String() string {
  143. return net.JoinHostPort(o.IP.String(), strconv.Itoa(o.Port))
  144. }