Skip to content

Commit 35e1007

Browse files
neildgopherbot
authored andcommitted
quic, internal/quic/quicwire: split wire encode/decode functions to new package
HTTP/3 also uses QUIC varints. Move the more general-purpose wire encoding/decoding functions into a new internal/quic/quicwire package so they can be shared. For golang/go#70914 Change-Id: Id888baf131e90a12247e15a6f7bc7dc37c6dc572 Reviewed-on: https://go-review.googlesource.com/c/net/+/641496 Auto-Submit: Damien Neil <[email protected]> Reviewed-by: Jonathan Amsterdam <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]>
1 parent 0a5dcdd commit 35e1007

13 files changed

+272
-250
lines changed

Diff for: quic/wire.go renamed to internal/quic/quicwire/wire.go

+27-25
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,22 @@
44

55
//go:build go1.21
66

7-
package quic
7+
// Package quicwire encodes and decode QUIC/HTTP3 wire encoding types,
8+
// particularly variable-length integers.
9+
package quicwire
810

911
import "encoding/binary"
1012

1113
const (
12-
maxVarintSize = 8 // encoded size in bytes
13-
maxVarint = (1 << 62) - 1
14+
MaxVarintSize = 8 // encoded size in bytes
15+
MaxVarint = (1 << 62) - 1
1416
)
1517

16-
// consumeVarint parses a variable-length integer, reporting its length.
18+
// ConsumeVarint parses a variable-length integer, reporting its length.
1719
// It returns a negative length upon an error.
1820
//
1921
// https://www.rfc-editor.org/rfc/rfc9000.html#section-16
20-
func consumeVarint(b []byte) (v uint64, n int) {
22+
func ConsumeVarint(b []byte) (v uint64, n int) {
2123
if len(b) < 1 {
2224
return 0, -1
2325
}
@@ -45,16 +47,16 @@ func consumeVarint(b []byte) (v uint64, n int) {
4547
}
4648

4749
// consumeVarintInt64 parses a variable-length integer as an int64.
48-
func consumeVarintInt64(b []byte) (v int64, n int) {
49-
u, n := consumeVarint(b)
50+
func ConsumeVarintInt64(b []byte) (v int64, n int) {
51+
u, n := ConsumeVarint(b)
5052
// QUIC varints are 62-bits large, so this conversion can never overflow.
5153
return int64(u), n
5254
}
5355

54-
// appendVarint appends a variable-length integer to b.
56+
// AppendVarint appends a variable-length integer to b.
5557
//
5658
// https://www.rfc-editor.org/rfc/rfc9000.html#section-16
57-
func appendVarint(b []byte, v uint64) []byte {
59+
func AppendVarint(b []byte, v uint64) []byte {
5860
switch {
5961
case v <= 63:
6062
return append(b, byte(v))
@@ -69,8 +71,8 @@ func appendVarint(b []byte, v uint64) []byte {
6971
}
7072
}
7173

72-
// sizeVarint returns the size of the variable-length integer encoding of f.
73-
func sizeVarint(v uint64) int {
74+
// SizeVarint returns the size of the variable-length integer encoding of f.
75+
func SizeVarint(v uint64) int {
7476
switch {
7577
case v <= 63:
7678
return 1
@@ -85,28 +87,28 @@ func sizeVarint(v uint64) int {
8587
}
8688
}
8789

88-
// consumeUint32 parses a 32-bit fixed-length, big-endian integer, reporting its length.
90+
// ConsumeUint32 parses a 32-bit fixed-length, big-endian integer, reporting its length.
8991
// It returns a negative length upon an error.
90-
func consumeUint32(b []byte) (uint32, int) {
92+
func ConsumeUint32(b []byte) (uint32, int) {
9193
if len(b) < 4 {
9294
return 0, -1
9395
}
9496
return binary.BigEndian.Uint32(b), 4
9597
}
9698

97-
// consumeUint64 parses a 64-bit fixed-length, big-endian integer, reporting its length.
99+
// ConsumeUint64 parses a 64-bit fixed-length, big-endian integer, reporting its length.
98100
// It returns a negative length upon an error.
99-
func consumeUint64(b []byte) (uint64, int) {
101+
func ConsumeUint64(b []byte) (uint64, int) {
100102
if len(b) < 8 {
101103
return 0, -1
102104
}
103105
return binary.BigEndian.Uint64(b), 8
104106
}
105107

106-
// consumeUint8Bytes parses a sequence of bytes prefixed with an 8-bit length,
108+
// ConsumeUint8Bytes parses a sequence of bytes prefixed with an 8-bit length,
107109
// reporting the total number of bytes consumed.
108110
// It returns a negative length upon an error.
109-
func consumeUint8Bytes(b []byte) ([]byte, int) {
111+
func ConsumeUint8Bytes(b []byte) ([]byte, int) {
110112
if len(b) < 1 {
111113
return nil, -1
112114
}
@@ -118,8 +120,8 @@ func consumeUint8Bytes(b []byte) ([]byte, int) {
118120
return b[n:][:size], size + n
119121
}
120122

121-
// appendUint8Bytes appends a sequence of bytes prefixed by an 8-bit length.
122-
func appendUint8Bytes(b, v []byte) []byte {
123+
// AppendUint8Bytes appends a sequence of bytes prefixed by an 8-bit length.
124+
func AppendUint8Bytes(b, v []byte) []byte {
123125
if len(v) > 0xff {
124126
panic("uint8-prefixed bytes too large")
125127
}
@@ -128,11 +130,11 @@ func appendUint8Bytes(b, v []byte) []byte {
128130
return b
129131
}
130132

131-
// consumeVarintBytes parses a sequence of bytes preceded by a variable-length integer length,
133+
// ConsumeVarintBytes parses a sequence of bytes preceded by a variable-length integer length,
132134
// reporting the total number of bytes consumed.
133135
// It returns a negative length upon an error.
134-
func consumeVarintBytes(b []byte) ([]byte, int) {
135-
size, n := consumeVarint(b)
136+
func ConsumeVarintBytes(b []byte) ([]byte, int) {
137+
size, n := ConsumeVarint(b)
136138
if n < 0 {
137139
return nil, -1
138140
}
@@ -142,9 +144,9 @@ func consumeVarintBytes(b []byte) ([]byte, int) {
142144
return b[n:][:size], int(size) + n
143145
}
144146

145-
// appendVarintBytes appends a sequence of bytes prefixed by a variable-length integer length.
146-
func appendVarintBytes(b, v []byte) []byte {
147-
b = appendVarint(b, uint64(len(v)))
147+
// AppendVarintBytes appends a sequence of bytes prefixed by a variable-length integer length.
148+
func AppendVarintBytes(b, v []byte) []byte {
149+
b = AppendVarint(b, uint64(len(v)))
148150
b = append(b, v...)
149151
return b
150152
}

Diff for: quic/wire_test.go renamed to internal/quic/quicwire/wire_test.go

+35-35
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
//go:build go1.21
66

7-
package quic
7+
package quicwire
88

99
import (
1010
"bytes"
@@ -32,22 +32,22 @@ func TestConsumeVarint(t *testing.T) {
3232
{[]byte{0x25}, 37, 1},
3333
{[]byte{0x40, 0x25}, 37, 2},
3434
} {
35-
got, gotLen := consumeVarint(test.b)
35+
got, gotLen := ConsumeVarint(test.b)
3636
if got != test.want || gotLen != test.wantLen {
37-
t.Errorf("consumeVarint(%x) = %v, %v; want %v, %v", test.b, got, gotLen, test.want, test.wantLen)
37+
t.Errorf("ConsumeVarint(%x) = %v, %v; want %v, %v", test.b, got, gotLen, test.want, test.wantLen)
3838
}
3939
// Extra data in the buffer is ignored.
4040
b := append(test.b, 0)
41-
got, gotLen = consumeVarint(b)
41+
got, gotLen = ConsumeVarint(b)
4242
if got != test.want || gotLen != test.wantLen {
43-
t.Errorf("consumeVarint(%x) = %v, %v; want %v, %v", b, got, gotLen, test.want, test.wantLen)
43+
t.Errorf("ConsumeVarint(%x) = %v, %v; want %v, %v", b, got, gotLen, test.want, test.wantLen)
4444
}
4545
// Short buffer results in an error.
4646
for i := 1; i <= len(test.b); i++ {
4747
b = test.b[:len(test.b)-i]
48-
got, gotLen = consumeVarint(b)
48+
got, gotLen = ConsumeVarint(b)
4949
if got != 0 || gotLen >= 0 {
50-
t.Errorf("consumeVarint(%x) = %v, %v; want 0, -1", b, got, gotLen)
50+
t.Errorf("ConsumeVarint(%x) = %v, %v; want 0, -1", b, got, gotLen)
5151
}
5252
}
5353
}
@@ -69,11 +69,11 @@ func TestAppendVarint(t *testing.T) {
6969
{15293, []byte{0x7b, 0xbd}},
7070
{37, []byte{0x25}},
7171
} {
72-
got := appendVarint([]byte{}, test.v)
72+
got := AppendVarint([]byte{}, test.v)
7373
if !bytes.Equal(got, test.want) {
7474
t.Errorf("AppendVarint(nil, %v) = %x, want %x", test.v, got, test.want)
7575
}
76-
if gotLen, wantLen := sizeVarint(test.v), len(got); gotLen != wantLen {
76+
if gotLen, wantLen := SizeVarint(test.v), len(got); gotLen != wantLen {
7777
t.Errorf("SizeVarint(%v) = %v, want %v", test.v, gotLen, wantLen)
7878
}
7979
}
@@ -88,8 +88,8 @@ func TestConsumeUint32(t *testing.T) {
8888
{[]byte{0x01, 0x02, 0x03, 0x04}, 0x01020304, 4},
8989
{[]byte{0x01, 0x02, 0x03}, 0, -1},
9090
} {
91-
if got, n := consumeUint32(test.b); got != test.want || n != test.wantLen {
92-
t.Errorf("consumeUint32(%x) = %v, %v; want %v, %v", test.b, got, n, test.want, test.wantLen)
91+
if got, n := ConsumeUint32(test.b); got != test.want || n != test.wantLen {
92+
t.Errorf("ConsumeUint32(%x) = %v, %v; want %v, %v", test.b, got, n, test.want, test.wantLen)
9393
}
9494
}
9595
}
@@ -103,8 +103,8 @@ func TestConsumeUint64(t *testing.T) {
103103
{[]byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}, 0x0102030405060708, 8},
104104
{[]byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}, 0, -1},
105105
} {
106-
if got, n := consumeUint64(test.b); got != test.want || n != test.wantLen {
107-
t.Errorf("consumeUint32(%x) = %v, %v; want %v, %v", test.b, got, n, test.want, test.wantLen)
106+
if got, n := ConsumeUint64(test.b); got != test.want || n != test.wantLen {
107+
t.Errorf("ConsumeUint32(%x) = %v, %v; want %v, %v", test.b, got, n, test.want, test.wantLen)
108108
}
109109
}
110110
}
@@ -120,22 +120,22 @@ func TestConsumeVarintBytes(t *testing.T) {
120120
{[]byte{0x04, 0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}, 5},
121121
{[]byte{0x40, 0x04, 0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}, 6},
122122
} {
123-
got, gotLen := consumeVarintBytes(test.b)
123+
got, gotLen := ConsumeVarintBytes(test.b)
124124
if !bytes.Equal(got, test.want) || gotLen != test.wantLen {
125-
t.Errorf("consumeVarintBytes(%x) = {%x}, %v; want {%x}, %v", test.b, got, gotLen, test.want, test.wantLen)
125+
t.Errorf("ConsumeVarintBytes(%x) = {%x}, %v; want {%x}, %v", test.b, got, gotLen, test.want, test.wantLen)
126126
}
127127
// Extra data in the buffer is ignored.
128128
b := append(test.b, 0)
129-
got, gotLen = consumeVarintBytes(b)
129+
got, gotLen = ConsumeVarintBytes(b)
130130
if !bytes.Equal(got, test.want) || gotLen != test.wantLen {
131-
t.Errorf("consumeVarintBytes(%x) = {%x}, %v; want {%x}, %v", b, got, gotLen, test.want, test.wantLen)
131+
t.Errorf("ConsumeVarintBytes(%x) = {%x}, %v; want {%x}, %v", b, got, gotLen, test.want, test.wantLen)
132132
}
133133
// Short buffer results in an error.
134134
for i := 1; i <= len(test.b); i++ {
135135
b = test.b[:len(test.b)-i]
136-
got, gotLen := consumeVarintBytes(b)
136+
got, gotLen := ConsumeVarintBytes(b)
137137
if len(got) > 0 || gotLen > 0 {
138-
t.Errorf("consumeVarintBytes(%x) = {%x}, %v; want {}, -1", b, got, gotLen)
138+
t.Errorf("ConsumeVarintBytes(%x) = {%x}, %v; want {}, -1", b, got, gotLen)
139139
}
140140
}
141141

@@ -147,9 +147,9 @@ func TestConsumeVarintBytesErrors(t *testing.T) {
147147
{0x01},
148148
{0x40, 0x01},
149149
} {
150-
got, gotLen := consumeVarintBytes(b)
150+
got, gotLen := ConsumeVarintBytes(b)
151151
if len(got) > 0 || gotLen > 0 {
152-
t.Errorf("consumeVarintBytes(%x) = {%x}, %v; want {}, -1", b, got, gotLen)
152+
t.Errorf("ConsumeVarintBytes(%x) = {%x}, %v; want {}, -1", b, got, gotLen)
153153
}
154154
}
155155
}
@@ -164,22 +164,22 @@ func TestConsumeUint8Bytes(t *testing.T) {
164164
{[]byte{0x01, 0x00}, []byte{0x00}, 2},
165165
{[]byte{0x04, 0x01, 0x02, 0x03, 0x04}, []byte{0x01, 0x02, 0x03, 0x04}, 5},
166166
} {
167-
got, gotLen := consumeUint8Bytes(test.b)
167+
got, gotLen := ConsumeUint8Bytes(test.b)
168168
if !bytes.Equal(got, test.want) || gotLen != test.wantLen {
169-
t.Errorf("consumeUint8Bytes(%x) = {%x}, %v; want {%x}, %v", test.b, got, gotLen, test.want, test.wantLen)
169+
t.Errorf("ConsumeUint8Bytes(%x) = {%x}, %v; want {%x}, %v", test.b, got, gotLen, test.want, test.wantLen)
170170
}
171171
// Extra data in the buffer is ignored.
172172
b := append(test.b, 0)
173-
got, gotLen = consumeUint8Bytes(b)
173+
got, gotLen = ConsumeUint8Bytes(b)
174174
if !bytes.Equal(got, test.want) || gotLen != test.wantLen {
175-
t.Errorf("consumeUint8Bytes(%x) = {%x}, %v; want {%x}, %v", b, got, gotLen, test.want, test.wantLen)
175+
t.Errorf("ConsumeUint8Bytes(%x) = {%x}, %v; want {%x}, %v", b, got, gotLen, test.want, test.wantLen)
176176
}
177177
// Short buffer results in an error.
178178
for i := 1; i <= len(test.b); i++ {
179179
b = test.b[:len(test.b)-i]
180-
got, gotLen := consumeUint8Bytes(b)
180+
got, gotLen := ConsumeUint8Bytes(b)
181181
if len(got) > 0 || gotLen > 0 {
182-
t.Errorf("consumeUint8Bytes(%x) = {%x}, %v; want {}, -1", b, got, gotLen)
182+
t.Errorf("ConsumeUint8Bytes(%x) = {%x}, %v; want {}, -1", b, got, gotLen)
183183
}
184184
}
185185

@@ -191,35 +191,35 @@ func TestConsumeUint8BytesErrors(t *testing.T) {
191191
{0x01},
192192
{0x04, 0x01, 0x02, 0x03},
193193
} {
194-
got, gotLen := consumeUint8Bytes(b)
194+
got, gotLen := ConsumeUint8Bytes(b)
195195
if len(got) > 0 || gotLen > 0 {
196-
t.Errorf("consumeUint8Bytes(%x) = {%x}, %v; want {}, -1", b, got, gotLen)
196+
t.Errorf("ConsumeUint8Bytes(%x) = {%x}, %v; want {}, -1", b, got, gotLen)
197197
}
198198
}
199199
}
200200

201201
func TestAppendUint8Bytes(t *testing.T) {
202202
var got []byte
203-
got = appendUint8Bytes(got, []byte{})
204-
got = appendUint8Bytes(got, []byte{0xaa, 0xbb})
203+
got = AppendUint8Bytes(got, []byte{})
204+
got = AppendUint8Bytes(got, []byte{0xaa, 0xbb})
205205
want := []byte{
206206
0x00,
207207
0x02, 0xaa, 0xbb,
208208
}
209209
if !bytes.Equal(got, want) {
210-
t.Errorf("appendUint8Bytes {}, {aabb} = {%x}; want {%x}", got, want)
210+
t.Errorf("AppendUint8Bytes {}, {aabb} = {%x}; want {%x}", got, want)
211211
}
212212
}
213213

214214
func TestAppendVarintBytes(t *testing.T) {
215215
var got []byte
216-
got = appendVarintBytes(got, []byte{})
217-
got = appendVarintBytes(got, []byte{0xaa, 0xbb})
216+
got = AppendVarintBytes(got, []byte{})
217+
got = AppendVarintBytes(got, []byte{0xaa, 0xbb})
218218
want := []byte{
219219
0x00,
220220
0x02, 0xaa, 0xbb,
221221
}
222222
if !bytes.Equal(got, want) {
223-
t.Errorf("appendVarintBytes {}, {aabb} = {%x}; want {%x}", got, want)
223+
t.Errorf("AppendVarintBytes {}, {aabb} = {%x}; want {%x}", got, want)
224224
}
225225
}

Diff for: quic/config.go

+5-3
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import (
1111
"log/slog"
1212
"math"
1313
"time"
14+
15+
"golang.org/x/net/internal/quic/quicwire"
1416
)
1517

1618
// A Config structure configures a QUIC endpoint.
@@ -134,15 +136,15 @@ func (c *Config) maxUniRemoteStreams() int64 {
134136
}
135137

136138
func (c *Config) maxStreamReadBufferSize() int64 {
137-
return configDefault(c.MaxStreamReadBufferSize, 1<<20, maxVarint)
139+
return configDefault(c.MaxStreamReadBufferSize, 1<<20, quicwire.MaxVarint)
138140
}
139141

140142
func (c *Config) maxStreamWriteBufferSize() int64 {
141-
return configDefault(c.MaxStreamWriteBufferSize, 1<<20, maxVarint)
143+
return configDefault(c.MaxStreamWriteBufferSize, 1<<20, quicwire.MaxVarint)
142144
}
143145

144146
func (c *Config) maxConnReadBufferSize() int64 {
145-
return configDefault(c.MaxConnReadBufferSize, 1<<20, maxVarint)
147+
return configDefault(c.MaxConnReadBufferSize, 1<<20, quicwire.MaxVarint)
146148
}
147149

148150
func (c *Config) handshakeTimeout() time.Duration {

Diff for: quic/packet.go

+9-7
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ package quic
99
import (
1010
"encoding/binary"
1111
"fmt"
12+
13+
"golang.org/x/net/internal/quic/quicwire"
1214
)
1315

1416
// packetType is a QUIC packet type.
@@ -196,10 +198,10 @@ func parseVersionNegotiation(pkt []byte) (dstConnID, srcConnID, versions []byte)
196198
// appendVersionNegotiation appends a Version Negotiation packet to pkt,
197199
// returning the result.
198200
func appendVersionNegotiation(pkt, dstConnID, srcConnID []byte, versions ...uint32) []byte {
199-
pkt = append(pkt, headerFormLong|fixedBit) // header byte
200-
pkt = append(pkt, 0, 0, 0, 0) // Version (0 for Version Negotiation)
201-
pkt = appendUint8Bytes(pkt, dstConnID) // Destination Connection ID
202-
pkt = appendUint8Bytes(pkt, srcConnID) // Source Connection ID
201+
pkt = append(pkt, headerFormLong|fixedBit) // header byte
202+
pkt = append(pkt, 0, 0, 0, 0) // Version (0 for Version Negotiation)
203+
pkt = quicwire.AppendUint8Bytes(pkt, dstConnID) // Destination Connection ID
204+
pkt = quicwire.AppendUint8Bytes(pkt, srcConnID) // Source Connection ID
203205
for _, v := range versions {
204206
pkt = binary.BigEndian.AppendUint32(pkt, v) // Supported Version
205207
}
@@ -243,21 +245,21 @@ func parseGenericLongHeaderPacket(b []byte) (p genericLongPacket, ok bool) {
243245
b = b[1:]
244246
// Version (32),
245247
var n int
246-
p.version, n = consumeUint32(b)
248+
p.version, n = quicwire.ConsumeUint32(b)
247249
if n < 0 {
248250
return genericLongPacket{}, false
249251
}
250252
b = b[n:]
251253
// Destination Connection ID Length (8),
252254
// Destination Connection ID (0..2048),
253-
p.dstConnID, n = consumeUint8Bytes(b)
255+
p.dstConnID, n = quicwire.ConsumeUint8Bytes(b)
254256
if n < 0 || len(p.dstConnID) > 2048/8 {
255257
return genericLongPacket{}, false
256258
}
257259
b = b[n:]
258260
// Source Connection ID Length (8),
259261
// Source Connection ID (0..2048),
260-
p.srcConnID, n = consumeUint8Bytes(b)
262+
p.srcConnID, n = quicwire.ConsumeUint8Bytes(b)
261263
if n < 0 || len(p.dstConnID) > 2048/8 {
262264
return genericLongPacket{}, false
263265
}

0 commit comments

Comments
 (0)