-
-
Notifications
You must be signed in to change notification settings - Fork 35
/
header.go
135 lines (121 loc) · 3.12 KB
/
header.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
package utp
import (
"encoding/binary"
"errors"
"fmt"
)
const (
extensionTypeSelectiveAck = 1
)
type extensionField struct {
Type byte
Bytes []byte
}
type header struct {
Type st
Version int
ConnID uint16
Timestamp uint32
TimestampDiff uint32
WndSize uint32
SeqNr uint16
AckNr uint16
Extensions []extensionField
}
func unmarshalExtensions(_type byte, b []byte) (n int, ef []extensionField, err error) {
for _type != 0 {
if _type != extensionTypeSelectiveAck {
// An extension type that is not known to us. Generally we're
// unmarshalling an packet that isn't actually uTP but we don't
// yet know for sure until we try to deliver it.
// logonce.Stderr.Printf("utp extension %d", _type)
}
if len(b) < 2 || len(b) < int(b[1])+2 {
err = fmt.Errorf("buffer ends prematurely: %x", b)
return
}
ef = append(ef, extensionField{
Type: _type,
Bytes: append([]byte(nil), b[2:int(b[1])+2]...),
})
_type = b[0]
n += 2 + int(b[1])
b = b[2+int(b[1]):]
}
return
}
var errInvalidHeader = errors.New("invalid header")
func (h *header) Unmarshal(b []byte) (n int, err error) {
h.Type = st(b[0] >> 4)
h.Version = int(b[0] & 0xf)
if h.Type > stMax || h.Version != 1 {
err = errInvalidHeader
return
}
n, h.Extensions, err = unmarshalExtensions(b[1], b[20:])
if err != nil {
return
}
h.ConnID = binary.BigEndian.Uint16(b[2:4])
h.Timestamp = binary.BigEndian.Uint32(b[4:8])
h.TimestampDiff = binary.BigEndian.Uint32(b[8:12])
h.WndSize = binary.BigEndian.Uint32(b[12:16])
h.SeqNr = binary.BigEndian.Uint16(b[16:18])
h.AckNr = binary.BigEndian.Uint16(b[18:20])
n += 20
return
}
func (h *header) Marshal(p []byte) (n int) {
n = 20 + func() (ret int) {
for _, ext := range h.Extensions {
ret += 2 + len(ext.Bytes)
}
return
}()
p = p[:n]
p[0] = byte(h.Type<<4 | 1)
binary.BigEndian.PutUint16(p[2:4], h.ConnID)
binary.BigEndian.PutUint32(p[4:8], h.Timestamp)
binary.BigEndian.PutUint32(p[8:12], h.TimestampDiff)
binary.BigEndian.PutUint32(p[12:16], h.WndSize)
binary.BigEndian.PutUint16(p[16:18], h.SeqNr)
binary.BigEndian.PutUint16(p[18:20], h.AckNr)
// Pointer to the last type field so the next extension can set it.
_type := &p[1]
// We're done with the basic header.
p = p[20:]
for _, ext := range h.Extensions {
*_type = ext.Type
// The next extension's type will go here.
_type = &p[0]
p[1] = uint8(len(ext.Bytes))
if int(p[1]) != copy(p[2:], ext.Bytes) {
panic("unexpected extension length")
}
p = p[2+len(ext.Bytes):]
}
*_type = 0
if len(p) != 0 {
panic("header length changed")
}
return
}
type selectiveAckBitmask struct {
Bytes []byte
}
func (me *selectiveAckBitmask) expandBytesForBit(index int) {
minLen := (3 + (index / 8) + 1) / 4 * 4
for len(me.Bytes) < minLen {
me.Bytes = append(me.Bytes, 0)
}
}
func (me *selectiveAckBitmask) NumBits() int {
return len(me.Bytes) * 8
}
func (me *selectiveAckBitmask) SetBit(index int) {
me.expandBytesForBit(index)
me.Bytes[index/8] |= 1 << uint(index%8)
}
func (me *selectiveAckBitmask) BitIsSet(index int) bool {
return me.Bytes[index/8]>>uint(index%8)&1 == 1
}