-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathaddress.go
91 lines (80 loc) · 2.03 KB
/
address.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
package stun
import (
"encoding/binary"
"net"
)
const (
iPv4Family = 0x01
iPv6Family = 0x02
)
func family(n int) uint8 {
switch n {
case net.IPv4len:
return iPv4Family
case net.IPv6len:
return iPv6Family
default:
return 0x00
}
}
type Address struct {
net.IP
Port uint16
buf [net.IPv6len]byte
}
func attrAddressFamily(attr []byte) byte { return attr[1] }
func (a *Address) Unmarshal(raw []byte, attrType attr, attrValue []byte) error {
if len(attrValue) < 4+net.IPv4len {
return ErrUnexpectedEOF
}
n := net.IPv4len
if f := attrAddressFamily(attrValue); f == iPv6Family {
n = net.IPv6len
} else if f != iPv4Family {
return ErrUnknownIPFamily
}
if len(attrValue) != 4+n {
return ErrUnexpectedEOF
}
if attributeSize(attrValue) != n {
return ErrMalformedAttribute
}
a.IP = a.buf[:n] // make([]byte, n)
copy(a.IP, attrValue[4:])
a.Port = binary.BigEndian.Uint16(attrValue[2:4])
switch attrType {
case attrXorMappedAddress:
for i, x := range raw[4 : 4+n] { // raw[4:4+n] spans magiccookie and transaction id if needed
a.IP[i] ^= x
}
a.Port ^= magicCookiePort
return nil
case attrMappedAddress, attrAlternateServer:
return nil
}
return ErrUnknownAddressAttribute
}
func appendAddress(m []byte, a attr, ip net.IP, port uint16) []byte {
n := len(ip)
m = append(m, byte(a>>8), byte(a),
0, byte(4+n), 0, family(n), byte(port>>8), byte(port))
return append(m, ip...)
}
func appendMappedAddress(m []byte, ip net.IP, port uint16) []byte {
return appendAddress(m, attrMappedAddress, ip, port)
}
func appendXorMappedAddress(m []byte, ip net.IP, port uint16) []byte {
port ^= magicCookiePort
n := len(ip)
m = append(m, byte(attrXorMappedAddress>>8), byte(attrXorMappedAddress),
0, byte(4+n), 0, family(n), byte(port>>8), byte(port))
m = append(m, m[4:4+n]...) // m[4:4+n] spans magiccookie and transaction id if needed
s := m[len(m)-n:]
for i, x := range ip {
s[i] ^= x
}
return m
}
func appendAlternateServer(m []byte, ip net.IP, port uint16) []byte {
return appendAddress(m, attrAlternateServer, ip, port)
}