attributes.go 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  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. AttrChangeRequest AttrType = 0x0003 // CHANGE-REQUEST
  69. AttrPadding AttrType = 0x0026 // PADDING
  70. AttrResponsePort AttrType = 0x0027 // RESPONSE-PORT
  71. AttrCacheTimeout AttrType = 0x8027 // CACHE-TIMEOUT
  72. AttrResponseOrigin AttrType = 0x802b // RESPONSE-ORIGIN
  73. AttrOtherAddress AttrType = 0x802C // OTHER-ADDRESS
  74. )
  75. // Attributes from RFC 3489, removed by RFC 5389,
  76. //
  77. // but still used by RFC5389-implementing software like Vovida.org, reTURNServer, etc.
  78. const (
  79. AttrSourceAddress AttrType = 0x0004 // SOURCE-ADDRESS
  80. AttrChangedAddress AttrType = 0x0005 // CHANGED-ADDRESS
  81. )
  82. // Attributes from RFC 6062 TURN Extensions for TCP Allocations.
  83. const (
  84. AttrConnectionID AttrType = 0x002a // CONNECTION-ID
  85. )
  86. // Attributes from RFC 6156 TURN IPv6.
  87. const (
  88. AttrRequestedAddressFamily AttrType = 0x0017 // REQUESTED-ADDRESS-FAMILY
  89. )
  90. // Attributes from An Origin Attribute for the STUN Protocol.
  91. const (
  92. AttrOrigin AttrType = 0x802F
  93. )
  94. // Attributes from RFC 8489 STUN.
  95. const (
  96. AttrMessageIntegritySHA256 AttrType = 0x001C // MESSAGE-INTEGRITY-SHA256
  97. AttrPasswordAlgorithm AttrType = 0x001D // PASSWORD-ALGORITHM
  98. AttrUserhash AttrType = 0x001E // USERHASH
  99. AttrPasswordAlgorithms AttrType = 0x8002 // PASSWORD-ALGORITHMS
  100. AttrAlternateDomain AttrType = 0x8003 // ALTERNATE-DOMAIN
  101. )
  102. // Value returns uint16 representation of attribute type.
  103. func (t AttrType) Value() uint16 {
  104. return uint16(t)
  105. }
  106. func attrNames() map[AttrType]string {
  107. return map[AttrType]string{
  108. AttrMappedAddress: "MAPPED-ADDRESS",
  109. AttrUsername: "USERNAME",
  110. AttrErrorCode: "ERROR-CODE",
  111. AttrMessageIntegrity: "MESSAGE-INTEGRITY",
  112. AttrUnknownAttributes: "UNKNOWN-ATTRIBUTES",
  113. AttrRealm: "REALM",
  114. AttrNonce: "NONCE",
  115. AttrXORMappedAddress: "XOR-MAPPED-ADDRESS",
  116. AttrSoftware: "SOFTWARE",
  117. AttrAlternateServer: "ALTERNATE-SERVER",
  118. AttrFingerprint: "FINGERPRINT",
  119. AttrPriority: "PRIORITY",
  120. AttrUseCandidate: "USE-CANDIDATE",
  121. AttrICEControlled: "ICE-CONTROLLED",
  122. AttrICEControlling: "ICE-CONTROLLING",
  123. AttrChannelNumber: "CHANNEL-NUMBER",
  124. AttrLifetime: "LIFETIME",
  125. AttrXORPeerAddress: "XOR-PEER-ADDRESS",
  126. AttrData: "DATA",
  127. AttrXORRelayedAddress: "XOR-RELAYED-ADDRESS",
  128. AttrEvenPort: "EVEN-PORT",
  129. AttrRequestedTransport: "REQUESTED-TRANSPORT",
  130. AttrDontFragment: "DONT-FRAGMENT",
  131. AttrReservationToken: "RESERVATION-TOKEN",
  132. AttrConnectionID: "CONNECTION-ID",
  133. AttrRequestedAddressFamily: "REQUESTED-ADDRESS-FAMILY",
  134. AttrMessageIntegritySHA256: "MESSAGE-INTEGRITY-SHA256",
  135. AttrPasswordAlgorithm: "PASSWORD-ALGORITHM",
  136. AttrUserhash: "USERHASH",
  137. AttrPasswordAlgorithms: "PASSWORD-ALGORITHMS",
  138. AttrAlternateDomain: "ALTERNATE-DOMAIN",
  139. }
  140. }
  141. func (t AttrType) String() string {
  142. s, ok := attrNames()[t]
  143. if !ok {
  144. // Just return hex representation of unknown attribute type.
  145. return fmt.Sprintf("0x%x", uint16(t))
  146. }
  147. return s
  148. }
  149. // RawAttribute is a Type-Length-Value (TLV) object that
  150. // can be added to a STUN message. Attributes are divided into two
  151. // types: comprehension-required and comprehension-optional. STUN
  152. // agents can safely ignore comprehension-optional attributes they
  153. // don't understand, but cannot successfully process a message if it
  154. // contains comprehension-required attributes that are not
  155. // understood.
  156. type RawAttribute struct {
  157. Type AttrType
  158. Length uint16 // ignored while encoding
  159. Value []byte
  160. }
  161. // AddTo implements Setter, adding attribute as a.Type with a.Value and ignoring
  162. // the Length field.
  163. func (a RawAttribute) AddTo(m *Message) error {
  164. m.Add(a.Type, a.Value)
  165. return nil
  166. }
  167. // Equal returns true if a == b.
  168. func (a RawAttribute) Equal(b RawAttribute) bool {
  169. if a.Type != b.Type {
  170. return false
  171. }
  172. if a.Length != b.Length {
  173. return false
  174. }
  175. if len(b.Value) != len(a.Value) {
  176. return false
  177. }
  178. for i, v := range a.Value {
  179. if b.Value[i] != v {
  180. return false
  181. }
  182. }
  183. return true
  184. }
  185. func (a RawAttribute) String() string {
  186. return fmt.Sprintf("%s: 0x%x", a.Type, a.Value)
  187. }
  188. // ErrAttributeNotFound means that attribute with provided attribute
  189. // type does not exist in message.
  190. var ErrAttributeNotFound = errors.New("attribute not found")
  191. // Get returns byte slice that represents attribute value,
  192. // if there is no attribute with such type,
  193. // ErrAttributeNotFound is returned.
  194. func (m *Message) Get(t AttrType) ([]byte, error) {
  195. v, ok := m.Attributes.Get(t)
  196. if !ok {
  197. return nil, ErrAttributeNotFound
  198. }
  199. return v.Value, nil
  200. }
  201. // STUN aligns attributes on 32-bit boundaries, attributes whose content
  202. // is not a multiple of 4 bytes are padded with 1, 2, or 3 bytes of
  203. // padding so that its value contains a multiple of 4 bytes. The
  204. // padding bits are ignored, and may be any value.
  205. //
  206. // https://tools.ietf.org/html/rfc5389#section-15
  207. const padding = 4
  208. func nearestPaddedValueLength(l int) int {
  209. n := padding * (l / padding)
  210. if n < l {
  211. n += padding
  212. }
  213. return n
  214. }
  215. // This method converts uint16 vlue to AttrType. If it finds an old attribute
  216. // type value, it also translates it to the new value to enable backward
  217. // compatibility. (See: https://github.com/pion/stun/issues/21)
  218. func compatAttrType(val uint16) AttrType {
  219. if val == 0x8020 { // draft-ietf-behave-rfc3489bis-02, MS-TURN
  220. return AttrXORMappedAddress // new: 0x0020 (from draft-ietf-behave-rfc3489bis-03 on)
  221. }
  222. return AttrType(val)
  223. }