add support for QUIC v1

This commit is contained in:
Marten Seemann 2021-03-02 16:01:34 +08:00
parent b8f07c728c
commit 6b771df453
8 changed files with 25 additions and 12 deletions

View file

@ -33,6 +33,7 @@ const (
nextProtoH3Draft29 = "h3-29" nextProtoH3Draft29 = "h3-29"
nextProtoH3Draft32 = "h3-32" nextProtoH3Draft32 = "h3-32"
nextProtoH3Draft34 = "h3-34" nextProtoH3Draft34 = "h3-34"
nextProtoH3 = "h3"
) )
const ( const (
@ -43,6 +44,9 @@ const (
) )
func versionToALPN(v protocol.VersionNumber) string { func versionToALPN(v protocol.VersionNumber) string {
if v == protocol.Version1 {
return nextProtoH3
}
if v == protocol.VersionTLS || v == protocol.VersionDraft29 { if v == protocol.VersionTLS || v == protocol.VersionDraft29 {
return nextProtoH3Draft29 return nextProtoH3Draft29
} }
@ -155,11 +159,14 @@ func (s *Server) serveImpl(tlsConf *tls.Config, conn net.PacketConn) error {
// determine the ALPN from the QUIC version used // determine the ALPN from the QUIC version used
proto := nextProtoH3Draft29 proto := nextProtoH3Draft29
if qconn, ok := ch.Conn.(handshake.ConnWithVersion); ok { if qconn, ok := ch.Conn.(handshake.ConnWithVersion); ok {
if qconn.GetQUICVersion() == quic.VersionDraft32 { //nolint:exhaustive
switch qconn.GetQUICVersion() {
case quic.VersionDraft32:
proto = nextProtoH3Draft32 proto = nextProtoH3Draft32
} case protocol.VersionDraft34:
if qconn.GetQUICVersion() == protocol.VersionDraft34 {
proto = nextProtoH3Draft34 proto = nextProtoH3Draft34
case protocol.Version1:
proto = nextProtoH3
} }
} }
config := tlsConf config := tlsConf

View file

@ -35,6 +35,8 @@ const (
VersionDraft32 = protocol.VersionDraft32 VersionDraft32 = protocol.VersionDraft32
// VersionDraft34 is IETF QUIC draft-34 // VersionDraft34 is IETF QUIC draft-34
VersionDraft34 = protocol.VersionDraft34 VersionDraft34 = protocol.VersionDraft34
// Version1 is RFC 9000
Version1 = protocol.Version1
) )
// A Token can be used to verify the ownership of the client address. // A Token can be used to verify the ownership of the client address.

View file

@ -14,7 +14,7 @@ var (
) )
func getSalt(v protocol.VersionNumber) []byte { func getSalt(v protocol.VersionNumber) []byte {
if v == protocol.VersionDraft34 { if v == protocol.VersionDraft34 || v == protocol.Version1 {
return quicSaltDraft34 return quicSaltDraft34
} }
return quicSaltOld return quicSaltOld

View file

@ -48,7 +48,7 @@ func GetRetryIntegrityTag(retry []byte, origDestConnID protocol.ConnectionID, ve
var tag [16]byte var tag [16]byte
var sealed []byte var sealed []byte
if version != protocol.VersionDraft34 { if version != protocol.VersionDraft34 && version != protocol.Version1 {
sealed = oldRetryAEAD.Seal(tag[:0], oldRetryNonce[:], nil, retryBuf.Bytes()) sealed = oldRetryAEAD.Seal(tag[:0], oldRetryNonce[:], nil, retryBuf.Bytes())
} else { } else {
sealed = retryAEAD.Seal(tag[:0], retryNonce[:], nil, retryBuf.Bytes()) sealed = retryAEAD.Seal(tag[:0], retryNonce[:], nil, retryBuf.Bytes())

View file

@ -24,7 +24,7 @@ var _ tlsExtensionHandler = &extensionHandler{}
// newExtensionHandler creates a new extension handler // newExtensionHandler creates a new extension handler
func newExtensionHandler(params []byte, pers protocol.Perspective, v protocol.VersionNumber) tlsExtensionHandler { func newExtensionHandler(params []byte, pers protocol.Perspective, v protocol.VersionNumber) tlsExtensionHandler {
et := uint16(quicTLSExtensionType) et := uint16(quicTLSExtensionType)
if v != protocol.VersionDraft34 { if v != protocol.VersionDraft34 && v != protocol.Version1 {
et = quicTLSExtensionTypeOldDrafts et = quicTLSExtensionTypeOldDrafts
} }
return &extensionHandler{ return &extensionHandler{

View file

@ -19,11 +19,12 @@ const (
// The version numbers, making grepping easier // The version numbers, making grepping easier
const ( const (
VersionTLS VersionNumber = 0x51474fff VersionTLS VersionNumber = 0x51474fff
VersionWhatever VersionNumber = 1 // for when the version doesn't matter VersionWhatever VersionNumber = math.MaxUint32 - 1 // for when the version doesn't matter
VersionUnknown VersionNumber = math.MaxUint32 VersionUnknown VersionNumber = math.MaxUint32
VersionDraft29 VersionNumber = 0xff00001d VersionDraft29 VersionNumber = 0xff00001d
VersionDraft32 VersionNumber = 0xff000020 VersionDraft32 VersionNumber = 0xff000020
VersionDraft34 VersionNumber = 0xff000022 // If everything goes according to plan at the IETF, this will one day be QUIC v1. VersionDraft34 VersionNumber = 0xff000022
Version1 VersionNumber = 0x1
) )
// SupportedVersions lists the versions that the server supports // SupportedVersions lists the versions that the server supports
@ -38,7 +39,7 @@ func IsValidVersion(v VersionNumber) bool {
func (vn VersionNumber) String() string { func (vn VersionNumber) String() string {
// For releases, VersionTLS will be set to a draft version. // For releases, VersionTLS will be set to a draft version.
// A switch statement can't contain duplicate cases. // A switch statement can't contain duplicate cases.
if vn == VersionTLS && VersionTLS != VersionDraft29 && VersionTLS != VersionDraft32 { if vn == VersionTLS && VersionTLS != VersionDraft29 && VersionTLS != VersionDraft32 && VersionTLS != Version1 {
return "TLS dev version (WIP)" return "TLS dev version (WIP)"
} }
//nolint:exhaustive //nolint:exhaustive
@ -53,6 +54,8 @@ func (vn VersionNumber) String() string {
return "draft-32" return "draft-32"
case VersionDraft34: case VersionDraft34:
return "draft-34" return "draft-34"
case Version1:
return "v1"
default: default:
if vn.isGQUIC() { if vn.isGQUIC() {
return fmt.Sprintf("gQUIC %d", vn.toGQUICVersion()) return fmt.Sprintf("gQUIC %d", vn.toGQUICVersion())

View file

@ -17,6 +17,7 @@ var _ = Describe("Version", func() {
Expect(IsValidVersion(VersionDraft29)).To(BeFalse()) Expect(IsValidVersion(VersionDraft29)).To(BeFalse())
Expect(IsValidVersion(VersionDraft32)).To(BeFalse()) Expect(IsValidVersion(VersionDraft32)).To(BeFalse())
Expect(IsValidVersion(VersionDraft34)).To(BeFalse()) Expect(IsValidVersion(VersionDraft34)).To(BeFalse())
Expect(IsValidVersion(Version1)).To(BeFalse())
Expect(IsValidVersion(1234)).To(BeFalse()) Expect(IsValidVersion(1234)).To(BeFalse())
}) })
@ -25,12 +26,12 @@ var _ = Describe("Version", func() {
}) })
It("has the right string representation", func() { It("has the right string representation", func() {
Expect(VersionTLS.String()).To(ContainSubstring("TLS"))
Expect(VersionWhatever.String()).To(Equal("whatever")) Expect(VersionWhatever.String()).To(Equal("whatever"))
Expect(VersionUnknown.String()).To(Equal("unknown")) Expect(VersionUnknown.String()).To(Equal("unknown"))
Expect(VersionDraft29.String()).To(Equal("draft-29")) Expect(VersionDraft29.String()).To(Equal("draft-29"))
Expect(VersionDraft32.String()).To(Equal("draft-32")) Expect(VersionDraft32.String()).To(Equal("draft-32"))
Expect(VersionDraft34.String()).To(Equal("draft-34")) Expect(VersionDraft34.String()).To(Equal("draft-34"))
Expect(Version1.String()).To(Equal("v1"))
// check with unsupported version numbers from the wiki // check with unsupported version numbers from the wiki
Expect(VersionNumber(0x51303039).String()).To(Equal("gQUIC 9")) Expect(VersionNumber(0x51303039).String()).To(Equal("gQUIC 9"))
Expect(VersionNumber(0x51303133).String()).To(Equal("gQUIC 13")) Expect(VersionNumber(0x51303133).String()).To(Equal("gQUIC 13"))
@ -46,7 +47,7 @@ var _ = Describe("Version", func() {
}) })
It("has supported versions in sorted order", func() { It("has supported versions in sorted order", func() {
for i := 0; i < len(SupportedVersions)-1; i++ { for i := 1; i < len(SupportedVersions)-1; i++ {
Expect(SupportedVersions[i]).To(BeNumerically(">", SupportedVersions[i+1])) Expect(SupportedVersions[i]).To(BeNumerically(">", SupportedVersions[i+1]))
} }
}) })

View file

@ -16,7 +16,7 @@ import (
"github.com/lucas-clemente/quic-go" "github.com/lucas-clemente/quic-go"
) )
const h09alpn = "hq-29" const h09alpn = "hq-interop"
type responseWriter struct { type responseWriter struct {
io.Writer io.Writer