This repository was archived by the owner on Aug 14, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathheaders.go
More file actions
234 lines (216 loc) · 6.96 KB
/
headers.go
File metadata and controls
234 lines (216 loc) · 6.96 KB
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
/*
Maxime Piraux's master's thesis
Copyright (C) 2017-2018 Maxime Piraux
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License version 3
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package masterthesis
import (
"bytes"
"encoding/binary"
"fmt"
. "github.com/mpiraux/master-thesis/lib"
)
type Header interface {
PacketType() PacketType
DestinationConnectionID() ConnectionID
PacketNumber() uint32
EncryptionLevel() EncryptionLevel
Encode() []byte
Length() int
}
func ReadHeader(buffer *bytes.Reader, conn *Connection) Header {
var h Header
typeByte, _ := buffer.ReadByte()
buffer.UnreadByte()
if typeByte & 0x80 == 0x80 {
h = ReadLongHeader(buffer)
} else {
h = ReadShortHeader(buffer, conn)
}
return h
}
type LongHeader struct {
packetType PacketType
Version uint32
DestinationCID ConnectionID
SourceCID ConnectionID
PayloadLength uint64
Token []byte
packetNumber uint32
LengthBeforePN int
length int
}
func (h *LongHeader) Encode() []byte {
buffer := new(bytes.Buffer)
typeByte := uint8(0x80)
typeByte |= uint8(h.packetType)
binary.Write(buffer, binary.BigEndian, typeByte)
binary.Write(buffer, binary.BigEndian, h.Version)
buffer.WriteByte((h.DestinationCID.CIDL() << 4) | h.SourceCID.CIDL())
binary.Write(buffer, binary.BigEndian, h.DestinationCID)
binary.Write(buffer, binary.BigEndian, h.SourceCID)
if h.packetType == Initial {
WriteVarInt(buffer, uint64(len(h.Token)))
buffer.Write(h.Token)
}
WriteVarInt(buffer, h.PayloadLength)
buffer.Write(EncodePacketNumber(h.packetNumber))
return buffer.Bytes()
}
func (h *LongHeader) PacketType() PacketType { return h.packetType }
func (h *LongHeader) DestinationConnectionID() ConnectionID { return h.DestinationCID }
func (h *LongHeader) PacketNumber() uint32 { return h.packetNumber }
func (h *LongHeader) EncryptionLevel() EncryptionLevel { return packetTypeToEncryptionLevel[h.PacketType()] }
func (h *LongHeader) Length() int { return h.length }
func ReadLongHeader(buffer *bytes.Reader) *LongHeader {
h := new(LongHeader)
h.length = buffer.Len()
h.LengthBeforePN = buffer.Len()
typeByte, _ := buffer.ReadByte()
h.packetType = PacketType(typeByte - 0x80)
binary.Read(buffer, binary.BigEndian, &h.Version)
CIDL, _ := buffer.ReadByte()
DCIL := 3 + ((CIDL & 0xf0) >> 4)
SCIL := 3 + (CIDL & 0xf)
h.DestinationCID = make([]byte, DCIL, DCIL)
binary.Read(buffer, binary.BigEndian, &h.DestinationCID)
h.SourceCID = make([]byte, SCIL, SCIL)
binary.Read(buffer, binary.BigEndian, &h.SourceCID)
if h.packetType == Initial {
tokenLength, _ := ReadVarInt(buffer)
h.Token = make([]byte, tokenLength)
buffer.Read(h.Token)
}
h.PayloadLength, _ = ReadVarInt(buffer)
h.LengthBeforePN -= buffer.Len()
h.packetNumber = DecodePacketNumber(buffer)
h.length -= buffer.Len()
return h
}
func NewLongHeader(packetType PacketType, conn *Connection, space PNSpace) *LongHeader {
h := new(LongHeader)
h.packetType = packetType
h.SourceCID = conn.SourceCID
if packetType == ZeroRTTProtected {
h.DestinationCID = conn.OriginalDestinationCID
} else {
h.DestinationCID = conn.DestinationCID
}
h.packetNumber = uint32(conn.nextPacketNumber(space))
h.Version = conn.Version
return h
}
type PacketType uint8
const (
Initial PacketType = 0x7f
Retry PacketType = 0x7e
Handshake PacketType = 0x7d
ZeroRTTProtected PacketType = 0x7c
ShortHeaderPacket PacketType = 0 // TODO: Find a way around this
)
var packetTypeToString = map[PacketType]string{
Initial: "Initial",
Retry: "Retry",
Handshake: "Handshake",
ZeroRTTProtected: "0-RTT Protected",
ShortHeaderPacket: "1-RTT Protected",
}
func (t PacketType) String() string {
return packetTypeToString[t]
}
type ShortHeader struct {
KeyPhase KeyPhaseBit
DestinationCID ConnectionID
packetNumber uint32
length int
}
func (h *ShortHeader) Encode() []byte {
buffer := new(bytes.Buffer)
var typeByte uint8
if h.KeyPhase == KeyPhaseOne {
typeByte |= 0x40
}
typeByte |= 0x30
binary.Write(buffer, binary.BigEndian, typeByte)
binary.Write(buffer, binary.BigEndian, h.DestinationCID)
buffer.Write(EncodePacketNumber(h.packetNumber))
return buffer.Bytes()
}
func (h *ShortHeader) PacketType() PacketType { return ShortHeaderPacket }
func (h *ShortHeader) DestinationConnectionID() ConnectionID { return h.DestinationCID }
func (h *ShortHeader) PacketNumber() uint32 { return h.packetNumber }
func (h *ShortHeader) EncryptionLevel() EncryptionLevel { return packetTypeToEncryptionLevel[h.PacketType()] }
func (h *ShortHeader) Length() int { return h.length }
func ReadShortHeader(buffer *bytes.Reader, conn *Connection) *ShortHeader {
h := new(ShortHeader)
h.length = buffer.Len()
typeByte, _ := buffer.ReadByte()
h.KeyPhase = (typeByte & 0x40) == 0x40
if typeByte & 0x38 != 0x30 {
fmt.Printf("SH fixed bits not respected: expected %b, got %b\n", 0x30, typeByte & 0x38)
}
h.DestinationCID = make([]byte, len(conn.SourceCID), len(conn.SourceCID))
buffer.Read(h.DestinationCID)
h.packetNumber = DecodePacketNumber(buffer)
h.length -= buffer.Len()
return h
}
func NewShortHeader(keyPhase KeyPhaseBit, conn *Connection) *ShortHeader {
h := new(ShortHeader)
h.KeyPhase = keyPhase
h.DestinationCID = conn.DestinationCID
h.packetNumber = uint32(conn.nextPacketNumber(PNSpaceAppData))
return h
}
type KeyPhaseBit bool
const KeyPhaseZero KeyPhaseBit = false
const KeyPhaseOne KeyPhaseBit = true
func EncodePacketNumber(packetNumber uint32) []byte {
if packetNumber <= 0x7f {
return []byte{byte(packetNumber)}
} else if packetNumber <= 0x3fff {
return Uint16ToBEBytes(uint16(0x8000 | packetNumber))
} else if packetNumber <= 0x3fffffff {
return Uint32ToBEBytes(uint32(0xc0000000 | packetNumber))
} else {
panic("Could not encode packet number")
}
}
func DecodePacketNumber(buffer *bytes.Reader) uint32 {
firstByte, _ := buffer.ReadByte()
if firstByte & 0x80 == 0 {
return uint32(firstByte)
} else if firstByte & 0xc0 == 0x80 {
twoBytes := make([]byte, 2)
buffer.UnreadByte()
buffer.Read(twoBytes)
return uint32(0x3fff & binary.BigEndian.Uint16(twoBytes))
} else if firstByte & 0xc0 == 0xc0 {
fourBytes := make([]byte, 4)
buffer.UnreadByte()
buffer.Read(fourBytes)
return uint32(0x3fffffff & binary.BigEndian.Uint32(fourBytes))
} else {
panic("Could not decode packet number")
}
}
func PacketNumberLen(packetNumber uint32) int {
switch {
case packetNumber <= 0x7f:
return 1
case packetNumber <= 0x3fff:
return 2
case packetNumber <= 0x3fffffff:
return 4
default:
panic("could not determine packet number length")
}
}