1
+ // Package stunlib provides an api for parsing and genrating stun packets
1
2
package stunlib // import "github.com/lwahlmeier/stunlib"
2
3
3
4
import (
@@ -59,31 +60,38 @@ type TransactionID struct {
59
60
tid []byte
60
61
}
61
62
63
+ //NewTID will create a new TransactionID from the provided []byte
64
+ //The []byte must be only 12 bytes
62
65
func NewTID (ba []byte ) (* TransactionID , error ) {
63
66
if len (ba ) != 12 {
64
67
return nil , errors .New ("Invalid TransactionID!" )
65
68
}
66
69
return & TransactionID {tid : ba }, nil
67
70
}
68
71
72
+ //CreateTID will create a new Random TransactionID
69
73
func CreateTID () * TransactionID {
70
74
ba := make ([]byte , 12 )
71
75
rand .Read (ba )
72
76
return & TransactionID {tid : ba }
73
77
}
74
78
75
- func (tid * TransactionID ) UnMaskAddress (addr []byte ) []byte {
76
- return UnmaskAddress (* tid , addr )
79
+ //UnMaskAddress uses this TransactionID to unmask an SAXORMappedAddress
80
+ func (tid * TransactionID ) UnMaskAddress (addr []byte ) * net.UDPAddr {
81
+ return UnMaskAddress (* tid , addr )
77
82
}
78
83
79
- func (tid * TransactionID ) MaskAddress (addr []byte ) []byte {
80
- return MaskAddress (* tid , addr )
84
+ //MaskAddress takes an net.UDPAddr and turns it into a SAXORMappedAddress []byte
85
+ func (tid * TransactionID ) MaskAddress (addr * net.UDPAddr ) []byte {
86
+ return CreateMaskedAddress (* tid , addr )
81
87
}
82
88
89
+ //GetTID provides this TransactionIDs []byte
83
90
func (tid * TransactionID ) GetTID () []byte {
84
91
return tid .tid
85
92
}
86
93
94
+ //This prints the TransactionID as a HexString
87
95
func (tid * TransactionID ) String () string {
88
96
return fmt .Sprintf ("%X" , tid .tid )
89
97
}
@@ -92,17 +100,20 @@ type StunPacket struct {
92
100
buffer []byte
93
101
}
94
102
103
+ //NewStunPacket create a new StunPacket from the provided []byte
95
104
func NewStunPacket (b []byte ) (* StunPacket , error ) {
96
105
if ! IsStunPacket (b ) {
97
106
return nil , errors .New ("Not a valid stun packet!" )
98
107
}
99
108
return & StunPacket {buffer : b }, nil
100
109
}
101
110
111
+ //GetStunMessageType will return the current StunMessage for this StunPacket
102
112
func (sp * StunPacket ) GetStunMessageType () StunMessage {
103
113
return StunMessage (binary .BigEndian .Uint16 (sp .buffer [:2 ]))
104
114
}
105
115
116
+ //GetAllAttributes will return all the StunAttributes in this StunPacket as an Array
106
117
func (sp * StunPacket ) GetAllAttributes () []StunAttribute {
107
118
sas := make ([]StunAttribute , 0 )
108
119
pos := 20
@@ -115,6 +126,7 @@ func (sp *StunPacket) GetAllAttributes() []StunAttribute {
115
126
return sas
116
127
}
117
128
129
+ //GetAttribute returns the []byte for a given StunAttribute
118
130
func (sp * StunPacket ) GetAttribute (sa StunAttribute ) []byte {
119
131
pos := 20
120
132
for pos < len (sp .buffer ) {
@@ -128,14 +140,17 @@ func (sp *StunPacket) GetAttribute(sa StunAttribute) []byte {
128
140
return nil
129
141
}
130
142
143
+ //GetTxID returns the TransactionID for this StunPacket
131
144
func (sp * StunPacket ) GetTxID () * TransactionID {
132
145
return & TransactionID {tid : sp .buffer [8 :20 ]}
133
146
}
134
147
148
+ //ToBuilder creates a StunPacketBuilder with this StunPackets Data as the base
135
149
func (sp * StunPacket ) ToBuilder () * StunPacketBuilder {
136
150
return fromStunPacket (sp )
137
151
}
138
152
153
+ //HasAddress returns true if this StunPacket has a MappedAddress of any kind.
139
154
func (sp * StunPacket ) HasAddress () bool {
140
155
sas := sp .GetAllAttributes ()
141
156
for _ , sa := range sas {
@@ -147,33 +162,39 @@ func (sp *StunPacket) HasAddress() bool {
147
162
return false
148
163
}
149
164
165
+ func (sp * StunPacket ) HasFingerPrint () bool {
166
+ sas := sp .GetAllAttributes ()
167
+ for _ , sa := range sas {
168
+ sab := StunAttribute (sa )
169
+ if sab == SAFingerPrint {
170
+ return true
171
+ }
172
+ }
173
+ return false
174
+ }
175
+
176
+ //GetBytes gets the underliying []byte for this StunPacket
150
177
func (sp * StunPacket ) GetBytes () []byte {
151
178
return sp .buffer
152
179
}
153
180
181
+ //GetAddress returns the MappedAddress or XORMappedAddress in this StunPacket if its exits
154
182
func (sp * StunPacket ) GetAddress () (* net.UDPAddr , error ) {
155
183
var ip net.IP
156
184
var port uint16
157
- ipv6 := false
158
185
sas := sp .GetAttribute (SAMappedAddress )
159
186
if len (sas ) == 0 {
160
187
sas = sp .GetAttribute (SAXORMappedAddress )
161
188
if len (sas ) == 0 {
162
189
return nil , errors .New ("MappedAddress Not found!" )
163
190
}
164
- ip = net .IP (sp .GetTxID ().UnMaskAddress (sas [4 :]))
165
-
166
- port = (binary .BigEndian .Uint16 (sas [2 :4 ]) ^ stunShortMagic )
167
- ipv6 = sas [1 ] == 2
191
+ return UnMaskAddress (* sp .GetTxID (), sas ), nil
168
192
} else {
169
193
ip = net .IP (sas [4 :])
170
194
port = (binary .BigEndian .Uint16 (sas [2 :4 ]))
171
- ipv6 = sas [1 ] == 2
172
- }
173
- if ipv6 {
174
195
return & net.UDPAddr {IP : ip , Port : int (port )}, nil
175
196
}
176
- return & net. UDPAddr { IP : ip , Port : int ( port )}, nil
197
+
177
198
}
178
199
179
200
type StunPacketBuilder struct {
@@ -255,18 +276,10 @@ func (spb *StunPacketBuilder) SetXORAddress(ua *net.UDPAddr) *StunPacketBuilder
255
276
if ip == nil {
256
277
ip = ua .IP
257
278
}
258
- aba := spb .tid .MaskAddress ([]byte (ip ))
259
- var saba []byte
260
- if len (aba ) == 4 {
261
- saba = make ([]byte , 8 )
262
- saba [1 ] = 1
263
- } else {
264
- saba = make ([]byte , 20 )
265
- saba [1 ] = 1
279
+ if spb .tid == nil {
280
+ spb .tid = CreateTID ()
266
281
}
267
- binary .BigEndian .PutUint16 (saba [2 :4 ], uint16 (ua .Port )^ stunShortMagic )
268
- copy (saba [4 :], aba )
269
- spb .SetAttribue (SAXORMappedAddress , saba )
282
+ spb .SetAttribue (SAXORMappedAddress , CreateMaskedAddress (* spb .tid , ua ))
270
283
return spb
271
284
}
272
285
@@ -276,12 +289,20 @@ func (spb *StunPacketBuilder) ClearAttributes() *StunPacketBuilder {
276
289
return spb
277
290
}
278
291
292
+ func (spb * StunPacketBuilder ) AddFingerprint (fp bool ) * StunPacketBuilder {
293
+ spb .fingerprint = fp
294
+ return spb
295
+ }
296
+
279
297
func (spb * StunPacketBuilder ) Build () * StunPacket {
280
298
size := 20
281
299
for _ , v := range spb .attribsBuffer {
282
300
size += len (v ) + 4
283
301
size = (size + 3 ) & ^ 3
284
302
}
303
+ if spb .fingerprint {
304
+ size += 8
305
+ }
285
306
ba := make ([]byte , size )
286
307
binary .BigEndian .PutUint16 (ba [:2 ], uint16 (spb .mt ))
287
308
binary .BigEndian .PutUint16 (ba [2 :4 ], uint16 (size - 20 ))
@@ -305,6 +326,13 @@ func (spb *StunPacketBuilder) Build() *StunPacket {
305
326
pos ++
306
327
}
307
328
}
329
+ if spb .fingerprint {
330
+ fps := size - 8
331
+ fp := CreateStunFingerPrint (ba [:fps ])
332
+ binary .BigEndian .PutUint16 (ba [fps :fps + 2 ], uint16 (SAFingerPrint ))
333
+ binary .BigEndian .PutUint16 (ba [fps + 2 :fps + 4 ], uint16 (4 ))
334
+ binary .BigEndian .PutUint32 (ba [fps + 4 :fps + 8 ], fp )
335
+ }
308
336
sp , _ := NewStunPacket (ba )
309
337
return sp
310
338
}
0 commit comments