123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254 |
- // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
- // SPDX-License-Identifier: MIT
- package stun
- import (
- "errors"
- "fmt"
- )
- // Attributes is list of message attributes.
- type Attributes []RawAttribute
- // Get returns first attribute from list by the type.
- // If attribute is present the RawAttribute is returned and the
- // boolean is true. Otherwise the returned RawAttribute will be
- // empty and boolean will be false.
- func (a Attributes) Get(t AttrType) (RawAttribute, bool) {
- for _, candidate := range a {
- if candidate.Type == t {
- return candidate, true
- }
- }
- return RawAttribute{}, false
- }
- // AttrType is attribute type.
- type AttrType uint16
- // Required returns true if type is from comprehension-required range (0x0000-0x7FFF).
- func (t AttrType) Required() bool {
- return t <= 0x7FFF
- }
- // Optional returns true if type is from comprehension-optional range (0x8000-0xFFFF).
- func (t AttrType) Optional() bool {
- return t >= 0x8000
- }
- // Attributes from comprehension-required range (0x0000-0x7FFF).
- const (
- AttrMappedAddress AttrType = 0x0001 // MAPPED-ADDRESS
- AttrUsername AttrType = 0x0006 // USERNAME
- AttrMessageIntegrity AttrType = 0x0008 // MESSAGE-INTEGRITY
- AttrErrorCode AttrType = 0x0009 // ERROR-CODE
- AttrUnknownAttributes AttrType = 0x000A // UNKNOWN-ATTRIBUTES
- AttrRealm AttrType = 0x0014 // REALM
- AttrNonce AttrType = 0x0015 // NONCE
- AttrXORMappedAddress AttrType = 0x0020 // XOR-MAPPED-ADDRESS
- )
- // Attributes from comprehension-optional range (0x8000-0xFFFF).
- const (
- AttrSoftware AttrType = 0x8022 // SOFTWARE
- AttrAlternateServer AttrType = 0x8023 // ALTERNATE-SERVER
- AttrFingerprint AttrType = 0x8028 // FINGERPRINT
- )
- // Attributes from RFC 5245 ICE.
- const (
- AttrPriority AttrType = 0x0024 // PRIORITY
- AttrUseCandidate AttrType = 0x0025 // USE-CANDIDATE
- AttrICEControlled AttrType = 0x8029 // ICE-CONTROLLED
- AttrICEControlling AttrType = 0x802A // ICE-CONTROLLING
- )
- // Attributes from RFC 5766 TURN.
- const (
- AttrChannelNumber AttrType = 0x000C // CHANNEL-NUMBER
- AttrLifetime AttrType = 0x000D // LIFETIME
- AttrXORPeerAddress AttrType = 0x0012 // XOR-PEER-ADDRESS
- AttrData AttrType = 0x0013 // DATA
- AttrXORRelayedAddress AttrType = 0x0016 // XOR-RELAYED-ADDRESS
- AttrEvenPort AttrType = 0x0018 // EVEN-PORT
- AttrRequestedTransport AttrType = 0x0019 // REQUESTED-TRANSPORT
- AttrDontFragment AttrType = 0x001A // DONT-FRAGMENT
- AttrReservationToken AttrType = 0x0022 // RESERVATION-TOKEN
- )
- // Attributes from RFC 5780 NAT Behavior Discovery
- const (
- AttrChangeRequest AttrType = 0x0003 // CHANGE-REQUEST
- AttrPadding AttrType = 0x0026 // PADDING
- AttrResponsePort AttrType = 0x0027 // RESPONSE-PORT
- AttrCacheTimeout AttrType = 0x8027 // CACHE-TIMEOUT
- AttrResponseOrigin AttrType = 0x802b // RESPONSE-ORIGIN
- AttrOtherAddress AttrType = 0x802C // OTHER-ADDRESS
- )
- // Attributes from RFC 3489, removed by RFC 5389,
- //
- // but still used by RFC5389-implementing software like Vovida.org, reTURNServer, etc.
- const (
- AttrSourceAddress AttrType = 0x0004 // SOURCE-ADDRESS
- AttrChangedAddress AttrType = 0x0005 // CHANGED-ADDRESS
- )
- // Attributes from RFC 6062 TURN Extensions for TCP Allocations.
- const (
- AttrConnectionID AttrType = 0x002a // CONNECTION-ID
- )
- // Attributes from RFC 6156 TURN IPv6.
- const (
- AttrRequestedAddressFamily AttrType = 0x0017 // REQUESTED-ADDRESS-FAMILY
- )
- // Attributes from An Origin Attribute for the STUN Protocol.
- const (
- AttrOrigin AttrType = 0x802F
- )
- // Attributes from RFC 8489 STUN.
- const (
- AttrMessageIntegritySHA256 AttrType = 0x001C // MESSAGE-INTEGRITY-SHA256
- AttrPasswordAlgorithm AttrType = 0x001D // PASSWORD-ALGORITHM
- AttrUserhash AttrType = 0x001E // USERHASH
- AttrPasswordAlgorithms AttrType = 0x8002 // PASSWORD-ALGORITHMS
- AttrAlternateDomain AttrType = 0x8003 // ALTERNATE-DOMAIN
- )
- // Value returns uint16 representation of attribute type.
- func (t AttrType) Value() uint16 {
- return uint16(t)
- }
- func attrNames() map[AttrType]string {
- return map[AttrType]string{
- AttrMappedAddress: "MAPPED-ADDRESS",
- AttrUsername: "USERNAME",
- AttrErrorCode: "ERROR-CODE",
- AttrMessageIntegrity: "MESSAGE-INTEGRITY",
- AttrUnknownAttributes: "UNKNOWN-ATTRIBUTES",
- AttrRealm: "REALM",
- AttrNonce: "NONCE",
- AttrXORMappedAddress: "XOR-MAPPED-ADDRESS",
- AttrSoftware: "SOFTWARE",
- AttrAlternateServer: "ALTERNATE-SERVER",
- AttrFingerprint: "FINGERPRINT",
- AttrPriority: "PRIORITY",
- AttrUseCandidate: "USE-CANDIDATE",
- AttrICEControlled: "ICE-CONTROLLED",
- AttrICEControlling: "ICE-CONTROLLING",
- AttrChannelNumber: "CHANNEL-NUMBER",
- AttrLifetime: "LIFETIME",
- AttrXORPeerAddress: "XOR-PEER-ADDRESS",
- AttrData: "DATA",
- AttrXORRelayedAddress: "XOR-RELAYED-ADDRESS",
- AttrEvenPort: "EVEN-PORT",
- AttrRequestedTransport: "REQUESTED-TRANSPORT",
- AttrDontFragment: "DONT-FRAGMENT",
- AttrReservationToken: "RESERVATION-TOKEN",
- AttrConnectionID: "CONNECTION-ID",
- AttrRequestedAddressFamily: "REQUESTED-ADDRESS-FAMILY",
- AttrMessageIntegritySHA256: "MESSAGE-INTEGRITY-SHA256",
- AttrPasswordAlgorithm: "PASSWORD-ALGORITHM",
- AttrUserhash: "USERHASH",
- AttrPasswordAlgorithms: "PASSWORD-ALGORITHMS",
- AttrAlternateDomain: "ALTERNATE-DOMAIN",
- }
- }
- func (t AttrType) String() string {
- s, ok := attrNames()[t]
- if !ok {
- // Just return hex representation of unknown attribute type.
- return fmt.Sprintf("0x%x", uint16(t))
- }
- return s
- }
- // RawAttribute is a Type-Length-Value (TLV) object that
- // can be added to a STUN message. Attributes are divided into two
- // types: comprehension-required and comprehension-optional. STUN
- // agents can safely ignore comprehension-optional attributes they
- // don't understand, but cannot successfully process a message if it
- // contains comprehension-required attributes that are not
- // understood.
- type RawAttribute struct {
- Type AttrType
- Length uint16 // ignored while encoding
- Value []byte
- }
- // AddTo implements Setter, adding attribute as a.Type with a.Value and ignoring
- // the Length field.
- func (a RawAttribute) AddTo(m *Message) error {
- m.Add(a.Type, a.Value)
- return nil
- }
- // Equal returns true if a == b.
- func (a RawAttribute) Equal(b RawAttribute) bool {
- if a.Type != b.Type {
- return false
- }
- if a.Length != b.Length {
- return false
- }
- if len(b.Value) != len(a.Value) {
- return false
- }
- for i, v := range a.Value {
- if b.Value[i] != v {
- return false
- }
- }
- return true
- }
- func (a RawAttribute) String() string {
- return fmt.Sprintf("%s: 0x%x", a.Type, a.Value)
- }
- // ErrAttributeNotFound means that attribute with provided attribute
- // type does not exist in message.
- var ErrAttributeNotFound = errors.New("attribute not found")
- // Get returns byte slice that represents attribute value,
- // if there is no attribute with such type,
- // ErrAttributeNotFound is returned.
- func (m *Message) Get(t AttrType) ([]byte, error) {
- v, ok := m.Attributes.Get(t)
- if !ok {
- return nil, ErrAttributeNotFound
- }
- return v.Value, nil
- }
- // STUN aligns attributes on 32-bit boundaries, attributes whose content
- // is not a multiple of 4 bytes are padded with 1, 2, or 3 bytes of
- // padding so that its value contains a multiple of 4 bytes. The
- // padding bits are ignored, and may be any value.
- //
- // https://tools.ietf.org/html/rfc5389#section-15
- const padding = 4
- func nearestPaddedValueLength(l int) int {
- n := padding * (l / padding)
- if n < l {
- n += padding
- }
- return n
- }
- // This method converts uint16 vlue to AttrType. If it finds an old attribute
- // type value, it also translates it to the new value to enable backward
- // compatibility. (See: https://github.com/pion/stun/issues/21)
- func compatAttrType(val uint16) AttrType {
- if val == 0x8020 { // draft-ietf-behave-rfc3489bis-02, MS-TURN
- return AttrXORMappedAddress // new: 0x0020 (from draft-ietf-behave-rfc3489bis-03 on)
- }
- return AttrType(val)
- }
|