package stun
import (
"errors"
"fmt"
)
type Attributes []RawAttribute
func (a Attributes ) Get (t AttrType ) (RawAttribute , bool ) {
for _ , candidate := range a {
if candidate .Type == t {
return candidate , true
}
}
return RawAttribute {}, false
}
type AttrType uint16
func (t AttrType ) Required () bool {
return t <= 0x7FFF
}
func (t AttrType ) Optional () bool {
return t >= 0x8000
}
const (
AttrMappedAddress AttrType = 0x0001
AttrUsername AttrType = 0x0006
AttrMessageIntegrity AttrType = 0x0008
AttrErrorCode AttrType = 0x0009
AttrUnknownAttributes AttrType = 0x000A
AttrRealm AttrType = 0x0014
AttrNonce AttrType = 0x0015
AttrXORMappedAddress AttrType = 0x0020
)
const (
AttrSoftware AttrType = 0x8022
AttrAlternateServer AttrType = 0x8023
AttrFingerprint AttrType = 0x8028
)
const (
AttrPriority AttrType = 0x0024
AttrUseCandidate AttrType = 0x0025
AttrICEControlled AttrType = 0x8029
AttrICEControlling AttrType = 0x802A
)
const (
AttrChannelNumber AttrType = 0x000C
AttrLifetime AttrType = 0x000D
AttrXORPeerAddress AttrType = 0x0012
AttrData AttrType = 0x0013
AttrXORRelayedAddress AttrType = 0x0016
AttrEvenPort AttrType = 0x0018
AttrRequestedTransport AttrType = 0x0019
AttrDontFragment AttrType = 0x001A
AttrReservationToken AttrType = 0x0022
)
const (
AttrChangeRequest AttrType = 0x0003
AttrPadding AttrType = 0x0026
AttrResponsePort AttrType = 0x0027
AttrCacheTimeout AttrType = 0x8027
AttrResponseOrigin AttrType = 0x802b
AttrOtherAddress AttrType = 0x802C
)
const (
AttrSourceAddress AttrType = 0x0004
AttrChangedAddress AttrType = 0x0005
)
const (
AttrConnectionID AttrType = 0x002a
)
const (
AttrRequestedAddressFamily AttrType = 0x0017
)
const (
AttrOrigin AttrType = 0x802F
)
const (
AttrMessageIntegritySHA256 AttrType = 0x001C
AttrPasswordAlgorithm AttrType = 0x001D
AttrUserhash AttrType = 0x001E
AttrPasswordAlgorithms AttrType = 0x8002
AttrAlternateDomain AttrType = 0x8003
)
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 {
return fmt .Sprintf ("0x%x" , uint16 (t ))
}
return s
}
type RawAttribute struct {
Type AttrType
Length uint16
Value []byte
}
func (a RawAttribute ) AddTo (m *Message ) error {
m .Add (a .Type , a .Value )
return nil
}
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 )
}
var ErrAttributeNotFound = errors .New ("attribute not found" )
func (m *Message ) Get (t AttrType ) ([]byte , error ) {
v , ok := m .Attributes .Get (t )
if !ok {
return nil , ErrAttributeNotFound
}
return v .Value , nil
}
const padding = 4
func nearestPaddedValueLength(l int ) int {
n := padding * (l / padding )
if n < l {
n += padding
}
return n
}
func compatAttrType(val uint16 ) AttrType {
if val == 0x8020 {
return AttrXORMappedAddress
}
return AttrType (val )
}
The pages are generated with Golds v0.8.2 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .