-
Notifications
You must be signed in to change notification settings - Fork 1.1k
/
conn_recv.go
337 lines (317 loc) · 10.3 KB
/
conn_recv.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
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
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
// Copyright 2023 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build go1.21
package quic
import (
"time"
)
func (c *Conn) handleDatagram(now time.Time, dgram *datagram) {
buf := dgram.b
c.loss.datagramReceived(now, len(buf))
for len(buf) > 0 {
var n int
ptype := getPacketType(buf)
switch ptype {
case packetTypeInitial:
if c.side == serverSide && len(dgram.b) < minimumClientInitialDatagramSize {
// Discard client-sent Initial packets in too-short datagrams.
// https://www.rfc-editor.org/rfc/rfc9000#section-14.1-4
return
}
n = c.handleLongHeader(now, ptype, initialSpace, buf)
case packetTypeHandshake:
n = c.handleLongHeader(now, ptype, handshakeSpace, buf)
case packetType1RTT:
n = c.handle1RTT(now, buf)
default:
return
}
if n <= 0 {
// Invalid data at the end of a datagram is ignored.
break
}
c.idleTimeout = now.Add(c.maxIdleTimeout)
buf = buf[n:]
}
}
func (c *Conn) handleLongHeader(now time.Time, ptype packetType, space numberSpace, buf []byte) int {
if !c.rkeys[space].isSet() {
return skipLongHeaderPacket(buf)
}
pnumMax := c.acks[space].largestSeen()
p, n := parseLongHeaderPacket(buf, c.rkeys[space], pnumMax)
if n < 0 {
return -1
}
if p.reservedBits != 0 {
// https://www.rfc-editor.org/rfc/rfc9000#section-17.2-8.2.1
c.abort(now, localTransportError(errProtocolViolation))
return -1
}
if !c.acks[space].shouldProcess(p.num) {
return n
}
if logPackets {
logInboundLongPacket(c, p)
}
c.connIDState.handlePacket(c.side, p.ptype, p.srcConnID)
ackEliciting := c.handleFrames(now, ptype, space, p.payload)
c.acks[space].receive(now, space, p.num, ackEliciting)
if p.ptype == packetTypeHandshake && c.side == serverSide {
c.loss.validateClientAddress()
// "[...] a server MUST discard Initial keys when it first successfully
// processes a Handshake packet [...]"
// https://www.rfc-editor.org/rfc/rfc9001#section-4.9.1-2
c.discardKeys(now, initialSpace)
}
return n
}
func (c *Conn) handle1RTT(now time.Time, buf []byte) int {
if !c.rkeys[appDataSpace].isSet() {
// 1-RTT packets extend to the end of the datagram,
// so skip the remainder of the datagram if we can't parse this.
return len(buf)
}
pnumMax := c.acks[appDataSpace].largestSeen()
p, n := parse1RTTPacket(buf, c.rkeys[appDataSpace], connIDLen, pnumMax)
if n < 0 {
return -1
}
if p.reservedBits != 0 {
// https://www.rfc-editor.org/rfc/rfc9000#section-17.3.1-4.8.1
c.abort(now, localTransportError(errProtocolViolation))
return -1
}
if !c.acks[appDataSpace].shouldProcess(p.num) {
return len(buf)
}
if logPackets {
logInboundShortPacket(c, p)
}
ackEliciting := c.handleFrames(now, packetType1RTT, appDataSpace, p.payload)
c.acks[appDataSpace].receive(now, appDataSpace, p.num, ackEliciting)
return len(buf)
}
func (c *Conn) handleFrames(now time.Time, ptype packetType, space numberSpace, payload []byte) (ackEliciting bool) {
if len(payload) == 0 {
// "An endpoint MUST treat receipt of a packet containing no frames
// as a connection error of type PROTOCOL_VIOLATION."
// https://www.rfc-editor.org/rfc/rfc9000#section-12.4-3
c.abort(now, localTransportError(errProtocolViolation))
return false
}
// frameOK verifies that ptype is one of the packets in mask.
frameOK := func(c *Conn, ptype, mask packetType) (ok bool) {
if ptype&mask == 0 {
// "An endpoint MUST treat receipt of a frame in a packet type
// that is not permitted as a connection error of type
// PROTOCOL_VIOLATION."
// https://www.rfc-editor.org/rfc/rfc9000#section-12.4-3
c.abort(now, localTransportError(errProtocolViolation))
return false
}
return true
}
// Packet masks from RFC 9000 Table 3.
// https://www.rfc-editor.org/rfc/rfc9000#table-3
const (
IH_1 = packetTypeInitial | packetTypeHandshake | packetType1RTT
__01 = packetType0RTT | packetType1RTT
___1 = packetType1RTT
)
for len(payload) > 0 {
switch payload[0] {
case frameTypePadding, frameTypeAck, frameTypeAckECN,
frameTypeConnectionCloseTransport, frameTypeConnectionCloseApplication:
default:
ackEliciting = true
}
n := -1
switch payload[0] {
case frameTypePadding:
// PADDING is OK in all spaces.
n = 1
case frameTypePing:
// PING is OK in all spaces.
//
// A PING frame causes us to respond with an ACK by virtue of being
// an ack-eliciting frame, but requires no other action.
n = 1
case frameTypeAck, frameTypeAckECN:
if !frameOK(c, ptype, IH_1) {
return
}
n = c.handleAckFrame(now, space, payload)
case frameTypeResetStream:
if !frameOK(c, ptype, __01) {
return
}
_, _, _, n = consumeResetStreamFrame(payload)
case frameTypeStopSending:
if !frameOK(c, ptype, __01) {
return
}
_, _, n = consumeStopSendingFrame(payload)
case frameTypeCrypto:
if !frameOK(c, ptype, IH_1) {
return
}
n = c.handleCryptoFrame(now, space, payload)
case frameTypeNewToken:
if !frameOK(c, ptype, ___1) {
return
}
_, n = consumeNewTokenFrame(payload)
case 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f: // STREAM
if !frameOK(c, ptype, __01) {
return
}
n = c.handleStreamFrame(now, space, payload)
case frameTypeMaxData:
if !frameOK(c, ptype, __01) {
return
}
_, n = consumeMaxDataFrame(payload)
case frameTypeMaxStreamData:
if !frameOK(c, ptype, __01) {
return
}
_, _, n = consumeMaxStreamDataFrame(payload)
case frameTypeMaxStreamsBidi, frameTypeMaxStreamsUni:
if !frameOK(c, ptype, __01) {
return
}
_, _, n = consumeMaxStreamsFrame(payload)
case frameTypeStreamsBlockedBidi, frameTypeStreamsBlockedUni:
if !frameOK(c, ptype, __01) {
return
}
_, _, n = consumeStreamsBlockedFrame(payload)
case frameTypeStreamDataBlocked:
if !frameOK(c, ptype, __01) {
return
}
_, _, n = consumeStreamDataBlockedFrame(payload)
case frameTypeNewConnectionID:
if !frameOK(c, ptype, __01) {
return
}
n = c.handleNewConnectionIDFrame(now, space, payload)
case frameTypeRetireConnectionID:
if !frameOK(c, ptype, __01) {
return
}
n = c.handleRetireConnectionIDFrame(now, space, payload)
case frameTypeConnectionCloseTransport:
// CONNECTION_CLOSE is OK in all spaces.
_, _, _, n = consumeConnectionCloseTransportFrame(payload)
// TODO: https://www.rfc-editor.org/rfc/rfc9000.html#section-10.2.2
c.abort(now, localTransportError(errNo))
case frameTypeConnectionCloseApplication:
// CONNECTION_CLOSE is OK in all spaces.
_, _, n = consumeConnectionCloseApplicationFrame(payload)
// TODO: https://www.rfc-editor.org/rfc/rfc9000.html#section-10.2.2
c.abort(now, localTransportError(errNo))
case frameTypeHandshakeDone:
if !frameOK(c, ptype, ___1) {
return
}
n = c.handleHandshakeDoneFrame(now, space, payload)
}
if n < 0 {
c.abort(now, localTransportError(errFrameEncoding))
return false
}
payload = payload[n:]
}
return ackEliciting
}
func (c *Conn) handleAckFrame(now time.Time, space numberSpace, payload []byte) int {
c.loss.receiveAckStart()
_, ackDelay, n := consumeAckFrame(payload, func(rangeIndex int, start, end packetNumber) {
if end > c.loss.nextNumber(space) {
// Acknowledgement of a packet we never sent.
c.abort(now, localTransportError(errProtocolViolation))
return
}
c.loss.receiveAckRange(now, space, rangeIndex, start, end, c.handleAckOrLoss)
})
// Prior to receiving the peer's transport parameters, we cannot
// interpret the ACK Delay field because we don't know the ack_delay_exponent
// to apply.
//
// For servers, we should always know the ack_delay_exponent because the
// client's transport parameters are carried in its Initial packets and we
// won't send an ack-eliciting Initial packet until after receiving the last
// client Initial packet.
//
// For clients, we won't receive the server's transport parameters until handling
// its Handshake flight, which will probably happen after reading its ACK for our
// Initial packet(s). However, the peer's acknowledgement delay cannot reduce our
// adjusted RTT sample below min_rtt, and min_rtt is generally going to be set
// by the packet containing the ACK for our Initial flight. Therefore, the
// ACK Delay for an ACK in the Initial space is likely to be ignored anyway.
//
// Long story short, setting the delay to 0 prior to reading transport parameters
// is usually going to have no effect, will have only a minor effect in the rare
// cases when it happens, and there aren't any good alternatives anyway since we
// can't interpret the ACK Delay field without knowing the exponent.
var delay time.Duration
if c.peerAckDelayExponent >= 0 {
delay = ackDelay.Duration(uint8(c.peerAckDelayExponent))
}
c.loss.receiveAckEnd(now, space, delay, c.handleAckOrLoss)
return n
}
func (c *Conn) handleCryptoFrame(now time.Time, space numberSpace, payload []byte) int {
off, data, n := consumeCryptoFrame(payload)
err := c.handleCrypto(now, space, off, data)
if err != nil {
c.abort(now, err)
return -1
}
return n
}
func (c *Conn) handleStreamFrame(now time.Time, space numberSpace, payload []byte) int {
id, off, fin, b, n := consumeStreamFrame(payload)
if n < 0 {
return -1
}
if s := c.streamForFrame(now, id, recvStream); s != nil {
if err := s.handleData(off, b, fin); err != nil {
c.abort(now, err)
}
}
return n
}
func (c *Conn) handleNewConnectionIDFrame(now time.Time, space numberSpace, payload []byte) int {
seq, retire, connID, resetToken, n := consumeNewConnectionIDFrame(payload)
if n < 0 {
return -1
}
if err := c.connIDState.handleNewConnID(seq, retire, connID, resetToken); err != nil {
c.abort(now, err)
}
return n
}
func (c *Conn) handleRetireConnectionIDFrame(now time.Time, space numberSpace, payload []byte) int {
seq, n := consumeRetireConnectionIDFrame(payload)
if n < 0 {
return -1
}
if err := c.connIDState.handleRetireConnID(seq, c.newConnIDFunc()); err != nil {
c.abort(now, err)
}
return n
}
func (c *Conn) handleHandshakeDoneFrame(now time.Time, space numberSpace, payload []byte) int {
if c.side == serverSide {
// Clients should never send HANDSHAKE_DONE.
// https://www.rfc-editor.org/rfc/rfc9000#section-19.20-4
c.abort(now, localTransportError(errProtocolViolation))
return -1
}
c.confirmHandshake(now)
return 1
}