Update deps

This commit is contained in:
Frank Denis 2023-05-01 16:05:02 +02:00
parent c66023c7d7
commit d381af5510
59 changed files with 640 additions and 637 deletions

10
go.mod
View File

@ -14,13 +14,13 @@ require (
github.com/jedisct1/go-clocksmith v0.0.0-20230211133011-392c1afea73e
github.com/jedisct1/go-dnsstamps v0.0.0-20230211133001-124a632de565
github.com/jedisct1/go-hpke-compact v0.0.0-20230211184420-51d4440017ce
github.com/jedisct1/go-minisign v0.0.0-20230211184525-1f273d8dc776
github.com/jedisct1/go-minisign v0.0.0-20230410063418-3d885d71f62c
github.com/jedisct1/xsecretbox v0.0.0-20230211185120-2025cdbb9f0f
github.com/k-sone/critbitgo v1.4.0
github.com/kardianos/service v1.2.2
github.com/miekg/dns v1.1.53
github.com/miekg/dns v1.1.54
github.com/powerman/check v1.7.0
github.com/quic-go/quic-go v0.33.0
github.com/quic-go/quic-go v0.34.0
golang.org/x/crypto v0.8.0
golang.org/x/net v0.9.0
golang.org/x/sys v0.7.0
@ -39,8 +39,8 @@ require (
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/powerman/deepequal v0.1.0 // indirect
github.com/quic-go/qpack v0.4.0 // indirect
github.com/quic-go/qtls-go1-19 v0.2.1 // indirect
github.com/quic-go/qtls-go1-20 v0.1.1 // indirect
github.com/quic-go/qtls-go1-19 v0.3.2 // indirect
github.com/quic-go/qtls-go1-20 v0.2.2 // indirect
github.com/smartystreets/goconvey v1.7.2 // indirect
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db // indirect
golang.org/x/mod v0.8.0 // indirect

20
go.sum
View File

@ -44,8 +44,8 @@ github.com/jedisct1/go-dnsstamps v0.0.0-20230211133001-124a632de565 h1:BPBMaUCgt
github.com/jedisct1/go-dnsstamps v0.0.0-20230211133001-124a632de565/go.mod h1:mEGEFZsGe4sG5Mb3Xi89pmsy+TZ0946ArbYMGKAM5uA=
github.com/jedisct1/go-hpke-compact v0.0.0-20230211184420-51d4440017ce h1:RvDulxEuYjqIWSphi54mQGXWDAp0yjeCJQKhBj6Qkmc=
github.com/jedisct1/go-hpke-compact v0.0.0-20230211184420-51d4440017ce/go.mod h1:T9nvXa0PqmoSt9JhtW0rv9iXg5xoxW/ZfVhdm9Y4QJw=
github.com/jedisct1/go-minisign v0.0.0-20230211184525-1f273d8dc776 h1:WXhZ7psl6HhDDW58rDWIJE6oB0ETjaQA4U6d8U7lMyg=
github.com/jedisct1/go-minisign v0.0.0-20230211184525-1f273d8dc776/go.mod h1:09CTTv5TZgz94QHts03Xnuzy5LmxCE8BNqQRFigO5gA=
github.com/jedisct1/go-minisign v0.0.0-20230410063418-3d885d71f62c h1:SJIUnIcy3NTjPM1acfLsIDQ6dZkBXkQLt/vrg7pshX0=
github.com/jedisct1/go-minisign v0.0.0-20230410063418-3d885d71f62c/go.mod h1:euIjSueBwqJWwVr7rS2bowelVBVoN827tx5n87jnSJM=
github.com/jedisct1/xsecretbox v0.0.0-20230211185120-2025cdbb9f0f h1:1qPoL+ur1rCouHMB737ujJGXVFoXGafDY+kmgXjpicA=
github.com/jedisct1/xsecretbox v0.0.0-20230211185120-2025cdbb9f0f/go.mod h1:39HtRgNq2rdKzzeqfPNFLY000t4ktVThX3ncyK58lsA=
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
@ -54,8 +54,8 @@ github.com/k-sone/critbitgo v1.4.0 h1:l71cTyBGeh6X5ATh6Fibgw3+rtNT80BA0uNNWgkPrb
github.com/k-sone/critbitgo v1.4.0/go.mod h1:7E6pyoyADnFxlUBEKcnfS49b7SUAQGMK+OAp/UQvo0s=
github.com/kardianos/service v1.2.2 h1:ZvePhAHfvo0A7Mftk/tEzqEZ7Q4lgnR8sGz4xu1YX60=
github.com/kardianos/service v1.2.2/go.mod h1:CIMRFEJVL+0DS1a3Nx06NaMn4Dz63Ng6O7dl0qH0zVM=
github.com/miekg/dns v1.1.53 h1:ZBkuHr5dxHtB1caEOlZTLPo7D3L3TWckgUUs/RHfDxw=
github.com/miekg/dns v1.1.53/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY=
github.com/miekg/dns v1.1.54 h1:5jon9mWcb0sFJGpnI99tOMhCPyJ+RPVz5b63MQG0VWI=
github.com/miekg/dns v1.1.54/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY=
github.com/onsi/ginkgo/v2 v2.2.0 h1:3ZNA3L1c5FYDFTTxbFeVGGD8jYvjYauHD30YgLxVsNI=
github.com/onsi/ginkgo/v2 v2.2.0/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk=
github.com/onsi/gomega v1.20.1 h1:PA/3qinGoukvymdIDV8pii6tiZgC8kbmJO6Z5+b002Q=
@ -69,12 +69,12 @@ github.com/powerman/deepequal v0.1.0 h1:sVwtyTsBuYIvdbLR1O2wzRY63YgPqdGZmk/o80l+
github.com/powerman/deepequal v0.1.0/go.mod h1:3k7aG/slufBhUANdN67o/UPg8i5YaiJ6FmibWX0cn04=
github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
github.com/quic-go/qtls-go1-19 v0.2.1 h1:aJcKNMkH5ASEJB9FXNeZCyTEIHU1J7MmHyz1Q1TSG1A=
github.com/quic-go/qtls-go1-19 v0.2.1/go.mod h1:ySOI96ew8lnoKPtSqx2BlI5wCpUVPT05RMAlajtnyOI=
github.com/quic-go/qtls-go1-20 v0.1.1 h1:KbChDlg82d3IHqaj2bn6GfKRj84Per2VGf5XV3wSwQk=
github.com/quic-go/qtls-go1-20 v0.1.1/go.mod h1:JKtK6mjbAVcUTN/9jZpvLbGxvdWIKS8uT7EiStoU1SM=
github.com/quic-go/quic-go v0.33.0 h1:ItNoTDN/Fm/zBlq769lLJc8ECe9gYaW40veHCCco7y0=
github.com/quic-go/quic-go v0.33.0/go.mod h1:YMuhaAV9/jIu0XclDXwZPAsP/2Kgr5yMYhe9oxhhOFA=
github.com/quic-go/qtls-go1-19 v0.3.2 h1:tFxjCFcTQzK+oMxG6Zcvp4Dq8dx4yD3dDiIiyc86Z5U=
github.com/quic-go/qtls-go1-19 v0.3.2/go.mod h1:ySOI96ew8lnoKPtSqx2BlI5wCpUVPT05RMAlajtnyOI=
github.com/quic-go/qtls-go1-20 v0.2.2 h1:WLOPx6OY/hxtTxKV1Zrq20FtXtDEkeY00CGQm8GEa3E=
github.com/quic-go/qtls-go1-20 v0.2.2/go.mod h1:JKtK6mjbAVcUTN/9jZpvLbGxvdWIKS8uT7EiStoU1SM=
github.com/quic-go/quic-go v0.34.0 h1:OvOJ9LFjTySgwOTYUZmNoq0FzVicP8YujpV0kB7m2lU=
github.com/quic-go/quic-go v0.34.0/go.mod h1:+4CVgVppm0FNjpG3UcX8Joi/frKOH7/ciD5yGcwOO1g=
github.com/smartystreets/assertions v1.2.0 h1:42S6lae5dvLc7BrLu/0ugRtcFVjoJNMC/N3yZFZkDFs=
github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
github.com/smartystreets/goconvey v1.7.2 h1:9RBaZCeXEQ3UselpuwUQHltGVXvdwm6cv1hgR6gDIPg=

View File

@ -6,7 +6,6 @@
"context"
"crypto/tls"
"encoding/binary"
"fmt"
"io"
"net"
"strings"
@ -56,14 +55,20 @@ type Client struct {
// Timeout is a cumulative timeout for dial, write and read, defaults to 0 (disabled) - overrides DialTimeout, ReadTimeout,
// WriteTimeout when non-zero. Can be overridden with net.Dialer.Timeout (see Client.ExchangeWithDialer and
// Client.Dialer) or context.Context.Deadline (see ExchangeContext)
Timeout time.Duration
DialTimeout time.Duration // net.DialTimeout, defaults to 2 seconds, or net.Dialer.Timeout if expiring earlier - overridden by Timeout when that value is non-zero
ReadTimeout time.Duration // net.Conn.SetReadTimeout value for connections, defaults to 2 seconds - overridden by Timeout when that value is non-zero
WriteTimeout time.Duration // net.Conn.SetWriteTimeout value for connections, defaults to 2 seconds - overridden by Timeout when that value is non-zero
TsigSecret map[string]string // secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be in canonical form (lowercase, fqdn, see RFC 4034 Section 6.2)
TsigProvider TsigProvider // An implementation of the TsigProvider interface. If defined it replaces TsigSecret and is used for all TSIG operations.
SingleInflight bool // if true suppress multiple outstanding queries for the same Qname, Qtype and Qclass
group singleflight
Timeout time.Duration
DialTimeout time.Duration // net.DialTimeout, defaults to 2 seconds, or net.Dialer.Timeout if expiring earlier - overridden by Timeout when that value is non-zero
ReadTimeout time.Duration // net.Conn.SetReadTimeout value for connections, defaults to 2 seconds - overridden by Timeout when that value is non-zero
WriteTimeout time.Duration // net.Conn.SetWriteTimeout value for connections, defaults to 2 seconds - overridden by Timeout when that value is non-zero
TsigSecret map[string]string // secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be in canonical form (lowercase, fqdn, see RFC 4034 Section 6.2)
TsigProvider TsigProvider // An implementation of the TsigProvider interface. If defined it replaces TsigSecret and is used for all TSIG operations.
// SingleInflight previously serialised multiple concurrent queries for the
// same Qname, Qtype and Qclass to ensure only one would be in flight at a
// time.
//
// Deprecated: This is a no-op. Callers should implement their own in flight
// query caching if needed. See github.com/miekg/dns/issues/1449.
SingleInflight bool
}
// Exchange performs a synchronous UDP query. It sends the message m to the address
@ -185,26 +190,7 @@ func (c *Client) ExchangeWithConn(m *Msg, conn *Conn) (r *Msg, rtt time.Duration
return c.exchangeWithConnContext(context.Background(), m, conn)
}
func (c *Client) exchangeWithConnContext(ctx context.Context, m *Msg, conn *Conn) (r *Msg, rtt time.Duration, err error) {
if !c.SingleInflight {
return c.exchangeContext(ctx, m, conn)
}
q := m.Question[0]
key := fmt.Sprintf("%s:%d:%d", q.Name, q.Qtype, q.Qclass)
r, rtt, err, shared := c.group.Do(key, func() (*Msg, time.Duration, error) {
// When we're doing singleflight we don't want one context cancellation, cancel _all_ outstanding queries.
// Hence we ignore the context and use Background().
return c.exchangeContext(context.Background(), m, conn)
})
if r != nil && shared {
r = r.Copy()
}
return r, rtt, err
}
func (c *Client) exchangeContext(ctx context.Context, m *Msg, co *Conn) (r *Msg, rtt time.Duration, err error) {
func (c *Client) exchangeWithConnContext(ctx context.Context, m *Msg, co *Conn) (r *Msg, rtt time.Duration, err error) {
opt := m.IsEdns0()
// If EDNS0 is used use that for size.
if opt != nil && opt.UDPSize() >= MinMsgSize {

View File

@ -272,18 +272,24 @@ func IsMsg(buf []byte) error {
// IsFqdn checks if a domain name is fully qualified.
func IsFqdn(s string) bool {
s2 := strings.TrimSuffix(s, ".")
if s == s2 {
// Check for (and remove) a trailing dot, returning if there isn't one.
if s == "" || s[len(s)-1] != '.' {
return false
}
s = s[:len(s)-1]
i := strings.LastIndexFunc(s2, func(r rune) bool {
// If we don't have an escape sequence before the final dot, we know it's
// fully qualified and can return here.
if s == "" || s[len(s)-1] != '\\' {
return true
}
// Otherwise we have to check if the dot is escaped or not by checking if
// there are an odd or even number of escape sequences before the dot.
i := strings.LastIndexFunc(s, func(r rune) bool {
return r != '\\'
})
// Test whether we have an even number of escape sequences before
// the dot or none.
return (len(s2)-i)%2 != 0
return (len(s)-i)%2 != 0
}
// IsRRset checks if a set of RRs is a valid RRset as defined by RFC 2181.

20
vendor/github.com/miekg/dns/scan.go generated vendored
View File

@ -10,13 +10,13 @@
"strings"
)
const maxTok = 2048 // Largest token we can return.
const maxTok = 512 // Token buffer start size, and growth size amount.
// The maximum depth of $INCLUDE directives supported by the
// ZoneParser API.
const maxIncludeDepth = 7
// Tokinize a RFC 1035 zone file. The tokenizer will normalize it:
// Tokenize a RFC 1035 zone file. The tokenizer will normalize it:
// * Add ownernames if they are left blank;
// * Suppress sequences of spaces;
// * Make each RR fit on one line (_NEWLINE is send as last)
@ -765,8 +765,8 @@ func (zl *zlexer) Next() (lex, bool) {
}
var (
str [maxTok]byte // Hold string text
com [maxTok]byte // Hold comment text
str = make([]byte, maxTok) // Hold string text
com = make([]byte, maxTok) // Hold comment text
stri int // Offset in str (0 means empty)
comi int // Offset in com (0 means empty)
@ -785,14 +785,12 @@ func (zl *zlexer) Next() (lex, bool) {
l.line, l.column = zl.line, zl.column
if stri >= len(str) {
l.token = "token length insufficient for parsing"
l.err = true
return *l, true
// if buffer length is insufficient, increase it.
str = append(str[:], make([]byte, maxTok)...)
}
if comi >= len(com) {
l.token = "comment length insufficient for parsing"
l.err = true
return *l, true
// if buffer length is insufficient, increase it.
com = append(com[:], make([]byte, maxTok)...)
}
switch x {
@ -816,7 +814,7 @@ func (zl *zlexer) Next() (lex, bool) {
if stri == 0 {
// Space directly in the beginning, handled in the grammar
} else if zl.owner {
// If we have a string and its the first, make it an owner
// If we have a string and it's the first, make it an owner
l.value = zOwner
l.token = string(str[:stri])

View File

@ -904,11 +904,18 @@ func (rr *RRSIG) parse(c *zlexer, o string) *ParseError {
c.Next() // zBlank
l, _ = c.Next()
i, e := strconv.ParseUint(l.token, 10, 8)
if e != nil || l.err {
if l.err {
return &ParseError{"", "bad RRSIG Algorithm", l}
}
rr.Algorithm = uint8(i)
i, e := strconv.ParseUint(l.token, 10, 8)
rr.Algorithm = uint8(i) // if 0 we'll check the mnemonic in the if
if e != nil {
v, ok := StringToAlgorithm[l.token]
if !ok {
return &ParseError{"", "bad RRSIG Algorithm", l}
}
rr.Algorithm = v
}
c.Next() // zBlank
l, _ = c.Next()

View File

@ -1,61 +0,0 @@
// Copyright 2013 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.
// Adapted for dns package usage by Miek Gieben.
package dns
import "sync"
import "time"
// call is an in-flight or completed singleflight.Do call
type call struct {
wg sync.WaitGroup
val *Msg
rtt time.Duration
err error
dups int
}
// singleflight represents a class of work and forms a namespace in
// which units of work can be executed with duplicate suppression.
type singleflight struct {
sync.Mutex // protects m
m map[string]*call // lazily initialized
dontDeleteForTesting bool // this is only to be used by TestConcurrentExchanges
}
// Do executes and returns the results of the given function, making
// sure that only one execution is in-flight for a given key at a
// time. If a duplicate comes in, the duplicate caller waits for the
// original to complete and receives the same results.
// The return value shared indicates whether v was given to multiple callers.
func (g *singleflight) Do(key string, fn func() (*Msg, time.Duration, error)) (v *Msg, rtt time.Duration, err error, shared bool) {
g.Lock()
if g.m == nil {
g.m = make(map[string]*call)
}
if c, ok := g.m[key]; ok {
c.dups++
g.Unlock()
c.wg.Wait()
return c.val, c.rtt, c.err, true
}
c := new(call)
c.wg.Add(1)
g.m[key] = c
g.Unlock()
c.val, c.rtt, c.err = fn()
c.wg.Done()
if !g.dontDeleteForTesting {
g.Lock()
delete(g.m, key)
g.Unlock()
}
return c.val, c.rtt, c.err, c.dups > 0
}

View File

@ -3,7 +3,7 @@
import "fmt"
// Version is current version of this library.
var Version = v{1, 1, 53}
var Version = v{1, 1, 54}
// v holds the version of this library.
type v struct {

View File

@ -144,22 +144,13 @@ func (c *Conn) makeClientHello() (*clientHelloMsg, ecdheParameters, error) {
var params ecdheParameters
if hello.supportedVersions[0] == VersionTLS13 {
var suites []uint16
for _, suiteID := range configCipherSuites {
for _, suite := range cipherSuitesTLS13 {
if suite.id == suiteID {
suites = append(suites, suiteID)
}
}
if len(hello.supportedVersions) == 1 {
hello.cipherSuites = hello.cipherSuites[:0]
}
if len(suites) > 0 {
hello.cipherSuites = suites
if hasAESGCMHardwareSupport {
hello.cipherSuites = append(hello.cipherSuites, defaultCipherSuitesTLS13...)
} else {
if hasAESGCMHardwareSupport {
hello.cipherSuites = append(hello.cipherSuites, defaultCipherSuitesTLS13...)
} else {
hello.cipherSuites = append(hello.cipherSuites, defaultCipherSuitesTLS13NoAES...)
}
hello.cipherSuites = append(hello.cipherSuites, defaultCipherSuitesTLS13NoAES...)
}
curveID := config.curvePreferences()[0]

View File

@ -147,27 +147,14 @@ func (hs *serverHandshakeStateTLS13) processClientHello() error {
hs.hello.sessionId = hs.clientHello.sessionId
hs.hello.compressionMethod = compressionNone
if hs.suite == nil {
var preferenceList []uint16
for _, suiteID := range c.config.CipherSuites {
for _, suite := range cipherSuitesTLS13 {
if suite.id == suiteID {
preferenceList = append(preferenceList, suiteID)
break
}
}
}
if len(preferenceList) == 0 {
preferenceList = defaultCipherSuitesTLS13
if !hasAESGCMHardwareSupport || !aesgcmPreferred(hs.clientHello.cipherSuites) {
preferenceList = defaultCipherSuitesTLS13NoAES
}
}
for _, suiteID := range preferenceList {
hs.suite = mutualCipherSuiteTLS13(hs.clientHello.cipherSuites, suiteID)
if hs.suite != nil {
break
}
preferenceList := defaultCipherSuitesTLS13
if !hasAESGCMHardwareSupport || !aesgcmPreferred(hs.clientHello.cipherSuites) {
preferenceList = defaultCipherSuitesTLS13NoAES
}
for _, suiteID := range preferenceList {
hs.suite = mutualCipherSuiteTLS13(hs.clientHello.cipherSuites, suiteID)
if hs.suite != nil {
break
}
}
if hs.suite == nil {

View File

@ -144,22 +144,13 @@ func (c *Conn) makeClientHello() (*clientHelloMsg, *ecdh.PrivateKey, error) {
var key *ecdh.PrivateKey
if hello.supportedVersions[0] == VersionTLS13 {
var suites []uint16
for _, suiteID := range configCipherSuites {
for _, suite := range cipherSuitesTLS13 {
if suite.id == suiteID {
suites = append(suites, suiteID)
}
}
if len(hello.supportedVersions) == 1 {
hello.cipherSuites = hello.cipherSuites[:0]
}
if len(suites) > 0 {
hello.cipherSuites = suites
if hasAESGCMHardwareSupport {
hello.cipherSuites = append(hello.cipherSuites, defaultCipherSuitesTLS13...)
} else {
if hasAESGCMHardwareSupport {
hello.cipherSuites = append(hello.cipherSuites, defaultCipherSuitesTLS13...)
} else {
hello.cipherSuites = append(hello.cipherSuites, defaultCipherSuitesTLS13NoAES...)
}
hello.cipherSuites = append(hello.cipherSuites, defaultCipherSuitesTLS13NoAES...)
}
curveID := config.curvePreferences()[0]

View File

@ -146,27 +146,14 @@ func (hs *serverHandshakeStateTLS13) processClientHello() error {
hs.hello.sessionId = hs.clientHello.sessionId
hs.hello.compressionMethod = compressionNone
if hs.suite == nil {
var preferenceList []uint16
for _, suiteID := range c.config.CipherSuites {
for _, suite := range cipherSuitesTLS13 {
if suite.id == suiteID {
preferenceList = append(preferenceList, suiteID)
break
}
}
}
if len(preferenceList) == 0 {
preferenceList = defaultCipherSuitesTLS13
if !hasAESGCMHardwareSupport || !aesgcmPreferred(hs.clientHello.cipherSuites) {
preferenceList = defaultCipherSuitesTLS13NoAES
}
}
for _, suiteID := range preferenceList {
hs.suite = mutualCipherSuiteTLS13(hs.clientHello.cipherSuites, suiteID)
if hs.suite != nil {
break
}
preferenceList := defaultCipherSuitesTLS13
if !hasAESGCMHardwareSupport || !aesgcmPreferred(hs.clientHello.cipherSuites) {
preferenceList = defaultCipherSuitesTLS13NoAES
}
for _, suiteID := range preferenceList {
hs.suite = mutualCipherSuiteTLS13(hs.clientHello.cipherSuites, suiteID)
if hs.suite != nil {
break
}
}
if hs.suite == nil {

View File

@ -1,14 +1,15 @@
run:
skip-files:
- internal/qtls/structs_equal_test.go
linters-settings:
depguard:
type: blacklist
packages:
- github.com/marten-seemann/qtls
- github.com/quic-go/qtls-go1-19
- github.com/quic-go/qtls-go1-20
packages-with-error-message:
- github.com/marten-seemann/qtls: "importing qtls only allowed in internal/qtls"
- github.com/quic-go/qtls-go1-19: "importing qtls only allowed in internal/qtls"
- github.com/quic-go/qtls-go1-20: "importing qtls only allowed in internal/qtls"
misspell:
ignore-words:
- ect
@ -17,7 +18,6 @@ linters:
disable-all: true
enable:
- asciicheck
- deadcode
- depguard
- exhaustive
- exportloopref
@ -30,11 +30,9 @@ linters:
- prealloc
- staticcheck
- stylecheck
- structcheck
- unconvert
- unparam
- unused
- varcheck
- vet
issues:

19
vendor/github.com/quic-go/quic-go/SECURITY.md generated vendored Normal file
View File

@ -0,0 +1,19 @@
# Security Policy
quic-go still in development. This means that there may be problems in our protocols,
or there may be mistakes in our implementations.
We take security vulnerabilities very seriously. If you discover a security issue,
please bring it to our attention right away!
## Reporting a Vulnerability
If you find a vulnerability that may affect live deployments -- for example, by exposing
a remote execution exploit -- please [**report privately**](https://github.com/quic-go/quic-go/security/advisories/new).
Please **DO NOT file a public issue**.
If the issue is an implementation weakness that cannot be immediately exploited or
something not yet deployed, just discuss it openly.
## Reporting a non security bug
For non-security bugs, please simply file a GitHub [issue](https://github.com/quic-go/quic-go/issues/new).

View File

@ -47,7 +47,6 @@ type client struct {
// DialAddr establishes a new QUIC connection to a server.
// It uses a new UDP connection and closes this connection when the QUIC connection is closed.
// The hostname for SNI is taken from the given address.
// The tls.Config.CipherSuites allows setting of TLS 1.3 cipher suites.
func DialAddr(
addr string,
tlsConf *tls.Config,
@ -59,7 +58,6 @@ func DialAddr(
// DialAddrEarly establishes a new 0-RTT QUIC connection to a server.
// It uses a new UDP connection and closes this connection when the QUIC connection is closed.
// The hostname for SNI is taken from the given address.
// The tls.Config.CipherSuites allows setting of TLS 1.3 cipher suites.
func DialAddrEarly(
addr string,
tlsConf *tls.Config,
@ -325,7 +323,7 @@ func (c *client) dial(ctx context.Context) error {
case <-earlyConnChan:
// ready to send 0-RTT data
return nil
case <-c.conn.HandshakeComplete().Done():
case <-c.conn.HandshakeComplete():
// handshake successfully completed
return nil
}

View File

@ -696,8 +696,8 @@ func (s *connection) earlyConnReady() <-chan struct{} {
return s.earlyConnReadyChan
}
func (s *connection) HandshakeComplete() context.Context {
return s.handshakeCtx
func (s *connection) HandshakeComplete() <-chan struct{} {
return s.handshakeCtx.Done()
}
func (s *connection) Context() context.Context {
@ -2195,7 +2195,7 @@ func (s *connection) GetVersion() protocol.VersionNumber {
}
func (s *connection) NextConnection() Connection {
<-s.HandshakeComplete().Done()
<-s.HandshakeComplete()
s.streamsMap.UseResetMaps()
return s
}

View File

@ -67,7 +67,7 @@ func (r *body) Read(b []byte) (int, error) {
}
func (r *body) Close() error {
r.str.CancelRead(quic.StreamErrorCode(errorRequestCanceled))
r.str.CancelRead(quic.StreamErrorCode(ErrCodeRequestCanceled))
return nil
}
@ -126,7 +126,7 @@ func (r *body) StreamID() quic.StreamID {
func (r *hijackableBody) Close() error {
r.requestDone()
// If the EOF was read, CancelRead() is a no-op.
r.str.CancelRead(quic.StreamErrorCode(errorRequestCanceled))
r.str.CancelRead(quic.StreamErrorCode(ErrCodeRequestCanceled))
return nil
}

View File

@ -33,7 +33,7 @@
var defaultQuicConfig = &quic.Config{
MaxIncomingStreams: -1, // don't allow the server to create bidirectional streams
KeepAlivePeriod: 10 * time.Second,
Versions: []protocol.VersionNumber{protocol.VersionTLS},
Versions: []protocol.VersionNumber{protocol.Version1},
}
type dialFunc func(ctx context.Context, addr string, tlsCfg *tls.Config, cfg *quic.Config) (quic.EarlyConnection, error)
@ -124,7 +124,7 @@ func (c *client) dial(ctx context.Context) error {
go func() {
if err := c.setupConn(conn); err != nil {
c.logger.Debugf("Setting up connection failed: %s", err)
conn.CloseWithError(quic.ApplicationErrorCode(errorInternalError), "")
conn.CloseWithError(quic.ApplicationErrorCode(ErrCodeInternalError), "")
}
}()
@ -166,7 +166,7 @@ func (c *client) handleBidirectionalStreams(conn quic.EarlyConnection) {
if err != nil {
c.logger.Debugf("error handling stream: %s", err)
}
conn.CloseWithError(quic.ApplicationErrorCode(errorFrameUnexpected), "received HTTP/3 frame on bidirectional stream")
conn.CloseWithError(quic.ApplicationErrorCode(ErrCodeFrameUnexpected), "received HTTP/3 frame on bidirectional stream")
}(str)
}
}
@ -197,23 +197,23 @@ func (c *client) handleUnidirectionalStreams(conn quic.EarlyConnection) {
return
case streamTypePushStream:
// We never increased the Push ID, so we don't expect any push streams.
conn.CloseWithError(quic.ApplicationErrorCode(errorIDError), "")
conn.CloseWithError(quic.ApplicationErrorCode(ErrCodeIDError), "")
return
default:
if c.opts.UniStreamHijacker != nil && c.opts.UniStreamHijacker(StreamType(streamType), conn, str, nil) {
return
}
str.CancelRead(quic.StreamErrorCode(errorStreamCreationError))
str.CancelRead(quic.StreamErrorCode(ErrCodeStreamCreationError))
return
}
f, err := parseNextFrame(str, nil)
if err != nil {
conn.CloseWithError(quic.ApplicationErrorCode(errorFrameError), "")
conn.CloseWithError(quic.ApplicationErrorCode(ErrCodeFrameError), "")
return
}
sf, ok := f.(*settingsFrame)
if !ok {
conn.CloseWithError(quic.ApplicationErrorCode(errorMissingSettings), "")
conn.CloseWithError(quic.ApplicationErrorCode(ErrCodeMissingSettings), "")
return
}
if !sf.Datagram {
@ -223,7 +223,7 @@ func (c *client) handleUnidirectionalStreams(conn quic.EarlyConnection) {
// we can expect it to have been negotiated both on the transport and on the HTTP/3 layer.
// Note: ConnectionState() will block until the handshake is complete (relevant when using 0-RTT).
if c.opts.EnableDatagram && !conn.ConnectionState().SupportsDatagrams {
conn.CloseWithError(quic.ApplicationErrorCode(errorSettingsError), "missing QUIC Datagram support")
conn.CloseWithError(quic.ApplicationErrorCode(ErrCodeSettingsError), "missing QUIC Datagram support")
}
}(str)
}
@ -234,7 +234,7 @@ func (c *client) Close() error {
if conn == nil {
return nil
}
return (*conn).CloseWithError(quic.ApplicationErrorCode(errorNoError), "")
return (*conn).CloseWithError(quic.ApplicationErrorCode(ErrCodeNoError), "")
}
func (c *client) maxHeaderBytes() uint64 {
@ -266,7 +266,7 @@ func (c *client) RoundTripOpt(req *http.Request, opt RoundTripOpt) (*http.Respon
} else {
// wait for the handshake to complete
select {
case <-conn.HandshakeComplete().Done():
case <-conn.HandshakeComplete():
case <-req.Context().Done():
return nil, req.Context().Err()
}
@ -286,8 +286,8 @@ func (c *client) RoundTripOpt(req *http.Request, opt RoundTripOpt) (*http.Respon
defer close(done)
select {
case <-req.Context().Done():
str.CancelWrite(quic.StreamErrorCode(errorRequestCanceled))
str.CancelRead(quic.StreamErrorCode(errorRequestCanceled))
str.CancelWrite(quic.StreamErrorCode(ErrCodeRequestCanceled))
str.CancelRead(quic.StreamErrorCode(ErrCodeRequestCanceled))
case <-reqDone:
}
}()
@ -339,7 +339,7 @@ func (c *client) sendRequestBody(str Stream, body io.ReadCloser) error {
if rerr == io.EOF {
break
}
str.CancelWrite(quic.StreamErrorCode(errorRequestCanceled))
str.CancelWrite(quic.StreamErrorCode(ErrCodeRequestCanceled))
return rerr
}
}
@ -352,14 +352,14 @@ func (c *client) doRequest(req *http.Request, conn quic.EarlyConnection, str qui
requestGzip = true
}
if err := c.requestWriter.WriteRequestHeader(str, req, requestGzip); err != nil {
return nil, newStreamError(errorInternalError, err)
return nil, newStreamError(ErrCodeInternalError, err)
}
if req.Body == nil && !opt.DontCloseRequestStream {
str.Close()
}
hstr := newStream(str, func() { conn.CloseWithError(quic.ApplicationErrorCode(errorFrameUnexpected), "") })
hstr := newStream(str, func() { conn.CloseWithError(quic.ApplicationErrorCode(ErrCodeFrameUnexpected), "") })
if req.Body != nil {
// send the request body asynchronously
go func() {
@ -374,23 +374,23 @@ func (c *client) doRequest(req *http.Request, conn quic.EarlyConnection, str qui
frame, err := parseNextFrame(str, nil)
if err != nil {
return nil, newStreamError(errorFrameError, err)
return nil, newStreamError(ErrCodeFrameError, err)
}
hf, ok := frame.(*headersFrame)
if !ok {
return nil, newConnError(errorFrameUnexpected, errors.New("expected first frame to be a HEADERS frame"))
return nil, newConnError(ErrCodeFrameUnexpected, errors.New("expected first frame to be a HEADERS frame"))
}
if hf.Length > c.maxHeaderBytes() {
return nil, newStreamError(errorFrameError, fmt.Errorf("HEADERS frame too large: %d bytes (max: %d)", hf.Length, c.maxHeaderBytes()))
return nil, newStreamError(ErrCodeFrameError, fmt.Errorf("HEADERS frame too large: %d bytes (max: %d)", hf.Length, c.maxHeaderBytes()))
}
headerBlock := make([]byte, hf.Length)
if _, err := io.ReadFull(str, headerBlock); err != nil {
return nil, newStreamError(errorRequestIncomplete, err)
return nil, newStreamError(ErrCodeRequestIncomplete, err)
}
hfs, err := c.decoder.DecodeFull(headerBlock)
if err != nil {
// TODO: use the right error code
return nil, newConnError(errorGeneralProtocolError, err)
return nil, newConnError(ErrCodeGeneralProtocolError, err)
}
connState := qtls.ToTLSConnectionState(conn.ConnectionState().TLS)
@ -406,7 +406,7 @@ func (c *client) doRequest(req *http.Request, conn quic.EarlyConnection, str qui
case ":status":
status, err := strconv.Atoi(hf.Value)
if err != nil {
return nil, newStreamError(errorGeneralProtocolError, errors.New("malformed non-numeric status pseudo header"))
return nil, newStreamError(ErrCodeGeneralProtocolError, errors.New("malformed non-numeric status pseudo header"))
}
res.StatusCode = status
res.Status = hf.Value + " " + http.StatusText(status)
@ -449,7 +449,7 @@ func (c *client) HandshakeComplete() bool {
return false
}
select {
case <-(*conn).HandshakeComplete().Done():
case <-(*conn).HandshakeComplete():
return true
default:
return false

View File

@ -6,66 +6,66 @@
"github.com/quic-go/quic-go"
)
type errorCode quic.ApplicationErrorCode
type ErrCode quic.ApplicationErrorCode
const (
errorNoError errorCode = 0x100
errorGeneralProtocolError errorCode = 0x101
errorInternalError errorCode = 0x102
errorStreamCreationError errorCode = 0x103
errorClosedCriticalStream errorCode = 0x104
errorFrameUnexpected errorCode = 0x105
errorFrameError errorCode = 0x106
errorExcessiveLoad errorCode = 0x107
errorIDError errorCode = 0x108
errorSettingsError errorCode = 0x109
errorMissingSettings errorCode = 0x10a
errorRequestRejected errorCode = 0x10b
errorRequestCanceled errorCode = 0x10c
errorRequestIncomplete errorCode = 0x10d
errorMessageError errorCode = 0x10e
errorConnectError errorCode = 0x10f
errorVersionFallback errorCode = 0x110
errorDatagramError errorCode = 0x4a1268
ErrCodeNoError ErrCode = 0x100
ErrCodeGeneralProtocolError ErrCode = 0x101
ErrCodeInternalError ErrCode = 0x102
ErrCodeStreamCreationError ErrCode = 0x103
ErrCodeClosedCriticalStream ErrCode = 0x104
ErrCodeFrameUnexpected ErrCode = 0x105
ErrCodeFrameError ErrCode = 0x106
ErrCodeExcessiveLoad ErrCode = 0x107
ErrCodeIDError ErrCode = 0x108
ErrCodeSettingsError ErrCode = 0x109
ErrCodeMissingSettings ErrCode = 0x10a
ErrCodeRequestRejected ErrCode = 0x10b
ErrCodeRequestCanceled ErrCode = 0x10c
ErrCodeRequestIncomplete ErrCode = 0x10d
ErrCodeMessageError ErrCode = 0x10e
ErrCodeConnectError ErrCode = 0x10f
ErrCodeVersionFallback ErrCode = 0x110
ErrCodeDatagramError ErrCode = 0x4a1268
)
func (e errorCode) String() string {
func (e ErrCode) String() string {
switch e {
case errorNoError:
case ErrCodeNoError:
return "H3_NO_ERROR"
case errorGeneralProtocolError:
case ErrCodeGeneralProtocolError:
return "H3_GENERAL_PROTOCOL_ERROR"
case errorInternalError:
case ErrCodeInternalError:
return "H3_INTERNAL_ERROR"
case errorStreamCreationError:
case ErrCodeStreamCreationError:
return "H3_STREAM_CREATION_ERROR"
case errorClosedCriticalStream:
case ErrCodeClosedCriticalStream:
return "H3_CLOSED_CRITICAL_STREAM"
case errorFrameUnexpected:
case ErrCodeFrameUnexpected:
return "H3_FRAME_UNEXPECTED"
case errorFrameError:
case ErrCodeFrameError:
return "H3_FRAME_ERROR"
case errorExcessiveLoad:
case ErrCodeExcessiveLoad:
return "H3_EXCESSIVE_LOAD"
case errorIDError:
case ErrCodeIDError:
return "H3_ID_ERROR"
case errorSettingsError:
case ErrCodeSettingsError:
return "H3_SETTINGS_ERROR"
case errorMissingSettings:
case ErrCodeMissingSettings:
return "H3_MISSING_SETTINGS"
case errorRequestRejected:
case ErrCodeRequestRejected:
return "H3_REQUEST_REJECTED"
case errorRequestCanceled:
case ErrCodeRequestCanceled:
return "H3_REQUEST_CANCELLED"
case errorRequestIncomplete:
case ErrCodeRequestIncomplete:
return "H3_INCOMPLETE_REQUEST"
case errorMessageError:
case ErrCodeMessageError:
return "H3_MESSAGE_ERROR"
case errorConnectError:
case ErrCodeConnectError:
return "H3_CONNECT_ERROR"
case errorVersionFallback:
case ErrCodeVersionFallback:
return "H3_VERSION_FALLBACK"
case errorDatagramError:
case ErrCodeDatagramError:
return "H3_DATAGRAM_ERROR"
default:
return fmt.Sprintf("unknown error code: %#x", uint16(e))

6
vendor/github.com/quic-go/quic-go/http3/mockgen.go generated vendored Normal file
View File

@ -0,0 +1,6 @@
//go:build gomock || generate
package http3
//go:generate sh -c "go run github.com/golang/mock/mockgen -build_flags=\"-tags=gomock\" -package http3 -destination mock_roundtripcloser_test.go github.com/quic-go/quic-go/http3 RoundTripCloser"
type RoundTripCloser = roundTripCloser

View File

@ -16,6 +16,9 @@
"github.com/quic-go/quic-go"
)
// declare this as a variable, such that we can it mock it in the tests
var quicDialer = quic.DialEarlyContext
type roundTripCloser interface {
RoundTripOpt(*http.Request, RoundTripOpt) (*http.Response, error)
HandshakeComplete() bool
@ -69,7 +72,8 @@ type RoundTripper struct {
// Dial specifies an optional dial function for creating QUIC
// connections for requests.
// If Dial is nil, quic.DialAddrEarlyContext will be used.
// If Dial is nil, a UDPConn will be created at the first request
// and will be reused for subsequent connections to other servers.
Dial func(ctx context.Context, addr string, tlsCfg *tls.Config, cfg *quic.Config) (quic.EarlyConnection, error)
// MaxResponseHeaderBytes specifies a limit on how many response bytes are
@ -79,6 +83,7 @@ type RoundTripper struct {
newClient func(hostname string, tlsConf *tls.Config, opts *roundTripperOpts, conf *quic.Config, dialer dialFunc) (roundTripCloser, error) // so we can mock it in tests
clients map[string]roundTripCloser
udpConn *net.UDPConn
}
// RoundTripOpt are options for the Transport.RoundTripOpt method.
@ -105,6 +110,10 @@ func (r *RoundTripper) RoundTripOpt(req *http.Request, opt RoundTripOpt) (*http.
closeRequestBody(req)
return nil, errors.New("http3: nil Request.URL")
}
if req.URL.Scheme != "https" {
closeRequestBody(req)
return nil, fmt.Errorf("http3: unsupported protocol scheme: %s", req.URL.Scheme)
}
if req.URL.Host == "" {
closeRequestBody(req)
return nil, errors.New("http3: no Host in request URL")
@ -113,10 +122,6 @@ func (r *RoundTripper) RoundTripOpt(req *http.Request, opt RoundTripOpt) (*http.
closeRequestBody(req)
return nil, errors.New("http3: nil Request.Header")
}
if req.URL.Scheme != "https" {
closeRequestBody(req)
return nil, fmt.Errorf("http3: unsupported protocol scheme: %s", req.URL.Scheme)
}
for k, vv := range req.Header {
if !httpguts.ValidHeaderFieldName(k) {
return nil, fmt.Errorf("http3: invalid http header field name %q", k)
@ -173,6 +178,16 @@ func (r *RoundTripper) getClient(hostname string, onlyCached bool) (rtc roundTri
if r.newClient != nil {
newCl = r.newClient
}
dial := r.Dial
if dial == nil {
if r.udpConn == nil {
r.udpConn, err = net.ListenUDP("udp", nil)
if err != nil {
return nil, false, err
}
}
dial = r.makeDialer()
}
client, err = newCl(
hostname,
r.TLSClientConfig,
@ -184,7 +199,7 @@ func (r *RoundTripper) getClient(hostname string, onlyCached bool) (rtc roundTri
UniStreamHijacker: r.UniStreamHijacker,
},
r.QuicConfig,
r.Dial,
dial,
)
if err != nil {
return nil, false, err
@ -205,7 +220,8 @@ func (r *RoundTripper) removeClient(hostname string) {
delete(r.clients, hostname)
}
// Close closes the QUIC connections that this RoundTripper has used
// Close closes the QUIC connections that this RoundTripper has used.
// It also closes the underlying UDPConn if it is not nil.
func (r *RoundTripper) Close() error {
r.mutex.Lock()
defer r.mutex.Unlock()
@ -215,6 +231,10 @@ func (r *RoundTripper) Close() error {
}
}
r.clients = nil
if r.udpConn != nil {
r.udpConn.Close()
r.udpConn = nil
}
return nil
}
@ -245,3 +265,14 @@ func validMethod(method string) bool {
func isNotToken(r rune) bool {
return !httpguts.IsTokenRune(r)
}
// makeDialer makes a QUIC dialer using r.udpConn.
func (r *RoundTripper) makeDialer() func(ctx context.Context, addr string, tlsCfg *tls.Config, cfg *quic.Config) (quic.EarlyConnection, error) {
return func(ctx context.Context, addr string, tlsCfg *tls.Config, cfg *quic.Config) (quic.EarlyConnection, error) {
udpAddr, err := net.ResolveUDPAddr("udp", addr)
if err != nil {
return nil, err
}
return quicDialer(ctx, r.udpConn, udpAddr, addr, tlsCfg, cfg)
}
}

View File

@ -14,7 +14,6 @@
"time"
"github.com/quic-go/quic-go"
"github.com/quic-go/quic-go/internal/handshake"
"github.com/quic-go/quic-go/internal/protocol"
"github.com/quic-go/quic-go/internal/utils"
"github.com/quic-go/quic-go/quicvarint"
@ -46,13 +45,15 @@
)
func versionToALPN(v protocol.VersionNumber) string {
if v == protocol.Version1 || v == protocol.Version2 {
//nolint:exhaustive // These are all the versions we care about.
switch v {
case protocol.Version1, protocol.Version2:
return NextProtoH3
}
if v == protocol.VersionTLS || v == protocol.VersionDraft29 {
case protocol.VersionDraft29:
return NextProtoH3Draft29
default:
return ""
}
return ""
}
// ConfigureTLSConfig creates a new tls.Config which can be used
@ -66,8 +67,9 @@ func ConfigureTLSConfig(tlsConf *tls.Config) *tls.Config {
GetConfigForClient: func(ch *tls.ClientHelloInfo) (*tls.Config, error) {
// determine the ALPN from the QUIC version used
proto := NextProtoH3
if qconn, ok := ch.Conn.(handshake.ConnWithVersion); ok {
proto = versionToALPN(qconn.GetQUICVersion())
val := ch.Context().Value(quic.QUICVersionContextKey)
if v, ok := val.(quic.VersionNumber); ok {
proto = versionToALPN(v)
}
config := tlsConf
if tlsConf.GetConfigForClient != nil {
@ -107,15 +109,15 @@ func (k *contextKey) String() string { return "quic-go/http3 context value " + k
type requestError struct {
err error
streamErr errorCode
connErr errorCode
streamErr ErrCode
connErr ErrCode
}
func newStreamError(code errorCode, err error) requestError {
func newStreamError(code ErrCode, err error) requestError {
return requestError{err: err, streamErr: code}
}
func newConnError(code errorCode, err error) requestError {
func newConnError(code ErrCode, err error) requestError {
return requestError{err: err, connErr: code}
}
@ -442,14 +444,14 @@ func (s *Server) handleConn(conn quic.Connection) error {
str, err := conn.AcceptStream(context.Background())
if err != nil {
var appErr *quic.ApplicationError
if errors.As(err, &appErr) && appErr.ErrorCode == quic.ApplicationErrorCode(errorNoError) {
if errors.As(err, &appErr) && appErr.ErrorCode == quic.ApplicationErrorCode(ErrCodeNoError) {
return nil
}
return fmt.Errorf("accepting stream failed: %w", err)
}
go func() {
rerr := s.handleRequest(conn, str, decoder, func() {
conn.CloseWithError(quic.ApplicationErrorCode(errorFrameUnexpected), "")
conn.CloseWithError(quic.ApplicationErrorCode(ErrCodeFrameUnexpected), "")
})
if rerr.err == errHijacked {
return
@ -498,23 +500,23 @@ func (s *Server) handleUnidirectionalStreams(conn quic.Connection) {
// TODO: check that only one stream of each type is opened.
return
case streamTypePushStream: // only the server can push
conn.CloseWithError(quic.ApplicationErrorCode(errorStreamCreationError), "")
conn.CloseWithError(quic.ApplicationErrorCode(ErrCodeStreamCreationError), "")
return
default:
if s.UniStreamHijacker != nil && s.UniStreamHijacker(StreamType(streamType), conn, str, nil) {
return
}
str.CancelRead(quic.StreamErrorCode(errorStreamCreationError))
str.CancelRead(quic.StreamErrorCode(ErrCodeStreamCreationError))
return
}
f, err := parseNextFrame(str, nil)
if err != nil {
conn.CloseWithError(quic.ApplicationErrorCode(errorFrameError), "")
conn.CloseWithError(quic.ApplicationErrorCode(ErrCodeFrameError), "")
return
}
sf, ok := f.(*settingsFrame)
if !ok {
conn.CloseWithError(quic.ApplicationErrorCode(errorMissingSettings), "")
conn.CloseWithError(quic.ApplicationErrorCode(ErrCodeMissingSettings), "")
return
}
if !sf.Datagram {
@ -524,7 +526,7 @@ func (s *Server) handleUnidirectionalStreams(conn quic.Connection) {
// we can expect it to have been negotiated both on the transport and on the HTTP/3 layer.
// Note: ConnectionState() will block until the handshake is complete (relevant when using 0-RTT).
if s.EnableDatagrams && !conn.ConnectionState().SupportsDatagrams {
conn.CloseWithError(quic.ApplicationErrorCode(errorSettingsError), "missing QUIC Datagram support")
conn.CloseWithError(quic.ApplicationErrorCode(ErrCodeSettingsError), "missing QUIC Datagram support")
}
}(str)
}
@ -547,28 +549,28 @@ func (s *Server) handleRequest(conn quic.Connection, str quic.Stream, decoder *q
if err == errHijacked {
return requestError{err: errHijacked}
}
return newStreamError(errorRequestIncomplete, err)
return newStreamError(ErrCodeRequestIncomplete, err)
}
hf, ok := frame.(*headersFrame)
if !ok {
return newConnError(errorFrameUnexpected, errors.New("expected first frame to be a HEADERS frame"))
return newConnError(ErrCodeFrameUnexpected, errors.New("expected first frame to be a HEADERS frame"))
}
if hf.Length > s.maxHeaderBytes() {
return newStreamError(errorFrameError, fmt.Errorf("HEADERS frame too large: %d bytes (max: %d)", hf.Length, s.maxHeaderBytes()))
return newStreamError(ErrCodeFrameError, fmt.Errorf("HEADERS frame too large: %d bytes (max: %d)", hf.Length, s.maxHeaderBytes()))
}
headerBlock := make([]byte, hf.Length)
if _, err := io.ReadFull(str, headerBlock); err != nil {
return newStreamError(errorRequestIncomplete, err)
return newStreamError(ErrCodeRequestIncomplete, err)
}
hfs, err := decoder.DecodeFull(headerBlock)
if err != nil {
// TODO: use the right error code
return newConnError(errorGeneralProtocolError, err)
return newConnError(ErrCodeGeneralProtocolError, err)
}
req, err := requestFromHeaders(hfs)
if err != nil {
// TODO: use the right error code
return newStreamError(errorGeneralProtocolError, err)
return newStreamError(ErrCodeGeneralProtocolError, err)
}
connState := conn.ConnectionState().TLS.ConnectionState
@ -622,7 +624,7 @@ func() {
r.WriteHeader(http.StatusOK)
}
// If the EOF was read by the handler, CancelRead() is a no-op.
str.CancelRead(quic.StreamErrorCode(errorNoError))
str.CancelRead(quic.StreamErrorCode(ErrCodeNoError))
return requestError{}
}

View File

@ -57,6 +57,10 @@ type TokenStore interface {
type connTracingCtxKey struct{}
// QUICVersionContextKey can be used to find out the QUIC version of a TLS handshake from the
// context returned by tls.Config.ClientHelloInfo.Context.
var QUICVersionContextKey = handshake.QUICVersionContextKey
// Stream is the interface implemented by QUIC streams
// In addition to the errors listed on the Connection,
// calls to stream functions can return a StreamError if the stream is canceled.
@ -193,9 +197,10 @@ type EarlyConnection interface {
Connection
// HandshakeComplete blocks until the handshake completes (or fails).
// Data sent before completion of the handshake is encrypted with 1-RTT keys.
// Note that the client's identity hasn't been verified yet.
HandshakeComplete() context.Context
// For the client, data sent before completion of the handshake is encrypted with 0-RTT keys.
// For the serfer, data sent before completion of the handshake is encrypted with 1-RTT keys,
// however the client's identity is only verified once the handshake completes.
HandshakeComplete() <-chan struct{}
NextConnection() Connection
}

View File

@ -1,3 +1,6 @@
//go:build gomock || generate
package ackhandler
//go:generate sh -c "../../mockgen_private.sh ackhandler mock_sent_packet_tracker_test.go github.com/quic-go/quic-go/internal/ackhandler sentPacketTracker"
//go:generate sh -c "go run github.com/golang/mock/mockgen -build_flags=\"-tags=gomock\" -package ackhandler -destination mock_sent_packet_tracker_test.go github.com/quic-go/quic-go/internal/ackhandler SentPacketTracker"
type SentPacketTracker = sentPacketTracker

View File

@ -2,6 +2,7 @@
import (
"bytes"
"context"
"crypto/tls"
"errors"
"fmt"
@ -20,6 +21,10 @@
"github.com/quic-go/quic-go/quicvarint"
)
type quicVersionContextKey struct{}
var QUICVersionContextKey = &quicVersionContextKey{}
// TLS unexpected_message alert
const alertUnexpectedMessage uint8 = 10
@ -64,30 +69,25 @@ func (m messageType) String() string {
type conn struct {
localAddr, remoteAddr net.Addr
version protocol.VersionNumber
}
var _ ConnWithVersion = &conn{}
func newConn(local, remote net.Addr, version protocol.VersionNumber) ConnWithVersion {
return &conn{
localAddr: local,
remoteAddr: remote,
version: version,
}
}
var _ net.Conn = &conn{}
func (c *conn) Read([]byte) (int, error) { return 0, nil }
func (c *conn) Write([]byte) (int, error) { return 0, nil }
func (c *conn) Close() error { return nil }
func (c *conn) RemoteAddr() net.Addr { return c.remoteAddr }
func (c *conn) LocalAddr() net.Addr { return c.localAddr }
func (c *conn) SetReadDeadline(time.Time) error { return nil }
func (c *conn) SetWriteDeadline(time.Time) error { return nil }
func (c *conn) SetDeadline(time.Time) error { return nil }
func (c *conn) GetQUICVersion() protocol.VersionNumber { return c.version }
func newConn(local, remote net.Addr) net.Conn {
return &conn{
localAddr: local,
remoteAddr: remote,
}
}
func (c *conn) Read([]byte) (int, error) { return 0, nil }
func (c *conn) Write([]byte) (int, error) { return 0, nil }
func (c *conn) Close() error { return nil }
func (c *conn) RemoteAddr() net.Addr { return c.remoteAddr }
func (c *conn) LocalAddr() net.Addr { return c.localAddr }
func (c *conn) SetReadDeadline(time.Time) error { return nil }
func (c *conn) SetWriteDeadline(time.Time) error { return nil }
func (c *conn) SetDeadline(time.Time) error { return nil }
type cryptoSetup struct {
tlsConf *tls.Config
@ -183,7 +183,7 @@ func NewCryptoSetupClient(
protocol.PerspectiveClient,
version,
)
cs.conn = qtls.Client(newConn(localAddr, remoteAddr, version), cs.tlsConf, cs.extraConf)
cs.conn = qtls.Client(newConn(localAddr, remoteAddr), cs.tlsConf, cs.extraConf)
return cs, clientHelloWritten
}
@ -218,7 +218,7 @@ func NewCryptoSetupServer(
version,
)
cs.allow0RTT = allow0RTT
cs.conn = qtls.Server(newConn(localAddr, remoteAddr, version), cs.tlsConf, cs.extraConf)
cs.conn = qtls.Server(newConn(localAddr, remoteAddr), cs.tlsConf, cs.extraConf)
return cs
}
@ -307,7 +307,7 @@ func (h *cryptoSetup) RunHandshake() {
handshakeErrChan := make(chan error, 1)
go func() {
defer close(h.handshakeDone)
if err := h.conn.Handshake(); err != nil {
if err := h.conn.HandshakeContext(context.WithValue(context.Background(), QUICVersionContextKey, h.version)); err != nil {
handshakeErrChan <- err
return
}
@ -408,8 +408,7 @@ func (h *cryptoSetup) HandleMessage(data []byte, encLevel protocol.EncryptionLev
func (h *cryptoSetup) checkEncryptionLevel(msgType messageType, encLevel protocol.EncryptionLevel) error {
var expected protocol.EncryptionLevel
switch msgType {
case typeClientHello,
typeServerHello:
case typeClientHello, typeServerHello:
expected = protocol.EncryptionInitial
case typeEncryptedExtensions,
typeCertificate,

View File

@ -3,7 +3,6 @@
import (
"errors"
"io"
"net"
"time"
"github.com/quic-go/quic-go/internal/protocol"
@ -93,10 +92,3 @@ type CryptoSetup interface {
Get0RTTSealer() (LongHeaderSealer, error)
Get1RTTSealer() (ShortHeaderSealer, error)
}
// ConnWithVersion is the connection used in the ClientHelloInfo.
// It can be used to determine the QUIC version in use.
type ConnWithVersion interface {
net.Conn
GetQUICVersion() protocol.VersionNumber
}

View File

@ -1,3 +1,6 @@
//go:build gomock || generate
package handshake
//go:generate sh -c "../../mockgen_private.sh handshake mock_handshake_runner_test.go github.com/quic-go/quic-go/internal/handshake handshakeRunner"
//go:generate sh -c "go run github.com/golang/mock/mockgen -build_flags=\"-tags=gomock\" -package handshake -destination mock_handshake_runner_test.go github.com/quic-go/quic-go/internal/handshake HandshakeRunner"
type HandshakeRunner = handshakeRunner

View File

@ -19,6 +19,10 @@
// It's a package-level variable to allow modifying it for testing purposes.
var KeyUpdateInterval uint64 = protocol.KeyUpdateInterval
// FirstKeyUpdateInterval is the maximum number of packets we send or receive before initiating the first key update.
// It's a package-level variable to allow modifying it for testing purposes.
var FirstKeyUpdateInterval uint64 = 100
type updatableAEAD struct {
suite *qtls.CipherSuiteTLS13
@ -27,7 +31,6 @@ type updatableAEAD struct {
firstPacketNumber protocol.PacketNumber
handshakeConfirmed bool
keyUpdateInterval uint64
invalidPacketLimit uint64
invalidPacketCount uint64
@ -74,7 +77,6 @@ func newUpdatableAEAD(rttStats *utils.RTTStats, tracer logging.ConnectionTracer,
largestAcked: protocol.InvalidPacketNumber,
firstRcvdWithCurrentKey: protocol.InvalidPacketNumber,
firstSentWithCurrentKey: protocol.InvalidPacketNumber,
keyUpdateInterval: KeyUpdateInterval,
rttStats: rttStats,
tracer: tracer,
logger: logger,
@ -116,6 +118,7 @@ func (a *updatableAEAD) getNextTrafficSecret(hash crypto.Hash, ts []byte) []byte
return hkdfExpandLabel(hash, ts, []byte{}, "quic ku", hash.Size())
}
// SetReadKey sets the read key.
// For the client, this function is called before SetWriteKey.
// For the server, this function is called after SetWriteKey.
func (a *updatableAEAD) SetReadKey(suite *qtls.CipherSuiteTLS13, trafficSecret []byte) {
@ -129,6 +132,7 @@ func (a *updatableAEAD) SetReadKey(suite *qtls.CipherSuiteTLS13, trafficSecret [
a.nextRcvAEAD = createAEAD(suite, a.nextRcvTrafficSecret, a.version)
}
// SetWriteKey sets the write key.
// For the client, this function is called after SetReadKey.
// For the server, this function is called before SetWriteKey.
func (a *updatableAEAD) SetWriteKey(suite *qtls.CipherSuiteTLS13, trafficSecret []byte) {
@ -284,11 +288,17 @@ func (a *updatableAEAD) shouldInitiateKeyUpdate() bool {
if !a.updateAllowed() {
return false
}
if a.numRcvdWithCurrentKey >= a.keyUpdateInterval {
// Initiate the first key update shortly after the handshake, in order to exercise the key update mechanism.
if a.keyPhase == 0 {
if a.numRcvdWithCurrentKey >= FirstKeyUpdateInterval || a.numSentWithCurrentKey >= FirstKeyUpdateInterval {
return true
}
}
if a.numRcvdWithCurrentKey >= KeyUpdateInterval {
a.logger.Debugf("Received %d packets with current key phase. Initiating key update to the next key phase: %d", a.numRcvdWithCurrentKey, a.keyPhase+1)
return true
}
if a.numSentWithCurrentKey >= a.keyUpdateInterval {
if a.numSentWithCurrentKey >= KeyUpdateInterval {
a.logger.Debugf("Sent %d packets with current key phase. Initiating key update to the next key phase: %d", a.numSentWithCurrentKey, a.keyPhase+1)
return true
}

View File

@ -18,12 +18,10 @@
// The version numbers, making grepping easier
const (
VersionTLS VersionNumber = 0x1
VersionWhatever VersionNumber = math.MaxUint32 - 1 // for when the version doesn't matter
VersionUnknown VersionNumber = math.MaxUint32
VersionDraft29 VersionNumber = 0xff00001d
Version1 VersionNumber = 0x1
Version2 VersionNumber = 0x6b3343cf
VersionUnknown VersionNumber = math.MaxUint32
VersionDraft29 VersionNumber = 0xff00001d
Version1 VersionNumber = 0x1
Version2 VersionNumber = 0x6b3343cf
)
// SupportedVersions lists the versions that the server supports
@ -32,19 +30,12 @@
// IsValidVersion says if the version is known to quic-go
func IsValidVersion(v VersionNumber) bool {
return v == VersionTLS || IsSupportedVersion(SupportedVersions, v)
return v == Version1 || IsSupportedVersion(SupportedVersions, v)
}
func (vn VersionNumber) String() string {
// For releases, VersionTLS will be set to a draft version.
// A switch statement can't contain duplicate cases.
if vn == VersionTLS && VersionTLS != VersionDraft29 && VersionTLS != Version1 {
return "TLS dev version (WIP)"
}
//nolint:exhaustive
switch vn {
case VersionWhatever:
return "whatever"
case VersionUnknown:
return "unknown"
case VersionDraft29:

View File

@ -6,6 +6,7 @@
"crypto"
"crypto/cipher"
"crypto/tls"
"fmt"
"net"
"unsafe"
@ -97,3 +98,48 @@ func CipherSuiteTLS13ByID(id uint16) *CipherSuiteTLS13 {
Hash: cs.Hash,
}
}
//go:linkname cipherSuitesTLS13 github.com/quic-go/qtls-go1-19.cipherSuitesTLS13
var cipherSuitesTLS13 []unsafe.Pointer
//go:linkname defaultCipherSuitesTLS13 github.com/quic-go/qtls-go1-19.defaultCipherSuitesTLS13
var defaultCipherSuitesTLS13 []uint16
//go:linkname defaultCipherSuitesTLS13NoAES github.com/quic-go/qtls-go1-19.defaultCipherSuitesTLS13NoAES
var defaultCipherSuitesTLS13NoAES []uint16
var cipherSuitesModified bool
// SetCipherSuite modifies the cipherSuiteTLS13 slice of cipher suites inside qtls
// such that it only contains the cipher suite with the chosen id.
// The reset function returned resets them back to the original value.
func SetCipherSuite(id uint16) (reset func()) {
if cipherSuitesModified {
panic("cipher suites modified multiple times without resetting")
}
cipherSuitesModified = true
origCipherSuitesTLS13 := append([]unsafe.Pointer{}, cipherSuitesTLS13...)
origDefaultCipherSuitesTLS13 := append([]uint16{}, defaultCipherSuitesTLS13...)
origDefaultCipherSuitesTLS13NoAES := append([]uint16{}, defaultCipherSuitesTLS13NoAES...)
// The order is given by the order of the slice elements in cipherSuitesTLS13 in qtls.
switch id {
case tls.TLS_AES_128_GCM_SHA256:
cipherSuitesTLS13 = cipherSuitesTLS13[:1]
case tls.TLS_CHACHA20_POLY1305_SHA256:
cipherSuitesTLS13 = cipherSuitesTLS13[1:2]
case tls.TLS_AES_256_GCM_SHA384:
cipherSuitesTLS13 = cipherSuitesTLS13[2:]
default:
panic(fmt.Sprintf("unexpected cipher suite: %d", id))
}
defaultCipherSuitesTLS13 = []uint16{id}
defaultCipherSuitesTLS13NoAES = []uint16{id}
return func() {
cipherSuitesTLS13 = origCipherSuitesTLS13
defaultCipherSuitesTLS13 = origDefaultCipherSuitesTLS13
defaultCipherSuitesTLS13NoAES = origDefaultCipherSuitesTLS13NoAES
cipherSuitesModified = false
}
}

View File

@ -6,6 +6,7 @@
"crypto"
"crypto/cipher"
"crypto/tls"
"fmt"
"net"
"unsafe"
@ -97,3 +98,48 @@ func CipherSuiteTLS13ByID(id uint16) *CipherSuiteTLS13 {
Hash: cs.Hash,
}
}
//go:linkname cipherSuitesTLS13 github.com/quic-go/qtls-go1-20.cipherSuitesTLS13
var cipherSuitesTLS13 []unsafe.Pointer
//go:linkname defaultCipherSuitesTLS13 github.com/quic-go/qtls-go1-20.defaultCipherSuitesTLS13
var defaultCipherSuitesTLS13 []uint16
//go:linkname defaultCipherSuitesTLS13NoAES github.com/quic-go/qtls-go1-20.defaultCipherSuitesTLS13NoAES
var defaultCipherSuitesTLS13NoAES []uint16
var cipherSuitesModified bool
// SetCipherSuite modifies the cipherSuiteTLS13 slice of cipher suites inside qtls
// such that it only contains the cipher suite with the chosen id.
// The reset function returned resets them back to the original value.
func SetCipherSuite(id uint16) (reset func()) {
if cipherSuitesModified {
panic("cipher suites modified multiple times without resetting")
}
cipherSuitesModified = true
origCipherSuitesTLS13 := append([]unsafe.Pointer{}, cipherSuitesTLS13...)
origDefaultCipherSuitesTLS13 := append([]uint16{}, defaultCipherSuitesTLS13...)
origDefaultCipherSuitesTLS13NoAES := append([]uint16{}, defaultCipherSuitesTLS13NoAES...)
// The order is given by the order of the slice elements in cipherSuitesTLS13 in qtls.
switch id {
case tls.TLS_AES_128_GCM_SHA256:
cipherSuitesTLS13 = cipherSuitesTLS13[:1]
case tls.TLS_CHACHA20_POLY1305_SHA256:
cipherSuitesTLS13 = cipherSuitesTLS13[1:2]
case tls.TLS_AES_256_GCM_SHA384:
cipherSuitesTLS13 = cipherSuitesTLS13[2:]
default:
panic(fmt.Sprintf("unexpected cipher suite: %d", id))
}
defaultCipherSuitesTLS13 = []uint16{id}
defaultCipherSuitesTLS13NoAES = []uint16{id}
return func() {
cipherSuitesTLS13 = origCipherSuitesTLS13
defaultCipherSuitesTLS13 = origDefaultCipherSuitesTLS13
defaultCipherSuitesTLS13NoAES = origDefaultCipherSuitesTLS13NoAES
cipherSuitesModified = false
}
}

View File

@ -22,12 +22,8 @@ type AckFrame struct {
}
// parseAckFrame reads an ACK frame
func parseAckFrame(r *bytes.Reader, ackDelayExponent uint8, _ protocol.VersionNumber) (*AckFrame, error) {
typeByte, err := r.ReadByte()
if err != nil {
return nil, err
}
ecn := typeByte&0x1 > 0
func parseAckFrame(r *bytes.Reader, typ uint64, ackDelayExponent uint8, _ protocol.VersionNumber) (*AckFrame, error) {
ecn := typ == ackECNFrameType
frame := GetAckFrame()
@ -110,9 +106,9 @@ func parseAckFrame(r *bytes.Reader, ackDelayExponent uint8, _ protocol.VersionNu
func (f *AckFrame) Append(b []byte, _ protocol.VersionNumber) ([]byte, error) {
hasECN := f.ECT0 > 0 || f.ECT1 > 0 || f.ECNCE > 0
if hasECN {
b = append(b, 0b11)
b = append(b, ackECNFrameType)
} else {
b = append(b, 0b10)
b = append(b, ackFrameType)
}
b = quicvarint.Append(b, uint64(f.LargestAcked()))
b = quicvarint.Append(b, encodeAckDelay(f.DelayTime))

View File

@ -16,13 +16,8 @@ type ConnectionCloseFrame struct {
ReasonPhrase string
}
func parseConnectionCloseFrame(r *bytes.Reader, _ protocol.VersionNumber) (*ConnectionCloseFrame, error) {
typeByte, err := r.ReadByte()
if err != nil {
return nil, err
}
f := &ConnectionCloseFrame{IsApplicationError: typeByte == 0x1d}
func parseConnectionCloseFrame(r *bytes.Reader, typ uint64, _ protocol.VersionNumber) (*ConnectionCloseFrame, error) {
f := &ConnectionCloseFrame{IsApplicationError: typ == applicationCloseFrameType}
ec, err := quicvarint.Read(r)
if err != nil {
return nil, err
@ -68,9 +63,9 @@ func (f *ConnectionCloseFrame) Length(protocol.VersionNumber) protocol.ByteCount
func (f *ConnectionCloseFrame) Append(b []byte, _ protocol.VersionNumber) ([]byte, error) {
if f.IsApplicationError {
b = append(b, 0x1d)
b = append(b, applicationCloseFrameType)
} else {
b = append(b, 0x1c)
b = append(b, connectionCloseFrameType)
}
b = quicvarint.Append(b, f.ErrorCode)

View File

@ -15,10 +15,6 @@ type CryptoFrame struct {
}
func parseCryptoFrame(r *bytes.Reader, _ protocol.VersionNumber) (*CryptoFrame, error) {
if _, err := r.ReadByte(); err != nil {
return nil, err
}
frame := &CryptoFrame{}
offset, err := quicvarint.Read(r)
if err != nil {
@ -43,7 +39,7 @@ func parseCryptoFrame(r *bytes.Reader, _ protocol.VersionNumber) (*CryptoFrame,
}
func (f *CryptoFrame) Append(b []byte, _ protocol.VersionNumber) ([]byte, error) {
b = append(b, 0x6)
b = append(b, cryptoFrameType)
b = quicvarint.Append(b, uint64(f.Offset))
b = quicvarint.Append(b, uint64(len(f.Data)))
b = append(b, f.Data...)

View File

@ -13,22 +13,16 @@ type DataBlockedFrame struct {
}
func parseDataBlockedFrame(r *bytes.Reader, _ protocol.VersionNumber) (*DataBlockedFrame, error) {
if _, err := r.ReadByte(); err != nil {
return nil, err
}
offset, err := quicvarint.Read(r)
if err != nil {
return nil, err
}
return &DataBlockedFrame{
MaximumData: protocol.ByteCount(offset),
}, nil
return &DataBlockedFrame{MaximumData: protocol.ByteCount(offset)}, nil
}
func (f *DataBlockedFrame) Append(b []byte, version protocol.VersionNumber) ([]byte, error) {
b = append(b, 0x14)
b = quicvarint.Append(b, uint64(f.MaximumData))
return b, nil
b = append(b, dataBlockedFrameType)
return quicvarint.Append(b, uint64(f.MaximumData)), nil
}
// Length of a written frame

View File

@ -14,14 +14,9 @@ type DatagramFrame struct {
Data []byte
}
func parseDatagramFrame(r *bytes.Reader, _ protocol.VersionNumber) (*DatagramFrame, error) {
typeByte, err := r.ReadByte()
if err != nil {
return nil, err
}
func parseDatagramFrame(r *bytes.Reader, typ uint64, _ protocol.VersionNumber) (*DatagramFrame, error) {
f := &DatagramFrame{}
f.DataLenPresent = typeByte&0x1 > 0
f.DataLenPresent = typ&0x1 > 0
var length uint64
if f.DataLenPresent {
@ -45,11 +40,11 @@ func parseDatagramFrame(r *bytes.Reader, _ protocol.VersionNumber) (*DatagramFra
}
func (f *DatagramFrame) Append(b []byte, _ protocol.VersionNumber) ([]byte, error) {
typeByte := uint8(0x30)
typ := uint8(0x30)
if f.DataLenPresent {
typeByte ^= 0b1
typ ^= 0b1
}
b = append(b, typeByte)
b = append(b, typ)
if f.DataLenPresent {
b = quicvarint.Append(b, uint64(len(f.Data)))
}

View File

@ -8,6 +8,32 @@
"github.com/quic-go/quic-go/internal/protocol"
"github.com/quic-go/quic-go/internal/qerr"
"github.com/quic-go/quic-go/quicvarint"
)
const (
pingFrameType = 0x1
ackFrameType = 0x2
ackECNFrameType = 0x3
resetStreamFrameType = 0x4
stopSendingFrameType = 0x5
cryptoFrameType = 0x6
newTokenFrameType = 0x7
maxDataFrameType = 0x10
maxStreamDataFrameType = 0x11
bidiMaxStreamsFrameType = 0x12
uniMaxStreamsFrameType = 0x13
dataBlockedFrameType = 0x14
streamDataBlockedFrameType = 0x15
bidiStreamBlockedFrameType = 0x16
uniStreamBlockedFrameType = 0x17
newConnectionIDFrameType = 0x18
retireConnectionIDFrameType = 0x19
pathChallengeFrameType = 0x1a
pathResponseFrameType = 0x1b
connectionCloseFrameType = 0x1c
applicationCloseFrameType = 0x1d
handshakeDoneFrameType = 0x1e
)
type frameParser struct {
@ -41,16 +67,21 @@ func (p *frameParser) ParseNext(data []byte, encLevel protocol.EncryptionLevel,
func (p *frameParser) parseNext(r *bytes.Reader, encLevel protocol.EncryptionLevel, v protocol.VersionNumber) (Frame, error) {
for r.Len() != 0 {
typeByte, _ := p.r.ReadByte()
if typeByte == 0x0 { // PADDING frame
continue
}
r.UnreadByte()
f, err := p.parseFrame(r, typeByte, encLevel, v)
typ, err := quicvarint.Read(r)
if err != nil {
return nil, &qerr.TransportError{
FrameType: uint64(typeByte),
ErrorCode: qerr.FrameEncodingError,
ErrorMessage: err.Error(),
}
}
if typ == 0x0 { // skip PADDING frames
continue
}
f, err := p.parseFrame(r, typ, encLevel, v)
if err != nil {
return nil, &qerr.TransportError{
FrameType: typ,
ErrorCode: qerr.FrameEncodingError,
ErrorMessage: err.Error(),
}
@ -60,56 +91,56 @@ func (p *frameParser) parseNext(r *bytes.Reader, encLevel protocol.EncryptionLev
return nil, nil
}
func (p *frameParser) parseFrame(r *bytes.Reader, typeByte byte, encLevel protocol.EncryptionLevel, v protocol.VersionNumber) (Frame, error) {
func (p *frameParser) parseFrame(r *bytes.Reader, typ uint64, encLevel protocol.EncryptionLevel, v protocol.VersionNumber) (Frame, error) {
var frame Frame
var err error
if typeByte&0xf8 == 0x8 {
frame, err = parseStreamFrame(r, v)
if typ&0xf8 == 0x8 {
frame, err = parseStreamFrame(r, typ, v)
} else {
switch typeByte {
case 0x1:
frame, err = parsePingFrame(r, v)
case 0x2, 0x3:
switch typ {
case pingFrameType:
frame = &PingFrame{}
case ackFrameType, ackECNFrameType:
ackDelayExponent := p.ackDelayExponent
if encLevel != protocol.Encryption1RTT {
ackDelayExponent = protocol.DefaultAckDelayExponent
}
frame, err = parseAckFrame(r, ackDelayExponent, v)
case 0x4:
frame, err = parseAckFrame(r, typ, ackDelayExponent, v)
case resetStreamFrameType:
frame, err = parseResetStreamFrame(r, v)
case 0x5:
case stopSendingFrameType:
frame, err = parseStopSendingFrame(r, v)
case 0x6:
case cryptoFrameType:
frame, err = parseCryptoFrame(r, v)
case 0x7:
case newTokenFrameType:
frame, err = parseNewTokenFrame(r, v)
case 0x10:
case maxDataFrameType:
frame, err = parseMaxDataFrame(r, v)
case 0x11:
case maxStreamDataFrameType:
frame, err = parseMaxStreamDataFrame(r, v)
case 0x12, 0x13:
frame, err = parseMaxStreamsFrame(r, v)
case 0x14:
case bidiMaxStreamsFrameType, uniMaxStreamsFrameType:
frame, err = parseMaxStreamsFrame(r, typ, v)
case dataBlockedFrameType:
frame, err = parseDataBlockedFrame(r, v)
case 0x15:
case streamDataBlockedFrameType:
frame, err = parseStreamDataBlockedFrame(r, v)
case 0x16, 0x17:
frame, err = parseStreamsBlockedFrame(r, v)
case 0x18:
case bidiStreamBlockedFrameType, uniStreamBlockedFrameType:
frame, err = parseStreamsBlockedFrame(r, typ, v)
case newConnectionIDFrameType:
frame, err = parseNewConnectionIDFrame(r, v)
case 0x19:
case retireConnectionIDFrameType:
frame, err = parseRetireConnectionIDFrame(r, v)
case 0x1a:
case pathChallengeFrameType:
frame, err = parsePathChallengeFrame(r, v)
case 0x1b:
case pathResponseFrameType:
frame, err = parsePathResponseFrame(r, v)
case 0x1c, 0x1d:
frame, err = parseConnectionCloseFrame(r, v)
case 0x1e:
frame, err = parseHandshakeDoneFrame(r, v)
case connectionCloseFrameType, applicationCloseFrameType:
frame, err = parseConnectionCloseFrame(r, typ, v)
case handshakeDoneFrameType:
frame = &HandshakeDoneFrame{}
case 0x30, 0x31:
if p.supportsDatagrams {
frame, err = parseDatagramFrame(r, v)
frame, err = parseDatagramFrame(r, typ, v)
break
}
fallthrough

View File

@ -1,24 +1,14 @@
package wire
import (
"bytes"
"github.com/quic-go/quic-go/internal/protocol"
)
// A HandshakeDoneFrame is a HANDSHAKE_DONE frame
type HandshakeDoneFrame struct{}
// ParseHandshakeDoneFrame parses a HandshakeDone frame
func parseHandshakeDoneFrame(r *bytes.Reader, _ protocol.VersionNumber) (*HandshakeDoneFrame, error) {
if _, err := r.ReadByte(); err != nil {
return nil, err
}
return &HandshakeDoneFrame{}, nil
}
func (f *HandshakeDoneFrame) Append(b []byte, _ protocol.VersionNumber) ([]byte, error) {
return append(b, 0x1e), nil
return append(b, handshakeDoneFrameType), nil
}
// Length of a written frame

View File

@ -108,13 +108,15 @@ func Is0RTTPacket(b []byte) bool {
return false
}
version := protocol.VersionNumber(binary.BigEndian.Uint32(b[1:5]))
if !protocol.IsSupportedVersion(protocol.SupportedVersions, version) {
//nolint:exhaustive // We only need to test QUIC versions that we support.
switch version {
case protocol.Version1, protocol.VersionDraft29:
return b[0]>>4&0b11 == 0b01
case protocol.Version2:
return b[0]>>4&0b11 == 0b10
default:
return false
}
if version == protocol.Version2 {
return b[0]>>4&0b11 == 0b10
}
return b[0]>>4&0b11 == 0b01
}
var ErrUnsupportedVersion = errors.New("unsupported version")

View File

@ -14,10 +14,6 @@ type MaxDataFrame struct {
// parseMaxDataFrame parses a MAX_DATA frame
func parseMaxDataFrame(r *bytes.Reader, _ protocol.VersionNumber) (*MaxDataFrame, error) {
if _, err := r.ReadByte(); err != nil {
return nil, err
}
frame := &MaxDataFrame{}
byteOffset, err := quicvarint.Read(r)
if err != nil {
@ -27,9 +23,8 @@ func parseMaxDataFrame(r *bytes.Reader, _ protocol.VersionNumber) (*MaxDataFrame
return frame, nil
}
// Write writes a MAX_STREAM_DATA frame
func (f *MaxDataFrame) Append(b []byte, _ protocol.VersionNumber) ([]byte, error) {
b = append(b, 0x10)
b = append(b, maxDataFrameType)
b = quicvarint.Append(b, uint64(f.MaximumData))
return b, nil
}

View File

@ -14,10 +14,6 @@ type MaxStreamDataFrame struct {
}
func parseMaxStreamDataFrame(r *bytes.Reader, _ protocol.VersionNumber) (*MaxStreamDataFrame, error) {
if _, err := r.ReadByte(); err != nil {
return nil, err
}
sid, err := quicvarint.Read(r)
if err != nil {
return nil, err
@ -34,7 +30,7 @@ func parseMaxStreamDataFrame(r *bytes.Reader, _ protocol.VersionNumber) (*MaxStr
}
func (f *MaxStreamDataFrame) Append(b []byte, version protocol.VersionNumber) ([]byte, error) {
b = append(b, 0x11)
b = append(b, maxStreamDataFrameType)
b = quicvarint.Append(b, uint64(f.StreamID))
b = quicvarint.Append(b, uint64(f.MaximumStreamData))
return b, nil

View File

@ -14,17 +14,12 @@ type MaxStreamsFrame struct {
MaxStreamNum protocol.StreamNum
}
func parseMaxStreamsFrame(r *bytes.Reader, _ protocol.VersionNumber) (*MaxStreamsFrame, error) {
typeByte, err := r.ReadByte()
if err != nil {
return nil, err
}
func parseMaxStreamsFrame(r *bytes.Reader, typ uint64, _ protocol.VersionNumber) (*MaxStreamsFrame, error) {
f := &MaxStreamsFrame{}
switch typeByte {
case 0x12:
switch typ {
case bidiMaxStreamsFrameType:
f.Type = protocol.StreamTypeBidi
case 0x13:
case uniMaxStreamsFrameType:
f.Type = protocol.StreamTypeUni
}
streamID, err := quicvarint.Read(r)
@ -41,9 +36,9 @@ func parseMaxStreamsFrame(r *bytes.Reader, _ protocol.VersionNumber) (*MaxStream
func (f *MaxStreamsFrame) Append(b []byte, _ protocol.VersionNumber) ([]byte, error) {
switch f.Type {
case protocol.StreamTypeBidi:
b = append(b, 0x12)
b = append(b, bidiMaxStreamsFrameType)
case protocol.StreamTypeUni:
b = append(b, 0x13)
b = append(b, uniMaxStreamsFrameType)
}
b = quicvarint.Append(b, uint64(f.MaxStreamNum))
return b, nil

View File

@ -18,10 +18,6 @@ type NewConnectionIDFrame struct {
}
func parseNewConnectionIDFrame(r *bytes.Reader, _ protocol.VersionNumber) (*NewConnectionIDFrame, error) {
if _, err := r.ReadByte(); err != nil {
return nil, err
}
seq, err := quicvarint.Read(r)
if err != nil {
return nil, err
@ -58,7 +54,7 @@ func parseNewConnectionIDFrame(r *bytes.Reader, _ protocol.VersionNumber) (*NewC
}
func (f *NewConnectionIDFrame) Append(b []byte, _ protocol.VersionNumber) ([]byte, error) {
b = append(b, 0x18)
b = append(b, newConnectionIDFrameType)
b = quicvarint.Append(b, f.SequenceNumber)
b = quicvarint.Append(b, f.RetirePriorTo)
connIDLen := f.ConnectionID.Len()

View File

@ -15,9 +15,6 @@ type NewTokenFrame struct {
}
func parseNewTokenFrame(r *bytes.Reader, _ protocol.VersionNumber) (*NewTokenFrame, error) {
if _, err := r.ReadByte(); err != nil {
return nil, err
}
tokenLen, err := quicvarint.Read(r)
if err != nil {
return nil, err
@ -36,7 +33,7 @@ func parseNewTokenFrame(r *bytes.Reader, _ protocol.VersionNumber) (*NewTokenFra
}
func (f *NewTokenFrame) Append(b []byte, _ protocol.VersionNumber) ([]byte, error) {
b = append(b, 0x7)
b = append(b, newTokenFrameType)
b = quicvarint.Append(b, uint64(len(f.Token)))
b = append(b, f.Token...)
return b, nil

View File

@ -13,9 +13,6 @@ type PathChallengeFrame struct {
}
func parsePathChallengeFrame(r *bytes.Reader, _ protocol.VersionNumber) (*PathChallengeFrame, error) {
if _, err := r.ReadByte(); err != nil {
return nil, err
}
frame := &PathChallengeFrame{}
if _, err := io.ReadFull(r, frame.Data[:]); err != nil {
if err == io.ErrUnexpectedEOF {
@ -27,7 +24,7 @@ func parsePathChallengeFrame(r *bytes.Reader, _ protocol.VersionNumber) (*PathCh
}
func (f *PathChallengeFrame) Append(b []byte, _ protocol.VersionNumber) ([]byte, error) {
b = append(b, 0x1a)
b = append(b, pathChallengeFrameType)
b = append(b, f.Data[:]...)
return b, nil
}

View File

@ -13,9 +13,6 @@ type PathResponseFrame struct {
}
func parsePathResponseFrame(r *bytes.Reader, _ protocol.VersionNumber) (*PathResponseFrame, error) {
if _, err := r.ReadByte(); err != nil {
return nil, err
}
frame := &PathResponseFrame{}
if _, err := io.ReadFull(r, frame.Data[:]); err != nil {
if err == io.ErrUnexpectedEOF {
@ -27,7 +24,7 @@ func parsePathResponseFrame(r *bytes.Reader, _ protocol.VersionNumber) (*PathRes
}
func (f *PathResponseFrame) Append(b []byte, _ protocol.VersionNumber) ([]byte, error) {
b = append(b, 0x1b)
b = append(b, pathResponseFrameType)
b = append(b, f.Data[:]...)
return b, nil
}

View File

@ -1,23 +1,14 @@
package wire
import (
"bytes"
"github.com/quic-go/quic-go/internal/protocol"
)
// A PingFrame is a PING frame
type PingFrame struct{}
func parsePingFrame(r *bytes.Reader, _ protocol.VersionNumber) (*PingFrame, error) {
if _, err := r.ReadByte(); err != nil {
return nil, err
}
return &PingFrame{}, nil
}
func (f *PingFrame) Append(b []byte, _ protocol.VersionNumber) ([]byte, error) {
return append(b, 0x1), nil
return append(b, pingFrameType), nil
}
// Length of a written frame

View File

@ -16,10 +16,6 @@ type ResetStreamFrame struct {
}
func parseResetStreamFrame(r *bytes.Reader, _ protocol.VersionNumber) (*ResetStreamFrame, error) {
if _, err := r.ReadByte(); err != nil { // read the TypeByte
return nil, err
}
var streamID protocol.StreamID
var byteOffset protocol.ByteCount
sid, err := quicvarint.Read(r)
@ -45,7 +41,7 @@ func parseResetStreamFrame(r *bytes.Reader, _ protocol.VersionNumber) (*ResetStr
}
func (f *ResetStreamFrame) Append(b []byte, _ protocol.VersionNumber) ([]byte, error) {
b = append(b, 0x4)
b = append(b, resetStreamFrameType)
b = quicvarint.Append(b, uint64(f.StreamID))
b = quicvarint.Append(b, uint64(f.ErrorCode))
b = quicvarint.Append(b, uint64(f.FinalSize))

View File

@ -13,10 +13,6 @@ type RetireConnectionIDFrame struct {
}
func parseRetireConnectionIDFrame(r *bytes.Reader, _ protocol.VersionNumber) (*RetireConnectionIDFrame, error) {
if _, err := r.ReadByte(); err != nil {
return nil, err
}
seq, err := quicvarint.Read(r)
if err != nil {
return nil, err
@ -25,7 +21,7 @@ func parseRetireConnectionIDFrame(r *bytes.Reader, _ protocol.VersionNumber) (*R
}
func (f *RetireConnectionIDFrame) Append(b []byte, _ protocol.VersionNumber) ([]byte, error) {
b = append(b, 0x19)
b = append(b, retireConnectionIDFrameType)
b = quicvarint.Append(b, f.SequenceNumber)
return b, nil
}

View File

@ -16,10 +16,6 @@ type StopSendingFrame struct {
// parseStopSendingFrame parses a STOP_SENDING frame
func parseStopSendingFrame(r *bytes.Reader, _ protocol.VersionNumber) (*StopSendingFrame, error) {
if _, err := r.ReadByte(); err != nil {
return nil, err
}
streamID, err := quicvarint.Read(r)
if err != nil {
return nil, err
@ -41,7 +37,7 @@ func (f *StopSendingFrame) Length(_ protocol.VersionNumber) protocol.ByteCount {
}
func (f *StopSendingFrame) Append(b []byte, _ protocol.VersionNumber) ([]byte, error) {
b = append(b, 0x5)
b = append(b, stopSendingFrameType)
b = quicvarint.Append(b, uint64(f.StreamID))
b = quicvarint.Append(b, uint64(f.ErrorCode))
return b, nil

View File

@ -14,10 +14,6 @@ type StreamDataBlockedFrame struct {
}
func parseStreamDataBlockedFrame(r *bytes.Reader, _ protocol.VersionNumber) (*StreamDataBlockedFrame, error) {
if _, err := r.ReadByte(); err != nil {
return nil, err
}
sid, err := quicvarint.Read(r)
if err != nil {
return nil, err

View File

@ -20,15 +20,10 @@ type StreamFrame struct {
fromPool bool
}
func parseStreamFrame(r *bytes.Reader, _ protocol.VersionNumber) (*StreamFrame, error) {
typeByte, err := r.ReadByte()
if err != nil {
return nil, err
}
hasOffset := typeByte&0b100 > 0
fin := typeByte&0b1 > 0
hasDataLen := typeByte&0b10 > 0
func parseStreamFrame(r *bytes.Reader, typ uint64, _ protocol.VersionNumber) (*StreamFrame, error) {
hasOffset := typ&0b100 > 0
fin := typ&0b1 > 0
hasDataLen := typ&0b10 > 0
streamID, err := quicvarint.Read(r)
if err != nil {
@ -89,18 +84,18 @@ func (f *StreamFrame) Append(b []byte, _ protocol.VersionNumber) ([]byte, error)
return nil, errors.New("StreamFrame: attempting to write empty frame without FIN")
}
typeByte := byte(0x8)
typ := byte(0x8)
if f.Fin {
typeByte ^= 0b1
typ ^= 0b1
}
hasOffset := f.Offset != 0
if f.DataLenPresent {
typeByte ^= 0b10
typ ^= 0b10
}
if hasOffset {
typeByte ^= 0b100
typ ^= 0b100
}
b = append(b, typeByte)
b = append(b, typ)
b = quicvarint.Append(b, uint64(f.StreamID))
if hasOffset {
b = quicvarint.Append(b, uint64(f.Offset))

View File

@ -14,17 +14,12 @@ type StreamsBlockedFrame struct {
StreamLimit protocol.StreamNum
}
func parseStreamsBlockedFrame(r *bytes.Reader, _ protocol.VersionNumber) (*StreamsBlockedFrame, error) {
typeByte, err := r.ReadByte()
if err != nil {
return nil, err
}
func parseStreamsBlockedFrame(r *bytes.Reader, typ uint64, _ protocol.VersionNumber) (*StreamsBlockedFrame, error) {
f := &StreamsBlockedFrame{}
switch typeByte {
case 0x16:
switch typ {
case bidiStreamBlockedFrameType:
f.Type = protocol.StreamTypeBidi
case 0x17:
case uniStreamBlockedFrameType:
f.Type = protocol.StreamTypeUni
}
streamLimit, err := quicvarint.Read(r)
@ -41,9 +36,9 @@ func parseStreamsBlockedFrame(r *bytes.Reader, _ protocol.VersionNumber) (*Strea
func (f *StreamsBlockedFrame) Append(b []byte, _ protocol.VersionNumber) ([]byte, error) {
switch f.Type {
case protocol.StreamTypeBidi:
b = append(b, 0x16)
b = append(b, bidiStreamBlockedFrameType)
case protocol.StreamTypeUni:
b = append(b, 0x17)
b = append(b, uniStreamBlockedFrameType)
}
b = quicvarint.Append(b, uint64(f.StreamLimit))
return b, nil

View File

@ -9,6 +9,7 @@
"math/rand"
"net"
"sort"
"sync"
"time"
"github.com/quic-go/quic-go/internal/protocol"
@ -17,10 +18,21 @@
"github.com/quic-go/quic-go/quicvarint"
)
// AdditionalTransportParametersClient are additional transport parameters that will be added
// to the client's transport parameters.
// This is not intended for production use, but _only_ to increase the size of the ClientHello beyond
// the usual size of less than 1 MTU.
var AdditionalTransportParametersClient map[uint64][]byte
const transportParameterMarshalingVersion = 1
var (
randomMutex sync.Mutex
random rand.Rand
)
func init() {
rand.Seed(time.Now().UTC().UnixNano())
random = *rand.New(rand.NewSource(time.Now().UnixNano()))
}
type transportParameterID uint64
@ -324,10 +336,12 @@ func (p *TransportParameters) Marshal(pers protocol.Perspective) []byte {
// add a greased value
b = quicvarint.Append(b, uint64(27+31*rand.Intn(100)))
length := rand.Intn(16)
randomMutex.Lock()
length := random.Intn(16)
b = quicvarint.Append(b, uint64(length))
b = b[:len(b)+length]
rand.Read(b[len(b)-length:])
random.Read(b[len(b)-length:])
randomMutex.Unlock()
// initial_max_stream_data_bidi_local
b = p.marshalVarintParam(b, initialMaxStreamDataBidiLocalParameterID, uint64(p.InitialMaxStreamDataBidiLocal))
@ -402,6 +416,15 @@ func (p *TransportParameters) Marshal(pers protocol.Perspective) []byte {
if p.MaxDatagramFrameSize != protocol.InvalidByteCount {
b = p.marshalVarintParam(b, maxDatagramFrameSizeParameterID, uint64(p.MaxDatagramFrameSize))
}
if pers == protocol.PerspectiveClient && len(AdditionalTransportParametersClient) > 0 {
for k, v := range AdditionalTransportParametersClient {
b = quicvarint.Append(b, k)
b = quicvarint.Append(b, uint64(len(v)))
b = append(b, v...)
}
}
return b
}

View File

@ -1,27 +1,77 @@
//go:build gomock || generate
package quic
//go:generate sh -c "./mockgen_private.sh quic mock_send_conn_test.go github.com/quic-go/quic-go sendConn"
//go:generate sh -c "./mockgen_private.sh quic mock_sender_test.go github.com/quic-go/quic-go sender"
//go:generate sh -c "./mockgen_private.sh quic mock_stream_internal_test.go github.com/quic-go/quic-go streamI"
//go:generate sh -c "./mockgen_private.sh quic mock_crypto_stream_test.go github.com/quic-go/quic-go cryptoStream"
//go:generate sh -c "./mockgen_private.sh quic mock_receive_stream_internal_test.go github.com/quic-go/quic-go receiveStreamI"
//go:generate sh -c "./mockgen_private.sh quic mock_send_stream_internal_test.go github.com/quic-go/quic-go sendStreamI"
//go:generate sh -c "./mockgen_private.sh quic mock_stream_sender_test.go github.com/quic-go/quic-go streamSender"
//go:generate sh -c "./mockgen_private.sh quic mock_stream_getter_test.go github.com/quic-go/quic-go streamGetter"
//go:generate sh -c "./mockgen_private.sh quic mock_crypto_data_handler_test.go github.com/quic-go/quic-go cryptoDataHandler"
//go:generate sh -c "./mockgen_private.sh quic mock_frame_source_test.go github.com/quic-go/quic-go frameSource"
//go:generate sh -c "./mockgen_private.sh quic mock_ack_frame_source_test.go github.com/quic-go/quic-go ackFrameSource"
//go:generate sh -c "./mockgen_private.sh quic mock_stream_manager_test.go github.com/quic-go/quic-go streamManager"
//go:generate sh -c "./mockgen_private.sh quic mock_sealing_manager_test.go github.com/quic-go/quic-go sealingManager"
//go:generate sh -c "./mockgen_private.sh quic mock_unpacker_test.go github.com/quic-go/quic-go unpacker"
//go:generate sh -c "./mockgen_private.sh quic mock_packer_test.go github.com/quic-go/quic-go packer"
//go:generate sh -c "./mockgen_private.sh quic mock_mtu_discoverer_test.go github.com/quic-go/quic-go mtuDiscoverer"
//go:generate sh -c "./mockgen_private.sh quic mock_conn_runner_test.go github.com/quic-go/quic-go connRunner"
//go:generate sh -c "./mockgen_private.sh quic mock_quic_conn_test.go github.com/quic-go/quic-go quicConn"
//go:generate sh -c "./mockgen_private.sh quic mock_packet_handler_test.go github.com/quic-go/quic-go packetHandler"
//go:generate sh -c "./mockgen_private.sh quic mock_unknown_packet_handler_test.go github.com/quic-go/quic-go unknownPacketHandler"
//go:generate sh -c "./mockgen_private.sh quic mock_packet_handler_manager_test.go github.com/quic-go/quic-go packetHandlerManager"
//go:generate sh -c "./mockgen_private.sh quic mock_multiplexer_test.go github.com/quic-go/quic-go multiplexer"
//go:generate sh -c "./mockgen_private.sh quic mock_batch_conn_test.go github.com/quic-go/quic-go batchConn"
//go:generate sh -c "go run github.com/golang/mock/mockgen -package quic -self_package github.com/quic-go/quic-go -destination mock_token_store_test.go github.com/quic-go/quic-go TokenStore"
//go:generate sh -c "go run github.com/golang/mock/mockgen -package quic -self_package github.com/quic-go/quic-go -destination mock_packetconn_test.go net PacketConn"
//go:generate sh -c "go run github.com/golang/mock/mockgen -build_flags=\"-tags=gomock\" -package quic -self_package github.com/quic-go/quic-go -destination mock_send_conn_test.go github.com/quic-go/quic-go SendConn"
type SendConn = sendConn
//go:generate sh -c "go run github.com/golang/mock/mockgen -build_flags=\"-tags=gomock\" -package quic -self_package github.com/quic-go/quic-go -destination mock_sender_test.go github.com/quic-go/quic-go Sender"
type Sender = sender
//go:generate sh -c "go run github.com/golang/mock/mockgen -build_flags=\"-tags=gomock\" -package quic -self_package github.com/quic-go/quic-go -destination mock_stream_internal_test.go github.com/quic-go/quic-go StreamI"
type StreamI = streamI
//go:generate sh -c "go run github.com/golang/mock/mockgen -build_flags=\"-tags=gomock\" -package quic -self_package github.com/quic-go/quic-go -destination mock_crypto_stream_test.go github.com/quic-go/quic-go CryptoStream"
type CryptoStream = cryptoStream
//go:generate sh -c "go run github.com/golang/mock/mockgen -build_flags=\"-tags=gomock\" -package quic -self_package github.com/quic-go/quic-go -destination mock_receive_stream_internal_test.go github.com/quic-go/quic-go ReceiveStreamI"
type ReceiveStreamI = receiveStreamI
//go:generate sh -c "go run github.com/golang/mock/mockgen -build_flags=\"-tags=gomock\" -package quic -self_package github.com/quic-go/quic-go -destination mock_send_stream_internal_test.go github.com/quic-go/quic-go SendStreamI"
type SendStreamI = sendStreamI
//go:generate sh -c "go run github.com/golang/mock/mockgen -build_flags=\"-tags=gomock\" -package quic -self_package github.com/quic-go/quic-go -destination mock_stream_getter_test.go github.com/quic-go/quic-go StreamGetter"
type StreamGetter = streamGetter
//go:generate sh -c "go run github.com/golang/mock/mockgen -build_flags=\"-tags=gomock\" -package quic -self_package github.com/quic-go/quic-go -destination mock_stream_sender_test.go github.com/quic-go/quic-go StreamSender"
type StreamSender = streamSender
//go:generate sh -c "go run github.com/golang/mock/mockgen -build_flags=\"-tags=gomock\" -package quic -self_package github.com/quic-go/quic-go -destination mock_crypto_data_handler_test.go github.com/quic-go/quic-go CryptoDataHandler"
type CryptoDataHandler = cryptoDataHandler
//go:generate sh -c "go run github.com/golang/mock/mockgen -build_flags=\"-tags=gomock\" -package quic -self_package github.com/quic-go/quic-go -destination mock_frame_source_test.go github.com/quic-go/quic-go FrameSource"
type FrameSource = frameSource
//go:generate sh -c "go run github.com/golang/mock/mockgen -build_flags=\"-tags=gomock\" -package quic -self_package github.com/quic-go/quic-go -destination mock_ack_frame_source_test.go github.com/quic-go/quic-go AckFrameSource"
type AckFrameSource = ackFrameSource
//go:generate sh -c "go run github.com/golang/mock/mockgen -build_flags=\"-tags=gomock\" -package quic -self_package github.com/quic-go/quic-go -destination mock_stream_manager_test.go github.com/quic-go/quic-go StreamManager"
type StreamManager = streamManager
//go:generate sh -c "go run github.com/golang/mock/mockgen -build_flags=\"-tags=gomock\" -package quic -self_package github.com/quic-go/quic-go -destination mock_sealing_manager_test.go github.com/quic-go/quic-go SealingManager"
type SealingManager = sealingManager
//go:generate sh -c "go run github.com/golang/mock/mockgen -build_flags=\"-tags=gomock\" -package quic -self_package github.com/quic-go/quic-go -destination mock_unpacker_test.go github.com/quic-go/quic-go Unpacker"
type Unpacker = unpacker
//go:generate sh -c "go run github.com/golang/mock/mockgen -build_flags=\"-tags=gomock\" -package quic -self_package github.com/quic-go/quic-go -destination mock_packer_test.go github.com/quic-go/quic-go Packer"
type Packer = packer
//go:generate sh -c "go run github.com/golang/mock/mockgen -build_flags=\"-tags=gomock\" -package quic -self_package github.com/quic-go/quic-go -destination mock_mtu_discoverer_test.go github.com/quic-go/quic-go MTUDiscoverer"
type MTUDiscoverer = mtuDiscoverer
//go:generate sh -c "go run github.com/golang/mock/mockgen -build_flags=\"-tags=gomock\" -package quic -self_package github.com/quic-go/quic-go -destination mock_conn_runner_test.go github.com/quic-go/quic-go ConnRunner"
type ConnRunner = connRunner
//go:generate sh -c "go run github.com/golang/mock/mockgen -build_flags=\"-tags=gomock\" -package quic -self_package github.com/quic-go/quic-go -destination mock_quic_conn_test.go github.com/quic-go/quic-go QUICConn"
type QUICConn = quicConn
//go:generate sh -c "go run github.com/golang/mock/mockgen -build_flags=\"-tags=gomock\" -package quic -self_package github.com/quic-go/quic-go -destination mock_packet_handler_test.go github.com/quic-go/quic-go PacketHandler"
type PacketHandler = packetHandler
//go:generate sh -c "go run github.com/golang/mock/mockgen -build_flags=\"-tags=gomock\" -package quic -self_package github.com/quic-go/quic-go -destination mock_unknown_packet_handler_test.go github.com/quic-go/quic-go UnknownPacketHandler"
type UnknownPacketHandler = unknownPacketHandler
//go:generate sh -c "go run github.com/golang/mock/mockgen -build_flags=\"-tags=gomock\" -package quic -self_package github.com/quic-go/quic-go -destination mock_packet_handler_manager_test.go github.com/quic-go/quic-go PacketHandlerManager"
type PacketHandlerManager = packetHandlerManager
//go:generate sh -c "go run github.com/golang/mock/mockgen -build_flags=\"-tags=gomock\" -package quic -self_package github.com/quic-go/quic-go -destination mock_multiplexer_test.go github.com/quic-go/quic-go Multiplexer"
type Multiplexer = multiplexer
// Need to use source mode for the batchConn, since reflect mode follows type aliases.
// See https://github.com/golang/mock/issues/244 for details.
//
//go:generate sh -c "go run github.com/golang/mock/mockgen -package quic -self_package github.com/quic-go/quic-go -source sys_conn_oob.go -destination mock_batch_conn_test.go -mock_names batchConn=MockBatchConn"
//go:generate sh -c "go run github.com/golang/mock/mockgen -package quic -self_package github.com/quic-go/quic-go -self_package github.com/quic-go/quic-go -destination mock_token_store_test.go github.com/quic-go/quic-go TokenStore"
//go:generate sh -c "go run github.com/golang/mock/mockgen -package quic -self_package github.com/quic-go/quic-go -self_package github.com/quic-go/quic-go -destination mock_packetconn_test.go net PacketConn"

View File

@ -1,49 +0,0 @@
#!/bin/bash
DEST=$2
PACKAGE=$3
TMPFILE="mockgen_tmp.go"
# uppercase the name of the interface
ORIG_INTERFACE_NAME=$4
INTERFACE_NAME="$(tr '[:lower:]' '[:upper:]' <<< ${ORIG_INTERFACE_NAME:0:1})${ORIG_INTERFACE_NAME:1}"
# Gather all files that contain interface definitions.
# These interfaces might be used as embedded interfaces,
# so we need to pass them to mockgen as aux_files.
AUX=()
for f in *.go; do
if [[ -z ${f##*_test.go} ]]; then
# skip test files
continue;
fi
if $(egrep -qe "type (.*) interface" $f); then
AUX+=("github.com/quic-go/quic-go=$f")
fi
done
# Find the file that defines the interface we're mocking.
for f in *.go; do
if [[ -z ${f##*_test.go} ]]; then
# skip test files
continue;
fi
INTERFACE=$(sed -n "/^type $ORIG_INTERFACE_NAME interface/,/^}/p" $f)
if [[ -n "$INTERFACE" ]]; then
SRC=$f
break
fi
done
if [[ -z "$INTERFACE" ]]; then
echo "Interface $ORIG_INTERFACE_NAME not found."
exit 1
fi
AUX_FILES=$(IFS=, ; echo "${AUX[*]}")
## create a public alias for the interface, so that mockgen can process it
echo -e "package $1\n" > $TMPFILE
echo "$INTERFACE" | sed "s/$ORIG_INTERFACE_NAME/$INTERFACE_NAME/" >> $TMPFILE
go run github.com/golang/mock/mockgen -package $1 -self_package $3 -destination $DEST -source=$TMPFILE -aux_files $AUX_FILES
sed "s/$TMPFILE/$SRC/" "$DEST" > "$DEST.new" && mv "$DEST.new" "$DEST"
rm "$TMPFILE"

View File

@ -417,6 +417,9 @@ func (h *packetHandlerMap) handlePacket(p *receivedPacket) {
}
if wire.Is0RTTPacket(p.data) {
if h.numZeroRTTEntries >= protocol.Max0RTTQueues {
if h.tracer != nil {
h.tracer.DroppedPacket(p.remoteAddr, logging.PacketType0RTT, p.Size(), logging.PacketDropDOSPrevention)
}
return
}
h.numZeroRTTEntries++
@ -456,8 +459,7 @@ func (h *packetHandlerMap) maybeHandleStatelessReset(data []byte) bool {
return false
}
var token protocol.StatelessResetToken
copy(token[:], data[len(data)-16:])
token := *(*protocol.StatelessResetToken)(data[len(data)-16:])
if sess, ok := h.resetTokens[token]; ok {
h.logger.Debugf("Received a stateless reset with token %#x. Closing connection.", token)
go sess.destroy(&StatelessResetError{Token: token})

View File

@ -157,11 +157,10 @@ func listenAddr(addr string, tlsConf *tls.Config, config *Config, acceptEarly bo
// and WriteMsgUDP will be used instead of ReadFrom and WriteTo to read/write
// packets. A single net.PacketConn only be used for a single call to Listen.
// The PacketConn can be used for simultaneous calls to Dial. QUIC connection
// IDs are used for demultiplexing the different connections. The tls.Config
// must not be nil and must contain a certificate configuration. The
// tls.Config.CipherSuites allows setting of TLS 1.3 cipher suites. Furthermore,
// it must define an application control (using NextProtos). The quic.Config may
// be nil, in that case the default values will be used.
// IDs are used for demultiplexing the different connections.
// The tls.Config must not be nil and must contain a certificate configuration.
// Furthermore, it must define an application control (using NextProtos).
// The quic.Config may be nil, in that case the default values will be used.
func Listen(conn net.PacketConn, tlsConf *tls.Config, config *Config) (Listener, error) {
return listen(conn, tlsConf, config, false)
}
@ -536,7 +535,7 @@ func (s *baseServer) handleNewConn(conn quicConn) {
} else {
// wait until the handshake is complete (or fails)
select {
case <-conn.HandshakeComplete().Done():
case <-conn.HandshakeComplete():
case <-connCtx.Done():
return
}

12
vendor/modules.txt vendored
View File

@ -58,8 +58,8 @@ github.com/jedisct1/go-dnsstamps
# github.com/jedisct1/go-hpke-compact v0.0.0-20230211184420-51d4440017ce
## explicit; go 1.19
github.com/jedisct1/go-hpke-compact
# github.com/jedisct1/go-minisign v0.0.0-20230211184525-1f273d8dc776
## explicit; go 1.19
# github.com/jedisct1/go-minisign v0.0.0-20230410063418-3d885d71f62c
## explicit; go 1.20
github.com/jedisct1/go-minisign
# github.com/jedisct1/xsecretbox v0.0.0-20230211185120-2025cdbb9f0f
## explicit; go 1.19
@ -70,7 +70,7 @@ github.com/k-sone/critbitgo
# github.com/kardianos/service v1.2.2
## explicit; go 1.12
github.com/kardianos/service
# github.com/miekg/dns v1.1.53
# github.com/miekg/dns v1.1.54
## explicit; go 1.19
github.com/miekg/dns
# github.com/onsi/ginkgo/v2 v2.2.0
@ -106,13 +106,13 @@ github.com/powerman/deepequal
# github.com/quic-go/qpack v0.4.0
## explicit; go 1.18
github.com/quic-go/qpack
# github.com/quic-go/qtls-go1-19 v0.2.1
# github.com/quic-go/qtls-go1-19 v0.3.2
## explicit; go 1.19
github.com/quic-go/qtls-go1-19
# github.com/quic-go/qtls-go1-20 v0.1.1
# github.com/quic-go/qtls-go1-20 v0.2.2
## explicit; go 1.20
github.com/quic-go/qtls-go1-20
# github.com/quic-go/quic-go v0.33.0
# github.com/quic-go/quic-go v0.34.0
## explicit; go 1.19
github.com/quic-go/quic-go
github.com/quic-go/quic-go/http3