Skip to content

Commit f8fd7be

Browse files
committed
added benchmarks, fingerprinting, optimized speed and allocations
1 parent 51c699d commit f8fd7be

File tree

3 files changed

+313
-33
lines changed

3 files changed

+313
-33
lines changed

stunlib.go

Lines changed: 52 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// Package stunlib provides an api for parsing and genrating stun packets
12
package stunlib // import "github.com/lwahlmeier/stunlib"
23

34
import (
@@ -59,31 +60,38 @@ type TransactionID struct {
5960
tid []byte
6061
}
6162

63+
//NewTID will create a new TransactionID from the provided []byte
64+
//The []byte must be only 12 bytes
6265
func NewTID(ba []byte) (*TransactionID, error) {
6366
if len(ba) != 12 {
6467
return nil, errors.New("Invalid TransactionID!")
6568
}
6669
return &TransactionID{tid: ba}, nil
6770
}
6871

72+
//CreateTID will create a new Random TransactionID
6973
func CreateTID() *TransactionID {
7074
ba := make([]byte, 12)
7175
rand.Read(ba)
7276
return &TransactionID{tid: ba}
7377
}
7478

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)
7782
}
7883

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)
8187
}
8288

89+
//GetTID provides this TransactionIDs []byte
8390
func (tid *TransactionID) GetTID() []byte {
8491
return tid.tid
8592
}
8693

94+
//This prints the TransactionID as a HexString
8795
func (tid *TransactionID) String() string {
8896
return fmt.Sprintf("%X", tid.tid)
8997
}
@@ -92,17 +100,20 @@ type StunPacket struct {
92100
buffer []byte
93101
}
94102

103+
//NewStunPacket create a new StunPacket from the provided []byte
95104
func NewStunPacket(b []byte) (*StunPacket, error) {
96105
if !IsStunPacket(b) {
97106
return nil, errors.New("Not a valid stun packet!")
98107
}
99108
return &StunPacket{buffer: b}, nil
100109
}
101110

111+
//GetStunMessageType will return the current StunMessage for this StunPacket
102112
func (sp *StunPacket) GetStunMessageType() StunMessage {
103113
return StunMessage(binary.BigEndian.Uint16(sp.buffer[:2]))
104114
}
105115

116+
//GetAllAttributes will return all the StunAttributes in this StunPacket as an Array
106117
func (sp *StunPacket) GetAllAttributes() []StunAttribute {
107118
sas := make([]StunAttribute, 0)
108119
pos := 20
@@ -115,6 +126,7 @@ func (sp *StunPacket) GetAllAttributes() []StunAttribute {
115126
return sas
116127
}
117128

129+
//GetAttribute returns the []byte for a given StunAttribute
118130
func (sp *StunPacket) GetAttribute(sa StunAttribute) []byte {
119131
pos := 20
120132
for pos < len(sp.buffer) {
@@ -128,14 +140,17 @@ func (sp *StunPacket) GetAttribute(sa StunAttribute) []byte {
128140
return nil
129141
}
130142

143+
//GetTxID returns the TransactionID for this StunPacket
131144
func (sp *StunPacket) GetTxID() *TransactionID {
132145
return &TransactionID{tid: sp.buffer[8:20]}
133146
}
134147

148+
//ToBuilder creates a StunPacketBuilder with this StunPackets Data as the base
135149
func (sp *StunPacket) ToBuilder() *StunPacketBuilder {
136150
return fromStunPacket(sp)
137151
}
138152

153+
//HasAddress returns true if this StunPacket has a MappedAddress of any kind.
139154
func (sp *StunPacket) HasAddress() bool {
140155
sas := sp.GetAllAttributes()
141156
for _, sa := range sas {
@@ -147,33 +162,39 @@ func (sp *StunPacket) HasAddress() bool {
147162
return false
148163
}
149164

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
150177
func (sp *StunPacket) GetBytes() []byte {
151178
return sp.buffer
152179
}
153180

181+
//GetAddress returns the MappedAddress or XORMappedAddress in this StunPacket if its exits
154182
func (sp *StunPacket) GetAddress() (*net.UDPAddr, error) {
155183
var ip net.IP
156184
var port uint16
157-
ipv6 := false
158185
sas := sp.GetAttribute(SAMappedAddress)
159186
if len(sas) == 0 {
160187
sas = sp.GetAttribute(SAXORMappedAddress)
161188
if len(sas) == 0 {
162189
return nil, errors.New("MappedAddress Not found!")
163190
}
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
168192
} else {
169193
ip = net.IP(sas[4:])
170194
port = (binary.BigEndian.Uint16(sas[2:4]))
171-
ipv6 = sas[1] == 2
172-
}
173-
if ipv6 {
174195
return &net.UDPAddr{IP: ip, Port: int(port)}, nil
175196
}
176-
return &net.UDPAddr{IP: ip, Port: int(port)}, nil
197+
177198
}
178199

179200
type StunPacketBuilder struct {
@@ -255,18 +276,10 @@ func (spb *StunPacketBuilder) SetXORAddress(ua *net.UDPAddr) *StunPacketBuilder
255276
if ip == nil {
256277
ip = ua.IP
257278
}
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()
266281
}
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))
270283
return spb
271284
}
272285

@@ -276,12 +289,20 @@ func (spb *StunPacketBuilder) ClearAttributes() *StunPacketBuilder {
276289
return spb
277290
}
278291

292+
func (spb *StunPacketBuilder) AddFingerprint(fp bool) *StunPacketBuilder {
293+
spb.fingerprint = fp
294+
return spb
295+
}
296+
279297
func (spb *StunPacketBuilder) Build() *StunPacket {
280298
size := 20
281299
for _, v := range spb.attribsBuffer {
282300
size += len(v) + 4
283301
size = (size + 3) & ^3
284302
}
303+
if spb.fingerprint {
304+
size += 8
305+
}
285306
ba := make([]byte, size)
286307
binary.BigEndian.PutUint16(ba[:2], uint16(spb.mt))
287308
binary.BigEndian.PutUint16(ba[2:4], uint16(size-20))
@@ -305,6 +326,13 @@ func (spb *StunPacketBuilder) Build() *StunPacket {
305326
pos++
306327
}
307328
}
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+
}
308336
sp, _ := NewStunPacket(ba)
309337
return sp
310338
}

0 commit comments

Comments
 (0)