-
Notifications
You must be signed in to change notification settings - Fork 95
/
attributes.go
254 lines (225 loc) · 8.07 KB
/
attributes.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
// 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)
}