attributes.go 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. package stun
  2. import (
  3. "errors"
  4. "fmt"
  5. )
  6. // Attributes is list of message attributes.
  7. type Attributes []RawAttribute
  8. // Get returns first attribute from list by the type.
  9. // If attribute is present the RawAttribute is returned and the
  10. // boolean is true. Otherwise the returned RawAttribute will be
  11. // empty and boolean will be false.
  12. func (a Attributes) Get(t AttrType) (RawAttribute, bool) {
  13. for _, candidate := range a {
  14. if candidate.Type == t {
  15. return candidate, true
  16. }
  17. }
  18. return RawAttribute{}, false
  19. }
  20. // AttrType is attribute type.
  21. type AttrType uint16
  22. // Required returns true if type is from comprehension-required range (0x0000-0x7FFF).
  23. func (t AttrType) Required() bool {
  24. return t <= 0x7FFF
  25. }
  26. // Optional returns true if type is from comprehension-optional range (0x8000-0xFFFF).
  27. func (t AttrType) Optional() bool {
  28. return t >= 0x8000
  29. }
  30. // Attributes from comprehension-required range (0x0000-0x7FFF).
  31. const (
  32. AttrMappedAddress AttrType = 0x0001 // MAPPED-ADDRESS
  33. AttrUsername AttrType = 0x0006 // USERNAME
  34. AttrMessageIntegrity AttrType = 0x0008 // MESSAGE-INTEGRITY
  35. AttrErrorCode AttrType = 0x0009 // ERROR-CODE
  36. AttrUnknownAttributes AttrType = 0x000A // UNKNOWN-ATTRIBUTES
  37. AttrRealm AttrType = 0x0014 // REALM
  38. AttrNonce AttrType = 0x0015 // NONCE
  39. AttrXORMappedAddress AttrType = 0x0020 // XOR-MAPPED-ADDRESS
  40. )
  41. // Attributes from comprehension-optional range (0x8000-0xFFFF).
  42. const (
  43. AttrSoftware AttrType = 0x8022 // SOFTWARE
  44. AttrAlternateServer AttrType = 0x8023 // ALTERNATE-SERVER
  45. AttrFingerprint AttrType = 0x8028 // FINGERPRINT
  46. )
  47. // Attributes from RFC 5245 ICE.
  48. const (
  49. AttrPriority AttrType = 0x0024 // PRIORITY
  50. AttrUseCandidate AttrType = 0x0025 // USE-CANDIDATE
  51. AttrICEControlled AttrType = 0x8029 // ICE-CONTROLLED
  52. AttrICEControlling AttrType = 0x802A // ICE-CONTROLLING
  53. )
  54. // Attributes from RFC 5766 TURN.
  55. const (
  56. AttrChannelNumber AttrType = 0x000C // CHANNEL-NUMBER
  57. AttrLifetime AttrType = 0x000D // LIFETIME
  58. AttrXORPeerAddress AttrType = 0x0012 // XOR-PEER-ADDRESS
  59. AttrData AttrType = 0x0013 // DATA
  60. AttrXORRelayedAddress AttrType = 0x0016 // XOR-RELAYED-ADDRESS
  61. AttrEvenPort AttrType = 0x0018 // EVEN-PORT
  62. AttrRequestedTransport AttrType = 0x0019 // REQUESTED-TRANSPORT
  63. AttrDontFragment AttrType = 0x001A // DONT-FRAGMENT
  64. AttrReservationToken AttrType = 0x0022 // RESERVATION-TOKEN
  65. )
  66. // Attributes from RFC 5780 NAT Behavior Discovery
  67. const (
  68. AttrOtherAddress AttrType = 0x802C // OTHER-ADDRESS
  69. AttrChangeRequest AttrType = 0x0003 // CHANGE-REQUEST
  70. )
  71. // Attributes from RFC 6062 TURN Extensions for TCP Allocations.
  72. const (
  73. AttrConnectionID AttrType = 0x002a // CONNECTION-ID
  74. )
  75. // Attributes from RFC 6156 TURN IPv6.
  76. const (
  77. AttrRequestedAddressFamily AttrType = 0x0017 // REQUESTED-ADDRESS-FAMILY
  78. )
  79. // Attributes from An Origin Attribute for the STUN Protocol.
  80. const (
  81. AttrOrigin AttrType = 0x802F
  82. )
  83. // Value returns uint16 representation of attribute type.
  84. func (t AttrType) Value() uint16 {
  85. return uint16(t)
  86. }
  87. var attrNames = map[AttrType]string{
  88. AttrMappedAddress: "MAPPED-ADDRESS",
  89. AttrUsername: "USERNAME",
  90. AttrErrorCode: "ERROR-CODE",
  91. AttrMessageIntegrity: "MESSAGE-INTEGRITY",
  92. AttrUnknownAttributes: "UNKNOWN-ATTRIBUTES",
  93. AttrRealm: "REALM",
  94. AttrNonce: "NONCE",
  95. AttrXORMappedAddress: "XOR-MAPPED-ADDRESS",
  96. AttrSoftware: "SOFTWARE",
  97. AttrAlternateServer: "ALTERNATE-SERVER",
  98. AttrOtherAddress: "OTHER-ADDRESS",
  99. AttrChangeRequest: "CHANGE-REQUEST",
  100. AttrFingerprint: "FINGERPRINT",
  101. AttrPriority: "PRIORITY",
  102. AttrUseCandidate: "USE-CANDIDATE",
  103. AttrICEControlled: "ICE-CONTROLLED",
  104. AttrICEControlling: "ICE-CONTROLLING",
  105. AttrChannelNumber: "CHANNEL-NUMBER",
  106. AttrLifetime: "LIFETIME",
  107. AttrXORPeerAddress: "XOR-PEER-ADDRESS",
  108. AttrData: "DATA",
  109. AttrXORRelayedAddress: "XOR-RELAYED-ADDRESS",
  110. AttrEvenPort: "EVEN-PORT",
  111. AttrRequestedTransport: "REQUESTED-TRANSPORT",
  112. AttrDontFragment: "DONT-FRAGMENT",
  113. AttrReservationToken: "RESERVATION-TOKEN",
  114. AttrConnectionID: "CONNECTION-ID",
  115. AttrRequestedAddressFamily: "REQUESTED-ADDRESS-FAMILY",
  116. AttrOrigin: "ORIGIN",
  117. }
  118. func (t AttrType) String() string {
  119. s, ok := attrNames[t]
  120. if !ok {
  121. // Just return hex representation of unknown attribute type.
  122. return fmt.Sprintf("0x%x", uint16(t))
  123. }
  124. return s
  125. }
  126. // RawAttribute is a Type-Length-Value (TLV) object that
  127. // can be added to a STUN message. Attributes are divided into two
  128. // types: comprehension-required and comprehension-optional. STUN
  129. // agents can safely ignore comprehension-optional attributes they
  130. // don't understand, but cannot successfully process a message if it
  131. // contains comprehension-required attributes that are not
  132. // understood.
  133. type RawAttribute struct {
  134. Type AttrType
  135. Length uint16 // ignored while encoding
  136. Value []byte
  137. }
  138. // AddTo implements Setter, adding attribute as a.Type with a.Value and ignoring
  139. // the Length field.
  140. func (a RawAttribute) AddTo(m *Message) error {
  141. m.Add(a.Type, a.Value)
  142. return nil
  143. }
  144. // Equal returns true if a == b.
  145. func (a RawAttribute) Equal(b RawAttribute) bool {
  146. if a.Type != b.Type {
  147. return false
  148. }
  149. if a.Length != b.Length {
  150. return false
  151. }
  152. if len(b.Value) != len(a.Value) {
  153. return false
  154. }
  155. for i, v := range a.Value {
  156. if b.Value[i] != v {
  157. return false
  158. }
  159. }
  160. return true
  161. }
  162. func (a RawAttribute) String() string {
  163. return fmt.Sprintf("%s: 0x%x", a.Type, a.Value)
  164. }
  165. // ErrAttributeNotFound means that attribute with provided attribute
  166. // type does not exist in message.
  167. var ErrAttributeNotFound = errors.New("attribute not found")
  168. // Get returns byte slice that represents attribute value,
  169. // if there is no attribute with such type,
  170. // ErrAttributeNotFound is returned.
  171. func (m *Message) Get(t AttrType) ([]byte, error) {
  172. v, ok := m.Attributes.Get(t)
  173. if !ok {
  174. return nil, ErrAttributeNotFound
  175. }
  176. return v.Value, nil
  177. }
  178. // STUN aligns attributes on 32-bit boundaries, attributes whose content
  179. // is not a multiple of 4 bytes are padded with 1, 2, or 3 bytes of
  180. // padding so that its value contains a multiple of 4 bytes. The
  181. // padding bits are ignored, and may be any value.
  182. //
  183. // https://tools.ietf.org/html/rfc5389#section-15
  184. const padding = 4
  185. func nearestPaddedValueLength(l int) int {
  186. n := padding * (l / padding)
  187. if n < l {
  188. n += padding
  189. }
  190. return n
  191. }
  192. // This method converts uint16 vlue to AttrType. If it finds an old attribute
  193. // type value, it also translates it to the new value to enable backward
  194. // compatibility. (See: https://github.com/pion/stun/issues/21)
  195. func compatAttrType(val uint16) AttrType {
  196. if val == 0x8020 {
  197. return AttrXORMappedAddress // new: 0x0020
  198. }
  199. return AttrType(val)
  200. }