1package stun 2 3import "errors" 4 5// UnknownAttributes represents UNKNOWN-ATTRIBUTES attribute. 6// 7// RFC 5389 Section 15.9 8type UnknownAttributes []AttrType 9 10func (a UnknownAttributes) String() string { 11 s := "" 12 if len(a) == 0 { 13 return "<nil>" 14 } 15 last := len(a) - 1 16 for i, t := range a { 17 s += t.String() 18 if i != last { 19 s += ", " 20 } 21 } 22 return s 23} 24 25// type size is 16 bit. 26const attrTypeSize = 4 27 28// AddTo adds UNKNOWN-ATTRIBUTES attribute to message. 29func (a UnknownAttributes) AddTo(m *Message) error { 30 v := make([]byte, 0, attrTypeSize*20) // 20 should be enough 31 // If len(a.Types) > 20, there will be allocations. 32 for i, t := range a { 33 v = append(v, 0, 0, 0, 0) // 4 times by 0 (16 bits) 34 first := attrTypeSize * i 35 last := first + attrTypeSize 36 bin.PutUint16(v[first:last], t.Value()) 37 } 38 m.Add(AttrUnknownAttributes, v) 39 return nil 40} 41 42// ErrBadUnknownAttrsSize means that UNKNOWN-ATTRIBUTES attribute value 43// has invalid length. 44var ErrBadUnknownAttrsSize = errors.New("bad UNKNOWN-ATTRIBUTES size") 45 46// GetFrom parses UNKNOWN-ATTRIBUTES from message. 47func (a *UnknownAttributes) GetFrom(m *Message) error { 48 v, err := m.Get(AttrUnknownAttributes) 49 if err != nil { 50 return err 51 } 52 if len(v)%attrTypeSize != 0 { 53 return ErrBadUnknownAttrsSize 54 } 55 *a = (*a)[:0] 56 first := 0 57 for first < len(v) { 58 last := first + attrTypeSize 59 *a = append(*a, AttrType(bin.Uint16(v[first:last]))) 60 first = last 61 } 62 return nil 63} 64