forked from quic-go/quic-go
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpacket_unpacker.go
130 lines (119 loc) · 4.2 KB
/
packet_unpacker.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
package quic
import (
"bytes"
"fmt"
"github.com/lucas-clemente/quic-go/internal/protocol"
"github.com/lucas-clemente/quic-go/internal/wire"
"github.com/lucas-clemente/quic-go/qerr"
)
type unpackedPacket struct {
encryptionLevel protocol.EncryptionLevel
frames []wire.Frame
}
type quicAEAD interface {
Open(dst, src []byte, packetNumber protocol.PacketNumber, associatedData []byte) ([]byte, protocol.EncryptionLevel, error)
}
type packetUnpacker struct {
version protocol.VersionNumber
aead quicAEAD
}
func (u *packetUnpacker) Unpack(headerBinary []byte, hdr *wire.Header, data []byte) (*unpackedPacket, error) {
buf := getPacketBuffer()
defer putPacketBuffer(buf)
decrypted, encryptionLevel, err := u.aead.Open(buf, data, hdr.PacketNumber, headerBinary)
if err != nil {
// Wrap err in quicError so that public reset is sent by session
return nil, qerr.Error(qerr.DecryptionFailure, err.Error())
}
r := bytes.NewReader(decrypted)
if r.Len() == 0 {
return nil, qerr.MissingPayload
}
fs := make([]wire.Frame, 0, 2)
// Read all frames in the packet
for r.Len() > 0 {
typeByte, _ := r.ReadByte()
if typeByte == 0x0 { // PADDING frame
continue
}
r.UnreadByte()
var frame wire.Frame
if typeByte&0x80 == 0x80 {
frame, err = wire.ParseStreamFrame(r, u.version)
if err != nil {
err = qerr.Error(qerr.InvalidStreamData, err.Error())
} else {
streamID := frame.(*wire.StreamFrame).StreamID
if streamID != u.version.CryptoStreamID() && encryptionLevel <= protocol.EncryptionUnencrypted {
err = qerr.Error(qerr.UnencryptedStreamData, fmt.Sprintf("received unencrypted stream data on stream %d", streamID))
}
}
} else if typeByte&0xc0 == 0x40 {
frame, err = wire.ParseAckFrame(r, u.version)
if err != nil {
err = qerr.Error(qerr.InvalidAckData, err.Error())
}
} else if typeByte == 0x01 {
frame, err = wire.ParseRstStreamFrame(r, u.version)
if err != nil {
err = qerr.Error(qerr.InvalidRstStreamData, err.Error())
}
} else if typeByte == 0x02 {
frame, err = wire.ParseConnectionCloseFrame(r, u.version)
if err != nil {
err = qerr.Error(qerr.InvalidConnectionCloseData, err.Error())
}
} else if typeByte == 0x3 {
frame, err = wire.ParseGoawayFrame(r, u.version)
if err != nil {
err = qerr.Error(qerr.InvalidGoawayData, err.Error())
}
} else if u.version.UsesMaxDataFrame() && typeByte == 0x4 { // in IETF QUIC, 0x4 is a MAX_DATA frame
frame, err = wire.ParseMaxDataFrame(r, u.version)
if err != nil {
err = qerr.Error(qerr.InvalidWindowUpdateData, err.Error())
}
} else if typeByte == 0x4 { // in gQUIC, 0x4 is a WINDOW_UPDATE frame
frame, err = wire.ParseWindowUpdateFrame(r, u.version)
if err != nil {
err = qerr.Error(qerr.InvalidWindowUpdateData, err.Error())
}
} else if u.version.UsesMaxDataFrame() && typeByte == 0x5 { // in IETF QUIC, 0x5 is a MAX_STREAM_DATA frame
frame, err = wire.ParseMaxStreamDataFrame(r, u.version)
if err != nil {
err = qerr.Error(qerr.InvalidWindowUpdateData, err.Error())
}
} else if typeByte == 0x5 { // in gQUIC, 0x5 is a BLOCKED frame
frame, err = wire.ParseBlockedFrameLegacy(r, u.version)
if err != nil {
err = qerr.Error(qerr.InvalidBlockedData, err.Error())
}
} else if typeByte == 0x6 {
frame, err = wire.ParseStopWaitingFrame(r, hdr.PacketNumber, hdr.PacketNumberLen, u.version)
if err != nil {
err = qerr.Error(qerr.InvalidStopWaitingData, err.Error())
}
} else if typeByte == 0x7 {
frame, err = wire.ParsePingFrame(r, u.version)
} else if u.version.UsesMaxDataFrame() && typeByte == 0x8 { // in IETF QUIC, 0x4 is a BLOCKED frame
frame, err = wire.ParseBlockedFrame(r, u.version)
} else if u.version.UsesMaxDataFrame() && typeByte == 0x9 { // in IETF QUIC, 0x4 is a STREAM_BLOCKED frame
frame, err = wire.ParseBlockedFrameLegacy(r, u.version)
if err != nil {
err = qerr.Error(qerr.InvalidBlockedData, err.Error())
}
} else {
err = qerr.Error(qerr.InvalidFrameData, fmt.Sprintf("unknown type byte 0x%x", typeByte))
}
if err != nil {
return nil, err
}
if frame != nil {
fs = append(fs, frame)
}
}
return &unpackedPacket{
encryptionLevel: encryptionLevel,
frames: fs,
}, nil
}