Repository: XTLS/Xray-core
Pull request #4642: QUIC sniffer: Full support for handling multiple initial packets
Author: login: j2rong4cn
Created: 2025-04-22T09:10:10Z | Merged: 2025-04-28T10:03:03Z

大部分代码来自 https://github.com/v2fly/v2ray-core/commit/8ceba34970d9588e7114dde522b6f92fb91a523c https://github.com/v2fly/v2ray-core/commit/c8c11207477fab4a806fd0ce80bf9bd1a36328f0


Diff:
diff --git a/app/dispatcher/default.go b/app/dispatcher/default.go
index 7bc580565f67..34a59fa5f78e 100644
--- a/app/dispatcher/default.go
+++ b/app/dispatcher/default.go
@@ -33,23 +33,21 @@ type cachedReader struct {
 	cache  buf.MultiBuffer
 }
 
-func (r *cachedReader) Cache(b *buf.Buffer) {
-	mb, _ := r.reader.ReadMultiBufferTimeout(time.Millisecond * 100)
+func (r *cachedReader) Cache(b *buf.Buffer, deadline time.Duration) error {
+	mb, err := r.reader.ReadMultiBufferTimeout(deadline)
+	if err != nil {
+		return err
+	}
 	r.Lock()
 	if !mb.IsEmpty() {
 		r.cache, _ = buf.MergeMulti(r.cache, mb)
 	}
-	cacheLen := r.cache.Len()
-	if cacheLen <= b.Cap() {
-		b.Clear()
-	} else {
-		b.Release()
-		*b = *buf.NewWithSize(cacheLen)
-	}
-	rawBytes := b.Extend(cacheLen)
+	b.Clear()
+	rawBytes := b.Extend(b.Cap())
 	n := r.cache.Copy(rawBytes)
 	b.Resize(0, int32(n))
 	r.Unlock()
+	return nil
 }
 
 func (r *cachedReader) readInternal() buf.MultiBuffer {
@@ -355,7 +353,7 @@ func (d *DefaultDispatcher) DispatchLink(ctx context.Context, destination net.De
 }
 
 func sniffer(ctx context.Context, cReader *cachedReader, metadataOnly bool, network net.Network) (SniffResult, error) {
-	payload := buf.New()
+	payload := buf.NewWithSize(32767)
 	defer payload.Release()
 
 	sniffer := NewSniffer(ctx)
@@ -367,26 +365,33 @@ func sniffer(ctx context.Context, cReader *cachedReader, metadataOnly bool, netw
 	}
 
 	contentResult, contentErr := func() (SniffResult, error) {
+		cacheDeadline := 200 * time.Millisecond
 		totalAttempt := 0
 		for {
 			select {
 			case <-ctx.Done():
 				return nil, ctx.Err()
 			default:
-				totalAttempt++
-				if totalAttempt > 2 {
-					return nil, errSniffingTimeout
-				}
+				cachingStartingTimeStamp := time.Now()
+				cacheErr := cReader.Cache(payload, cacheDeadline)
+				cachingTimeElapsed := time.Since(cachingStartingTimeStamp)
+				cacheDeadline -= cachingTimeElapsed
 
-				cReader.Cache(payload)
 				if !payload.IsEmpty() {
 					result, err := sniffer.Sniff(ctx, payload.Bytes(), network)
-					if err != common.ErrNoClue {
+					switch err {
+					case common.ErrNoClue: // No Clue: protocol not matches, and sniffer cannot determine whether there will be a match or not
+						totalAttempt++
+					case protocol.ErrProtoNeedMoreData: // Protocol Need More Data: protocol matches, but need more data to complete sniffing
+						if cacheErr != nil { // Cache error (e.g. timeout) counts for failed attempt
+							totalAttempt++
+						}
+					default:
 						return result, err
 					}
 				}
-				if payload.IsFull() {
-					return nil, errUnknownContent
+				if totalAttempt >= 2 || cacheDeadline <= 0 {
+					return nil, errSniffingTimeout
 				}
 			}
 		}
diff --git a/app/dispatcher/sniffer.go b/app/dispatcher/sniffer.go
index c138447dc086..d6acf0d934ba 100644
--- a/app/dispatcher/sniffer.go
+++ b/app/dispatcher/sniffer.go
@@ -6,6 +6,7 @@ import (
 	"github.com/xtls/xray-core/common"
 	"github.com/xtls/xray-core/common/errors"
 	"github.com/xtls/xray-core/common/net"
+	"github.com/xtls/xray-core/common/protocol"
 	"github.com/xtls/xray-core/common/protocol/bittorrent"
 	"github.com/xtls/xray-core/common/protocol/http"
 	"github.com/xtls/xray-core/common/protocol/quic"
@@ -58,14 +59,17 @@ var errUnknownContent = errors.New("unknown content")
 func (s *Sniffer) Sniff(c context.Context, payload []byte, network net.Network) (SniffResult, error) {
 	var pendingSniffer []protocolSnifferWithMetadata
 	for _, si := range s.sniffer {
-		s := si.protocolSniffer
+		protocolSniffer := si.protocolSniffer
 		if si.metadataSniffer || si.network != network {
 			continue
 		}
-		result, err := s(c, payload)
+		result, err := protocolSniffer(c, payload)
 		if err == common.ErrNoClue {
 			pendingSniffer = append(pendingSniffer, si)
 			continue
+		} else if err == protocol.ErrProtoNeedMoreData { // Sniffer protocol matched, but need more data to complete sniffing
+			s.sniffer = []protocolSnifferWithMetadata{si}
+			return nil, err
 		}
 
 		if err == nil && result != nil {
diff --git a/common/buf/buffer.go b/common/buf/buffer.go
index 63779586fd8d..facf6812dfbf 100644
--- a/common/buf/buffer.go
+++ b/common/buf/buffer.go
@@ -15,6 +15,15 @@ const (
 
 var pool = bytespool.GetPool(Size)
 
+// ownership represents the data owner of the buffer.
+type ownership uint8
+
+const (
+	managed ownership = iota
+	unmanaged
+	bytespools
+)
+
 // Buffer is a recyclable allocation of a byte array. Buffer.Release() recycles
 // the buffer into an internal buffer pool, in order to recreate a buffer more
 // quickly.
@@ -22,11 +31,11 @@ type Buffer struct {
 	v         []byte
 	start     int32
 	end       int32
-	unmanaged bool
+	ownership ownership
 	UDP       *net.Destination
 }
 
-// New creates a Buffer with 0 length and 8K capacity.
+// New creates a Buffer with 0 length and 8K capacity, managed.
 func New() *Buffer {
 	buf := pool.Get().([]byte)
 	if cap(buf) >= Size {
@@ -40,7 +49,7 @@ func New() *Buffer {
 	}
 }
 
-// NewExisted creates a managed, standard size Buffer with an existed bytearray
+// NewExisted creates a standard size Buffer with an existed bytearray, managed.
 func NewExisted(b []byte) *Buffer {
 	if cap(b) < Size {
 		panic("Invalid buffer")
@@ -57,16 +66,16 @@ func NewExisted(b []byte) *Buffer {
 	}
 }
 
-// FromBytes creates a Buffer with an existed bytearray
+// FromBytes creates a Buffer with an existed bytearray, unmanaged.
 func FromBytes(b []byte) *Buffer {
 	return &Buffer{
 		v:         b,
 		end:       int32(len(b)),
-		unmanaged: true,
+		ownership: unmanaged,
 	}
 }
 
-// StackNew creates a new Buffer object on stack.
+// StackNew creates a new Buffer object on stack, managed.
 // This method is for buffers that is released in the same function.
 func StackNew() Buffer {
 	buf := pool.Get().([]byte)
@@ -81,9 +90,17 @@ func StackNew() Buffer {
 	}
 }
 
+// NewWithSize creates a Buffer with 0 length and capacity with at least the given size, bytespool's.
+func NewWithSize(size int32) *Buffer {
+	return &Buffer{
+		v:         bytespool.Alloc(size),
+		ownership: bytespools,
+	}
+}
+
 // Release recycles the buffer into an internal buffer pool.
 func (b *Buffer) Release() {
-	if b == nil || b.v == nil || b.unmanaged {
+	if b == nil || b.v == nil || b.ownership == unmanaged {
 		return
 	}
 
@@ -91,8 +108,13 @@ func (b *Buffer) Release() {
 	b.v = nil
 	b.Clear()
 
-	if cap(p) == Size {
-		pool.Put(p)
+	switch b.ownership {
+	case managed:
+		if cap(p) == Size {
+			pool.Put(p)
+		}
+	case bytespools:
+		bytespool.Free(p)
 	}
 	b.UDP = nil
 }
@@ -215,13 +237,6 @@ func (b *Buffer) Cap() int32 {
 	return int32(len(b.v))
 }
 
-// NewWithSize creates a Buffer with 0 length and capacity with at least the given size.
-func NewWithSize(size int32) *Buffer {
-	return &Buffer{
-		v: bytespool.Alloc(size),
-	}
-}
-
 // IsEmpty returns true if the buffer is empty.
 func (b *Buffer) IsEmpty() bool {
 	return b.Len() == 0
diff --git a/common/protocol/protocol.go b/common/protocol/protocol.go
index 28b5e51b3afe..61c963c5c6f7 100644
--- a/common/protocol/protocol.go
+++ b/common/protocol/protocol.go
@@ -1 +1,7 @@
 package protocol // import "github.com/xtls/xray-core/common/protocol"
+
+import (
+	"errors"
+)
+
+var ErrProtoNeedMoreData = errors.New("protocol matches, but need more data to complete sniffing")
diff --git a/common/protocol/quic/sniff.go b/common/protocol/quic/sniff.go
index 779e291bd388..61171c016649 100644
--- a/common/protocol/quic/sniff.go
+++ b/common/protocol/quic/sniff.go
@@ -1,7 +1,6 @@
 package quic
 
 import (
-	"context"
 	"crypto"
 	"crypto/aes"
 	"crypto/tls"
@@ -13,6 +12,7 @@ import (
 	"github.com/xtls/xray-core/common/buf"
 	"github.com/xtls/xray-core/common/bytespool"
 	"github.com/xtls/xray-core/common/errors"
+	"github.com/xtls/xray-core/common/protocol"
 	ptls "github.com/xtls/xray-core/common/protocol/tls"
 	"golang.org/x/crypto/hkdf"
 )
@@ -47,22 +47,17 @@ var (
 	errNotQuicInitial = errors.New("not initial packet")
 )
 
-func SniffQUIC(b []byte) (resultReturn *SniffHeader, errorReturn error) {
-	// In extremely rare cases, this sniffer may cause slice error
-	// and we set recover() here to prevent crash.
-	// TODO: Thoroughly fix this panic
-	defer func() {
-		if r := recover(); r != nil {
-			errors.LogError(context.Background(), "Failed to sniff QUIC: ", r)
-			resultReturn = nil
-			errorReturn = common.ErrNoClue
-		}
-	}()
+func SniffQUIC(b []byte) (*SniffHeader, error) {
+	if len(b) == 0 {
+		return nil, common.ErrNoClue
+	}
 
 	// Crypto data separated across packets
 	cryptoLen := 0
-	cryptoData := bytespool.Alloc(int32(len(b)))
+	cryptoData := bytespool.Alloc(32767)
 	defer bytespool.Free(cryptoData)
+	cache := buf.New()
+	defer cache.Release()
 
 	// Parse QUIC packets
 	for len(b) > 0 {
@@ -105,13 +100,15 @@ func SniffQUIC(b []byte) (resultReturn *SniffHeader, errorReturn error) {
 			return nil, errNotQuic
 		}
 
-		tokenLen, err := quicvarint.Read(buffer)
-		if err != nil || tokenLen > uint64(len(b)) {
-			return nil, errNotQuic
-		}
+		if isQuicInitial { // Only initial packets have token, see https://datatracker.ietf.org/doc/html/rfc9000#section-17.2.2
+			tokenLen, err := quicvarint.Read(buffer)
+			if err != nil || tokenLen > uint64(len(b)) {
+				return nil, errNotQuic
+			}
 
-		if _, err = buffer.ReadBytes(int32(tokenLen)); err != nil {
-			return nil, errNotQuic
+			if _, err = buffer.ReadBytes(int32(tokenLen)); err != nil {
+				return nil, errNotQuic
+			}
 		}
 
 		packetLen, err := quicvarint.Read(buffer)
@@ -130,9 +127,6 @@ func SniffQUIC(b []byte) (resultReturn *SniffHeader, errorReturn error) {
 			continue
 		}
 
-		origPNBytes := make([]byte, 4)
-		copy(origPNBytes, b[hdrLen:hdrLen+4])
-
 		var salt []byte
 		if versionNumber == version1 {
 			salt = quicSalt
@@ -147,44 +141,34 @@ func SniffQUIC(b []byte) (resultReturn *SniffHeader, errorReturn error) {
 			return nil, err
 		}
 
-		cache := buf.New()
-		defer cache.Release()
-
+		cache.Clear()
 		mask := cache.Extend(int32(block.BlockSize()))
 		block.Encrypt(mask, b[hdrLen+4:hdrLen+4+16])
 		b[0] ^= mask[0] & 0xf
-		for i := range b[hdrLen : hdrLen+4] {
+		packetNumberLength := int(b[0]&0x3 + 1)
+		for i := range packetNumberLength {
 			b[hdrLen+i] ^= mask[i+1]
 		}
-		packetNumberLength := b[0]&0x3 + 1
-		if packetNumberLength != 1 {
-			return nil, errNotQuicInitial
-		}
-		var packetNumber uint32
-		{
-			n, err := buffer.ReadByte()
-			if err != nil {
-				return nil, err
-			}
-			packetNumber = uint32(n)
-		}
-
-		extHdrLen := hdrLen + int(packetNumberLength)
-		copy(b[extHdrLen:hdrLen+4], origPNBytes[packetNumberLength:])
-		data := b[extHdrLen : int(packetLen)+hdrLen]
 
 		key := hkdfExpandLabel(crypto.SHA256, secret, []byte{}, "quic key", 16)
 		iv := hkdfExpandLabel(crypto.SHA256, secret, []byte{}, "quic iv", 12)
 		cipher := AEADAESGCMTLS13(key, iv)
+
 		nonce := cache.Extend(int32(cipher.NonceSize()))
-		binary.BigEndian.PutUint64(nonce[len(nonce)-8:], uint64(packetNumber))
+		_, err = buffer.Read(nonce[len(nonce)-packetNumberLength:])
+		if err != nil {
+			return nil, err
+		}
+
+		extHdrLen := hdrLen + packetNumberLength
+		data := b[extHdrLen : int(packetLen)+hdrLen]
 		decrypted, err := cipher.Open(b[extHdrLen:extHdrLen], nonce, data, b[:extHdrLen])
 		if err != nil {
 			return nil, err
 		}
 		buffer = buf.FromBytes(decrypted)
-		for i := 0; !buffer.IsEmpty(); i++ {
-			frameType := byte(0x0) // Default to PADDING frame
+		for !buffer.IsEmpty() {
+			frameType, _ := buffer.ReadByte()
 			for frameType == 0x0 && !buffer.IsEmpty() {
 				frameType, _ = buffer.ReadByte()
 			}
@@ -234,13 +218,12 @@ func SniffQUIC(b []byte) (resultReturn *SniffHeader, errorReturn error) {
 					return nil, io.ErrUnexpectedEOF
 				}
 				if cryptoLen < int(offset+length) {
-					cryptoLen = int(offset + length)
-					if len(cryptoData) < cryptoLen {
-						newCryptoData := bytespool.Alloc(int32(cryptoLen))
-						copy(newCryptoData, cryptoData)
-						bytespool.Free(cryptoData)
-						cryptoData = newCryptoData
+					newCryptoLen := int(offset + length)
+					if len(cryptoData) < newCryptoLen {
+						return nil, io.ErrShortBuffer
 					}
+					wipeBytes(cryptoData[cryptoLen:newCryptoLen])
+					cryptoLen = newCryptoLen
 				}
 				if _, err := buffer.Read(cryptoData[offset : offset+length]); err != nil { // Field: Crypto Data
 					return nil, io.ErrUnexpectedEOF
@@ -276,7 +259,14 @@ func SniffQUIC(b []byte) (resultReturn *SniffHeader, errorReturn error) {
 		}
 		return &SniffHeader{domain: tlsHdr.Domain()}, nil
 	}
-	return nil, common.ErrNoClue
+	// All payload is parsed as valid QUIC packets, but we need more packets for crypto data to read client hello.
+	return nil, protocol.ErrProtoNeedMoreData
+}
+
+func wipeBytes(b []byte) {
+	for i := range len(b) {
+		b[i] = 0x0
+	}
 }
 
 func hkdfExpandLabel(hash crypto.Hash, secret, context []byte, label string, length int) []byte {
diff --git a/common/protocol/quic/sniff_test.go b/common/protocol/quic/sniff_test.go
index cddb4c878bc5..121279b5d612 100644
--- a/common/protocol/quic/sniff_test.go
+++ b/common/protocol/quic/sniff_test.go
@@ -2,9 +2,11 @@ package quic_test
 
 import (
 	"encoding/hex"
+	"errors"
 	"testing"
 
 	"github.com/xtls/xray-core/common"
+	"github.com/xtls/xray-core/common/protocol"
 	"github.com/xtls/xray-core/common/protocol/quic"
 )
 
@@ -16,3 +18,252 @@ func TestSniffQUIC(t *testing.T) {
 		t.Error("failed")
 	}
 }
+
+func TestSniffQUICComplex(t *testing.T) {
+	tests := []struct {
+		name          string
+		hexData       string
+		domain        string
+		wantErr       bool
+		needsMoreData bool
+	}{
+		{
+			name:          "EmptyPacket",
+			hexData:       "0000000000000000000000000000000000000000000000000000000000000000",
+			domain:        "",
+			wantErr:       true,
+			needsMoreData: false,
+		},
+		{
+			name:          "NTP Packet Client",
+			hexData:       "23000000000000000000000000000000000000000000000000000000000000000000000000000000acb84a797d4044c9",
+			domain:        "",
+			wantErr:       true,
+			needsMoreData: false,
+		},
+		{
+			name:          "NTP Packet Server",
+			hexData:       "240106ec000000000000000e47505373ea4dcaef2f4b4c31acb84a797d4044c9eb58b8693dd70c27eb58b8693dd7dde2",
+			domain:        "",
+			wantErr:       true,
+			needsMoreData: false,
+		},
+		{
+			name:          "DNS Packet Client",
+			hexData:       "4500004a8e2d40003f1146392a2a2d03080808081eea00350036a8175ad4010000010000000000000675706461746504636f64650c76697375616c73747564696f03636f6d0000010001",
+			domain:        "",
+			wantErr:       true,
+			needsMoreData: false,
+		},
+		{
+			name:          "DNS Packet Client",
+			hexData:       "4500004a667a40003f116dec2a2a2d030808080866980035003605d9b524010000010000000000000675706461746504636f64650c76697375616c73747564696f03636f6d0000410001",
+			domain:        "",
+			wantErr:       true,
+			needsMoreData: false,
+		},
+		{
+			name:          "DNS Packet Server",
+			hexData:       "b524818000010006000100000675706461746504636f64650c76697375616c73747564696f03636f6d0000410001c00c00050001000000ec00301e7673636f64652d7570646174652d67366763623667676474686b63746439037a303107617a7572656664036e657400c03a000500010000000b002311737461722d617a75726566642d70726f640e747261666669636d616e61676572c065c076000500010000003c002c0473686564086475616c2d6c6f770b732d706172742d3030313706742d3030303908742d6d7365646765c065c0a5000500010000006c001411617a75726566642d742d66622d70726f64c088c0dd000500010000003c0026046475616c0b732d706172742d3030313706742d303030390b66622d742d6d7365646765c065c0fd00050001000000300002c102c1150006000100000030002d036e7331c115066d736e687374096d6963726f736f6674c0257848b78d00000708000003840024ea000000003c",
+			domain:        "",
+			wantErr:       true,
+			needsMoreData: false,
+		},
+		{
+			name:          "DNS Packet Server",
+			hexData:       "5ad4818000010007000000000675706461746504636f64650c76697375616c73747564696f03636f6d0000010001c00c000500010000008400301e7673636f64652d7570646174652d67366763623667676474686b63746439037a303107617a7572656664036e657400c03a000500010000001e002311737461722d617a75726566642d70726f640e747261666669636d616e61676572c065c076000500010000003c002c0473686564086475616c2d6c6f770b732d706172742d3030313706742d3030303908742d6d7365646765c065c0a50005000100000010001411617a75726566642d742d66622d70726f64c088c0dd000500010000003c0026046475616c0b732d706172742d3030313706742d303030390b66622d742d6d7365646765c065c0fd00050001000000100002c102c102000100010000001000040d6bfd2d",
+			domain:        "",
+			wantErr:       true,
+			needsMoreData: false,
+		},
+		{
+			name:          "QUIC, NonHandshake Packet",
+			hexData:       "548439ba3a0cffd27dabe08ebf9e603dd4801781e133b1a0276d29a047c3b8856adcced0067c4b11a08985bf93c05863305bd4b43ee9168cd5fdae0c392ff74ae06ce13e8d97dabec81ee927a844fa840f781edf9deb22f3162bf77009b3f5800c5e45539ac104368e7df8ba",
+			domain:        "",
+			wantErr:       true,
+			needsMoreData: false,
+		},
+		{
+			name:          "QUIC, NonHandshake Packet",
+			hexData:       "53f4144825dab3ba251b83d0089e910210bec1a6507cca92ad9ff539cc21f6c75e3551ca44003d9a",
+			domain:        "",
+			wantErr:       true,
+			needsMoreData: false,
+		},
+		{
+			name:          "QUIC, NonHandshake Packet",
+			hexData:       "528dc5524c03e7517949422cc3f6ffbfff74b2ec30a87654a71a",
+			domain:        "",
+			wantErr:       true,
+			needsMoreData: false,
+		},
+		{
+			name:          "QUIC Chromebook Handshake[1]; packet 1",
+			hexData:       "cb00000001088ca3be26059ca269000044d088950f316207d551c91c88d791557c440a19184322536d2c900034358c1b3964f2d2935337b8d044d35bf62b4eea9ceaac64121aa634c7cd28630722d169fa0f215b940d47d7996ca56f0d463dbf97a4a1b5818c5297a26fe58f5553dfb513ad589750a61682f229996555c7121c8bf48b06b68ab06427b01af485d832f9894099a20d3baadcff7b1cf07e2c059d3e7ba88d4ad35ef0ffea1fdc6ac3db271dfcca892a41ab25284936225c9bc593ce242b11b8abed4a8df902987eef0c6d90669e3606f47dd6ad05f44ba3a0cd356854261bbb1e2d8f6b83cc57cfa57eda3e5d7181b6ec418f6eeca81c259a33e4b0a913de720f2f8782764766ac9602a7f52a1082ec3da30dbefcf38c781a3e033810c4f2babf9b72adf7164159d98142181492e4468c0e10ab29013bf238e7360e09767ca49d59a9eb18f06a372bad711fefa90295f8e0839b1080570648212b321e5bd6f614bf0d3dc2817628b0c052a32820c16cb7f531c49244c48eb1429625246f9c164ae4ee1e83eaa8ff0eef1acf5a3d8ca88f1e4597db5ba5c0cb23d6100dd53da4f439ae64c4d3d43d1fbb5677f4fdc3bd2c2948dfc7e0be1a33c842033da15529cfd3cae00da68343d835db867f746854804410ba68f0dd7711b0fe55817b83f6ce1a12ad38acf2a3156f819f0dc68ea799c05583d9728f2856577811b260dba40d6c5e82c9e558c5b8f3f4599caf05ea591118e0b80ad621e0a76e4926047593a896752cb168420cb1b02d4211de5e5b7c891f319b5c0cf687e1d261a01f2acbade6bd73cd1ade0a02e240e9351384e1a6868c21a4878f39f0fa94ee1e36c5a46449241a3fe0147ff50176787eca7f3a936c901aeef56770bff74feecb985e6670d20dfd8ed17952dca5a5292213345c61db09bb5bcf5bf74565f61f9dccab51a289c3160ffe4a9b29cc76ea46778d9317a890efea2ad905f4219463a3baca3c02f5c3682634be7c2e86e366272a8263fec8e871644a79299d4aa74f1b1414b2f963cce6e059978faf813625af7869c1dec92035478c0e46dc66d938d4131aca27a59b2103b8cefa8e08aeb44b53b205b932902aea8d519faaaa12e354a6f532b4f716d7929e655dc2e98b494a99153854af5732a2659f2c21e4069896a1835ad05c5e53781cab16599cf4af47c196deeff9115c80d13f93aeb28b08023e6a1d3cf7da2a4457a9e443176bcdfef8f8de630c02bd0efdc5ddda56ad8f6b47edbda6353205e6e655f690092a48deb7f8a5254a7d778e07216cd97dfefcf740c1acd2977ef0fa17f798ea9752bae46e3aa3ec9b13f4c95c20a7839b8409000fa1f17e8dc46cc05c41bff696ee03c0371cae8638e8018ff4ebedd9f27d56443e534a72dd3d18a64790b676ddd060376759fa4a12ffc17f4be83492126ec1dc0fcd4aefef73a0b9c443ec3532b9a66b1a60daacf45e6557115edc0cc4d08758754a44beffedaa0d1265e50beed1a01752904ee3f7e706ed290b1a79071b142105b7c02e692ff318710e3ce9c3b9ec557cdecef173796417341ada414faa06b52adf645db454b56468ccf0da50a942ebc09487797cb45a085ec1e2e06fcd1f5b72eac291955a62e5aa379a374aea3a0dec3e4e0ba1dde350a94c72dbea7505922e26e99d62f751c2b301413a73fb6b20a36052151473ebecd04d0a771ec326957bc28c2020fdf6f01d9abed69b3c3e73168b404a1748b15310b167396da01c7d",
+			domain:        "",
+			wantErr:       true,
+			needsMoreData: true,
+		},
+		{
+			name:          "QUIC Chromebook Handshake[1]; packet 1 - 2",
+			hexData:       "cb00000001088ca3be26059ca269000044d088950f316207d551c91c88d791557c440a19184322536d2c900034358c1b3964f2d2935337b8d044d35bf62b4eea9ceaac64121aa634c7cd28630722d169fa0f215b940d47d7996ca56f0d463dbf97a4a1b5818c5297a26fe58f5553dfb513ad589750a61682f229996555c7121c8bf48b06b68ab06427b01af485d832f9894099a20d3baadcff7b1cf07e2c059d3e7ba88d4ad35ef0ffea1fdc6ac3db271dfcca892a41ab25284936225c9bc593ce242b11b8abed4a8df902987eef0c6d90669e3606f47dd6ad05f44ba3a0cd356854261bbb1e2d8f6b83cc57cfa57eda3e5d7181b6ec418f6eeca81c259a33e4b0a913de720f2f8782764766ac9602a7f52a1082ec3da30dbefcf38c781a3e033810c4f2babf9b72adf7164159d98142181492e4468c0e10ab29013bf238e7360e09767ca49d59a9eb18f06a372bad711fefa90295f8e0839b1080570648212b321e5bd6f614bf0d3dc2817628b0c052a32820c16cb7f531c49244c48eb1429625246f9c164ae4ee1e83eaa8ff0eef1acf5a3d8ca88f1e4597db5ba5c0cb23d6100dd53da4f439ae64c4d3d43d1fbb5677f4fdc3bd2c2948dfc7e0be1a33c842033da15529cfd3cae00da68343d835db867f746854804410ba68f0dd7711b0fe55817b83f6ce1a12ad38acf2a3156f819f0dc68ea799c05583d9728f2856577811b260dba40d6c5e82c9e558c5b8f3f4599caf05ea591118e0b80ad621e0a76e4926047593a896752cb168420cb1b02d4211de5e5b7c891f319b5c0cf687e1d261a01f2acbade6bd73cd1ade0a02e240e9351384e1a6868c21a4878f39f0fa94ee1e36c5a46449241a3fe0147ff50176787eca7f3a936c901aeef56770bff74feecb985e6670d20dfd8ed17952dca5a5292213345c61db09bb5bcf5bf74565f61f9dccab51a289c3160ffe4a9b29cc76ea46778d9317a890efea2ad905f4219463a3baca3c02f5c3682634be7c2e86e366272a8263fec8e871644a79299d4aa74f1b1414b2f963cce6e059978faf813625af7869c1dec92035478c0e46dc66d938d4131aca27a59b2103b8cefa8e08aeb44b53b205b932902aea8d519faaaa12e354a6f532b4f716d7929e655dc2e98b494a99153854af5732a2659f2c21e4069896a1835ad05c5e53781cab16599cf4af47c196deeff9115c80d13f93aeb28b08023e6a1d3cf7da2a4457a9e443176bcdfef8f8de630c02bd0efdc5ddda56ad8f6b47edbda6353205e6e655f690092a48deb7f8a5254a7d778e07216cd97dfefcf740c1acd2977ef0fa17f798ea9752bae46e3aa3ec9b13f4c95c20a7839b8409000fa1f17e8dc46cc05c41bff696ee03c0371cae8638e8018ff4ebedd9f27d56443e534a72dd3d18a64790b676ddd060376759fa4a12ffc17f4be83492126ec1dc0fcd4aefef73a0b9c443ec3532b9a66b1a60daacf45e6557115edc0cc4d08758754a44beffedaa0d1265e50beed1a01752904ee3f7e706ed290b1a79071b142105b7c02e692ff318710e3ce9c3b9ec557cdecef173796417341ada414faa06b52adf645db454b56468ccf0da50a942ebc09487797cb45a085ec1e2e06fcd1f5b72eac291955a62e5aa379a374aea3a0dec3e4e0ba1dde350a94c72dbea7505922e26e99d62f751c2b301413a73fb6b20a36052151473ebecd04d0a771ec326957bc28c2020fdf6f01d9abed69b3c3e73168b404a1748b15310b167396da01c7dc700000001088ca3be26059ca269000044d00a7e7a252620d0fdfb63c0c193d6a9fe6a36aa9ce1b29dfa5f11f2567850b88384a2cc682eca2e292749365b833e5f7540019cd4f3143ed078aec07990b0d6ece18310403e73e1fe2975a8f9cb05796fa6196faaba3ee12a22b63a28a624cf4f7bedd44de000dc5ea698c65664df995b7d5fade0aab1cf0ecc5afd5ecb8fb80deecae3a8c97c20171f00ac3b5dc9a9027ca9c25571c72bb32070f6e3fb583560b0da6041b72e0a9601b8ad17d3c45e9dcc059f9f4758e8c35a839a9f6f4c501cb64e32e886fc733bc51069fbe4406f04d908285974c387d5b3e5f0f674941d05993bf8bda0d5ffd8c4fb528e150ff4bf37e38bd9c6346816fe360d4a206da81e815c1f7905184b6146b33427c6e38f1179981c18b82a3544442dd997c182d956037ae8f106eaf67ba133e7f15f1550b257d431f01ba0472659c6a5c2e6ff5e4ce9e692f4ef9fb169a75df4eb13f0b20e1994f3f8687bdca300c7e749af7b7a3b6597a6b950fe378a68c77766fdabe95248ed41d37805756b7ffa9cee0898bd661f6657cbf1af9aa8c7e437d432ca854c95307e6a7dfb6504ee3f7852fb3c246d168a03810b6c3d4e3d40bdee3def579effb66563f5bac98cfa1b071cd6f33e425e016bb3514a183b72cb3a393e9e519ba60e2177c98f530835e3b6eab78cdcb8abdbc769bc07e10c8e38bea710d5de1bdb2fa8d0d9b19e8cc31d16725a696e55342c89b667497e3d7f90e48f8503d8ead2a32a1930c3b24a4a9dcf2d8ec781705dd97d7df6e26828712fe42114419d5b8346bd86c239bd02f34e55f71400cb10c1fac7d8efa1a2ab258c17ace4288c8576ab92447b648fd15f4e038ec1c81a135e3bbb6f581a994c6a4902aeb1b5588cb1b5b53c8540296d96b6d2eccd67bae9609233f36304b5186d4698b88bb3ce8b1191a62b990436cf10718fd5759cb2281ac122f49ccbef8a3206348c1a930e7fc4bb498a11d89374e1480c7b8725b5f65e8c8d6f58da17f9134abce77eb9a6fcda514e7d3ab2e3610f86945f0dca519a3844da1b3a4b0e03c80528a2f79be478d07ff26166e30294bf0e69bf07a5bbd6d879adf6d618a1ec8365023408980bf67f0525a2fdee97fccc38fe104d4f58ed15e3671dfedf684856a27fbe286adba40ff0336def93f0174e9e35d341f5de73190d330d72227db9a866b69418e17e8e19ec884c1ffe2f0ad6deec37c9d49d536d0242fab282b0cf86cc9b15341757e0d361bddcbe5cbb062b3148d7c3c62af5c5dd5922a49920f351647030f62ed16929a404aa514fcbc38e67ba4f275e02a04c486b1a8e5b5efda197fd63e6f41fdeffa652c690dd6b00ca65df3688672ead9744f7d631e42e3b42f3ed1bff51b30f89211a7467cde65eab3659af7690cf307420a5823f31999d8f63c6c6ba0296ed4a46d5df6404f8db33e7252cc6bfcf7f55fee1f1e3b0573b6c6615793ff0691b7cfd23c195f66eb333d7efb0cfb74cf159787f87ad01fc131c6763bb1117bbfb8c2e8197ffba6b8c747565b1332bdbd6553b840939c2f98aa8eb1c549491c640e012fc549852fa7a93f81e5db152c761fc7d01bce0325619965c09f6730a162e7be53af7d9ce4b5ac0f4eb487361d2ac231d4ce92e5d9a084bc7b609ccf60056ecc82cd0c06a088cfbcf7d764b3109331c42f989da82b05cfe4c134a6784e664fa67a89c0624e3cc73ccfdea3f292db28f7c7b1b109f680f6b537f135c62f764",
+			domain:        "dns.google",
+			wantErr:       false,
+			needsMoreData: false,
+		},
+		{
+			name:          "QUIC Chromebook Handshake[2]; packet 1",
+			hexData:       "cf0000000108452af27900a1723300404600ca8530029a6bc59ff3e85beb5fc838ac3147ba5c2f6421ddcffdd85167d8de70eff2b1fa016dad4918337dec0feb660edb98e078dea51fa914055984b7957bd732fa4c831e448967af34752fd95835e3caba1e022d6d164f3f53f1bd7f60d560a8684079e90626aa1a4d3fe728158f7e1055ff76d1566072113982b193fb932265381e4de7afb35caa4ec56f31595a33fa2eb0bc84feb9f273224050938825fd21aa7317042ad00785ffd36151aee566a5dfe17d72591af1235059171568e5af0d13fc56e7897c3d632be753d8dea184c3d96d92bc56978cc669d94dd4c5e8dc3dcba7f0a39368fb1e87981e54bba7b86fbd8e8023a94d84f0290f402a5244cb4b0eeaaa57610ea59711a43932c521f10edb4560375693cbea60240389b8cebfd94035cabe4fc96ce8a726b979775e06c3bb0e3c4c866fe82e89fb725499e711e39310b93c785b313459f22d4ba37f90b19447165c2584269d98bf47d1f7ca89585797e4d6f1a4a1db7d2b0ae91a93fb15c3bb0ab953c3656b3b2ca20833d15e95329baff6d2ade1b0921b5ed3ae96648bf123b5265e27b049e9a8674455ff5f763f039568026e4fbe9882fef761c573d8f12e342c274a8dd3ad9854a688ce57cdddb52c758161ae3a59f67fc0d5b85f12e27617e7f4366e97a61fcda084e620dde35686f01dac49ce4bd76b986e3223c215919a1b228beeb74b7fcf32827d55be8f1b3b5fed24df2db023faecbb313b18a151cc4af8199d4bb08f8127b8207a0286d52758eaca87fd476ece0e3b17bcd8afb0289e8fd33c4455d4db6f058826c301ea303bfe2c0a6651a8fb6a2e1897852d758076adb04ad907077c5d5f94089da78d8923a34f1022ed672f378fe0dd81a709b372c0a2042a42e683c051c653e42b43c4a0ea8e961074d2901d4157ac9878b13a207b05ec471cff10d922b74d05623513cd6a4ea192ad21d4089de269633d4d2d1388d98d7c8a9e29848d5558b8aa2b73b437446a640230e6adb7f4b317ee5d66681c4aae11f69b1e5f96cb32ca6331405426cb706167d86f6f8fd588a72d7b2a6906798b81f174d808e1e3fc461e598e797c41bced26b87d09282d7b6d95076c285462e0c420a6f0e171ffe2791b5d221c03520409fe36622ff77796d9b7ef82babb25313acda9c621b22bf45ed909f9365b508860645af4c3aca78e6abca2d3a65c9159fbcd577438505d3f65a57c9412c12c069ad4d6db450beb08603abef621a9e029593fb5881dbd524ea2953b4acaaf59269b584c754e88c033247bb7c032e548d34fd9b2678e62fdf953dabf2be21c3e2d7b18ec7e3aedaf2cd082e19a369c1bcd4ca67e3d464e2200ecc3df98b0aa7f349415d68bcab0441ac3366607eff024bb786aec031a4619f8a24f554fe93c8520a03affcf11e40b6d5002f98c1708cac6c56e77eccba85ea6600d1391cfd202cc7914bfbaa3303266d1a820bf2dc84d2dfcdc4cdb79e6de3fbe3c02b288dcf955652f674f3f59b50849ea7dbf755bdafa27fba3db1267fb1354d8bf25a60cacb900b4d7ba913f9ba5f6b00559ad58b2f34a658ff7ef7f7d1ceeffd9c8325f271e6b5ba44d89685b744306963aa5e05ac0e8b00ada772dd5ae5ffb7043109afea86593743564c7acb4c8e7ef0e57d081eb1b9c0916078b113ece8a6036264a9b9781183c035342d50c7b069f3a01a40230e37ed8efde073c07d0e68066541d78c2f3cbe1e603cfcaaa",
+			domain:        "",
+			wantErr:       true,
+			needsMoreData: true,
+		},
+		{
+			name:          "QUIC Chromebook Handshake[2]; packet 1-2",
+			hexData:       "cf0000000108452af27900a1723300404600ca8530029a6bc59ff3e85beb5fc838ac3147ba5c2f6421ddcffdd85167d8de70eff2b1fa016dad4918337dec0feb660edb98e078dea51fa914055984b7957bd732fa4c831e448967af34752fd95835e3caba1e022d6d164f3f53f1bd7f60d560a8684079e90626aa1a4d3fe728158f7e1055ff76d1566072113982b193fb932265381e4de7afb35caa4ec56f31595a33fa2eb0bc84feb9f273224050938825fd21aa7317042ad00785ffd36151aee566a5dfe17d72591af1235059171568e5af0d13fc56e7897c3d632be753d8dea184c3d96d92bc56978cc669d94dd4c5e8dc3dcba7f0a39368fb1e87981e54bba7b86fbd8e8023a94d84f0290f402a5244cb4b0eeaaa57610ea59711a43932c521f10edb4560375693cbea60240389b8cebfd94035cabe4fc96ce8a726b979775e06c3bb0e3c4c866fe82e89fb725499e711e39310b93c785b313459f22d4ba37f90b19447165c2584269d98bf47d1f7ca89585797e4d6f1a4a1db7d2b0ae91a93fb15c3bb0ab953c3656b3b2ca20833d15e95329baff6d2ade1b0921b5ed3ae96648bf123b5265e27b049e9a8674455ff5f763f039568026e4fbe9882fef761c573d8f12e342c274a8dd3ad9854a688ce57cdddb52c758161ae3a59f67fc0d5b85f12e27617e7f4366e97a61fcda084e620dde35686f01dac49ce4bd76b986e3223c215919a1b228beeb74b7fcf32827d55be8f1b3b5fed24df2db023faecbb313b18a151cc4af8199d4bb08f8127b8207a0286d52758eaca87fd476ece0e3b17bcd8afb0289e8fd33c4455d4db6f058826c301ea303bfe2c0a6651a8fb6a2e1897852d758076adb04ad907077c5d5f94089da78d8923a34f1022ed672f378fe0dd81a709b372c0a2042a42e683c051c653e42b43c4a0ea8e961074d2901d4157ac9878b13a207b05ec471cff10d922b74d05623513cd6a4ea192ad21d4089de269633d4d2d1388d98d7c8a9e29848d5558b8aa2b73b437446a640230e6adb7f4b317ee5d66681c4aae11f69b1e5f96cb32ca6331405426cb706167d86f6f8fd588a72d7b2a6906798b81f174d808e1e3fc461e598e797c41bced26b87d09282d7b6d95076c285462e0c420a6f0e171ffe2791b5d221c03520409fe36622ff77796d9b7ef82babb25313acda9c621b22bf45ed909f9365b508860645af4c3aca78e6abca2d3a65c9159fbcd577438505d3f65a57c9412c12c069ad4d6db450beb08603abef621a9e029593fb5881dbd524ea2953b4acaaf59269b584c754e88c033247bb7c032e548d34fd9b2678e62fdf953dabf2be21c3e2d7b18ec7e3aedaf2cd082e19a369c1bcd4ca67e3d464e2200ecc3df98b0aa7f349415d68bcab0441ac3366607eff024bb786aec031a4619f8a24f554fe93c8520a03affcf11e40b6d5002f98c1708cac6c56e77eccba85ea6600d1391cfd202cc7914bfbaa3303266d1a820bf2dc84d2dfcdc4cdb79e6de3fbe3c02b288dcf955652f674f3f59b50849ea7dbf755bdafa27fba3db1267fb1354d8bf25a60cacb900b4d7ba913f9ba5f6b00559ad58b2f34a658ff7ef7f7d1ceeffd9c8325f271e6b5ba44d89685b744306963aa5e05ac0e8b00ada772dd5ae5ffb7043109afea86593743564c7acb4c8e7ef0e57d081eb1b9c0916078b113ece8a6036264a9b9781183c035342d50c7b069f3a01a40230e37ed8efde073c07d0e68066541d78c2f3cbe1e603cfcaaac40000000108452af27900a1723300404600ca8530029a6bc59ff3e85beb5fc838ac3147ba5c2f6421ddcffdd85167d8de70eff2b1fa016dad4918337dec0feb660edb98e078dea51fa914055984b7957bd732fa4c831e4489522d29bb5c84749f83c8e1edfd9da8d1738164a8a9c59e37a5c9994d90bb982dcfa69b20f868960dc139618f1adc2546d34340ae13d826260c54a456bbf7469ee37b1be1d7177004468d7e92cac62a0b165d6a114ad479861dd58959e094b5a6250359301d4a614d529660760e3d1cdec9bf444a3761309bab40e4a977bc749e0dae431952f5f7e6b1ebc1383d343359a387da4301f7fa4b400475e9b82367e56278376dd1c80349f083988945a13649008109cc12a3acf569ffcc5481fbcd86b544e7dc8434e9dd42bd8e5716a844d37879568db046857389d36cc7550c75f94e314db6749aa987f0fc730fae0fcf465d01c2fb745269dfc10132ddb5404dda2f9455780f5818730834aa9db4740793359884b9927b0bd1a5ca96052b4f17397d8b78aa891401bb8bed6726ea2229d919798c50e24d5f40576ac204847be9244aadbe5c773684c37475036541d209c177d4e9c22a1253292ce4ffb886b925b6cf83cc251976a68887eda2777590f51804b790b51eee77e717b7ef0eea71634594df36e6ae9e7574d65c51ac3196f0b2a3b0f023c81f05f7807f958dda03418ed49e14b645e814b9aa55b37c809be3172ca21fe4c7a78e17e9ece8def2dd2949310ecaa41b1b477f4e85db5288aa144e333f47ef291d0e822941181c13859d9fd6d640904ee764c9276125228c932dff3fb12f564f039b52f5ba1ab4d119641df8fe13f784802b99347f0046da63f471e34b1d12d3111cffe7b5d90cf5999879f6f23e7785f09cb10df32821bb68dd8fdcfcdbedd63f2428b2292b9f0e76ff36403c9644fd43e01112ee6218d0ec1c86f6d147e4b802293e906750c7046f53bf05a144e321d3b45e08e4064fd3828fdd1b5d1ceed74081f61319dc0ad9a6e8a3b9cc802e952d24e2271712e2c2cda7daca2f835e6c804feeef8d918404cc82a1aa9534bddff68a472b208a0d0a7fd68a08fbc411132af47a6b67a32617b7b9991524c21599e8e3cb9395cdab87a3f5bf5d1833a9c7ea021b29cf428c877c6b21d62f99340ac7f85ae721acc10968e7d79f111ca40c75e14060d07cffa046d71151a0b00eab657300344b04bd1a8871650c34ceda8610d7c1ba8d37673da6aaa580400e0230c69fba8ba21927de2f5897656144694550d1df3d268804adc707e7b236501734aeabb2e61cb08012bd96eca5a486d7a55f996992c36233815abd71c30e263ba0c5d9456fe0828df16f6af7929390bb143c426d9dfeaf4bb373554479ebe609b36b4bc3dd08ce216b9cdc5726edb458c5e4036d0edc688d3e39d20f8254b5d1f174518f15b344efc27fc56572c0159aa593d5b46bc33818f986e3df8caebd4c7b702ef50dd582714a2b94ecd1c4e90af37d388445c478a32ff6e8f5852ee115966b708eed04da322b98813a69423e95f90b89ce85518e39bcef36fdd5bd312b2c6c5ee85962675274c18f39ee35155517f70fd74b31bb2de6b5108d369252e6fb289e453833132ef7960da1cc0934790c039b9a1b0c74f23eb3b61fe9b4d0ea67de757b93af451eef303b1373199af446a0fa98d5991bbd4771ee63317e6da86efbe213dfff595c41b98e0e89f4f2df110104e760feebf4cb3361171c9fceb1e1c809a268",
+			domain:        "",
+			wantErr:       true,
+			needsMoreData: true,
+		},
+		{
+			name:          "QUIC Chromebook Handshake[2]; packet 1-3",
+			hexData:       "cf0000000108452af27900a1723300404600ca8530029a6bc59ff3e85beb5fc838ac3147ba5c2f6421ddcffdd85167d8de70eff2b1fa016dad4918337dec0feb660edb98e078dea51fa914055984b7957bd732fa4c831e448967af34752fd95835e3caba1e022d6d164f3f53f1bd7f60d560a8684079e90626aa1a4d3fe728158f7e1055ff76d1566072113982b193fb932265381e4de7afb35caa4ec56f31595a33fa2eb0bc84feb9f273224050938825fd21aa7317042ad00785ffd36151aee566a5dfe17d72591af1235059171568e5af0d13fc56e7897c3d632be753d8dea184c3d96d92bc56978cc669d94dd4c5e8dc3dcba7f0a39368fb1e87981e54bba7b86fbd8e8023a94d84f0290f402a5244cb4b0eeaaa57610ea59711a43932c521f10edb4560375693cbea60240389b8cebfd94035cabe4fc96ce8a726b979775e06c3bb0e3c4c866fe82e89fb725499e711e39310b93c785b313459f22d4ba37f90b19447165c2584269d98bf47d1f7ca89585797e4d6f1a4a1db7d2b0ae91a93fb15c3bb0ab953c3656b3b2ca20833d15e95329baff6d2ade1b0921b5ed3ae96648bf123b5265e27b049e9a8674455ff5f763f039568026e4fbe9882fef761c573d8f12e342c274a8dd3ad9854a688ce57cdddb52c758161ae3a59f67fc0d5b85f12e27617e7f4366e97a61fcda084e620dde35686f01dac49ce4bd76b986e3223c215919a1b228beeb74b7fcf32827d55be8f1b3b5fed24df2db023faecbb313b18a151cc4af8199d4bb08f8127b8207a0286d52758eaca87fd476ece0e3b17bcd8afb0289e8fd33c4455d4db6f058826c301ea303bfe2c0a6651a8fb6a2e1897852d758076adb04ad907077c5d5f94089da78d8923a34f1022ed672f378fe0dd81a709b372c0a2042a42e683c051c653e42b43c4a0ea8e961074d2901d4157ac9878b13a207b05ec471cff10d922b74d05623513cd6a4ea192ad21d4089de269633d4d2d1388d98d7c8a9e29848d5558b8aa2b73b437446a640230e6adb7f4b317ee5d66681c4aae11f69b1e5f96cb32ca6331405426cb706167d86f6f8fd588a72d7b2a6906798b81f174d808e1e3fc461e598e797c41bced26b87d09282d7b6d95076c285462e0c420a6f0e171ffe2791b5d221c03520409fe36622ff77796d9b7ef82babb25313acda9c621b22bf45ed909f9365b508860645af4c3aca78e6abca2d3a65c9159fbcd577438505d3f65a57c9412c12c069ad4d6db450beb08603abef621a9e029593fb5881dbd524ea2953b4acaaf59269b584c754e88c033247bb7c032e548d34fd9b2678e62fdf953dabf2be21c3e2d7b18ec7e3aedaf2cd082e19a369c1bcd4ca67e3d464e2200ecc3df98b0aa7f349415d68bcab0441ac3366607eff024bb786aec031a4619f8a24f554fe93c8520a03affcf11e40b6d5002f98c1708cac6c56e77eccba85ea6600d1391cfd202cc7914bfbaa3303266d1a820bf2dc84d2dfcdc4cdb79e6de3fbe3c02b288dcf955652f674f3f59b50849ea7dbf755bdafa27fba3db1267fb1354d8bf25a60cacb900b4d7ba913f9ba5f6b00559ad58b2f34a658ff7ef7f7d1ceeffd9c8325f271e6b5ba44d89685b744306963aa5e05ac0e8b00ada772dd5ae5ffb7043109afea86593743564c7acb4c8e7ef0e57d081eb1b9c0916078b113ece8a6036264a9b9781183c035342d50c7b069f3a01a40230e37ed8efde073c07d0e68066541d78c2f3cbe1e603cfcaaac40000000108452af27900a1723300404600ca8530029a6bc59ff3e85beb5fc838ac3147ba5c2f6421ddcffdd85167d8de70eff2b1fa016dad4918337dec0feb660edb98e078dea51fa914055984b7957bd732fa4c831e4489522d29bb5c84749f83c8e1edfd9da8d1738164a8a9c59e37a5c9994d90bb982dcfa69b20f868960dc139618f1adc2546d34340ae13d826260c54a456bbf7469ee37b1be1d7177004468d7e92cac62a0b165d6a114ad479861dd58959e094b5a6250359301d4a614d529660760e3d1cdec9bf444a3761309bab40e4a977bc749e0dae431952f5f7e6b1ebc1383d343359a387da4301f7fa4b400475e9b82367e56278376dd1c80349f083988945a13649008109cc12a3acf569ffcc5481fbcd86b544e7dc8434e9dd42bd8e5716a844d37879568db046857389d36cc7550c75f94e314db6749aa987f0fc730fae0fcf465d01c2fb745269dfc10132ddb5404dda2f9455780f5818730834aa9db4740793359884b9927b0bd1a5ca96052b4f17397d8b78aa891401bb8bed6726ea2229d919798c50e24d5f40576ac204847be9244aadbe5c773684c37475036541d209c177d4e9c22a1253292ce4ffb886b925b6cf83cc251976a68887eda2777590f51804b790b51eee77e717b7ef0eea71634594df36e6ae9e7574d65c51ac3196f0b2a3b0f023c81f05f7807f958dda03418ed49e14b645e814b9aa55b37c809be3172ca21fe4c7a78e17e9ece8def2dd2949310ecaa41b1b477f4e85db5288aa144e333f47ef291d0e822941181c13859d9fd6d640904ee764c9276125228c932dff3fb12f564f039b52f5ba1ab4d119641df8fe13f784802b99347f0046da63f471e34b1d12d3111cffe7b5d90cf5999879f6f23e7785f09cb10df32821bb68dd8fdcfcdbedd63f2428b2292b9f0e76ff36403c9644fd43e01112ee6218d0ec1c86f6d147e4b802293e906750c7046f53bf05a144e321d3b45e08e4064fd3828fdd1b5d1ceed74081f61319dc0ad9a6e8a3b9cc802e952d24e2271712e2c2cda7daca2f835e6c804feeef8d918404cc82a1aa9534bddff68a472b208a0d0a7fd68a08fbc411132af47a6b67a32617b7b9991524c21599e8e3cb9395cdab87a3f5bf5d1833a9c7ea021b29cf428c877c6b21d62f99340ac7f85ae721acc10968e7d79f111ca40c75e14060d07cffa046d71151a0b00eab657300344b04bd1a8871650c34ceda8610d7c1ba8d37673da6aaa580400e0230c69fba8ba21927de2f5897656144694550d1df3d268804adc707e7b236501734aeabb2e61cb08012bd96eca5a486d7a55f996992c36233815abd71c30e263ba0c5d9456fe0828df16f6af7929390bb143c426d9dfeaf4bb373554479ebe609b36b4bc3dd08ce216b9cdc5726edb458c5e4036d0edc688d3e39d20f8254b5d1f174518f15b344efc27fc56572c0159aa593d5b46bc33818f986e3df8caebd4c7b702ef50dd582714a2b94ecd1c4e90af37d388445c478a32ff6e8f5852ee115966b708eed04da322b98813a69423e95f90b89ce85518e39bcef36fdd5bd312b2c6c5ee85962675274c18f39ee35155517f70fd74b31bb2de6b5108d369252e6fb289e453833132ef7960da1cc0934790c039b9a1b0c74f23eb3b61fe9b4d0ea67de757b93af451eef303b1373199af446a0fa98d5991bbd4771ee63317e6da86efbe213dfff595c41b98e0e89f4f2df110104e760feebf4cb3361171c9fceb1e1c809a268c60000000108452af27900a1723300404600ca8530029a6bc59ff3e85beb5fc838ac3147ba5c2f6421ddcffdd85167d8de70eff2b1fa016dad4918337dec0feb660edb98e078dea51fa914055984b7957bd732fa4c831e44892ff5e6b16d8a259a9128c2c0c3c525462781a344c3df7f19a747e0e79ca8714995c867fc697a3cb87b35e769465a8e966bcb35b7e897ad036aa23a6c021e2445a0eb79962151cd20dbb43ae1231847de01caf4e5589dfebf026e95f7d1d742e140d9dda849396a70cc0798f1eef06fd5f4cfbc9a190ddf04cc332c5b7b15e53af311190ced92a1291c12b8799f2b50e076539a8370ee667e1791a78f38e565a48acbaa1c78ba941dba8b0d040f8fb8bbcc9f6bf5705efa613a24b12d6ac9cebb4f3fac1b09a07b49d8a3a62808eb0a324629f13a012e6ad0feb11ad97c1572983c713b62f27584809ba43e64e4af9845af807c0783104838f4e2ac33fa848866f3cc64a7b6203a5c09e8ad231f0f06ae2fb7b39a64cedd823b0ff297ad9be1ccac436777ccb3e22ef6b9c12e6d5e34926f50e8ca8c8c0532c810b074d001c11791a01bf25786b57a5da54065dcee4962822e929f47ee44d3b8c83d45a8b7a936dc2a6fa396e4194fa032d1627eca59f69857fc40dab5835d3613dade1c74b09c345bd32c509e9545d2330b157a7acb76409f3ac8eaa22802414f38c5422fe4c5189caaf5c1b93ce7c0892f0cfc477490d335aa78961d632a973cf106bd974c2714176fb0f98cf12f2887a0d7bd491756dd374331eb3e6adb9f2bd0d6b273403fd14b314eb27ebbb6f6e78ce310437004b757c048149cf04429ae4a6d6e65c9b3e0b9c9c4d4ef52007eaaad9670320f10cd5317b3d3edc374d45c98b217dd28fb3c2c2fb6e74a3aced143e3242084b192ba6df24e69fdb883e850714fe27a45f43883486a986574fd1fc10f259fe90786441554514c8dade1f3b86fdaf5f54ab655e2d803c98aa56073b00c32148a1ed367dff3a2bd934ecba55141389990b661bbd9ce1ef1def13747d45500daf92cec9e60908274703e761cd46affd46622f2a2192a79425ebf51c875fc7ba3598e15e0ba2465fc3e87c8a5da1915d3b8abe4b16d21259f311183eee1e7d2b808a91a7c89b284df0eb6a2a79c610bbe47722b3e04d5a6c0e574816a94d97349b6976010eb8c7debf42210982f78de482b7cd068051bf57908dbf46b5ceaf64f5fb33ede4412c1ce81eb1dfb4e99e10dd9b57ebc6e62ecbf4ee2db04d9e48c62bd45f8fa51704d414296a2d51d25ced6a192034a44c67e09d8985b573f98e03fa36dd8dcce2c04b4d5b1f276b6a642aadbdcafcf09de1d234bf8bbbf64aeadf01519ddafb419b3e62d204e04c3d7ebaf54b09e387ac3e9c4781c11625a2f44fddb7a1886f21929bd01c283f64903b6ccbb463984dfadc00f6af2a421517da023fd319f528195cac5fe907624b70c0172479d07d78e266dbf20ab8fc302228f279ffdba7395a839c4a9d7a4e001a260e1702393968f1e9722f023b204cf09cfee9a7bba045e4a2a449ee9fbb5c36e93028cfc87a2e34914b1b4f01beeded175ac0fa73fea9292f2bc3b1247164d8e05cddc3981bdc24e5f596571c418f6fa00fd9d4d0898cbf0d2f5413bed5f100f1854903017b6bc88bd7e303b5e0e2417bbcc984731128eda550d31f9af0e6e743eb6916466bbd435617d56fa60b05cd7dca66a9f6f4be23d3c5ff5d900822c6d1d8d71b0bab24f57d9682381a87c",
+			domain:        "signaler-pa.clients6.google.com",
+			wantErr:       false,
+			needsMoreData: false,
+		},
+		{
+			name:          "QUIC Chromebook Handshake[3]; packet 1",
+			hexData:       "cb0000000108676ef9ec3514fd5f004046001ae0c831dde6ac72f1337c9ca111f5b32afdf102d75c017d3bccb6fa89902b750b00c51bb226afa517754b72e962ff007c1c8c8749a21be1d8d94f7bf73437c010cd60e0bd4489d0a84868f32ecd4bd0d4c95a8a08d60d8303ef02323bdbcd96a33940824d25b9594bd8ae5716b9d043ab27ba03a2593c4d149b923711dd98e45456db19c8ea71e982562ae787c1b6cbe3ca1b03df2df62aa8e3127c5f68bdf80ed90588e7ec1f41f5a6281b87a12348cb17a04e9eaa461fef2e0e3ae70ebdc7bffa15c6b61ab270173e46dec0fd081f935a5fe6338d3b9cd38fcb52cb159edb66d2927238294313990da25c22f40d40e3cd72e76bbd066de731cf8fb6b4b7bc7639efb788c0b108dbf8280845a2cc62fbaf5fb8e1ecbe5ba7791aab94786c1c71c9058d0153b34a3f5bc8903e0d120f353defbe973cd33568bd03609dcdab8af1e8563897f5dd0251c6e6514bf40bd447d376fed21b2c54ebf74680df241bdc2ea5579bc0736cf3257c20d275746e8e6853aa89dcda8c2dbe523438ab92ca1ed1ab4f109e4ea84de57dfb6c544d695a5b710fe2d432f2b58644f8aeb965752d3a1d1a3057c2229192f89b254f5d292c22f1060642729df3667ef39e27691c82da9be847a59a17ba7345d23a37e31ec135633cc5ea84c752f56d4ec75878a2920b93e9b4e091e0114552712e1e50ade42e26ac0266b84043a493e1ce2e80cd57422de16a88deceaa55385dc2a977ffc9063e7c427200b6d8511ef9004f89412587bd6d0057898f5ae284db78b0ec861fed36dfb7c7a9679ad0480eefe71985ba6f731bd0e816a901e0c017dd0cb7fc8a4606dec2091a51aab16d6f9bbdecf3fea177671e68250a84fe19de8df78d711e22b81372bc22ae21ac7208ed41201f6e26cd6748e9d6e2f4884f5acba736b2432536718891638d43991bd97c232829e26be6e6bb303d44849b245ef758eb2813bc87cf21a30f132360111e3015de5d1e4f0c5a98aff159c29f6debed7c2f18f455dfc7f33995a90b7625688507ecef1e7db48e7030ea6c4fa835bbc1dfbea6c0a6c704d658d4866a42b9860b1c8b5b64cb669e102c81e369b5f07b8fa08816a566a99f4d2910f6e8d751d52f1e2889f0ec9acfcb4627e0da5c35452be05c7766eddf3c42ceb6a312044075a4231b4203718c886498a313f3ba12e44e368b04ec3ea6e72d6fed9b6b334cbc0ba89f0aa9a129b1bad5b0ad8690291a344967f58e52415859852c6ca3ea24bc93ec1041fd1dc8a6a181326d3026098db0cddec90b3cd6df1e7638a3703f70c9a3baff8f005b90f362459a275a8b39daa78ff24613434594f96b8023a41a17d815e5c0319a39e07d32841339f14f404030b4a22551b86ba94832a1c49053d63140b503f2f64354ce10abe6c08f6cdaf6d8dc361c3c9d1a8077ad34dccc699b6fe07c16f8f7743d04003d672f82e643b3f1d5e263495504e11e6b2e676c11b3d0033d5f837e6bfd01602584ff181e3cb86f081015a9311eed546b42a8280680aa538353949f89674c554b43241e36536430ae9e0190729ce902e8f06a952d23b62816deb3b62b45375033ede2d8065a8e7b38f5aee0a5c66eb2f21f33fa6795d4b086e6f6ac941ba0c883ccf6e54e52164384045e0b0d74a9361f224303c841ec907be250725ab06cf79dd8bff8f46c08963a409b9b71b5c634c987c5e163f73fc32553be1231c72444c5e2a91189824034a784948f",
+			domain:        "",
+			wantErr:       true,
+			needsMoreData: true,
+		},
+		{
+			name:          "QUIC Chromebook Handshake[3]; packet 1-2",
+			hexData:       "cb0000000108676ef9ec3514fd5f004046001ae0c831dde6ac72f1337c9ca111f5b32afdf102d75c017d3bccb6fa89902b750b00c51bb226afa517754b72e962ff007c1c8c8749a21be1d8d94f7bf73437c010cd60e0bd4489d0a84868f32ecd4bd0d4c95a8a08d60d8303ef02323bdbcd96a33940824d25b9594bd8ae5716b9d043ab27ba03a2593c4d149b923711dd98e45456db19c8ea71e982562ae787c1b6cbe3ca1b03df2df62aa8e3127c5f68bdf80ed90588e7ec1f41f5a6281b87a12348cb17a04e9eaa461fef2e0e3ae70ebdc7bffa15c6b61ab270173e46dec0fd081f935a5fe6338d3b9cd38fcb52cb159edb66d2927238294313990da25c22f40d40e3cd72e76bbd066de731cf8fb6b4b7bc7639efb788c0b108dbf8280845a2cc62fbaf5fb8e1ecbe5ba7791aab94786c1c71c9058d0153b34a3f5bc8903e0d120f353defbe973cd33568bd03609dcdab8af1e8563897f5dd0251c6e6514bf40bd447d376fed21b2c54ebf74680df241bdc2ea5579bc0736cf3257c20d275746e8e6853aa89dcda8c2dbe523438ab92ca1ed1ab4f109e4ea84de57dfb6c544d695a5b710fe2d432f2b58644f8aeb965752d3a1d1a3057c2229192f89b254f5d292c22f1060642729df3667ef39e27691c82da9be847a59a17ba7345d23a37e31ec135633cc5ea84c752f56d4ec75878a2920b93e9b4e091e0114552712e1e50ade42e26ac0266b84043a493e1ce2e80cd57422de16a88deceaa55385dc2a977ffc9063e7c427200b6d8511ef9004f89412587bd6d0057898f5ae284db78b0ec861fed36dfb7c7a9679ad0480eefe71985ba6f731bd0e816a901e0c017dd0cb7fc8a4606dec2091a51aab16d6f9bbdecf3fea177671e68250a84fe19de8df78d711e22b81372bc22ae21ac7208ed41201f6e26cd6748e9d6e2f4884f5acba736b2432536718891638d43991bd97c232829e26be6e6bb303d44849b245ef758eb2813bc87cf21a30f132360111e3015de5d1e4f0c5a98aff159c29f6debed7c2f18f455dfc7f33995a90b7625688507ecef1e7db48e7030ea6c4fa835bbc1dfbea6c0a6c704d658d4866a42b9860b1c8b5b64cb669e102c81e369b5f07b8fa08816a566a99f4d2910f6e8d751d52f1e2889f0ec9acfcb4627e0da5c35452be05c7766eddf3c42ceb6a312044075a4231b4203718c886498a313f3ba12e44e368b04ec3ea6e72d6fed9b6b334cbc0ba89f0aa9a129b1bad5b0ad8690291a344967f58e52415859852c6ca3ea24bc93ec1041fd1dc8a6a181326d3026098db0cddec90b3cd6df1e7638a3703f70c9a3baff8f005b90f362459a275a8b39daa78ff24613434594f96b8023a41a17d815e5c0319a39e07d32841339f14f404030b4a22551b86ba94832a1c49053d63140b503f2f64354ce10abe6c08f6cdaf6d8dc361c3c9d1a8077ad34dccc699b6fe07c16f8f7743d04003d672f82e643b3f1d5e263495504e11e6b2e676c11b3d0033d5f837e6bfd01602584ff181e3cb86f081015a9311eed546b42a8280680aa538353949f89674c554b43241e36536430ae9e0190729ce902e8f06a952d23b62816deb3b62b45375033ede2d8065a8e7b38f5aee0a5c66eb2f21f33fa6795d4b086e6f6ac941ba0c883ccf6e54e52164384045e0b0d74a9361f224303c841ec907be250725ab06cf79dd8bff8f46c08963a409b9b71b5c634c987c5e163f73fc32553be1231c72444c5e2a91189824034a784948fc90000000108676ef9ec3514fd5f004046001ae0c831dde6ac72f1337c9ca111f5b32afdf102d75c017d3bccb6fa89902b750b00c51bb226afa517754b72e962ff007c1c8c8749a21be1d8d94f7bf73437c010cd60e0bd448983eee52163a177650f57b2cd8404bc619b9b59e796f9808bcd549ae6ae30d448c90f2783978bf9314a8038f45c0da5983163bd26f38f559f59447e8cf004f93b6b5c8af7b09603db021d4bdfa641bd83926eae1709a7a427add14df90cb258c6d4663d4d29709da89c90613d2ff9334637d53ca89407804eb863f78e110b866af2734c980705d9f969730a41132e788fc9e426d0f68ed24157aaff0383438d2715262e9b8b03cff850ba88127a05a8b68ac9a5ae5b098bb9ba5eaadd71ae846b3c0f68db728361eb8c8ed899c77725afbdfabf93812c49cbf4ee64047a96ea71258dbe5be3f988029d005fa2d9fc6e1e53fbeb6888074521b972e2ac71b4f22b754fc743e0de21af1e2ab416b2481e03227a1c7d7ea6cac5bc37ee3597d3bf11bf13a688dfa3d9aeff1eb1a7fdfcf8b6c722a4853f7c2b2d31e0b2b691f4273d4793fbb7a00f27a25577bfcba95e60699c9d2a926e71d64f535b633f2fd03320b28fe86c6619c54b34e6caf8f5a71b8a144c9236bf07edaacb486ff8ac63173af099efe7c9d006a5bb756449fb32b1fbff2e315fd5e96b586bb922a9795e29ffe6ead037c556e1bf30e24afb344cf873201007096b6f687f157588e236b71ade4d9245d8f065f2e23b36fad798d0f5504ddf25b828698d0cbdc28478b20d692d2ab605797a67232b0795927d886de798f00b4e7c69517d62b748e62e01d53dd1e77ac9a1605c0408713ff309ad53ff8f2bef17f9074f01134374068bf1f5dc07125180b5ea6902ec2d55c7d6d5f7ed4ef8732f9d34b4627678611fc9579e4321cea012c4e457dee6a11c41bdd1eb965056e885757af389079a558434eb3d59ae56a232302759431172ecc88de1c5400265f0f47e21396e3c38e0ba022c3e55ee4b85527cf49dece94445adc740cd26c18004a1cb984cc1732a138844da1ab003f89c589b6f3cc10c99a1b0d87be763f83e1b12c6fa6938ebc55d2ba33c25ca816dde207f7186f0c70b56b33feb538eb31175fdcfb036e365087f1b630628affdbbdee20d1976cb009f32db5f35aadb8117aa02ff2da9bdeaffbcc8bf3412efefeb00365e5f1ea577afd6e1c3585c67ffe1fa120382aa54028dcae9bbd624432a6256687d05483f2611f1ddd14b40f66fdf547e7eba904a79bd27733c9a8fbfb01154dda3457c4eacff8116941777ec570ff040e217d648ea5076588a6417462481eba68ebc59af04ba49b92f70b68a007977fde48b94b0af35475ea19cbec92df6449b065880bf03452cb3b3582f3d1a010e585be6506f3e067226471a94ce46c515f20502b3866553c10f037d9be89ad5858d6b2d2d94c70159247f66958d0e841d1c5b4254809d52475fdf96d087c3c6647b86006147a9ebb3f52ea6f4b89d886725b9e9243efd95e434bd8dd785143c57c06863b68df8f832987eb0c730c8b96634c1f888da2ef420cb0ebacf81f4b25c65962ae40c09ac4b0b2d440e3bdaa7309d87a1fa6af1c2e13e7a63c253fae027ceb2067cef8421b62d205f5d37c7204eaf594b1b43f9d9b67509a6709df48769ab9e1078f9e59d7656ec2132b5ebccf297e757a052835fffe94ae073131ac49c4f4374a1904cd4bf3041b236b73ea19eaa583db577fe35",
+			domain:        "",
+			wantErr:       true,
+			needsMoreData: true,
+		},
+		{
+			name:          "QUIC Chromebook Handshake[3]; packet 1-3",
+			hexData:       "cb0000000108676ef9ec3514fd5f004046001ae0c831dde6ac72f1337c9ca111f5b32afdf102d75c017d3bccb6fa89902b750b00c51bb226afa517754b72e962ff007c1c8c8749a21be1d8d94f7bf73437c010cd60e0bd4489d0a84868f32ecd4bd0d4c95a8a08d60d8303ef02323bdbcd96a33940824d25b9594bd8ae5716b9d043ab27ba03a2593c4d149b923711dd98e45456db19c8ea71e982562ae787c1b6cbe3ca1b03df2df62aa8e3127c5f68bdf80ed90588e7ec1f41f5a6281b87a12348cb17a04e9eaa461fef2e0e3ae70ebdc7bffa15c6b61ab270173e46dec0fd081f935a5fe6338d3b9cd38fcb52cb159edb66d2927238294313990da25c22f40d40e3cd72e76bbd066de731cf8fb6b4b7bc7639efb788c0b108dbf8280845a2cc62fbaf5fb8e1ecbe5ba7791aab94786c1c71c9058d0153b34a3f5bc8903e0d120f353defbe973cd33568bd03609dcdab8af1e8563897f5dd0251c6e6514bf40bd447d376fed21b2c54ebf74680df241bdc2ea5579bc0736cf3257c20d275746e8e6853aa89dcda8c2dbe523438ab92ca1ed1ab4f109e4ea84de57dfb6c544d695a5b710fe2d432f2b58644f8aeb965752d3a1d1a3057c2229192f89b254f5d292c22f1060642729df3667ef39e27691c82da9be847a59a17ba7345d23a37e31ec135633cc5ea84c752f56d4ec75878a2920b93e9b4e091e0114552712e1e50ade42e26ac0266b84043a493e1ce2e80cd57422de16a88deceaa55385dc2a977ffc9063e7c427200b6d8511ef9004f89412587bd6d0057898f5ae284db78b0ec861fed36dfb7c7a9679ad0480eefe71985ba6f731bd0e816a901e0c017dd0cb7fc8a4606dec2091a51aab16d6f9bbdecf3fea177671e68250a84fe19de8df78d711e22b81372bc22ae21ac7208ed41201f6e26cd6748e9d6e2f4884f5acba736b2432536718891638d43991bd97c232829e26be6e6bb303d44849b245ef758eb2813bc87cf21a30f132360111e3015de5d1e4f0c5a98aff159c29f6debed7c2f18f455dfc7f33995a90b7625688507ecef1e7db48e7030ea6c4fa835bbc1dfbea6c0a6c704d658d4866a42b9860b1c8b5b64cb669e102c81e369b5f07b8fa08816a566a99f4d2910f6e8d751d52f1e2889f0ec9acfcb4627e0da5c35452be05c7766eddf3c42ceb6a312044075a4231b4203718c886498a313f3ba12e44e368b04ec3ea6e72d6fed9b6b334cbc0ba89f0aa9a129b1bad5b0ad8690291a344967f58e52415859852c6ca3ea24bc93ec1041fd1dc8a6a181326d3026098db0cddec90b3cd6df1e7638a3703f70c9a3baff8f005b90f362459a275a8b39daa78ff24613434594f96b8023a41a17d815e5c0319a39e07d32841339f14f404030b4a22551b86ba94832a1c49053d63140b503f2f64354ce10abe6c08f6cdaf6d8dc361c3c9d1a8077ad34dccc699b6fe07c16f8f7743d04003d672f82e643b3f1d5e263495504e11e6b2e676c11b3d0033d5f837e6bfd01602584ff181e3cb86f081015a9311eed546b42a8280680aa538353949f89674c554b43241e36536430ae9e0190729ce902e8f06a952d23b62816deb3b62b45375033ede2d8065a8e7b38f5aee0a5c66eb2f21f33fa6795d4b086e6f6ac941ba0c883ccf6e54e52164384045e0b0d74a9361f224303c841ec907be250725ab06cf79dd8bff8f46c08963a409b9b71b5c634c987c5e163f73fc32553be1231c72444c5e2a91189824034a784948fc90000000108676ef9ec3514fd5f004046001ae0c831dde6ac72f1337c9ca111f5b32afdf102d75c017d3bccb6fa89902b750b00c51bb226afa517754b72e962ff007c1c8c8749a21be1d8d94f7bf73437c010cd60e0bd448983eee52163a177650f57b2cd8404bc619b9b59e796f9808bcd549ae6ae30d448c90f2783978bf9314a8038f45c0da5983163bd26f38f559f59447e8cf004f93b6b5c8af7b09603db021d4bdfa641bd83926eae1709a7a427add14df90cb258c6d4663d4d29709da89c90613d2ff9334637d53ca89407804eb863f78e110b866af2734c980705d9f969730a41132e788fc9e426d0f68ed24157aaff0383438d2715262e9b8b03cff850ba88127a05a8b68ac9a5ae5b098bb9ba5eaadd71ae846b3c0f68db728361eb8c8ed899c77725afbdfabf93812c49cbf4ee64047a96ea71258dbe5be3f988029d005fa2d9fc6e1e53fbeb6888074521b972e2ac71b4f22b754fc743e0de21af1e2ab416b2481e03227a1c7d7ea6cac5bc37ee3597d3bf11bf13a688dfa3d9aeff1eb1a7fdfcf8b6c722a4853f7c2b2d31e0b2b691f4273d4793fbb7a00f27a25577bfcba95e60699c9d2a926e71d64f535b633f2fd03320b28fe86c6619c54b34e6caf8f5a71b8a144c9236bf07edaacb486ff8ac63173af099efe7c9d006a5bb756449fb32b1fbff2e315fd5e96b586bb922a9795e29ffe6ead037c556e1bf30e24afb344cf873201007096b6f687f157588e236b71ade4d9245d8f065f2e23b36fad798d0f5504ddf25b828698d0cbdc28478b20d692d2ab605797a67232b0795927d886de798f00b4e7c69517d62b748e62e01d53dd1e77ac9a1605c0408713ff309ad53ff8f2bef17f9074f01134374068bf1f5dc07125180b5ea6902ec2d55c7d6d5f7ed4ef8732f9d34b4627678611fc9579e4321cea012c4e457dee6a11c41bdd1eb965056e885757af389079a558434eb3d59ae56a232302759431172ecc88de1c5400265f0f47e21396e3c38e0ba022c3e55ee4b85527cf49dece94445adc740cd26c18004a1cb984cc1732a138844da1ab003f89c589b6f3cc10c99a1b0d87be763f83e1b12c6fa6938ebc55d2ba33c25ca816dde207f7186f0c70b56b33feb538eb31175fdcfb036e365087f1b630628affdbbdee20d1976cb009f32db5f35aadb8117aa02ff2da9bdeaffbcc8bf3412efefeb00365e5f1ea577afd6e1c3585c67ffe1fa120382aa54028dcae9bbd624432a6256687d05483f2611f1ddd14b40f66fdf547e7eba904a79bd27733c9a8fbfb01154dda3457c4eacff8116941777ec570ff040e217d648ea5076588a6417462481eba68ebc59af04ba49b92f70b68a007977fde48b94b0af35475ea19cbec92df6449b065880bf03452cb3b3582f3d1a010e585be6506f3e067226471a94ce46c515f20502b3866553c10f037d9be89ad5858d6b2d2d94c70159247f66958d0e841d1c5b4254809d52475fdf96d087c3c6647b86006147a9ebb3f52ea6f4b89d886725b9e9243efd95e434bd8dd785143c57c06863b68df8f832987eb0c730c8b96634c1f888da2ef420cb0ebacf81f4b25c65962ae40c09ac4b0b2d440e3bdaa7309d87a1fa6af1c2e13e7a63c253fae027ceb2067cef8421b62d205f5d37c7204eaf594b1b43f9d9b67509a6709df48769ab9e1078f9e59d7656ec2132b5ebccf297e757a052835fffe94ae073131ac49c4f4374a1904cd4bf3041b236b73ea19eaa583db577fe35ca0000000108676ef9ec3514fd5f004046001ae0c831dde6ac72f1337c9ca111f5b32afdf102d75c017d3bccb6fa89902b750b00c51bb226afa517754b72e962ff007c1c8c8749a21be1d8d94f7bf73437c010cd60e0bd4489ea77dbb530c7ba127c66c3d7bbc00c336fd4e09e1775c646dffaa8696f7b8b00bf91261fc5164d57a4b9652b7cff4e301d32224b4e48cbfca535b2070ac46181615358d87e244ba6e369f6719bd5a551ac05dc78c222fd0969d0d943cbfaa3570ec25ab2768e9679d1cd1a3528659d010c409a0719526c44e4d9915dc5b0618ebc9e35f06b31bfd8e01fad99dabe32f6bfa00b3a5db5a01920d6685c34efb958729ffc5acfe46b3605715149b65b2f638007885a0866bbdde6765992b9acce2f527de906443f8643845489f1224fd3bbbb3fa78ca4848fe0167ec7cff8a05a17eb7c7a05a80c3106647e5d9aae350f33d10f3a60ab1c705858323a8f610d98cc68ef3cea66eedbb788b9a3da873bfd44ed632aa952ed7bb2004f4502260cef0596ec6e82e7683bdd2cb1f63b01b3f928ffa86b89cbeee922f1fd192fea0bdd17cf62d14f06f9e27bf5cafec90ab26f103e1dcb96ae4335e444b1fbad294cc395c5dc3a1c0c1fb4078d362eb229c42bc42ff53115c51f137d75596b3e6d3d28974720d6935430054c6b630bade51ad508d31fdfd572bd37f70e3dc06021d2b0ccf91a7975aa501e152d62980f02ce0ee94b547a2fbede47cf1f5c0a541ccc8992dd006f77437ce6a6b1f4f91833914a1cc51acf9336a620c4a22073966cde3ecac3224941dec004e741e05c11b43796dc531ce33e7c9a4fa68fa689880842e37a3a04fb75f3fcee86813388df74d443d1c35d7adea290effa98309b22ceca9bc252ccb4c443733db691adf0af559a5b7565043f84e91c5ed9f79ebf49f0bd60b68a7b8730032574e8e21548204c75321a374bbbf822efb1281ddf32feeced4bfe22bcf7c1a309954c1e356175a8a1a1a074a22f4561acd872d813c88ea9f0f22ac8d7b7b2088bc8565e1c56dfbc84f57aa38c2600ee20e8736076a91ee73f3137e8da3fe3871587b8bdb0a08af40babbe5493f036b45eea837dc15f761d9475d27a512a2d9dfc1ccdb81e2b581f91a5d7fe67cf6955427315a4e9c158806e651e4acff40051cd8a44b0108876c82f7b4d69033bfd8216234de545bf8fb58e489bc74d366db5e48711ba7f317dcdd1708ed5de97468a6026e15bc68ab11efc90f5465b4466bf384a8cc95f9c7fff91d776cccceeae5badebc31c3516c93a7b4682212e5a4902a9fd0327234749d83c141db2eee9688a76f4361f8b6213c88ebde69ebb84488c9ab8f42737da123eaf39373ac687df65f817939296f5477f92ad3fda0effbdd5d0594eb59d80265eef6cfcaf81b386c9d03c205c1b6714bf31be15e8f871b4791aec10884938285d6b8c18a0dfe750b753de88a2d2d855b9d1a0068ac4d2ce3a259bfdd30414380bf8b287abf2a28de442552f1d70a0aeb0867d9c7ed4e9717565ebc6aca21d85d2845faacfd8fadb1a76d9a2cd619413e631666009085bc7dad7492654ec20431e37ddd55588d2cd4d256021547cac768dfe3f7dcc9a18f0c72a743de799e98398b9bb2f216aea727d240b2f52ee269f4df4b8d7bdb439f074e3ef179ae2ae44daba64864fe427574b659a5e79defaf43e45e1357e1ff48e28ba6384c559cd036c9229151f917865b5575cda11e1ee0690bfbdb628b9a17e9c37190102",
+			domain:        "signaler-pa.clients6.google.com",
+			wantErr:       false,
+			needsMoreData: false,
+		},
+		{
+			name:          "QUIC Chromebook Handshake[4]; packet 1",
+			hexData:       "cc0000000108a3e7f3133d37e2970040460094b49b4808cfaa190ce163e91b9d2c0105f36a2c93f670114f7b60598f03d6c596ceb19f410e9660903f590e3f25cf619e5c171001990b1d1b97f789595d3039e666345cc944894c6153ddd936992f160ae349757507f79fd0485766987d986518d9f19270a0021c52bff14e594c074f3c5664cf3de3b761cd36c16acf68565aaaeebf196da581533f19a464b22404b13b46ae3e4819bd4a7a85db6ddf379bb84f8dffcbb412c9ce405d8b4c98d303cb13df2e80a88ca0f09e2e2489c8d0b6d5ba9262b85869f8f989e9b82c4a270592894fda96bd27ce03e0cb4d4a4e130d9655e6da02f4348c949bc9b2aa609fdb4b9a0a3e45be25b18fbde569bb996d6419e98f2d9b7a0ca63f52f054b50771dc7c580596d86b4a94642be9a9b78a01ad2deae4607d8e0e25641aa8ed46b20fe027f4b9f77d1736aa0fec4f837cf5d878b3dcefdf3c6e82eb943dd022e98d623403950e6ea3addc0f93f92a422ed686b7beee437a4040f4a440dfd071d8c09f1344c28545b4488765a455e33e13d17434b9642dedadcb6a13ec35d51c3e7a03ae9a76cca6b1cba8312b7d8bae703e0a378300a17b7483d07893ddd941dd3e545a66faa0fabb4dc967c807665ebf4562fede176719d1a126f228acc0902e7235972a6db4eedd6547c38705629ee2574c5d2dd6c76c5c82e741f33291506e66a8df65ef6d1e7e6628fe4a4f5e141d482fc5f9d26609e64da8061eef5c0fca421d5334b199ca8270612074a1f9fbaad8b98ff7b81f8871f4ada6976f254e47c51e03d4c628beb3471ba375642ae0b41d65dec1419cd31f20ec779f5666717c1e7b4240fdcfa46a774234961083e1915e938ae0d41a66868b91949d856065c4e6813e0cbd9680a916b5eb78655dea9ad0f9c0ad0f5c244a72fcb8b589321519e34f0e6e25e6bb43abfa84a7241bc02555fa9060b9ef55f1e3a9dc3a575e16b23a36aabbd3ddeaf8f2516224179a4039a891e7f29631c2a08745bb184c66ffe98bc960e6c08a14524ae34444433591cdf7adc14419310b74594305f67c3087a2c21733e6e0be748e7af6fb6717946c313fbc0935ad3559e2d6323979cdc3bd48753b5a438605e15832efb8a0c4144060f41ed27a82dd067f2caaea3830abc97d9e080b3fd762aecbd58e8b2b17dae553dacdf3ee44198d2f19c0522b6a1b17923a210cf24902c5590afe808fd22e54e586399665d588a7febd0b402a4e6283679e1f95a2d4d7d3945e2bb8f44225ad8aa07cd07d3323ce94f39ae4c9466c05ceeb0a30981cea022d1bcab8a4b0c8e42e08211ee727728c74d7945f2350a149eb9cb7eb3a280954b64e612b53b19016a4c07427945345ffb86982c113ed797172ded4428d6b95b9ce64b48e98ab96421a179983c4a74b986f3f52d9a2d7fac8ea0955835d241bf4817a42950e2b298e51de20c026df81fdb0d28c68841bf62dfcfb4684def62c13ceddce9a25b446043056006ec8582aea14eee602eb2963f575dedfd2313d7d561c6ceac0d08c94645a222b25b7493542fee52c316f06f583612ab2ec3d420a01a61fe80b099386c2fe647292769d4571239592fe7e27f4324456ef894643f72ac450628cdcc9f376607b85f369a092c64d7d5a0559193e29cbc48e9ed77fa3fa05776d6169fbdbafa507db1e1d33a4550003a3a1a794b266e886f483eba76a8629d17d9596574068ffce61a52b209c21c77f5e7337e5541755c9f1c6b4",
+			domain:        "",
+			wantErr:       true,
+			needsMoreData: true,
+		},
+		{
+			name:          "QUIC Chromebook Handshake[4]; packet 1-2",
+			hexData:       "cc0000000108a3e7f3133d37e2970040460094b49b4808cfaa190ce163e91b9d2c0105f36a2c93f670114f7b60598f03d6c596ceb19f410e9660903f590e3f25cf619e5c171001990b1d1b97f789595d3039e666345cc944894c6153ddd936992f160ae349757507f79fd0485766987d986518d9f19270a0021c52bff14e594c074f3c5664cf3de3b761cd36c16acf68565aaaeebf196da581533f19a464b22404b13b46ae3e4819bd4a7a85db6ddf379bb84f8dffcbb412c9ce405d8b4c98d303cb13df2e80a88ca0f09e2e2489c8d0b6d5ba9262b85869f8f989e9b82c4a270592894fda96bd27ce03e0cb4d4a4e130d9655e6da02f4348c949bc9b2aa609fdb4b9a0a3e45be25b18fbde569bb996d6419e98f2d9b7a0ca63f52f054b50771dc7c580596d86b4a94642be9a9b78a01ad2deae4607d8e0e25641aa8ed46b20fe027f4b9f77d1736aa0fec4f837cf5d878b3dcefdf3c6e82eb943dd022e98d623403950e6ea3addc0f93f92a422ed686b7beee437a4040f4a440dfd071d8c09f1344c28545b4488765a455e33e13d17434b9642dedadcb6a13ec35d51c3e7a03ae9a76cca6b1cba8312b7d8bae703e0a378300a17b7483d07893ddd941dd3e545a66faa0fabb4dc967c807665ebf4562fede176719d1a126f228acc0902e7235972a6db4eedd6547c38705629ee2574c5d2dd6c76c5c82e741f33291506e66a8df65ef6d1e7e6628fe4a4f5e141d482fc5f9d26609e64da8061eef5c0fca421d5334b199ca8270612074a1f9fbaad8b98ff7b81f8871f4ada6976f254e47c51e03d4c628beb3471ba375642ae0b41d65dec1419cd31f20ec779f5666717c1e7b4240fdcfa46a774234961083e1915e938ae0d41a66868b91949d856065c4e6813e0cbd9680a916b5eb78655dea9ad0f9c0ad0f5c244a72fcb8b589321519e34f0e6e25e6bb43abfa84a7241bc02555fa9060b9ef55f1e3a9dc3a575e16b23a36aabbd3ddeaf8f2516224179a4039a891e7f29631c2a08745bb184c66ffe98bc960e6c08a14524ae34444433591cdf7adc14419310b74594305f67c3087a2c21733e6e0be748e7af6fb6717946c313fbc0935ad3559e2d6323979cdc3bd48753b5a438605e15832efb8a0c4144060f41ed27a82dd067f2caaea3830abc97d9e080b3fd762aecbd58e8b2b17dae553dacdf3ee44198d2f19c0522b6a1b17923a210cf24902c5590afe808fd22e54e586399665d588a7febd0b402a4e6283679e1f95a2d4d7d3945e2bb8f44225ad8aa07cd07d3323ce94f39ae4c9466c05ceeb0a30981cea022d1bcab8a4b0c8e42e08211ee727728c74d7945f2350a149eb9cb7eb3a280954b64e612b53b19016a4c07427945345ffb86982c113ed797172ded4428d6b95b9ce64b48e98ab96421a179983c4a74b986f3f52d9a2d7fac8ea0955835d241bf4817a42950e2b298e51de20c026df81fdb0d28c68841bf62dfcfb4684def62c13ceddce9a25b446043056006ec8582aea14eee602eb2963f575dedfd2313d7d561c6ceac0d08c94645a222b25b7493542fee52c316f06f583612ab2ec3d420a01a61fe80b099386c2fe647292769d4571239592fe7e27f4324456ef894643f72ac450628cdcc9f376607b85f369a092c64d7d5a0559193e29cbc48e9ed77fa3fa05776d6169fbdbafa507db1e1d33a4550003a3a1a794b266e886f483eba76a8629d17d9596574068ffce61a52b209c21c77f5e7337e5541755c9f1c6b4cd0000000108a3e7f3133d37e2970040460094b49b4808cfaa190ce163e91b9d2c0105f36a2c93f670114f7b60598f03d6c596ceb19f410e9660903f590e3f25cf619e5c171001990b1d1b97f789595d3039e666345cc944892d4ba45357f2ca515d03b90820bb91c531a4be27266fda6022856da650cfb9c34139e8a3180e93cb73a6864471f849bdfa26c03e30c0e4d00309207cd46fb48887f60d7c51b208c247d1b311b35da70dd682cb1f7ae6a64215e5fefe25249daf308083837a3898e6052ebcf6cef3cb8e987ee1eb5ea797642d76391ae363b8eb2409d7486dd4a67c9e9b755376ca61009cb853835850e4fc1844f8e9eebca73e89317003482f70c4795ce9e2724c6d62172e010233e7bf203dde6eea9976f29896df562e8640a4ed88b5b3dff50296d0db43885f162c588d72de357c2ee049d9532642576de64d4e13cce77208e0aa9cf9838166f3375a968a5a6a01cf066ea0ca27fe4471cf0bf7eb36227867928076985588d05692d3f81d9a1158d150b2701399ee0a32693aaac43c27b76c657343b2a307e7018c2e9fe6317ec09f9afb762075430140b15016ae44acffc7467f4b1cec619942e916047c2db27f89742e53856d8c7c098beaba710340674a3f8455ab38fa2a4156fa3a45dffca1e20ec86ae792988dcb52bbf2ac97ea878e80511d3e4e70ece4b2816401ad450b9d13a1fecd7a5a363dd120285a972d52c06b632362cb8f897f799fb8342850b6670eb5083347347bd48b559f118839aa627598379963ecf18c2a900399ed936ab77ebdf95bdc5eaa75a903005e38dd99362b3d99f07ee2aea1a0ada77ec5ba76a7da2a80b672f4709bd32fad36787e37467e75fe594a24b402a6fa7e858c2abe9cffd9e885cc7091c035e4354779fc113bc084b5f6fcbd7bc618e9cc15205538cf781c96b658565cd8e39d95001d085d52f87a2970eb8f72149f4061d629ca0a928442b586aef9105326e13c015ce2b987c442b574180550302c48c2cf763b45492e25adee42d23bb2608e284caea4b3a28b77a20768dee6c0002b16e5d714eca22ca0c58195e03951b9564079ffa61c81afb2c5783ea2b8c0605d3994cfaed3c33af2279469c771269174fc5879b67617f571eb376161241ca5a89332074635413661b7fc5f925d86afb56b296dedce33d2b5011fc3b85cfb769c4a1cf5d6217ba3db367ead2159a310cd398b31df83f48f722a1df6c4b6604b2e288aa57cbc9afcf42764ccbc718a3ca42895b8e8287d632d2dd47d933a7472fd7be596c4241220917e636a44a139ec16600d74104fa6055a77c34bdbe14fb1ee56b4084d1d2dc1d56f8d636a8393385fcb4916670eaf8553b2126b12c8f187f58f00ba9bdbe8f06662688b9b8c7327b2d2c2f1443c8b87930d0948c3db62c8becb5b38cc7e484be184400f8c6293568abf1714e2832ad2c0aeb88dde64686fa7b4cd8c452b7365e70221e62dd971db057d4f8eed86e6802bbe8f56f75a8fe65d8216c81265e514042dca73f20a50373fb32e9bd62b741021337a3200b5f0a1b1329e99c57c75a60850f6c2f82cbeb9001edb54d985b7d5cd5957b31f79ee77dd8e1ce5e70d50806273885886b93a12c3dc0f211383d180a475d65bb54b0c5f761f456bfc7d045acd2c7ac648f3bf27bdb52218be48cdef7aa1ddc93e3ce11067ef4819796a4e2a30459c879841789b358b9430368b0910d6e6eaa14894f36b12fe9dd2bd1a20ddb6b12ab8fcec7d0629c9a7",
+			domain:        "play.google.com",
+			wantErr:       false,
+			needsMoreData: false,
+		},
+		{
+			name:          "QUIC Chromebook Handshake[5]; packet 1",
+			hexData:       "c200000001085b15f32cf8fb5a3f00404600f909e38ed514455146c4ab8e53dd225a775dab2a06eaf73c2ec6b36c95c40873910eaa7e424e1b1fcb15892cf9e37a0ad2a1b67e9e8c6ec0c3a99e3d8775afe1e0aac824704489c14d28b48268df096f2db0c040c0ffdfb1817c4e1dd32005e87a74104515069ccd1b12f6fa3f657891bca8f0d27f4bb42b23c8310897ac09241f511888ac2e431e3ba8d9114b3f8bb1470324c8a0815dd1589686d058d03fa2669ad7367dc8877abce4700ae999112eb7cba755b20b7db66918021a36a66c60ecaaeb3e0859e3f50d14c1f8c3f56966043f437bfc16098deeb02e2236cc42d2f2802f4082bec30afc347a75f78c5e7337c52502e8e8d945bb4d792ef69419e57ee4e8f3465de4d0a49955787dff0756f1bcd98268919c112ae5e87ec333d590988e111724627143bf5a0aa69c77ee322b1240a65718e0033c4b70c6a5dc2d3248aef71598d73effa0eb397b79279ce846d9c2556fca28595eb3b196f40f052f0127711abbbc334571b8de67f7d39bd9437f9196bfe0650c4972462473776eccae42418b16edd5f45414e1a5e13300ae6705a49ef68e1748e876ce04fe611c973f94fcbe18b0c1a0ae506ce6eac268021e9744899c33ffe44dabdf1ea5413c20ab1013326255ae6df2d6861a7e914001e231ce4065e0d89fb439afb928d660cea26f99eafe65c9f89c5639f3ba8ffdcdf7a777d7859ca948f123a5c4f1491e22803754373ab0f1b605ac09ca6018c6acca7f52aad786ce96d9ae28d09a77dd88d77f23e2e33475973a23dea914fb049662800cfbed416b61835bd3bc22dace817b3b271c816ccf9603de2209067def5b8747112c49659cf6c5281402bed38a4176c0331e0841592c503d342188ac97266866a102864f76b0ff2adf781e0af84ae725fb6db418545dbb70adde5d4ea6d87f8c9b64b579d4f969830056dc0007cdad648035ccdf2c24264905422dfc1a85ac7f519f475351e046a27268312d4ab6a66ea55be01226fd5dfce06f804cafe85ad997946db3d029ef28ebdd36103c8fc05b522c1d4debe034523595cef576c771f0848a221d76c63dd044ea61a3adcbe5d4f0ebcd0bb631f4db1d88a609a1c2a6cc3de29ccd8a40e8a770d806abdae300cc178a32b4ba979652d0b8849dff252571f0b09935744c5b33628a190ae2eb43543ed8dee8539fd464abfcd3cf826aa18c4e84cd11975c5e3bfd0827f7cd211a2084c8626ed4e32bb9877f4801dabe695132b835e335563cb2f4c3e9377cac57f7766a10620f1c57c9f485d66918613daf8b257035ec91481d0076899c45abdbec38b63745428dee481c1cba81b0ab6e7efd6b0c431e018b6503cb13d4df18dbbff195bad1063d59ca5066e0733d3f499109111d22304066e7656e755518ceb6d862095ae54e532fad82f6c21c0c4d776dfecc516b00fa59e117e79481d3fd386c9b0c4d6fa4ec295a5b5b67207c3db20a206e0e31dad2c8dafb38e35dde331730bea33af32893653763e82565689009265db76b3b142d60f302a9545d82900aa6a017643c5c60583aefae43066ea3908e299612b078d06f102280dce4429461a42d80acdb6279c7aa190f9a8f61b485ffa430cbef199e1732da3d9b96cfac7ecc3b4959b86260eba763abb74c249180f67997967e716c95788bb6c04f182f40b795a929370c7fc72f1785f94cd36e3ddaddc15c7adb226cc131abc1863352caceb541d3924094db9c8a1c21c21640",
+			domain:        "",
+			wantErr:       true,
+			needsMoreData: true,
+		},
+		{
+			name:          "QUIC Chromebook Handshake[5]; packet 1-2",
+			hexData:       "c200000001085b15f32cf8fb5a3f00404600f909e38ed514455146c4ab8e53dd225a775dab2a06eaf73c2ec6b36c95c40873910eaa7e424e1b1fcb15892cf9e37a0ad2a1b67e9e8c6ec0c3a99e3d8775afe1e0aac824704489c14d28b48268df096f2db0c040c0ffdfb1817c4e1dd32005e87a74104515069ccd1b12f6fa3f657891bca8f0d27f4bb42b23c8310897ac09241f511888ac2e431e3ba8d9114b3f8bb1470324c8a0815dd1589686d058d03fa2669ad7367dc8877abce4700ae999112eb7cba755b20b7db66918021a36a66c60ecaaeb3e0859e3f50d14c1f8c3f56966043f437bfc16098deeb02e2236cc42d2f2802f4082bec30afc347a75f78c5e7337c52502e8e8d945bb4d792ef69419e57ee4e8f3465de4d0a49955787dff0756f1bcd98268919c112ae5e87ec333d590988e111724627143bf5a0aa69c77ee322b1240a65718e0033c4b70c6a5dc2d3248aef71598d73effa0eb397b79279ce846d9c2556fca28595eb3b196f40f052f0127711abbbc334571b8de67f7d39bd9437f9196bfe0650c4972462473776eccae42418b16edd5f45414e1a5e13300ae6705a49ef68e1748e876ce04fe611c973f94fcbe18b0c1a0ae506ce6eac268021e9744899c33ffe44dabdf1ea5413c20ab1013326255ae6df2d6861a7e914001e231ce4065e0d89fb439afb928d660cea26f99eafe65c9f89c5639f3ba8ffdcdf7a777d7859ca948f123a5c4f1491e22803754373ab0f1b605ac09ca6018c6acca7f52aad786ce96d9ae28d09a77dd88d77f23e2e33475973a23dea914fb049662800cfbed416b61835bd3bc22dace817b3b271c816ccf9603de2209067def5b8747112c49659cf6c5281402bed38a4176c0331e0841592c503d342188ac97266866a102864f76b0ff2adf781e0af84ae725fb6db418545dbb70adde5d4ea6d87f8c9b64b579d4f969830056dc0007cdad648035ccdf2c24264905422dfc1a85ac7f519f475351e046a27268312d4ab6a66ea55be01226fd5dfce06f804cafe85ad997946db3d029ef28ebdd36103c8fc05b522c1d4debe034523595cef576c771f0848a221d76c63dd044ea61a3adcbe5d4f0ebcd0bb631f4db1d88a609a1c2a6cc3de29ccd8a40e8a770d806abdae300cc178a32b4ba979652d0b8849dff252571f0b09935744c5b33628a190ae2eb43543ed8dee8539fd464abfcd3cf826aa18c4e84cd11975c5e3bfd0827f7cd211a2084c8626ed4e32bb9877f4801dabe695132b835e335563cb2f4c3e9377cac57f7766a10620f1c57c9f485d66918613daf8b257035ec91481d0076899c45abdbec38b63745428dee481c1cba81b0ab6e7efd6b0c431e018b6503cb13d4df18dbbff195bad1063d59ca5066e0733d3f499109111d22304066e7656e755518ceb6d862095ae54e532fad82f6c21c0c4d776dfecc516b00fa59e117e79481d3fd386c9b0c4d6fa4ec295a5b5b67207c3db20a206e0e31dad2c8dafb38e35dde331730bea33af32893653763e82565689009265db76b3b142d60f302a9545d82900aa6a017643c5c60583aefae43066ea3908e299612b078d06f102280dce4429461a42d80acdb6279c7aa190f9a8f61b485ffa430cbef199e1732da3d9b96cfac7ecc3b4959b86260eba763abb74c249180f67997967e716c95788bb6c04f182f40b795a929370c7fc72f1785f94cd36e3ddaddc15c7adb226cc131abc1863352caceb541d3924094db9c8a1c21c21640c900000001085b15f32cf8fb5a3f00404600f909e38ed514455146c4ab8e53dd225a775dab2a06eaf73c2ec6b36c95c40873910eaa7e424e1b1fcb15892cf9e37a0ad2a1b67e9e8c6ec0c3a99e3d8775afe1e0aac8247044898c283466f3b200164ad9b30e17b425e07f6722df94b9a77dd555fbf25e5b0bae4fef254daf03f156b78afd967614c78208deaadef3552040c055487804c047604c5d6846e67d33e5fb5f743a81f688220d6f4c87091a860885af95d2db27e9c5dd2361f8196f5c1ade8fb37e159980547c38c6a6ddd0e055fbbd52bd7615615ffca15a0c144899d25f21156c53cb3922d2ccb83073e26074025a3c39f64a67dc02044ce0d630d9120041b2233bd26282bd2d7d1a81d486b64cab6dba7fb4375e200f53523f714a066b96769f9b1dc7c14353fc1faa51c0aeb99507ff3ae90ad6f4bfbc9b9ea00a87f8bf8e213a84a9efe2ce624e629261d93c83642df97fe146bdef478cc92bba387c9b524ac83cde55ad8f4a4d8fb3c09c8245a50ac16ebb67d651110a10ad1f7dc74ed32b9d644bc4b229c56942072aae5c311059165ef6839e7cfa0717c7032b667b8618527722fdc10a4c0ea900e9b414521b89ca83f253ea414a410a8b0b13da25c4b618f2ccd79e5d2a7579b4c431107d56ab8df16125bc25673181a6bd5abb09941515806fda32659e5281457d8c093314da0087169781b306f348d3994d84bdef936bb11355c41ce02c359174dc2a366509c130c96ddf5f156e0eb7912ac56611cf4f59ff3a8785034e81738a53ebc7fb60aaed709d78980d39822aae7e9a9d985aee6c11252a5e984ff1d167b9d4dc5d02ca8ba1167422dfc0f68b3b5902f3fd032204a5020b14a288ecd845816575fca7ef13c85765385e9964a9f0f6e2e5c4e600b190b275cd91ee8a38ecf73d35bad7371c15fdb73059afb3178786e76750845232ef787767c6985ea9b9ed9ff73430b7afb8e0b66aa210ab1943b606021bb8f50c55534e1014003d947533c1c0bd0c16dfaabf4914497583b818e643a2d8bc32d33a07133b4eecf8bcbd802dfaae894ebd473338e074af1b3672c6f03c55e6c3885848a4379cdb5873d9ff3015f9ddf8d954b3cb4eb9f56f2e8ccb519dcba72c5832146011068d3074520370fc8008b62f3fdd65978865df1a85e58fb62315dc617a3367e6c9564fbf74f5d5015932d435f3aaaaed37bc7d14d974c0e15d899c684f17db3b4790bdeba076624f4f45a0cc1c6c078a527695110842e837ded310f8c6ddf69a18e455f09130d4b4136ca6d02eee0f103b9923adefe8cb36b8fd554a27fa7300c4a6173835ca2c4d38cc11e3849ebbf73c475b7d0713caed6e70f55b34ccffe03978f231d5f92bc1e2da7ce589e2cc2cd76183394469fa537cb927db14a383dc589cf10819eb90dbdb7981cd1eeb3a284c9ce55ed859fbfbe73ca22328073b534bc81d319b5fdb97e66d532b5ffc19516b4c70ecb68f963b053a82915f3f74c8809f082bbc89d97dff9e8c82a65ed4be8e2975b82f0b7c73f34797c61db4ea8ee273116564288563a71747cf31568317363dffdff1d9e159b2f9bcd3fe5be96a9c50ac885493cc16234c58cdf471381664c1e3b54d147ea5c779c9c9b06d5c493231d9c03b50c6cba315a5ee766a6e8578105306e0911270d347e8ade2b354037f507e4993708191d32b51a79f023f4fccabb7d2ac262004745cc528b8a6dc1d8849e9d4a0152ab326b1eab8a505eef65076aca156f7b9",
+			domain:        "optimizationguide-pa.googleapis.com",
+			wantErr:       false,
+			needsMoreData: false,
+		},
+		{
+			name:          "QUIC Chromebook Handshake[6]; packet 1",
+			hexData:       "c500000001087e13dee82c592724000044d0a17c2a188dadf8c82a018cabf25d25211d9987189b2900ad36a8fa366990353230bc8d41ec5543e91e119a0fd35f72d320d670074d02f412a5418c9a3e25489db73b1f5e5ddb8fc8d6c51fd6a12dcade71e1fc8e89d2663e206185247847d218d695793a8a1054afd18d42a4feaa9bb5fae7651eab0bc5e9aa91539c311cbfd17f46d8894ac45eade657bd456ee87b4475f5e84a2c07571b082ecfdafd1a660075692ae22048d163067a60e06cf879eab20a464c6e44b242da94cc6b92e064ee6a52cb34c115056925d4615e51157da4e88f019ae144040827cf2cd2806b3f4018cde5f42e041ef55eab35fe65ff79dba1ddad5aba6221e93d4555510176463888666b1d1f53a2f3c71e8872b05717002717edd3a9c5c651be47a663ee877962623ee92310b2b1dbcd75ec2f31d9e2f0c87affe3ee083aaa0868c03c9b4e78660d8afa4e936f81dfcb2fc33dbc1ed3828195c8de3130a2757641652de23d270c8a25976546c46460d9635f499a650475a4288d1c62241f65ddd346e2bde3f4fb5fec76646f51d829b55e16a0975494c11101abb504f5398a761d59355a4843e14bfeced024239ca06717d27e932df5e050d7c54c9b3cc937f6b0731f0b1dc312b14cf4388bbc0c601abf8ca16ed7d9b597dd414156d75b486ac256f8989a072fe680961ac7446201aca359337ef0e58ffa2aa12bb3c9bd1a9f6237b5c37880cd450d8a95db7c1463c53ac4bca174f278be1a99fb75ded9fe282e0e44a03b51ad943cf8970e4ca7f8567d9a3883d07bc0ff6c11639ebc7614fa88496488cb2a49a158d0f008a6a03caf97d77c3d03a98c5a611b04f865d134e258f4094bd220e00bde789c3b3158e622d509073179c0725c7a14dde1cd76b4c6b61fc7ba87f05742f081a5c42dbe83445132b8ad1539ee36e221a9dc700ccab55e34688b082a1a8edc48335760f3d5fb7e92b548e7a09d11f15b97bda08ebb5ea355e274587720d7c1189e9ffbb00dba3c13da94d646e7742e3641d59aee50a5bd400cd992c5614325d8f1ff3529637c3f60adc1682fa6b5e26f3d52de73236680abde87ead74368e05c600a2fd291a592be00fba64eea78c9e1f5e55e61f691b3eb0ef17b7bd11f06427c89c4c930d18c0b28221a6c918322cae56397c7e2978bf253e7f2d987f4cbe66c44a96b45cddb9d5f6dae47bbc9e1f9dcbe6280e50c5dfc91efb469f408b28fed49c583800009dc8bfb4bc42174175df987a3be833582abd9aa09ba0425973de2ea9a4149a81ae1863e0c9f1b1075c26bf965dcbec2bea47ff6042495ed715b65fdd3266800994463c95960dfb6ceadfa07d58910d329fa7ef7a8f14da4a6d3b09faa5b17cbac8481ea46cbfcfb54f660929e268bcf2f86cd88a1b065dcc27f18110db9efb6fcf1eec62874ed3657b1d43419f39e785c510d239c021b7e97d258d789c90d39b434f1667495bd4f5dc5e0eb97df376d801cced0da3a85aab6ca12893d8622314b5d530f28ead33075891d0ee553d5bedcffb20fce9933ab5e117df816c96398f6a60c9e6f5b9182fd7d58869de01635b2c178ae7738beb81e318934ecd752393129fda6833718d6984d8e1a8d7bf52e9d93ad0902c0fbe3e66ae8305e43363d8996626646a684bebfb1809ac9823be750e84308ef573243b884d09ef294094ef256cfc13cb0fedb1e095ff71687c09a767bff308e562e1a6ce9964014a7afc8db2481d8d07486",
+			domain:        "",
+			wantErr:       true,
+			needsMoreData: true,
+		},
+		{
+			name:          "QUIC Chromebook Handshake[6]; packet 1-2",
+			hexData:       "c500000001087e13dee82c592724000044d0a17c2a188dadf8c82a018cabf25d25211d9987189b2900ad36a8fa366990353230bc8d41ec5543e91e119a0fd35f72d320d670074d02f412a5418c9a3e25489db73b1f5e5ddb8fc8d6c51fd6a12dcade71e1fc8e89d2663e206185247847d218d695793a8a1054afd18d42a4feaa9bb5fae7651eab0bc5e9aa91539c311cbfd17f46d8894ac45eade657bd456ee87b4475f5e84a2c07571b082ecfdafd1a660075692ae22048d163067a60e06cf879eab20a464c6e44b242da94cc6b92e064ee6a52cb34c115056925d4615e51157da4e88f019ae144040827cf2cd2806b3f4018cde5f42e041ef55eab35fe65ff79dba1ddad5aba6221e93d4555510176463888666b1d1f53a2f3c71e8872b05717002717edd3a9c5c651be47a663ee877962623ee92310b2b1dbcd75ec2f31d9e2f0c87affe3ee083aaa0868c03c9b4e78660d8afa4e936f81dfcb2fc33dbc1ed3828195c8de3130a2757641652de23d270c8a25976546c46460d9635f499a650475a4288d1c62241f65ddd346e2bde3f4fb5fec76646f51d829b55e16a0975494c11101abb504f5398a761d59355a4843e14bfeced024239ca06717d27e932df5e050d7c54c9b3cc937f6b0731f0b1dc312b14cf4388bbc0c601abf8ca16ed7d9b597dd414156d75b486ac256f8989a072fe680961ac7446201aca359337ef0e58ffa2aa12bb3c9bd1a9f6237b5c37880cd450d8a95db7c1463c53ac4bca174f278be1a99fb75ded9fe282e0e44a03b51ad943cf8970e4ca7f8567d9a3883d07bc0ff6c11639ebc7614fa88496488cb2a49a158d0f008a6a03caf97d77c3d03a98c5a611b04f865d134e258f4094bd220e00bde789c3b3158e622d509073179c0725c7a14dde1cd76b4c6b61fc7ba87f05742f081a5c42dbe83445132b8ad1539ee36e221a9dc700ccab55e34688b082a1a8edc48335760f3d5fb7e92b548e7a09d11f15b97bda08ebb5ea355e274587720d7c1189e9ffbb00dba3c13da94d646e7742e3641d59aee50a5bd400cd992c5614325d8f1ff3529637c3f60adc1682fa6b5e26f3d52de73236680abde87ead74368e05c600a2fd291a592be00fba64eea78c9e1f5e55e61f691b3eb0ef17b7bd11f06427c89c4c930d18c0b28221a6c918322cae56397c7e2978bf253e7f2d987f4cbe66c44a96b45cddb9d5f6dae47bbc9e1f9dcbe6280e50c5dfc91efb469f408b28fed49c583800009dc8bfb4bc42174175df987a3be833582abd9aa09ba0425973de2ea9a4149a81ae1863e0c9f1b1075c26bf965dcbec2bea47ff6042495ed715b65fdd3266800994463c95960dfb6ceadfa07d58910d329fa7ef7a8f14da4a6d3b09faa5b17cbac8481ea46cbfcfb54f660929e268bcf2f86cd88a1b065dcc27f18110db9efb6fcf1eec62874ed3657b1d43419f39e785c510d239c021b7e97d258d789c90d39b434f1667495bd4f5dc5e0eb97df376d801cced0da3a85aab6ca12893d8622314b5d530f28ead33075891d0ee553d5bedcffb20fce9933ab5e117df816c96398f6a60c9e6f5b9182fd7d58869de01635b2c178ae7738beb81e318934ecd752393129fda6833718d6984d8e1a8d7bf52e9d93ad0902c0fbe3e66ae8305e43363d8996626646a684bebfb1809ac9823be750e84308ef573243b884d09ef294094ef256cfc13cb0fedb1e095ff71687c09a767bff308e562e1a6ce9964014a7afc8db2481d8d07486cd00000001087e13dee82c592724000044d0b2c403d66eaa310a954540668e9edc4b17a321446ac931672ca3d9097b2854efdfa7a8f610be76592b56ef9154b9ab42f4dafc575a9b9572433fa2bba180194a32a72a92a42560ae840508317cf34015b1d7d88a633588ce4333cd12bec1f9d53fe905130eb136852d4f405ef66254a0807640fe415e6d667b9f5e2148826d5a6c36b3c44b822cfb7a1e76954610a522e1bc9703e155f8f1e0c705e411d09c5dec1183c61608174767408558da03290f5536682373a09c762deb829dfe3ee061ac9f509a2b3d20dbb77f262e9ba8a5ff50f895165742c90c4ff48eb0438d5ff8491700f97fbfced20e8e95ab9b67078ece6664527eb8a4e78944c07c6bc5c48776e141418c3b5a0e58d24114b7d65a83619525f5a10be53a55f6e3e65080cf42109aa2ec166fbb9079444ea6c809b5062227fed7cc81609a6d7ea471bc82cd0759a354aa896c7a8242c3d8c845aa52225bbaf7546a0de6510189cd2852f7b70a29687eee6a3a99a3a288f3c3672a72dba2843fcee320e18ea906adf1629cc7f8220b6be890a8d37f4093022717d8c6d76080d07798ba74e9cda1a4c26189c367a6d12da14621b93fbfd2d2365465350b5864e4981955750c6d4038b74644827cd60c8cad0d6a18869f99d61b214becedd8f71a476c2a1a0ea8fade7b15de6ee522b6b90d0cc4e6d40eb85d9b5097e2969e85eae6710285016ae47fbc858d63e13d882721aaef3cbe0a6e4c4910e8b3e465fa66a738d8979a444b4a4804baf5b4f9a5fc8438f4991c32d280c5d273d0a1e0d9eea30d003162cd313780a5b000f70fb7797e6111b354c3deac241cb816328b77d71584852966392cab9b1a3d64ead878a2cfac085452397ba17b5cddf96415c31846a80fa9a5a21fd5f9963324ad75505d4b5c70903ec3b5f91c3460d88a7d1c6b111a5206d11accac8a2115e1ce8e834b01f48e041dcd71585c6fcdd3a2e83ec2ff1a2b85e75134ec966afec023d375a2a8bcd54ef0c42d50e20c6cd9b9fdab63785e62c5a4ceb8451c560b647a6cd87698e56e0be4e2990337f45f1cb4c73f0dbf98da1158d75df6eb60ab7a61d836c7b7f3e5c809b850a5cc5369ddd4e455da5e88179e932311873d177febf6226a378c72324ea710e10ef74f6462e7dba25b7df336cb2947df749ad0b8455f3c5c9ba5c0c8eb1e665fe50451c928ce87cc81a0ae2102e7a4fc297392818db885943112fae3c4547ea48c89ef9cd44c2edba4856dbc72b956e4fc6a875bdac57b1cd2378ddb9322e5a1d1844977ff2a6e94d8a00f4ef0a7ef7949f0840c6cc781252830c70d37df9846a69eb95bc733ec420b7b3724572521496da27bba1fcb73c28eed1eefb094283ab01284ebd82004e0be9977f23fbf135b8162ac41a2bf9e1b941b05cb52c80279775070cf2f851bb0168235c97de47880d2d51f1d5ba8327af33f16f49d44326b0d08d20ca7880ff88a14d3201452d7fd452b24fc3b69b89c5149795bc4d0bf51b6ace2c9146048e5ca0259b4955a069a16d5a73e72248cec44b2ca542dcd326aca3ba53bd48368719f44d53eddbace11ff28c11c7fd90c38966752532d3f81325d1682839b2da3d69acc85275c71ef3b10c4d983cfb0cb464f554d9360b0d6ec8fd25b85824350866207eef9e2c66e43f5d08e86aa6186b36d9ece72f56e06ac8e51a1b53fab4cc496e69307e9810a9b5cf960f306ec54131dd8e917a5861ba92f6885e41993",
+			domain:        "lh3.google.com",
+			wantErr:       false,
+			needsMoreData: false,
+		},
+		{
+			name:          "QUIC Chromebook Handshake[7]; packet 1",
+			hexData:       "c9000000010852e6d0c4f5f177b700404600eae9a1449fd711efdca846f59b6c9975a2189c1430f740e0e0eb4d50be086b798a47e037ee6afe9785b45df6302cfb87d39b9c03d0712f11793adab33e74904249722c4a1544896cd650da62160bdb601194f82a98c06df2546b79b5bab9503eafdbfbcfd1128204b52c9c5dde4d661cb84f2e015b7de9e10109874176362b7f06d4b49d850f2dcc8485aacb82fed8017fe454a1c31cfb82d392d6894081fa3ab1e5f2b71df79bf5a52a68a90d4752cf441220acbb274e3473f65c1a6e4cea3295da23e4a07818d5ba80b0668638c6ecb0b3ee12ecb8bed4ca32e27f4eee7376010b3905b8f7055728b8b1eda2e2707338b86f9a6115a23b29a010769d9a0e19d2bd06b81a507c4775d7215030862a026f168664255912c321669a5eff84ded4fec82af394cee909110758e5ad4de945236001bc0627d8e88ead3c3a6790d7e50887ced96f8380a80b11477147abc24dc4963c1907a07fec13e3cd8d5bab83cabd7cf8bb66af4911dfcdaf0f13aade34865b0740bebe4b4a482f1e3105bb9c3e5fece975187fa4eae5cb8fc868376b8b8329f89e407618aa5265f8ce73437e9f2714d752dad78025a38eaca1ebd6617a9a8a0bdefa8b3d3daad006978ba85d17ce3269da06be92eec61e4c5c99712517f01588b0b7deb4d7a75cadd5643daebc731f4a7bfaf17e8f002721b054a5d6d6ca7a3430c9480daff6adfd0a5480968b4fe0ee616d2e1f2f01268dcda2ee523fa593a0c83cbfc051dd7d503d48b152eb53894f79d4f6d38f05af35b287d16df579575b755f36e87b6df082108fda812195d5f60d2ceb59a54f09bb270d660c1d923348c7fdad97dc081e749a393af83bbcdd3c290efa19bce1a0f68dab0061df9dbee778dffb7754db10cbcc354a4b66c614e29d216a3a45a38594d337f775cb88c940924734ad52f8856606147b14ae2cf2990e1c401d79d27e4d6723afa4047454580698b9108b952b78b6bfd31db3b376f0879b2a0d8949b8443ffb9f7eb84b8024c620680481944312e86d183735effadab2d9f144a72d170fb035ed230f1451c94cb3f39bc28929e7480b22bbf6c906070eda03884cdd7ada9b10b7af27315c3bde8b4a273d46d1f764669aca152120da3e0a4fcf1be84b4f3cdfefe235a16598022cc74ad8f32e78aa06eb74ef61cccfc82ed35bcb70f008368ccdc17a6f64a316fcc9f006f307fa7a1a50f28c343c4c93a39df73a0d0a6dfc6f8ab10e966f738bee331e5a29d91ed993fd2638f0ec9d0ce539552b0a312fb85ed5e9f392fbc76a6164298b9de2c47dcb21a895957e92bc1270dfef3f00f44cc42c5f5005132dd030f9aec804045731c6a3eed3776beebe9451488932a1172b979f371aa370308037e57513a8fc9dd03d63fc2e5f7dcd683de26e116ea11a1d3b5e61fb5bbddc98e4ccd20be9ee71c02cacc95cbb17dd404558f586d4f0334bd12fc0a584d29eef3b4c2ce3f87babc462b6d24ca10aa8f1eb1abbd29d11ce3f1c92426c4950e53ba6c914cb4bf0bb1b44b25452cafbf246b76ce17f829bef3178174fbac4f932e6ac18e579fbbf8790611187c6f01de70fa82a21e979c90eed3c7f7b7e416491a000b5f2216e54858fa61893391b115573b2b960a0f7dc1e2a703a6f38485589c9133b4509fb54b4a602cc7d3341298e8e5da88d5e06aad28738650c08d8c71239735375e5bca7ea91dd78d748d65af598192317fd69e03daeecc99b8b",
+			domain:        "",
+			wantErr:       true,
+			needsMoreData: true,
+		},
+		{
+			name:          "QUIC Chromebook Handshake[7]; packet 1-2",
+			hexData:       "c9000000010852e6d0c4f5f177b700404600eae9a1449fd711efdca846f59b6c9975a2189c1430f740e0e0eb4d50be086b798a47e037ee6afe9785b45df6302cfb87d39b9c03d0712f11793adab33e74904249722c4a1544896cd650da62160bdb601194f82a98c06df2546b79b5bab9503eafdbfbcfd1128204b52c9c5dde4d661cb84f2e015b7de9e10109874176362b7f06d4b49d850f2dcc8485aacb82fed8017fe454a1c31cfb82d392d6894081fa3ab1e5f2b71df79bf5a52a68a90d4752cf441220acbb274e3473f65c1a6e4cea3295da23e4a07818d5ba80b0668638c6ecb0b3ee12ecb8bed4ca32e27f4eee7376010b3905b8f7055728b8b1eda2e2707338b86f9a6115a23b29a010769d9a0e19d2bd06b81a507c4775d7215030862a026f168664255912c321669a5eff84ded4fec82af394cee909110758e5ad4de945236001bc0627d8e88ead3c3a6790d7e50887ced96f8380a80b11477147abc24dc4963c1907a07fec13e3cd8d5bab83cabd7cf8bb66af4911dfcdaf0f13aade34865b0740bebe4b4a482f1e3105bb9c3e5fece975187fa4eae5cb8fc868376b8b8329f89e407618aa5265f8ce73437e9f2714d752dad78025a38eaca1ebd6617a9a8a0bdefa8b3d3daad006978ba85d17ce3269da06be92eec61e4c5c99712517f01588b0b7deb4d7a75cadd5643daebc731f4a7bfaf17e8f002721b054a5d6d6ca7a3430c9480daff6adfd0a5480968b4fe0ee616d2e1f2f01268dcda2ee523fa593a0c83cbfc051dd7d503d48b152eb53894f79d4f6d38f05af35b287d16df579575b755f36e87b6df082108fda812195d5f60d2ceb59a54f09bb270d660c1d923348c7fdad97dc081e749a393af83bbcdd3c290efa19bce1a0f68dab0061df9dbee778dffb7754db10cbcc354a4b66c614e29d216a3a45a38594d337f775cb88c940924734ad52f8856606147b14ae2cf2990e1c401d79d27e4d6723afa4047454580698b9108b952b78b6bfd31db3b376f0879b2a0d8949b8443ffb9f7eb84b8024c620680481944312e86d183735effadab2d9f144a72d170fb035ed230f1451c94cb3f39bc28929e7480b22bbf6c906070eda03884cdd7ada9b10b7af27315c3bde8b4a273d46d1f764669aca152120da3e0a4fcf1be84b4f3cdfefe235a16598022cc74ad8f32e78aa06eb74ef61cccfc82ed35bcb70f008368ccdc17a6f64a316fcc9f006f307fa7a1a50f28c343c4c93a39df73a0d0a6dfc6f8ab10e966f738bee331e5a29d91ed993fd2638f0ec9d0ce539552b0a312fb85ed5e9f392fbc76a6164298b9de2c47dcb21a895957e92bc1270dfef3f00f44cc42c5f5005132dd030f9aec804045731c6a3eed3776beebe9451488932a1172b979f371aa370308037e57513a8fc9dd03d63fc2e5f7dcd683de26e116ea11a1d3b5e61fb5bbddc98e4ccd20be9ee71c02cacc95cbb17dd404558f586d4f0334bd12fc0a584d29eef3b4c2ce3f87babc462b6d24ca10aa8f1eb1abbd29d11ce3f1c92426c4950e53ba6c914cb4bf0bb1b44b25452cafbf246b76ce17f829bef3178174fbac4f932e6ac18e579fbbf8790611187c6f01de70fa82a21e979c90eed3c7f7b7e416491a000b5f2216e54858fa61893391b115573b2b960a0f7dc1e2a703a6f38485589c9133b4509fb54b4a602cc7d3341298e8e5da88d5e06aad28738650c08d8c71239735375e5bca7ea91dd78d748d65af598192317fd69e03daeecc99b8bc4000000010852e6d0c4f5f177b700404600eae9a1449fd711efdca846f59b6c9975a2189c1430f740e0e0eb4d50be086b798a47e037ee6afe9785b45df6302cfb87d39b9c03d0712f11793adab33e74904249722c4a1544898bcc839c7364f9518287bbf01c06e9fd67f74096cab78bc885ad264ca9151a48420ea11d5b9e3bc899cc0d663509c926bee5ef2a389a9945f5919677472b3245a2a68ab91654ba5f75026ae738a9e10b6b7439503961bedbfa2494099a9bba3b9595f70cacd8950abd5d3b8a85ac61e6482847e0ac71cbd63df462f4978afc7084ec5c9e65f3b57ad22f802d699c94f260212a61db6e6958ed60356bf991d3af9582cd1724a90f08e869ebd7f29fc3fb9e1198819a967096de1bdeea692fade6229b41c5efe6cdae313014db328e99bae1f323584a308f575b923a11185634b24c8cc1d608303c8ca5c1ae3d54b8b7ecb689d5e0e22323c5e47d8f9093080bcf1553f7fa238e156658ef50281f633f184e47992645c82ab9985b9b13f97f0bbd9db94285c131fff5870ea38691ade2e017ee6417a118a9b31f5b85ba2c76163f8668d90d448976d9d37238605d36b0b7e7abfb0e9c2866bb11b128bb70f003aeb77f439c6148d28719a4f336f4d622140faff82595233cff94906695e402b9115ba7b99f7d832f55d8de481af808ed9d48a493c3301d2b633cdcdc7a64acefaa9408b99a52768edeb9824cdb49257c6d3ea3f23763f70b74fc46252a97f7b3e173a93e81cca50fb12e8b0ea1083f9262e1607156296b5ff85e1531335441c90b442aa5dc616ed7b520bc040502280a0bdb011d6e9dac154587f033b3e9434cef567b724bf5203c315ef5e283028ec72ff33736499b8d326cd643e3a37d53e70b9a2384ac6037f488075eef8b2e507774d3d450ea4b1b65c1587eb2a60c6aad0ae20745a2c50f8acd8bc1e25740b4e7ab4b03a59731ccc487831b46ca0211264f4fd4a498e145aca0d7339663d29a7f32a14fc2b62a32f6354abf2d7de5ed9d7e0a1d6dbbfe14af25ca8c927dc8eeb2618f308eac81405552f1bafcaaede51f560fe5eb6aa78b8650ae97040b46469503c85994ebcf7ffa0222905657111325f861d380935c2a5b9ad26094e85b92327f79f66b4a2f8cd674344f931f0e056ba58a084a1026bc422b80ec11b17de1ca965e8ac9ede1464588303986ba8fabb395b55de5580131ae3bf61822e4e2817dacf765e034542e435c4e9ebc58f21cfa7901dfbcc2b2be98cc55fa6d9e0030e17a32abf84d551a74f7391dd204847c25ee6382f6374b8ecc5b29b598b9ba562e0a6f25ebb932570ae8ab7ef7d06e444fdf79845e88b3132ffb6e1f330e3424272da082486aba357bd254ef0738bb7f5c9db73d2a9ba0c9afeb34e09ff0e20bd44ba1a46ad3081db2f750d00b647756dec1bb41032e1aaf56f58d7046102aef6ae40517f9cbc148692401ad06ea4ff6ed3e5c8a0cff8f9466a3530a99cfb9b5a857a967675df0cfbe3b798fdc2d929fa4c86e3b3e3c45b75fa5db6c15953f25bcd025d7efc3172b2206a200128f6d8caca97154b2608511b35b0cba9a550d8f791552faed64036cfb8498dc60492207ab81c3f3edeafd9d3acf5bca2f2735117a273c70345d3b7e289b9948edda3d5ebb8adde7de2451fe2d942d92ab383dc9a9adb6fb9e8cbc0b73d852f176e0265a6107e6a59746e2f2e7203fd445e5fe278d02cd5dac1b7988e205c37bc5f35dc27572743810453b9b27e55c",
+			domain:        "",
+			wantErr:       true,
+			needsMoreData: true,
+		},
+		{
+			name:          "QUIC Chromebook Handshake[7]; packet 1-3",
+			hexData:       "c9000000010852e6d0c4f5f177b700404600eae9a1449fd711efdca846f59b6c9975a2189c1430f740e0e0eb4d50be086b798a47e037ee6afe9785b45df6302cfb87d39b9c03d0712f11793adab33e74904249722c4a1544896cd650da62160bdb601194f82a98c06df2546b79b5bab9503eafdbfbcfd1128204b52c9c5dde4d661cb84f2e015b7de9e10109874176362b7f06d4b49d850f2dcc8485aacb82fed8017fe454a1c31cfb82d392d6894081fa3ab1e5f2b71df79bf5a52a68a90d4752cf441220acbb274e3473f65c1a6e4cea3295da23e4a07818d5ba80b0668638c6ecb0b3ee12ecb8bed4ca32e27f4eee7376010b3905b8f7055728b8b1eda2e2707338b86f9a6115a23b29a010769d9a0e19d2bd06b81a507c4775d7215030862a026f168664255912c321669a5eff84ded4fec82af394cee909110758e5ad4de945236001bc0627d8e88ead3c3a6790d7e50887ced96f8380a80b11477147abc24dc4963c1907a07fec13e3cd8d5bab83cabd7cf8bb66af4911dfcdaf0f13aade34865b0740bebe4b4a482f1e3105bb9c3e5fece975187fa4eae5cb8fc868376b8b8329f89e407618aa5265f8ce73437e9f2714d752dad78025a38eaca1ebd6617a9a8a0bdefa8b3d3daad006978ba85d17ce3269da06be92eec61e4c5c99712517f01588b0b7deb4d7a75cadd5643daebc731f4a7bfaf17e8f002721b054a5d6d6ca7a3430c9480daff6adfd0a5480968b4fe0ee616d2e1f2f01268dcda2ee523fa593a0c83cbfc051dd7d503d48b152eb53894f79d4f6d38f05af35b287d16df579575b755f36e87b6df082108fda812195d5f60d2ceb59a54f09bb270d660c1d923348c7fdad97dc081e749a393af83bbcdd3c290efa19bce1a0f68dab0061df9dbee778dffb7754db10cbcc354a4b66c614e29d216a3a45a38594d337f775cb88c940924734ad52f8856606147b14ae2cf2990e1c401d79d27e4d6723afa4047454580698b9108b952b78b6bfd31db3b376f0879b2a0d8949b8443ffb9f7eb84b8024c620680481944312e86d183735effadab2d9f144a72d170fb035ed230f1451c94cb3f39bc28929e7480b22bbf6c906070eda03884cdd7ada9b10b7af27315c3bde8b4a273d46d1f764669aca152120da3e0a4fcf1be84b4f3cdfefe235a16598022cc74ad8f32e78aa06eb74ef61cccfc82ed35bcb70f008368ccdc17a6f64a316fcc9f006f307fa7a1a50f28c343c4c93a39df73a0d0a6dfc6f8ab10e966f738bee331e5a29d91ed993fd2638f0ec9d0ce539552b0a312fb85ed5e9f392fbc76a6164298b9de2c47dcb21a895957e92bc1270dfef3f00f44cc42c5f5005132dd030f9aec804045731c6a3eed3776beebe9451488932a1172b979f371aa370308037e57513a8fc9dd03d63fc2e5f7dcd683de26e116ea11a1d3b5e61fb5bbddc98e4ccd20be9ee71c02cacc95cbb17dd404558f586d4f0334bd12fc0a584d29eef3b4c2ce3f87babc462b6d24ca10aa8f1eb1abbd29d11ce3f1c92426c4950e53ba6c914cb4bf0bb1b44b25452cafbf246b76ce17f829bef3178174fbac4f932e6ac18e579fbbf8790611187c6f01de70fa82a21e979c90eed3c7f7b7e416491a000b5f2216e54858fa61893391b115573b2b960a0f7dc1e2a703a6f38485589c9133b4509fb54b4a602cc7d3341298e8e5da88d5e06aad28738650c08d8c71239735375e5bca7ea91dd78d748d65af598192317fd69e03daeecc99b8bc4000000010852e6d0c4f5f177b700404600eae9a1449fd711efdca846f59b6c9975a2189c1430f740e0e0eb4d50be086b798a47e037ee6afe9785b45df6302cfb87d39b9c03d0712f11793adab33e74904249722c4a1544898bcc839c7364f9518287bbf01c06e9fd67f74096cab78bc885ad264ca9151a48420ea11d5b9e3bc899cc0d663509c926bee5ef2a389a9945f5919677472b3245a2a68ab91654ba5f75026ae738a9e10b6b7439503961bedbfa2494099a9bba3b9595f70cacd8950abd5d3b8a85ac61e6482847e0ac71cbd63df462f4978afc7084ec5c9e65f3b57ad22f802d699c94f260212a61db6e6958ed60356bf991d3af9582cd1724a90f08e869ebd7f29fc3fb9e1198819a967096de1bdeea692fade6229b41c5efe6cdae313014db328e99bae1f323584a308f575b923a11185634b24c8cc1d608303c8ca5c1ae3d54b8b7ecb689d5e0e22323c5e47d8f9093080bcf1553f7fa238e156658ef50281f633f184e47992645c82ab9985b9b13f97f0bbd9db94285c131fff5870ea38691ade2e017ee6417a118a9b31f5b85ba2c76163f8668d90d448976d9d37238605d36b0b7e7abfb0e9c2866bb11b128bb70f003aeb77f439c6148d28719a4f336f4d622140faff82595233cff94906695e402b9115ba7b99f7d832f55d8de481af808ed9d48a493c3301d2b633cdcdc7a64acefaa9408b99a52768edeb9824cdb49257c6d3ea3f23763f70b74fc46252a97f7b3e173a93e81cca50fb12e8b0ea1083f9262e1607156296b5ff85e1531335441c90b442aa5dc616ed7b520bc040502280a0bdb011d6e9dac154587f033b3e9434cef567b724bf5203c315ef5e283028ec72ff33736499b8d326cd643e3a37d53e70b9a2384ac6037f488075eef8b2e507774d3d450ea4b1b65c1587eb2a60c6aad0ae20745a2c50f8acd8bc1e25740b4e7ab4b03a59731ccc487831b46ca0211264f4fd4a498e145aca0d7339663d29a7f32a14fc2b62a32f6354abf2d7de5ed9d7e0a1d6dbbfe14af25ca8c927dc8eeb2618f308eac81405552f1bafcaaede51f560fe5eb6aa78b8650ae97040b46469503c85994ebcf7ffa0222905657111325f861d380935c2a5b9ad26094e85b92327f79f66b4a2f8cd674344f931f0e056ba58a084a1026bc422b80ec11b17de1ca965e8ac9ede1464588303986ba8fabb395b55de5580131ae3bf61822e4e2817dacf765e034542e435c4e9ebc58f21cfa7901dfbcc2b2be98cc55fa6d9e0030e17a32abf84d551a74f7391dd204847c25ee6382f6374b8ecc5b29b598b9ba562e0a6f25ebb932570ae8ab7ef7d06e444fdf79845e88b3132ffb6e1f330e3424272da082486aba357bd254ef0738bb7f5c9db73d2a9ba0c9afeb34e09ff0e20bd44ba1a46ad3081db2f750d00b647756dec1bb41032e1aaf56f58d7046102aef6ae40517f9cbc148692401ad06ea4ff6ed3e5c8a0cff8f9466a3530a99cfb9b5a857a967675df0cfbe3b798fdc2d929fa4c86e3b3e3c45b75fa5db6c15953f25bcd025d7efc3172b2206a200128f6d8caca97154b2608511b35b0cba9a550d8f791552faed64036cfb8498dc60492207ab81c3f3edeafd9d3acf5bca2f2735117a273c70345d3b7e289b9948edda3d5ebb8adde7de2451fe2d942d92ab383dc9a9adb6fb9e8cbc0b73d852f176e0265a6107e6a59746e2f2e7203fd445e5fe278d02cd5dac1b7988e205c37bc5f35dc27572743810453b9b27e55cc5000000010852e6d0c4f5f177b700404600eae9a1449fd711efdca846f59b6c9975a2189c1430f740e0e0eb4d50be086b798a47e037ee6afe9785b45df6302cfb87d39b9c03d0712f11793adab33e74904249722c4a1544894fb2a6f735bea394066ea4ab5d3ef6f419c4bb099bcea8fd7e36d8ec14fae027d0c84ba8c38a5ea1e2e9ff24ec334dee8085d1fa9d88df2c5ce3dddd981f7b2a68011f2d4034f8e4c6f43e645fc71e19927aec56045f0ef72d9da1942dbe3e42248c2f695525c8d8fcf6dbc970c2eb5d607e07dce5c8c66d4de07de6b2c35bd3bfa12cd4e4fcd4cdda3e0b2ff7575d406db96502f1ec4d9b5748215fe2a4018c7dbdb5ead1ddfc06da5233ce359e4f3924f2af1b80c7af9d13437e0107f7e240e485458a3a656e31a543bc5a80f6a598dcbbd87ff9cb4ce6842abadb72d62ae03e6d12b7f43ac1805e408d738148fa3a5c34deae7378d7d7309a7e09f5bac848f4c031693fbe3382a2de66a9d007420512e24b8a78a9489b30794c7cc51dd751c1cdeb2870b7c4a9b9606547f843c1a16d9be986b2f3e3d2f73f89c8e15da9de3dfdf7a667ced977332c5c62fd83d3c9a5e9718643e716db8f1b6fb58904ca17c24c9a4a191ec42be4c405fb00e443429582ff712dfdbadf1bb7e2d2abb0cc14f39c13a3b7013c62fd99488f043a6aec3ed7998b943ee24905fc915e3144c54393fa67ff34fdce2e48bba044f13ee1cd9c4f59a1a41f7fb7bdd8daee73461234f7cce5d54b078c3ad2b0aa37850ed4bb24f4d310d4ce75ede546ed6e73c0ee495ff8ce4b7256e8f43949539bf9df6e8d0fbf066fb506020c5a72e5e8b686641b78b365474c65fe9d8dd41133e27326fe82744b45b6ad1170433f3746647a68b824e94a213cda4c02f78465acbccdccb5bad1c70806d5a5c98c94338f88bf980b05b72cb82a4fd5b2a8586a5e5c5f2760115df595091809cfd12829f09622b53ca1d3809060aa7ab5d1f3640b3c2792a55c58fc3e80ac5d7f39ab5774a80fa1fc70461d396fa70dad1f90598244ce4197cb3ea42dce4afd61ca8ef93c8bc254d347872db21edcc3857bcb8dbe627508aa4856bd7d46e512db071905b3db100f425ba9f7181f0cce005cee2a95ffc190ddc1939e7049e58791b0e186433b0409f5a49e4e3262690a5160f8267c9099afdc58182236833fe7f825dfca34b08801345c1592bbab4964b34d7efa6c9d92e0106ede9a10fbf2a1be32f61f914211c3caa8b4c14edec5f9c139ee14789fe7d6634ede9bf9789caa60f5bf30b092e65ff95d3b32cbdc3e5842e3b16b935d31a3a0963bb0fe60f41efb6590f24eaf5e84006b28b3c755203113237e43fa70a37a009f71da49ea3f8097914d6128ee2b18adac49b5111fd3d18db9fd61ef8a2202fac5cfce646ccbea7eaaa81df0f1b7243465de15a3900143f479852f0e40bfad434b96eea3941f527b0d31c3d8f43188b911140766b5d7146feb93bf4da1ec47023dcd8f89863e487ba25c3105a4e43c4ea90f479eb0f774f3aa044b817f7e69b5dd1b3954e7dcdb2a6c4d191d5b9178262449413310f3876dd93145716781cb077025deb37d23c35e6fdf867d5353d10303b9e60efa50e9ecd013cd3f5270fc0e117a19ffb63038c594190018bd9c1c18a799f548c08a3e6f768de0de344cff160689fed73aa7fc4edc26f77413145775745c25fc2c9da5b62e24eab9b21895cfcda6e6457ae9fdfa6c54b49b0d160dad0aa7f8cbd3820a3098",
+			domain:        "ogads-pa.clients6.google.com",
+			wantErr:       false,
+			needsMoreData: false,
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			pkt, err := hex.DecodeString(tt.hexData)
+			if err != nil {
+				t.Fatalf("failed to decode hex string: %v", err)
+			}
+			quicHdr, err := quic.SniffQUIC(pkt)
+			if (err != nil) != tt.wantErr {
+				t.Errorf("SniffQUIC() error = %v, wantErr %v", err, tt.wantErr)
+				return
+			}
+			if (errors.Is(err, protocol.ErrProtoNeedMoreData)) != tt.needsMoreData {
+				t.Errorf("SniffQUIC() error = %v, expectsNoClue %v", err, tt.needsMoreData)
+				return
+			}
+			if err == nil && quicHdr.Domain() != tt.domain {
+				t.Errorf("SniffQUIC() domain = %v, want %v", quicHdr.Domain(), tt.domain)
+			}
+		})
+	}
+}
+
+func TestSniffQUICIncompleteServerName(t *testing.T) {
+	// 2 packets
+	pkts, err := hex.DecodeString("ca0000000108d799f48baf472fc3004047005411dcdaa24bd4c3cdbef653940a1ea0a671bb8c23222a8502bfcbd0a335af016df330b1190e4b1efd420aa82c4414a7dfd7b1aa63aa7bd0269ec8ed0d24895a467b737fcc514488a8142241b81c4952fb32e9f123f3f8d1be9eecc1340d7fa747c6f4838810209d51ad453fcec084ffaa382f9fed010a0585f8ce73c36dc6c628df940f72fb5b8e3e06f4612128d3b8f87725770d81305489a3a23cd443fcc668fece0ec9a909c82cfdb66819ce031422c3edd49ea72b6216efb940b8c186e2510b0f93d4cf3b6434ed9f5817c5a5a19fa861d24883bd48ba296df81e887fcb9ef18013ab1070df268049f3d35e8ddfffd2b100e4eb687176a02e7975085caa138e9df7cb6f9862356faafba3300f586df09af3b4e3eec15b6d1f14b34fe4eeb8e762ff482f3b7b0595c16d3eb20cf9c892b3f7c6449e51ffa33f3dc877d32e572e10ba4d5a320117110b150bec4a9434103de963aa2de1b22eaa992b59a8583c7a2d4e5743ef98a1b1f5f4aaeb2b49dbe441c331e7cb028e70432ce0890f78d40671f13d5feccc4ab264ae903affaa951897128d598ed8e8542294aa03abb0a2a7ec970ab874387b8777827c4847bb29ff93d0427c1fcc581407465611e4400bfeab39de4c4f65572365156421503706d66138317e514214db27303ad8b5b17eb443e959faad1ccb3d3def5f3843b241dd9a60378cd907a02cc5c6e8527715c7734079cf9143586ed471587690816133fa8f09b8421f2de6ff1f5cecc134ac404e53a367b57fd4f3c85fe7e121e7094fbf93c06d427cec30cd519ee43a6018a8bb8717c05d7660b379101a182bfd3018d485d5b46e81d39445ccd4d8baefdd7590e664f2289f11bbad3d35ea6d70e157aaa7f9e91a692794b85c5b86db33863151468d32792ecfdb2aec52784ded5aa431fa9a7337ddd9e95313a897fe5ca6ef3c7e0cf3d41f7f104506f8695f2ba307715022e5e98472d6ff24125004d14db2c7a4cc71ca39a9874bfb93b64dd54ef451097059bbdfa96aca6c6c01e1f000b8d35bdead1502874e5d80ac00a79593b6d7e2fbee406c2212b4abd7b7e9f0037518de232cd6559443f4e3f0f03c17cef616a74992f65754bb6699b08c0eb2ec59508086e496e070c6239a73f11a9d14a727b10188ca97ebf04851fa475ed1774836a94cfb6543c33888dfc250100e9992b0cca8bd27ae8552541f1b3d81546f15b740e4f07b41af864769fe17290eb7076c0c1f938ce56a45ead6deb6c89164f829543414a1b8cd2361c3d9b22cf85d4ad0d4221dcc87533506e32c1cfdc8240636b669f97f7c6e150ea3753fcb63a7b9eedb5615b257651e090b567a20fdc5c167ad58fa940985572db004db2b14709a6663c1fb79dc045e45cb7228f11eab4c60a48fffc702cd74dcf5aabded8355a5ae1a5e6325a3afff608e53af3aa944437139c438e6200c75bb27c8a8ce7ce9f9ec9723c4423e9e49c807b12484783ed79fc501b544f03e4b29bdf0c74eb055dbac9b78fe87a66efc819f9d2ea637dd478b920b7196232b970ed092050ba0621329aa2b3e26184176137a9c6283e4cc2c03c07e28d2da7b0485da51f131686f4dd6b23735c66316142f48781885c35c9940054a4b9187a20914bedd1c48e94af358994da5c6060dd224b0ba84ddd5e95f395fe941d464e2cccd857a180de756d32407540c3611b649c7a71cbf5a492bf5c8d4e112a743498ce83ea3e94bcaa6c00000000108d799f48baf472fc3004047005411dcdaa24bd4c3cdbef653940a1ea0a671bb8c23222a8502bfcbd0a335af016df330b1190e4b1efd420aa82c4414a7dfd7b1aa63aa7bd0269ec8ed0d24895a467b737fcc514488e7151df796764293639665547941eaaa7d83dfc9d42952583a821611921cba9e0276f9244f197e011b6c2d898255802c81c8792dd68d03cd8982ee6146c8734814e9640e0999312f97e898db60642ceca21700be9e698b5e577062148d1ac840e737f7bc4f18f9ffd13e656fca1517c96d0e0c607b67d7e75795f62131255b44c2178d896192348d5f053060fa21c855236401e853e435fbc71a428c8e126cd8393cb860193fd6304d9576e8a8ce7f6959739afa7d7ffaf86516afb061ade1eef603e8e5c66f002cacbef25546e84b59be707c547837f7b49471a59325ad58a4f189a525a3a354a4be5ffd3db34ce0585ec470f78f0ff6eb807989d5998e2fccc80bd651de654da3581b6c8a858b56c4df47c3041c50d74f0b3a3a5a325882cd356d0c46d6db74559cef934a1655c65a06daff218244f5f4e95b96794e45d371a03afee2c89768fe3d7bc134844f45440620a88d6ddb5d07b7f6c9b2adfbf5743c5c586520504febf14ee4b216f8186ee1bf9802ccebd4dac519bd337a554940a3873cd21ef32f3d4d4fdfd3eaabb172b5314490b3587a9ca2dc12637fa80dcd526859bb83d54f67dedeb173470e052beec9edba4b41444d31253accb3381237179a5381d437fc4d47c0a82f1c9da8c76ad3eee9417bf69acb8d530ac824e65d796b84bee40b14daa9e80c11e466f93233e1768ecc6c0237e71b901f1faa093bbd9e5324b2a160d02f09d4590392279a15c73edc4d1d7501ebad992fc8f1c9dce96c190879225dbbb09d20532f9dcbb845e3484c87cb8c3b06fe892b07bdc60926e3d4b5c9024acde5abed0a72686d546da535a2122cfd6d6488a491dc9612b90f3f6709835e83f59fd612c2259c3ac944fdae87ffd744176a92fbea1efd037565a39d5bc38991cfe6617135b43cd6c6484a3b228e10d3f8184227a7ee63121be20f099c4264461d52aecf4b8ee1a4d0ec41717f9a68e1394544cf3be0a3a171ece35c879b67afdaac49c12731e6dc5ccaa49fa72610901036a7f0752951077cd9f1d77eb6e4f12c16dab08e1a9655fda3ba0e80c34c767f40e61491f706ab9d1b50f48273ca4e37708d075909a3e2c4b173510114d8377b5300994f9a4f794db2781b98c2e9d0056fdbe87b249beb3e7301c86efe6b32242b4c7fabef280a1ca7bdd6abb38624cbebb01b6b75b07d0cd9090b2c296d0e330b9008788dd6f7e1af1dd63b02408f1a67b57be3316152270bf90c36e9f74322c9caba5adab3309e5bd7c44d3c2ac77329e167dafda7395e37313723fb550a6ab96729a9fa8f9e4a3e5957bffa3302617d48fd38196635309928c491ca974a112768de16043fc618001780b49a0bac2ea9fc2607ebd1f25b8ef65a6cab42d16c9184e23af496ac5cfab274d9557006d9c52bb56cd8c019ddf085f260a0582ef465c73f97fedc02271dda53eec20e6aa50503357ed1847f7d976899cb24e5dd42dd87ae48db3c9335b38957fc0f86a6ceee590b1cbee41fc6ace3189886bd86f9b082e66fb263f1a98dd8e564bff9ec412ae79e29fd519ac96e9c5b446b436b78a6ca555c496ca5c5e73c2c1c5837b13f7a953d57738440d4ed60efd4701bbbbcad79e1697b5724695f52dab8bce02e7f")
+	common.Must(err)
+	// The first packet ServerName is incomplete
+	pkt1 := make([]byte, 1250)
+	copy(pkt1, pkts)
+	quicHdr, err := quic.SniffQUIC(pkt1)
+	if !errors.Is(err, protocol.ErrProtoNeedMoreData) {
+		t.Error("failed")
+	} else {
+		quicHdr, err = quic.SniffQUIC(pkts)
+	}
+	if err != nil || quicHdr.Domain() != "play.google.com" {
+		t.Error("failed")
+	}
+}
+
+func TestSniffQUICPacketNumberLength4(t *testing.T) {
+	// packetNumberLength = 4
+	pkt, err := hex.DecodeString("c60000000108fa6cc47e912693590000449e5ea65fc129945b27f59f0b18f737a53e44f322681ecec36beeb943293db0ed751bd86413a840f9b9e9be718f3e2dba1100a8bab3a21e1541580ffd98e79aa89fa723e8d3a46f7876504c82b9ef3a081b0f8cb551370d9801ee86da77f09eec5aa19b7bf580a80ded3c9c83378285177115fd30b350c2a596ae265b3b538a81c183c0cfd13eabecfbbeb38416a5b19259731b838842c0eb33e646b9bb1f672043e90de33c3442151ee8db7d9cd66238f769f4486432ac28785a5083c616539f8320321060f64f9a0dc6af718754d645892397ff32956c4c1c97d0d9e44cdfa8d1a0ad90c3bbb7810b2196d638fd772a172a9510ea12ef12fe4050c5678851be26ec6ea6ab11824cc86ce071d110f72816166c01622c0207e9d97f8867ec7c63149e974c5a81db9cb5e0061cff2713538daa1c9ad1382ab7d883ecc85158dc76587793b258b4b0aded3f4c12b515a9183ee419b304cf748fc321f15b3f80cc53da1b889d1ac06b996d35e8d01306885851ad253083f37d0d588c9f619da25f6eb8360b846bc26913af616e2c3eabce9dbb61f7dc96b6dcb79e19905ac9ba8f3938d03f8a3647403dc919f37bb585a0d67b7ce955547d15c82eed6d94b04dfa009eaf8b30448e1450043c48845acb4fefcf29bdd55ec14e395d0e8cd8400ffdda5a58747c6e8a66d0dc5fb25f3615081b2b546e004079573e99290f5daf72705ca495707468dd26d94c7f04d7e6f89d8148ecbab67c8c0062984e0ba02539527370a2a157a58eab342ad671641812ed35b4a52ba07d244d9b5d64e29f012133d21fa4afa31645c21f6d836ad937bb75f7177768b5f94bb77e95aaf9a85f8fb7e599d482724f694cf5d7d3f61bfca892794bdcb3de7a5f321db8120560bc32b8839c0a5994917c151cc6bd4c1614c5f117e637c19dab7cff28c4848c3b328eb97e49cefded2d44a824f2705807770c2ef9dd07f0fe0198659ad062e1889e280e5f3d1c52a92ef27d4565ebae9b9a18a803b70f38e5db237ed99583d8952c79492e35e1f1c41664f1f45566126a7ec44a90004b015b893aa805fcd772737fb8dbbe7af56b9eac288ef6cab7cbb6f7a3c0b29a43bc84b6280def0f7d727b3238cba3eda2e2d110de87ad0f10e25a60783cdb0c05116df5359b19b40007812b898d03dc1d697690761856d785b83ac95778db69c3df7a8f0e092ee6ed2c9c189ebe40734b02cee2d02599e931d4cc560d38a7ec355b9f339b932613ee18f8162e8d3cb81301bfc6d726b7c26ec96d5edcaf0de171563482ed2f2de3001dbca2aee1029fdaece4340fd2d5ae8333819d5ece7c9d3f77f99a81fccd1fbcc3ea585c1538e0363141e0fd20338a193695377987afacd0baf1f0dce11b4bbf29965109bddb508e8a0974c08906d4ea340d51af376c3dda55bf97e3ba5d688533980e12704679bb18d0ef4ddd5b3af1b7676528c4bf4a84c84d40892715c0a8808ad51d6ebcc6469da708d6953e9ddcfbd19bae90e9b078f1b6641401b979304b0ef52b1441e1797ed366bb0519ca8bf9c6eba72518647d0a1400ca66a20fdd8e3ff06ee52c199bd8f941b1722a0bbf8c15447452788ba81a68431f735d99e8a80691ef64d1bf470350c8878aed3e2421223d0ba6a3d84928c8e6db0972263df9da49b8f5")
+	common.Must(err)
+	quicHdr, err := quic.SniffQUIC(pkt)
+	if err != nil || quicHdr.Domain() != "www.google.com" {
+		t.Error("failed")
+	}
+}
diff --git a/common/protocol/tls/sniff.go b/common/protocol/tls/sniff.go
index e7661fa7e0f5..11660b92b30c 100644
--- a/common/protocol/tls/sniff.go
+++ b/common/protocol/tls/sniff.go
@@ -3,9 +3,9 @@ package tls
 import (
 	"encoding/binary"
 	"errors"
-	"strings"
 
 	"github.com/xtls/xray-core/common"
+	"github.com/xtls/xray-core/common/protocol"
 )
 
 type SniffHeader struct {
@@ -59,9 +59,6 @@ func ReadClientHello(data []byte, h *SniffHeader) error {
 	}
 	data = data[1+compressionMethodsLen:]
 
-	if len(data) == 0 {
-		return errNotClientHello
-	}
 	if len(data) < 2 {
 		return errNotClientHello
 	}
@@ -104,13 +101,21 @@ func ReadClientHello(data []byte, h *SniffHeader) error {
 					return errNotClientHello
 				}
 				if nameType == 0 {
-					serverName := string(d[:nameLen])
+					// QUIC separated across packets
+					// May cause the serverName to be incomplete
+					b := byte(0)
+					for _, b = range d[:nameLen] {
+						if b <= ' ' {
+							return protocol.ErrProtoNeedMoreData
+						}
+					}
 					// An SNI value may not include a
 					// trailing dot. See
 					// https://tools.ietf.org/html/rfc6066#section-3.
-					if strings.HasSuffix(serverName, ".") {
+					if b == '.' {
 						return errNotClientHello
 					}
+					serverName := string(d[:nameLen])
 					h.domain = serverName
 					return nil
 				}


Reviews:
user: login: j2rong4cn
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-23T13:13:35Z
user: login: onediram
state: DISMISSED
author_association: NONE
submitted_at: 2025-04-23T13:47:39Z
user: login: j2rong4cn
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-28T10:16:41Z
user: login: j2rong4cn
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-28T10:49:22Z
user: login: j2rong4cn
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-28T10:50:51Z
user: login: RPRX
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-28T11:23:12Z

Review comments:
diff_hunk: @@ -33,8 +33,11 @@ type cachedReader struct {
 	cache  buf.MultiBuffer
 }
path: app/dispatcher/default.go
user: login: onediram
body: Jdhddhsh7737ebd82ie 
Wie the
4
5. Tudn3ndhhsj
37e7373
created_at: 2025-04-22T12:10:28Z
author_association: NONE
diff_hunk: @@ -16,3 +18,258 @@ func TestSniffQUIC(t *testing.T) {
 		t.Error("failed")
 	}
 }
+
+func TestSniffQUICComplex(t *testing.T) {
+	tests := []struct {
+		name          string
+		hexData       string
+		domain        string
+		wantErr       bool
+		needsMoreData bool
+	}{
+		{
+			name:          "EmptyPacket",
+			hexData:       "0000000000000000000000000000000000000000000000000000000000000000",
+			domain:        "",
+			wantErr:       true,
+			needsMoreData: false,
+		},
+		{
+			name:          "NTP Packet Client",
+			hexData:       "23000000000000000000000000000000000000000000000000000000000000000000000000000000acb84a797d4044c9",
+			domain:        "",
+			wantErr:       true,
+			needsMoreData: false,
+		},
+		{
+			name:          "NTP Packet Server",
+			hexData:       "240106ec000000000000000e47505373ea4dcaef2f4b4c31acb84a797d4044c9eb58b8693dd70c27eb58b8693dd7dde2",
+			domain:        "",
+			wantErr:       true,
+			needsMoreData: false,
+		},
+		{
+			name:          "DNS Packet Client",
+			hexData:       "4500004a8e2d40003f1146392a2a2d03080808081eea00350036a8175ad4010000010000000000000675706461746504636f64650c76697375616c73747564696f03636f6d0000010001",
+			domain:        "",
+			wantErr:       true,
+			needsMoreData: false,
+		},
+		{
+			name:          "DNS Packet Client",
+			hexData:       "4500004a667a40003f116dec2a2a2d030808080866980035003605d9b524010000010000000000000675706461746504636f64650c76697375616c73747564696f03636f6d0000410001",
+			domain:        "",
+			wantErr:       true,
+			needsMoreData: false,
+		},
+		{
+			name:          "DNS Packet Server",
+			hexData:       "b524818000010006000100000675706461746504636f64650c76697375616c73747564696f03636f6d0000410001c00c00050001000000ec00301e7673636f64652d7570646174652d67366763623667676474686b63746439037a303107617a7572656664036e657400c03a000500010000000b002311737461722d617a75726566642d70726f640e747261666669636d616e61676572c065c076000500010000003c002c0473686564086475616c2d6c6f770b732d706172742d3030313706742d3030303908742d6d7365646765c065c0a5000500010000006c001411617a75726566642d742d66622d70726f64c088c0dd000500010000003c0026046475616c0b732d706172742d3030313706742d303030390b66622d742d6d7365646765c065c0fd00050001000000300002c102c1150006000100000030002d036e7331c115066d736e687374096d6963726f736f6674c0257848b78d00000708000003840024ea000000003c",
+			domain:        "",
+			wantErr:       true,
+			needsMoreData: false,
+		},
+		{
+			name:          "DNS Packet Server",
+			hexData:       "5ad4818000010007000000000675706461746504636f64650c76697375616c73747564696f03636f6d0000010001c00c000500010000008400301e7673636f64652d7570646174652d67366763623667676474686b63746439037a303107617a7572656664036e657400c03a000500010000001e002311737461722d617a75726566642d70726f640e747261666669636d616e61676572c065c076000500010000003c002c0473686564086475616c2d6c6f770b732d706172742d3030313706742d3030303908742d6d7365646765c065c0a50005000100000010001411617a75726566642d742d66622d70726f64c088c0dd000500010000003c0026046475616c0b732d706172742d3030313706742d303030390b66622d742d6d7365646765c065c0fd00050001000000100002c102c102000100010000001000040d6bfd2d",
+			domain:        "",
+			wantErr:       true,
+			needsMoreData: false,
+		},
+		{
+			name:          "QUIC, NonHandshake Packet",
+			hexData:       "548439ba3a0cffd27dabe08ebf9e603dd4801781e133b1a0276d29a047c3b8856adcced0067c4b11a08985bf93c05863305bd4b43ee9168cd5fdae0c392ff74ae06ce13e8d97dabec81ee927a844fa840f781edf9deb22f3162bf77009b3f5800c5e45539ac104368e7df8ba",
+			domain:        "",
+			wantErr:       true,
+			needsMoreData: false,
+		},
+		{
+			name:          "QUIC, NonHandshake Packet",
+			hexData:       "53f4144825dab3ba251b83d0089e910210bec1a6507cca92ad9ff539cc21f6c75e3551ca44003d9a",
+			domain:        "",
+			wantErr:       true,
+			needsMoreData: false,
+		},
+		{
+			name:          "QUIC, NonHandshake Packet",
+			hexData:       "528dc5524c03e7517949422cc3f6ffbfff74b2ec30a87654a71a",
+			domain:        "",
+			wantErr:       true,
+			needsMoreData: false,
+		},
+		{
+			name:          "QUIC Chromebook Handshake[1]; packet 1",
+			hexData:       "cb00000001088ca3be26059ca269000044d088950f316207d551c91c88d791557c440a19184322536d2c900034358c1b3964f2d2935337b8d044d35bf62b4eea9ceaac64121aa634c7cd28630722d169fa0f215b940d47d7996ca56f0d463dbf97a4a1b5818c5297a26fe58f5553dfb513ad589750a61682f229996555c7121c8bf48b06b68ab06427b01af485d832f9894099a20d3baadcff7b1cf07e2c059d3e7ba88d4ad35ef0ffea1fdc6ac3db271dfcca892a41ab25284936225c9bc593ce242b11b8abed4a8df902987eef0c6d90669e3606f47dd6ad05f44ba3a0cd356854261bbb1e2d8f6b83cc57cfa57eda3e5d7181b6ec418f6eeca81c259a33e4b0a913de720f2f8782764766ac9602a7f52a1082ec3da30dbefcf38c781a3e033810c4f2babf9b72adf7164159d98142181492e4468c0e10ab29013bf238e7360e09767ca49d59a9eb18f06a372bad711fefa90295f8e0839b1080570648212b321e5bd6f614bf0d3dc2817628b0c052a32820c16cb7f531c49244c48eb1429625246f9c164ae4ee1e83eaa8ff0eef1acf5a3d8ca88f1e4597db5ba5c0cb23d6100dd53da4f439ae64c4d3d43d1fbb5677f4fdc3bd2c2948dfc7e0be1a33c842033da15529cfd3cae00da68343d835db867f746854804410ba68f0dd7711b0fe55817b83f6ce1a12ad38acf2a3156f819f0dc68ea799c05583d9728f2856577811b260dba40d6c5e82c9e558c5b8f3f4599caf05ea591118e0b80ad621e0a76e4926047593a896752cb168420cb1b02d4211de5e5b7c891f319b5c0cf687e1d261a01f2acbade6bd73cd1ade0a02e240e9351384e1a6868c21a4878f39f0fa94ee1e36c5a46449241a3fe0147ff50176787eca7f3a936c901aeef56770bff74feecb985e6670d20dfd8ed17952dca5a5292213345c61db09bb5bcf5bf74565f61f9dccab51a289c3160ffe4a9b29cc76ea46778d9317a890efea2ad905f4219463a3baca3c02f5c3682634be7c2e86e366272a8263fec8e871644a79299d4aa74f1b1414b2f963cce6e059978faf813625af7869c1dec92035478c0e46dc66d938d4131aca27a59b2103b8cefa8e08aeb44b53b205b932902aea8d519faaaa12e354a6f532b4f716d7929e655dc2e98b494a99153854af5732a2659f2c21e4069896a1835ad05c5e53781cab16599cf4af47c196deeff9115c80d13f93aeb28b08023e6a1d3cf7da2a4457a9e443176bcdfef8f8de630c02bd0efdc5ddda56ad8f6b47edbda6353205e6e655f690092a48deb7f8a5254a7d778e07216cd97dfefcf740c1acd2977ef0fa17f798ea9752bae46e3aa3ec9b13f4c95c20a7839b8409000fa1f17e8dc46cc05c41bff696ee03c0371cae8638e8018ff4ebedd9f27d56443e534a72dd3d18a64790b676ddd060376759fa4a12ffc17f4be83492126ec1dc0fcd4aefef73a0b9c443ec3532b9a66b1a60daacf45e6557115edc0cc4d08758754a44beffedaa0d1265e50beed1a01752904ee3f7e706ed290b1a79071b142105b7c02e692ff318710e3ce9c3b9ec557cdecef173796417341ada414faa06b52adf645db454b56468ccf0da50a942ebc09487797cb45a085ec1e2e06fcd1f5b72eac291955a62e5aa379a374aea3a0dec3e4e0ba1dde350a94c72dbea7505922e26e99d62f751c2b301413a73fb6b20a36052151473ebecd04d0a771ec326957bc28c2020fdf6f01d9abed69b3c3e73168b404a1748b15310b167396da01c7d",
+			domain:        "",
+			wantErr:       true,
+			needsMoreData: true,
+		},
+		{
+			name:          "QUIC Chromebook Handshake[1]; packet 1 - 2",
+			hexData:       "cb00000001088ca3be26059ca269000044d088950f316207d551c91c88d791557c440a19184322536d2c900034358c1b3964f2d2935337b8d044d35bf62b4eea9ceaac64121aa634c7cd28630722d169fa0f215b940d47d7996ca56f0d463dbf97a4a1b5818c5297a26fe58f5553dfb513ad589750a61682f229996555c7121c8bf48b06b68ab06427b01af485d832f9894099a20d3baadcff7b1cf07e2c059d3e7ba88d4ad35ef0ffea1fdc6ac3db271dfcca892a41ab25284936225c9bc593ce242b11b8abed4a8df902987eef0c6d90669e3606f47dd6ad05f44ba3a0cd356854261bbb1e2d8f6b83cc57cfa57eda3e5d7181b6ec418f6eeca81c259a33e4b0a913de720f2f8782764766ac9602a7f52a1082ec3da30dbefcf38c781a3e033810c4f2babf9b72adf7164159d98142181492e4468c0e10ab29013bf238e7360e09767ca49d59a9eb18f06a372bad711fefa90295f8e0839b1080570648212b321e5bd6f614bf0d3dc2817628b0c052a32820c16cb7f531c49244c48eb1429625246f9c164ae4ee1e83eaa8ff0eef1acf5a3d8ca88f1e4597db5ba5c0cb23d6100dd53da4f439ae64c4d3d43d1fbb5677f4fdc3bd2c2948dfc7e0be1a33c842033da15529cfd3cae00da68343d835db867f746854804410ba68f0dd7711b0fe55817b83f6ce1a12ad38acf2a3156f819f0dc68ea799c05583d9728f2856577811b260dba40d6c5e82c9e558c5b8f3f4599caf05ea591118e0b80ad621e0a76e4926047593a896752cb168420cb1b02d4211de5e5b7c891f319b5c0cf687e1d261a01f2acbade6bd73cd1ade0a02e240e9351384e1a6868c21a4878f39f0fa94ee1e36c5a46449241a3fe0147ff50176787eca7f3a936c901aeef56770bff74feecb985e6670d20dfd8ed17952dca5a5292213345c61db09bb5bcf5bf74565f61f9dccab51a289c3160ffe4a9b29cc76ea46778d9317a890efea2ad905f4219463a3baca3c02f5c3682634be7c2e86e366272a8263fec8e871644a79299d4aa74f1b1414b2f963cce6e059978faf813625af7869c1dec92035478c0e46dc66d938d4131aca27a59b2103b8cefa8e08aeb44b53b205b932902aea8d519faaaa12e354a6f532b4f716d7929e655dc2e98b494a99153854af5732a2659f2c21e4069896a1835ad05c5e53781cab16599cf4af47c196deeff9115c80d13f93aeb28b08023e6a1d3cf7da2a4457a9e443176bcdfef8f8de630c02bd0efdc5ddda56ad8f6b47edbda6353205e6e655f690092a48deb7f8a5254a7d778e07216cd97dfefcf740c1acd2977ef0fa17f798ea9752bae46e3aa3ec9b13f4c95c20a7839b8409000fa1f17e8dc46cc05c41bff696ee03c0371cae8638e8018ff4ebedd9f27d56443e534a72dd3d18a64790b676ddd060376759fa4a12ffc17f4be83492126ec1dc0fcd4aefef73a0b9c443ec3532b9a66b1a60daacf45e6557115edc0cc4d08758754a44beffedaa0d1265e50beed1a01752904ee3f7e706ed290b1a79071b142105b7c02e692ff318710e3ce9c3b9ec557cdecef173796417341ada414faa06b52adf645db454b56468ccf0da50a942ebc09487797cb45a085ec1e2e06fcd1f5b72eac291955a62e5aa379a374aea3a0dec3e4e0ba1dde350a94c72dbea7505922e26e99d62f751c2b301413a73fb6b20a36052151473ebecd04d0a771ec326957bc28c2020fdf6f01d9abed69b3c3e73168b404a1748b15310b167396da01c7dc700000001088ca3be26059ca269000044d00a7e7a252620d0fdfb63c0c193d6a9fe6a36aa9ce1b29dfa5f11f2567850b88384a2cc682eca2e292749365b833e5f7540019cd4f3143ed078aec07990b0d6ece18310403e73e1fe2975a8f9cb05796fa6196faaba3ee12a22b63a28a624cf4f7bedd44de000dc5ea698c65664df995b7d5fade0aab1cf0ecc5afd5ecb8fb80deecae3a8c97c20171f00ac3b5dc9a9027ca9c25571c72bb32070f6e3fb583560b0da6041b72e0a9601b8ad17d3c45e9dcc059f9f4758e8c35a839a9f6f4c501cb64e32e886fc733bc51069fbe4406f04d908285974c387d5b3e5f0f674941d05993bf8bda0d5ffd8c4fb528e150ff4bf37e38bd9c6346816fe360d4a206da81e815c1f7905184b6146b33427c6e38f1179981c18b82a3544442dd997c182d956037ae8f106eaf67ba133e7f15f1550b257d431f01ba0472659c6a5c2e6ff5e4ce9e692f4ef9fb169a75df4eb13f0b20e1994f3f8687bdca300c7e749af7b7a3b6597a6b950fe378a68c77766fdabe95248ed41d37805756b7ffa9cee0898bd661f6657cbf1af9aa8c7e437d432ca854c95307e6a7dfb6504ee3f7852fb3c246d168a03810b6c3d4e3d40bdee3def579effb66563f5bac98cfa1b071cd6f33e425e016bb3514a183b72cb3a393e9e519ba60e2177c98f530835e3b6eab78cdcb8abdbc769bc07e10c8e38bea710d5de1bdb2fa8d0d9b19e8cc31d16725a696e55342c89b667497e3d7f90e48f8503d8ead2a32a1930c3b24a4a9dcf2d8ec781705dd97d7df6e26828712fe42114419d5b8346bd86c239bd02f34e55f71400cb10c1fac7d8efa1a2ab258c17ace4288c8576ab92447b648fd15f4e038ec1c81a135e3bbb6f581a994c6a4902aeb1b5588cb1b5b53c8540296d96b6d2eccd67bae9609233f36304b5186d4698b88bb3ce8b1191a62b990436cf10718fd5759cb2281ac122f49ccbef8a3206348c1a930e7fc4bb498a11d89374e1480c7b8725b5f65e8c8d6f58da17f9134abce77eb9a6fcda514e7d3ab2e3610f86945f0dca519a3844da1b3a4b0e03c80528a2f79be478d07ff26166e30294bf0e69bf07a5bbd6d879adf6d618a1ec8365023408980bf67f0525a2fdee97fccc38fe104d4f58ed15e3671dfedf684856a27fbe286adba40ff0336def93f0174e9e35d341f5de73190d330d72227db9a866b69418e17e8e19ec884c1ffe2f0ad6deec37c9d49d536d0242fab282b0cf86cc9b15341757e0d361bddcbe5cbb062b3148d7c3c62af5c5dd5922a49920f351647030f62ed16929a404aa514fcbc38e67ba4f275e02a04c486b1a8e5b5efda197fd63e6f41fdeffa652c690dd6b00ca65df3688672ead9744f7d631e42e3b42f3ed1bff51b30f89211a7467cde65eab3659af7690cf307420a5823f31999d8f63c6c6ba0296ed4a46d5df6404f8db33e7252cc6bfcf7f55fee1f1e3b0573b6c6615793ff0691b7cfd23c195f66eb333d7efb0cfb74cf159787f87ad01fc131c6763bb1117bbfb8c2e8197ffba6b8c747565b1332bdbd6553b840939c2f98aa8eb1c549491c640e012fc549852fa7a93f81e5db152c761fc7d01bce0325619965c09f6730a162e7be53af7d9ce4b5ac0f4eb487361d2ac231d4ce92e5d9a084bc7b609ccf60056ecc82cd0c06a088cfbcf7d764b3109331c42f989da82b05cfe4c134a6784e664fa67a89c0624e3cc73ccfdea3f292db28f7c7b1b109f680f6b537f135c62f764",
+			domain:        "dns.google",
+			wantErr:       false,
+			needsMoreData: false,
+		},
+		{
+			name:          "QUIC Chromebook Handshake[2]; packet 1",
+			hexData:       "cf0000000108452af27900a1723300404600ca8530029a6bc59ff3e85beb5fc838ac3147ba5c2f6421ddcffdd85167d8de70eff2b1fa016dad4918337dec0feb660edb98e078dea51fa914055984b7957bd732fa4c831e448967af34752fd95835e3caba1e022d6d164f3f53f1bd7f60d560a8684079e90626aa1a4d3fe728158f7e1055ff76d1566072113982b193fb932265381e4de7afb35caa4ec56f31595a33fa2eb0bc84feb9f273224050938825fd21aa7317042ad00785ffd36151aee566a5dfe17d72591af1235059171568e5af0d13fc56e7897c3d632be753d8dea184c3d96d92bc56978cc669d94dd4c5e8dc3dcba7f0a39368fb1e87981e54bba7b86fbd8e8023a94d84f0290f402a5244cb4b0eeaaa57610ea59711a43932c521f10edb4560375693cbea60240389b8cebfd94035cabe4fc96ce8a726b979775e06c3bb0e3c4c866fe82e89fb725499e711e39310b93c785b313459f22d4ba37f90b19447165c2584269d98bf47d1f7ca89585797e4d6f1a4a1db7d2b0ae91a93fb15c3bb0ab953c3656b3b2ca20833d15e95329baff6d2ade1b0921b5ed3ae96648bf123b5265e27b049e9a8674455ff5f763f039568026e4fbe9882fef761c573d8f12e342c274a8dd3ad9854a688ce57cdddb52c758161ae3a59f67fc0d5b85f12e27617e7f4366e97a61fcda084e620dde35686f01dac49ce4bd76b986e3223c215919a1b228beeb74b7fcf32827d55be8f1b3b5fed24df2db023faecbb313b18a151cc4af8199d4bb08f8127b8207a0286d52758eaca87fd476ece0e3b17bcd8afb0289e8fd33c4455d4db6f058826c301ea303bfe2c0a6651a8fb6a2e1897852d758076adb04ad907077c5d5f94089da78d8923a34f1022ed672f378fe0dd81a709b372c0a2042a42e683c051c653e42b43c4a0ea8e961074d2901d4157ac9878b13a207b05ec471cff10d922b74d05623513cd6a4ea192ad21d4089de269633d4d2d1388d98d7c8a9e29848d5558b8aa2b73b437446a640230e6adb7f4b317ee5d66681c4aae11f69b1e5f96cb32ca6331405426cb706167d86f6f8fd588a72d7b2a6906798b81f174d808e1e3fc461e598e797c41bced26b87d09282d7b6d95076c285462e0c420a6f0e171ffe2791b5d221c03520409fe36622ff77796d9b7ef82babb25313acda9c621b22bf45ed909f9365b508860645af4c3aca78e6abca2d3a65c9159fbcd577438505d3f65a57c9412c12c069ad4d6db450beb08603abef621a9e029593fb5881dbd524ea2953b4acaaf59269b584c754e88c033247bb7c032e548d34fd9b2678e62fdf953dabf2be21c3e2d7b18ec7e3aedaf2cd082e19a369c1bcd4ca67e3d464e2200ecc3df98b0aa7f349415d68bcab0441ac3366607eff024bb786aec031a4619f8a24f554fe93c8520a03affcf11e40b6d5002f98c1708cac6c56e77eccba85ea6600d1391cfd202cc7914bfbaa3303266d1a820bf2dc84d2dfcdc4cdb79e6de3fbe3c02b288dcf955652f674f3f59b50849ea7dbf755bdafa27fba3db1267fb1354d8bf25a60cacb900b4d7ba913f9ba5f6b00559ad58b2f34a658ff7ef7f7d1ceeffd9c8325f271e6b5ba44d89685b744306963aa5e05ac0e8b00ada772dd5ae5ffb7043109afea86593743564c7acb4c8e7ef0e57d081eb1b9c0916078b113ece8a6036264a9b9781183c035342d50c7b069f3a01a40230e37ed8efde073c07d0e68066541d78c2f3cbe1e603cfcaaa",
+			domain:        "",
+			wantErr:       true,
+			needsMoreData: true,
+		},
+		{
+			name:          "QUIC Chromebook Handshake[2]; packet 1-2",
+			hexData:       "cf0000000108452af27900a1723300404600ca8530029a6bc59ff3e85beb5fc838ac3147ba5c2f6421ddcffdd85167d8de70eff2b1fa016dad4918337dec0feb660edb98e078dea51fa914055984b7957bd732fa4c831e448967af34752fd95835e3caba1e022d6d164f3f53f1bd7f60d560a8684079e90626aa1a4d3fe728158f7e1055ff76d1566072113982b193fb932265381e4de7afb35caa4ec56f31595a33fa2eb0bc84feb9f273224050938825fd21aa7317042ad00785ffd36151aee566a5dfe17d72591af1235059171568e5af0d13fc56e7897c3d632be753d8dea184c3d96d92bc56978cc669d94dd4c5e8dc3dcba7f0a39368fb1e87981e54bba7b86fbd8e8023a94d84f0290f402a5244cb4b0eeaaa57610ea59711a43932c521f10edb4560375693cbea60240389b8cebfd94035cabe4fc96ce8a726b979775e06c3bb0e3c4c866fe82e89fb725499e711e39310b93c785b313459f22d4ba37f90b19447165c2584269d98bf47d1f7ca89585797e4d6f1a4a1db7d2b0ae91a93fb15c3bb0ab953c3656b3b2ca20833d15e95329baff6d2ade1b0921b5ed3ae96648bf123b5265e27b049e9a8674455ff5f763f039568026e4fbe9882fef761c573d8f12e342c274a8dd3ad9854a688ce57cdddb52c758161ae3a59f67fc0d5b85f12e27617e7f4366e97a61fcda084e620dde35686f01dac49ce4bd76b986e3223c215919a1b228beeb74b7fcf32827d55be8f1b3b5fed24df2db023faecbb313b18a151cc4af8199d4bb08f8127b8207a0286d52758eaca87fd476ece0e3b17bcd8afb0289e8fd33c4455d4db6f058826c301ea303bfe2c0a6651a8fb6a2e1897852d758076adb04ad907077c5d5f94089da78d8923a34f1022ed672f378fe0dd81a709b372c0a2042a42e683c051c653e42b43c4a0ea8e961074d2901d4157ac9878b13a207b05ec471cff10d922b74d05623513cd6a4ea192ad21d4089de269633d4d2d1388d98d7c8a9e29848d5558b8aa2b73b437446a640230e6adb7f4b317ee5d66681c4aae11f69b1e5f96cb32ca6331405426cb706167d86f6f8fd588a72d7b2a6906798b81f174d808e1e3fc461e598e797c41bced26b87d09282d7b6d95076c285462e0c420a6f0e171ffe2791b5d221c03520409fe36622ff77796d9b7ef82babb25313acda9c621b22bf45ed909f9365b508860645af4c3aca78e6abca2d3a65c9159fbcd577438505d3f65a57c9412c12c069ad4d6db450beb08603abef621a9e029593fb5881dbd524ea2953b4acaaf59269b584c754e88c033247bb7c032e548d34fd9b2678e62fdf953dabf2be21c3e2d7b18ec7e3aedaf2cd082e19a369c1bcd4ca67e3d464e2200ecc3df98b0aa7f349415d68bcab0441ac3366607eff024bb786aec031a4619f8a24f554fe93c8520a03affcf11e40b6d5002f98c1708cac6c56e77eccba85ea6600d1391cfd202cc7914bfbaa3303266d1a820bf2dc84d2dfcdc4cdb79e6de3fbe3c02b288dcf955652f674f3f59b50849ea7dbf755bdafa27fba3db1267fb1354d8bf25a60cacb900b4d7ba913f9ba5f6b00559ad58b2f34a658ff7ef7f7d1ceeffd9c8325f271e6b5ba44d89685b744306963aa5e05ac0e8b00ada772dd5ae5ffb7043109afea86593743564c7acb4c8e7ef0e57d081eb1b9c0916078b113ece8a6036264a9b9781183c035342d50c7b069f3a01a40230e37ed8efde073c07d0e68066541d78c2f3cbe1e603cfcaaac40000000108452af27900a1723300404600ca8530029a6bc59ff3e85beb5fc838ac3147ba5c2f6421ddcffdd85167d8de70eff2b1fa016dad4918337dec0feb660edb98e078dea51fa914055984b7957bd732fa4c831e4489522d29bb5c84749f83c8e1edfd9da8d1738164a8a9c59e37a5c9994d90bb982dcfa69b20f868960dc139618f1adc2546d34340ae13d826260c54a456bbf7469ee37b1be1d7177004468d7e92cac62a0b165d6a114ad479861dd58959e094b5a6250359301d4a614d529660760e3d1cdec9bf444a3761309bab40e4a977bc749e0dae431952f5f7e6b1ebc1383d343359a387da4301f7fa4b400475e9b82367e56278376dd1c80349f083988945a13649008109cc12a3acf569ffcc5481fbcd86b544e7dc8434e9dd42bd8e5716a844d37879568db046857389d36cc7550c75f94e314db6749aa987f0fc730fae0fcf465d01c2fb745269dfc10132ddb5404dda2f9455780f5818730834aa9db4740793359884b9927b0bd1a5ca96052b4f17397d8b78aa891401bb8bed6726ea2229d919798c50e24d5f40576ac204847be9244aadbe5c773684c37475036541d209c177d4e9c22a1253292ce4ffb886b925b6cf83cc251976a68887eda2777590f51804b790b51eee77e717b7ef0eea71634594df36e6ae9e7574d65c51ac3196f0b2a3b0f023c81f05f7807f958dda03418ed49e14b645e814b9aa55b37c809be3172ca21fe4c7a78e17e9ece8def2dd2949310ecaa41b1b477f4e85db5288aa144e333f47ef291d0e822941181c13859d9fd6d640904ee764c9276125228c932dff3fb12f564f039b52f5ba1ab4d119641df8fe13f784802b99347f0046da63f471e34b1d12d3111cffe7b5d90cf5999879f6f23e7785f09cb10df32821bb68dd8fdcfcdbedd63f2428b2292b9f0e76ff36403c9644fd43e01112ee6218d0ec1c86f6d147e4b802293e906750c7046f53bf05a144e321d3b45e08e4064fd3828fdd1b5d1ceed74081f61319dc0ad9a6e8a3b9cc802e952d24e2271712e2c2cda7daca2f835e6c804feeef8d918404cc82a1aa9534bddff68a472b208a0d0a7fd68a08fbc411132af47a6b67a32617b7b9991524c21599e8e3cb9395cdab87a3f5bf5d1833a9c7ea021b29cf428c877c6b21d62f99340ac7f85ae721acc10968e7d79f111ca40c75e14060d07cffa046d71151a0b00eab657300344b04bd1a8871650c34ceda8610d7c1ba8d37673da6aaa580400e0230c69fba8ba21927de2f5897656144694550d1df3d268804adc707e7b236501734aeabb2e61cb08012bd96eca5a486d7a55f996992c36233815abd71c30e263ba0c5d9456fe0828df16f6af7929390bb143c426d9dfeaf4bb373554479ebe609b36b4bc3dd08ce216b9cdc5726edb458c5e4036d0edc688d3e39d20f8254b5d1f174518f15b344efc27fc56572c0159aa593d5b46bc33818f986e3df8caebd4c7b702ef50dd582714a2b94ecd1c4e90af37d388445c478a32ff6e8f5852ee115966b708eed04da322b98813a69423e95f90b89ce85518e39bcef36fdd5bd312b2c6c5ee85962675274c18f39ee35155517f70fd74b31bb2de6b5108d369252e6fb289e453833132ef7960da1cc0934790c039b9a1b0c74f23eb3b61fe9b4d0ea67de757b93af451eef303b1373199af446a0fa98d5991bbd4771ee63317e6da86efbe213dfff595c41b98e0e89f4f2df110104e760feebf4cb3361171c9fceb1e1c809a268",
+			domain:        "",
+			wantErr:       true,
+			needsMoreData: true,
+		},
+		{
+			name:          "QUIC Chromebook Handshake[2]; packet 1-3",
+			hexData:       "cf0000000108452af27900a1723300404600ca8530029a6bc59ff3e85beb5fc838ac3147ba5c2f6421ddcffdd85167d8de70eff2b1fa016dad4918337dec0feb660edb98e078dea51fa914055984b7957bd732fa4c831e448967af34752fd95835e3caba1e022d6d164f3f53f1bd7f60d560a8684079e90626aa1a4d3fe728158f7e1055ff76d1566072113982b193fb932265381e4de7afb35caa4ec56f31595a33fa2eb0bc84feb9f273224050938825fd21aa7317042ad00785ffd36151aee566a5dfe17d72591af1235059171568e5af0d13fc56e7897c3d632be753d8dea184c3d96d92bc56978cc669d94dd4c5e8dc3dcba7f0a39368fb1e87981e54bba7b86fbd8e8023a94d84f0290f402a5244cb4b0eeaaa57610ea59711a43932c521f10edb4560375693cbea60240389b8cebfd94035cabe4fc96ce8a726b979775e06c3bb0e3c4c866fe82e89fb725499e711e39310b93c785b313459f22d4ba37f90b19447165c2584269d98bf47d1f7ca89585797e4d6f1a4a1db7d2b0ae91a93fb15c3bb0ab953c3656b3b2ca20833d15e95329baff6d2ade1b0921b5ed3ae96648bf123b5265e27b049e9a8674455ff5f763f039568026e4fbe9882fef761c573d8f12e342c274a8dd3ad9854a688ce57cdddb52c758161ae3a59f67fc0d5b85f12e27617e7f4366e97a61fcda084e620dde35686f01dac49ce4bd76b986e3223c215919a1b228beeb74b7fcf32827d55be8f1b3b5fed24df2db023faecbb313b18a151cc4af8199d4bb08f8127b8207a0286d52758eaca87fd476ece0e3b17bcd8afb0289e8fd33c4455d4db6f058826c301ea303bfe2c0a6651a8fb6a2e1897852d758076adb04ad907077c5d5f94089da78d8923a34f1022ed672f378fe0dd81a709b372c0a2042a42e683c051c653e42b43c4a0ea8e961074d2901d4157ac9878b13a207b05ec471cff10d922b74d05623513cd6a4ea192ad21d4089de269633d4d2d1388d98d7c8a9e29848d5558b8aa2b73b437446a640230e6adb7f4b317ee5d66681c4aae11f69b1e5f96cb32ca6331405426cb706167d86f6f8fd588a72d7b2a6906798b81f174d808e1e3fc461e598e797c41bced26b87d09282d7b6d95076c285462e0c420a6f0e171ffe2791b5d221c03520409fe36622ff77796d9b7ef82babb25313acda9c621b22bf45ed909f9365b508860645af4c3aca78e6abca2d3a65c9159fbcd577438505d3f65a57c9412c12c069ad4d6db450beb08603abef621a9e029593fb5881dbd524ea2953b4acaaf59269b584c754e88c033247bb7c032e548d34fd9b2678e62fdf953dabf2be21c3e2d7b18ec7e3aedaf2cd082e19a369c1bcd4ca67e3d464e2200ecc3df98b0aa7f349415d68bcab0441ac3366607eff024bb786aec031a4619f8a24f554fe93c8520a03affcf11e40b6d5002f98c1708cac6c56e77eccba85ea6600d1391cfd202cc7914bfbaa3303266d1a820bf2dc84d2dfcdc4cdb79e6de3fbe3c02b288dcf955652f674f3f59b50849ea7dbf755bdafa27fba3db1267fb1354d8bf25a60cacb900b4d7ba913f9ba5f6b00559ad58b2f34a658ff7ef7f7d1ceeffd9c8325f271e6b5ba44d89685b744306963aa5e05ac0e8b00ada772dd5ae5ffb7043109afea86593743564c7acb4c8e7ef0e57d081eb1b9c0916078b113ece8a6036264a9b9781183c035342d50c7b069f3a01a40230e37ed8efde073c07d0e68066541d78c2f3cbe1e603cfcaaac40000000108452af27900a1723300404600ca8530029a6bc59ff3e85beb5fc838ac3147ba5c2f6421ddcffdd85167d8de70eff2b1fa016dad4918337dec0feb660edb98e078dea51fa914055984b7957bd732fa4c831e4489522d29bb5c84749f83c8e1edfd9da8d1738164a8a9c59e37a5c9994d90bb982dcfa69b20f868960dc139618f1adc2546d34340ae13d826260c54a456bbf7469ee37b1be1d7177004468d7e92cac62a0b165d6a114ad479861dd58959e094b5a6250359301d4a614d529660760e3d1cdec9bf444a3761309bab40e4a977bc749e0dae431952f5f7e6b1ebc1383d343359a387da4301f7fa4b400475e9b82367e56278376dd1c80349f083988945a13649008109cc12a3acf569ffcc5481fbcd86b544e7dc8434e9dd42bd8e5716a844d37879568db046857389d36cc7550c75f94e314db6749aa987f0fc730fae0fcf465d01c2fb745269dfc10132ddb5404dda2f9455780f5818730834aa9db4740793359884b9927b0bd1a5ca96052b4f17397d8b78aa891401bb8bed6726ea2229d919798c50e24d5f40576ac204847be9244aadbe5c773684c37475036541d209c177d4e9c22a1253292ce4ffb886b925b6cf83cc251976a68887eda2777590f51804b790b51eee77e717b7ef0eea71634594df36e6ae9e7574d65c51ac3196f0b2a3b0f023c81f05f7807f958dda03418ed49e14b645e814b9aa55b37c809be3172ca21fe4c7a78e17e9ece8def2dd2949310ecaa41b1b477f4e85db5288aa144e333f47ef291d0e822941181c13859d9fd6d640904ee764c9276125228c932dff3fb12f564f039b52f5ba1ab4d119641df8fe13f784802b99347f0046da63f471e34b1d12d3111cffe7b5d90cf5999879f6f23e7785f09cb10df32821bb68dd8fdcfcdbedd63f2428b2292b9f0e76ff36403c9644fd43e01112ee6218d0ec1c86f6d147e4b802293e906750c7046f53bf05a144e321d3b45e08e4064fd3828fdd1b5d1ceed74081f61319dc0ad9a6e8a3b9cc802e952d24e2271712e2c2cda7daca2f835e6c804feeef8d918404cc82a1aa9534bddff68a472b208a0d0a7fd68a08fbc411132af47a6b67a32617b7b9991524c21599e8e3cb9395cdab87a3f5bf5d1833a9c7ea021b29cf428c877c6b21d62f99340ac7f85ae721acc10968e7d79f111ca40c75e14060d07cffa046d71151a0b00eab657300344b04bd1a8871650c34ceda8610d7c1ba8d37673da6aaa580400e0230c69fba8ba21927de2f5897656144694550d1df3d268804adc707e7b236501734aeabb2e61cb08012bd96eca5a486d7a55f996992c36233815abd71c30e263ba0c5d9456fe0828df16f6af7929390bb143c426d9dfeaf4bb373554479ebe609b36b4bc3dd08ce216b9cdc5726edb458c5e4036d0edc688d3e39d20f8254b5d1f174518f15b344efc27fc56572c0159aa593d5b46bc33818f986e3df8caebd4c7b702ef50dd582714a2b94ecd1c4e90af37d388445c478a32ff6e8f5852ee115966b708eed04da322b98813a69423e95f90b89ce85518e39bcef36fdd5bd312b2c6c5ee85962675274c18f39ee35155517f70fd74b31bb2de6b5108d369252e6fb289e453833132ef7960da1cc0934790c039b9a1b0c74f23eb3b61fe9b4d0ea67de757b93af451eef303b1373199af446a0fa98d5991bbd4771ee63317e6da86efbe213dfff595c41b98e0e89f4f2df110104e760feebf4cb3361171c9fceb1e1c809a268c60000000108452af27900a1723300404600ca8530029a6bc59ff3e85beb5fc838ac3147ba5c2f6421ddcffdd85167d8de70eff2b1fa016dad4918337dec0feb660edb98e078dea51fa914055984b7957bd732fa4c831e44892ff5e6b16d8a259a9128c2c0c3c525462781a344c3df7f19a747e0e79ca8714995c867fc697a3cb87b35e769465a8e966bcb35b7e897ad036aa23a6c021e2445a0eb79962151cd20dbb43ae1231847de01caf4e5589dfebf026e95f7d1d742e140d9dda849396a70cc0798f1eef06fd5f4cfbc9a190ddf04cc332c5b7b15e53af311190ced92a1291c12b8799f2b50e076539a8370ee667e1791a78f38e565a48acbaa1c78ba941dba8b0d040f8fb8bbcc9f6bf5705efa613a24b12d6ac9cebb4f3fac1b09a07b49d8a3a62808eb0a324629f13a012e6ad0feb11ad97c1572983c713b62f27584809ba43e64e4af9845af807c0783104838f4e2ac33fa848866f3cc64a7b6203a5c09e8ad231f0f06ae2fb7b39a64cedd823b0ff297ad9be1ccac436777ccb3e22ef6b9c12e6d5e34926f50e8ca8c8c0532c810b074d001c11791a01bf25786b57a5da54065dcee4962822e929f47ee44d3b8c83d45a8b7a936dc2a6fa396e4194fa032d1627eca59f69857fc40dab5835d3613dade1c74b09c345bd32c509e9545d2330b157a7acb76409f3ac8eaa22802414f38c5422fe4c5189caaf5c1b93ce7c0892f0cfc477490d335aa78961d632a973cf106bd974c2714176fb0f98cf12f2887a0d7bd491756dd374331eb3e6adb9f2bd0d6b273403fd14b314eb27ebbb6f6e78ce310437004b757c048149cf04429ae4a6d6e65c9b3e0b9c9c4d4ef52007eaaad9670320f10cd5317b3d3edc374d45c98b217dd28fb3c2c2fb6e74a3aced143e3242084b192ba6df24e69fdb883e850714fe27a45f43883486a986574fd1fc10f259fe90786441554514c8dade1f3b86fdaf5f54ab655e2d803c98aa56073b00c32148a1ed367dff3a2bd934ecba55141389990b661bbd9ce1ef1def13747d45500daf92cec9e60908274703e761cd46affd46622f2a2192a79425ebf51c875fc7ba3598e15e0ba2465fc3e87c8a5da1915d3b8abe4b16d21259f311183eee1e7d2b808a91a7c89b284df0eb6a2a79c610bbe47722b3e04d5a6c0e574816a94d97349b6976010eb8c7debf42210982f78de482b7cd068051bf57908dbf46b5ceaf64f5fb33ede4412c1ce81eb1dfb4e99e10dd9b57ebc6e62ecbf4ee2db04d9e48c62bd45f8fa51704d414296a2d51d25ced6a192034a44c67e09d8985b573f98e03fa36dd8dcce2c04b4d5b1f276b6a642aadbdcafcf09de1d234bf8bbbf64aeadf01519ddafb419b3e62d204e04c3d7ebaf54b09e387ac3e9c4781c11625a2f44fddb7a1886f21929bd01c283f64903b6ccbb463984dfadc00f6af2a421517da023fd319f528195cac5fe907624b70c0172479d07d78e266dbf20ab8fc302228f279ffdba7395a839c4a9d7a4e001a260e1702393968f1e9722f023b204cf09cfee9a7bba045e4a2a449ee9fbb5c36e93028cfc87a2e34914b1b4f01beeded175ac0fa73fea9292f2bc3b1247164d8e05cddc3981bdc24e5f596571c418f6fa00fd9d4d0898cbf0d2f5413bed5f100f1854903017b6bc88bd7e303b5e0e2417bbcc984731128eda550d31f9af0e6e743eb6916466bbd435617d56fa60b05cd7dca66a9f6f4be23d3c5ff5d900822c6d1d8d71b0bab24f57d9682381a87c",
+			domain:        "signaler-pa.clients6.google.com",
+			wantErr:       false,
+			needsMoreData: false,
+		},
+		{
+			name:          "QUIC Chromebook Handshake[3]; packet 1",
+			hexData:       "cb0000000108676ef9ec3514fd5f004046001ae0c831dde6ac72f1337c9ca111f5b32afdf102d75c017d3bccb6fa89902b750b00c51bb226afa517754b72e962ff007c1c8c8749a21be1d8d94f7bf73437c010cd60e0bd4489d0a84868f32ecd4bd0d4c95a8a08d60d8303ef02323bdbcd96a33940824d25b9594bd8ae5716b9d043ab27ba03a2593c4d149b923711dd98e45456db19c8ea71e982562ae787c1b6cbe3ca1b03df2df62aa8e3127c5f68bdf80ed90588e7ec1f41f5a6281b87a12348cb17a04e9eaa461fef2e0e3ae70ebdc7bffa15c6b61ab270173e46dec0fd081f935a5fe6338d3b9cd38fcb52cb159edb66d2927238294313990da25c22f40d40e3cd72e76bbd066de731cf8fb6b4b7bc7639efb788c0b108dbf8280845a2cc62fbaf5fb8e1ecbe5ba7791aab94786c1c71c9058d0153b34a3f5bc8903e0d120f353defbe973cd33568bd03609dcdab8af1e8563897f5dd0251c6e6514bf40bd447d376fed21b2c54ebf74680df241bdc2ea5579bc0736cf3257c20d275746e8e6853aa89dcda8c2dbe523438ab92ca1ed1ab4f109e4ea84de57dfb6c544d695a5b710fe2d432f2b58644f8aeb965752d3a1d1a3057c2229192f89b254f5d292c22f1060642729df3667ef39e27691c82da9be847a59a17ba7345d23a37e31ec135633cc5ea84c752f56d4ec75878a2920b93e9b4e091e0114552712e1e50ade42e26ac0266b84043a493e1ce2e80cd57422de16a88deceaa55385dc2a977ffc9063e7c427200b6d8511ef9004f89412587bd6d0057898f5ae284db78b0ec861fed36dfb7c7a9679ad0480eefe71985ba6f731bd0e816a901e0c017dd0cb7fc8a4606dec2091a51aab16d6f9bbdecf3fea177671e68250a84fe19de8df78d711e22b81372bc22ae21ac7208ed41201f6e26cd6748e9d6e2f4884f5acba736b2432536718891638d43991bd97c232829e26be6e6bb303d44849b245ef758eb2813bc87cf21a30f132360111e3015de5d1e4f0c5a98aff159c29f6debed7c2f18f455dfc7f33995a90b7625688507ecef1e7db48e7030ea6c4fa835bbc1dfbea6c0a6c704d658d4866a42b9860b1c8b5b64cb669e102c81e369b5f07b8fa08816a566a99f4d2910f6e8d751d52f1e2889f0ec9acfcb4627e0da5c35452be05c7766eddf3c42ceb6a312044075a4231b4203718c886498a313f3ba12e44e368b04ec3ea6e72d6fed9b6b334cbc0ba89f0aa9a129b1bad5b0ad8690291a344967f58e52415859852c6ca3ea24bc93ec1041fd1dc8a6a181326d3026098db0cddec90b3cd6df1e7638a3703f70c9a3baff8f005b90f362459a275a8b39daa78ff24613434594f96b8023a41a17d815e5c0319a39e07d32841339f14f404030b4a22551b86ba94832a1c49053d63140b503f2f64354ce10abe6c08f6cdaf6d8dc361c3c9d1a8077ad34dccc699b6fe07c16f8f7743d04003d672f82e643b3f1d5e263495504e11e6b2e676c11b3d0033d5f837e6bfd01602584ff181e3cb86f081015a9311eed546b42a8280680aa538353949f89674c554b43241e36536430ae9e0190729ce902e8f06a952d23b62816deb3b62b45375033ede2d8065a8e7b38f5aee0a5c66eb2f21f33fa6795d4b086e6f6ac941ba0c883ccf6e54e52164384045e0b0d74a9361f224303c841ec907be250725ab06cf79dd8bff8f46c08963a409b9b71b5c634c987c5e163f73fc32553be1231c72444c5e2a91189824034a784948f",
+			domain:        "",
+			wantErr:       true,
+			needsMoreData: true,
+		},
+		{
+			name:          "QUIC Chromebook Handshake[3]; packet 1-2",
+			hexData:       "cb0000000108676ef9ec3514fd5f004046001ae0c831dde6ac72f1337c9ca111f5b32afdf102d75c017d3bccb6fa89902b750b00c51bb226afa517754b72e962ff007c1c8c8749a21be1d8d94f7bf73437c010cd60e0bd4489d0a84868f32ecd4bd0d4c95a8a08d60d8303ef02323bdbcd96a33940824d25b9594bd8ae5716b9d043ab27ba03a2593c4d149b923711dd98e45456db19c8ea71e982562ae787c1b6cbe3ca1b03df2df62aa8e3127c5f68bdf80ed90588e7ec1f41f5a6281b87a12348cb17a04e9eaa461fef2e0e3ae70ebdc7bffa15c6b61ab270173e46dec0fd081f935a5fe6338d3b9cd38fcb52cb159edb66d2927238294313990da25c22f40d40e3cd72e76bbd066de731cf8fb6b4b7bc7639efb788c0b108dbf8280845a2cc62fbaf5fb8e1ecbe5ba7791aab94786c1c71c9058d0153b34a3f5bc8903e0d120f353defbe973cd33568bd03609dcdab8af1e8563897f5dd0251c6e6514bf40bd447d376fed21b2c54ebf74680df241bdc2ea5579bc0736cf3257c20d275746e8e6853aa89dcda8c2dbe523438ab92ca1ed1ab4f109e4ea84de57dfb6c544d695a5b710fe2d432f2b58644f8aeb965752d3a1d1a3057c2229192f89b254f5d292c22f1060642729df3667ef39e27691c82da9be847a59a17ba7345d23a37e31ec135633cc5ea84c752f56d4ec75878a2920b93e9b4e091e0114552712e1e50ade42e26ac0266b84043a493e1ce2e80cd57422de16a88deceaa55385dc2a977ffc9063e7c427200b6d8511ef9004f89412587bd6d0057898f5ae284db78b0ec861fed36dfb7c7a9679ad0480eefe71985ba6f731bd0e816a901e0c017dd0cb7fc8a4606dec2091a51aab16d6f9bbdecf3fea177671e68250a84fe19de8df78d711e22b81372bc22ae21ac7208ed41201f6e26cd6748e9d6e2f4884f5acba736b2432536718891638d43991bd97c232829e26be6e6bb303d44849b245ef758eb2813bc87cf21a30f132360111e3015de5d1e4f0c5a98aff159c29f6debed7c2f18f455dfc7f33995a90b7625688507ecef1e7db48e7030ea6c4fa835bbc1dfbea6c0a6c704d658d4866a42b9860b1c8b5b64cb669e102c81e369b5f07b8fa08816a566a99f4d2910f6e8d751d52f1e2889f0ec9acfcb4627e0da5c35452be05c7766eddf3c42ceb6a312044075a4231b4203718c886498a313f3ba12e44e368b04ec3ea6e72d6fed9b6b334cbc0ba89f0aa9a129b1bad5b0ad8690291a344967f58e52415859852c6ca3ea24bc93ec1041fd1dc8a6a181326d3026098db0cddec90b3cd6df1e7638a3703f70c9a3baff8f005b90f362459a275a8b39daa78ff24613434594f96b8023a41a17d815e5c0319a39e07d32841339f14f404030b4a22551b86ba94832a1c49053d63140b503f2f64354ce10abe6c08f6cdaf6d8dc361c3c9d1a8077ad34dccc699b6fe07c16f8f7743d04003d672f82e643b3f1d5e263495504e11e6b2e676c11b3d0033d5f837e6bfd01602584ff181e3cb86f081015a9311eed546b42a8280680aa538353949f89674c554b43241e36536430ae9e0190729ce902e8f06a952d23b62816deb3b62b45375033ede2d8065a8e7b38f5aee0a5c66eb2f21f33fa6795d4b086e6f6ac941ba0c883ccf6e54e52164384045e0b0d74a9361f224303c841ec907be250725ab06cf79dd8bff8f46c08963a409b9b71b5c634c987c5e163f73fc32553be1231c72444c5e2a91189824034a784948fc90000000108676ef9ec3514fd5f004046001ae0c831dde6ac72f1337c9ca111f5b32afdf102d75c017d3bccb6fa89902b750b00c51bb226afa517754b72e962ff007c1c8c8749a21be1d8d94f7bf73437c010cd60e0bd448983eee52163a177650f57b2cd8404bc619b9b59e796f9808bcd549ae6ae30d448c90f2783978bf9314a8038f45c0da5983163bd26f38f559f59447e8cf004f93b6b5c8af7b09603db021d4bdfa641bd83926eae1709a7a427add14df90cb258c6d4663d4d29709da89c90613d2ff9334637d53ca89407804eb863f78e110b866af2734c980705d9f969730a41132e788fc9e426d0f68ed24157aaff0383438d2715262e9b8b03cff850ba88127a05a8b68ac9a5ae5b098bb9ba5eaadd71ae846b3c0f68db728361eb8c8ed899c77725afbdfabf93812c49cbf4ee64047a96ea71258dbe5be3f988029d005fa2d9fc6e1e53fbeb6888074521b972e2ac71b4f22b754fc743e0de21af1e2ab416b2481e03227a1c7d7ea6cac5bc37ee3597d3bf11bf13a688dfa3d9aeff1eb1a7fdfcf8b6c722a4853f7c2b2d31e0b2b691f4273d4793fbb7a00f27a25577bfcba95e60699c9d2a926e71d64f535b633f2fd03320b28fe86c6619c54b34e6caf8f5a71b8a144c9236bf07edaacb486ff8ac63173af099efe7c9d006a5bb756449fb32b1fbff2e315fd5e96b586bb922a9795e29ffe6ead037c556e1bf30e24afb344cf873201007096b6f687f157588e236b71ade4d9245d8f065f2e23b36fad798d0f5504ddf25b828698d0cbdc28478b20d692d2ab605797a67232b0795927d886de798f00b4e7c69517d62b748e62e01d53dd1e77ac9a1605c0408713ff309ad53ff8f2bef17f9074f01134374068bf1f5dc07125180b5ea6902ec2d55c7d6d5f7ed4ef8732f9d34b4627678611fc9579e4321cea012c4e457dee6a11c41bdd1eb965056e885757af389079a558434eb3d59ae56a232302759431172ecc88de1c5400265f0f47e21396e3c38e0ba022c3e55ee4b85527cf49dece94445adc740cd26c18004a1cb984cc1732a138844da1ab003f89c589b6f3cc10c99a1b0d87be763f83e1b12c6fa6938ebc55d2ba33c25ca816dde207f7186f0c70b56b33feb538eb31175fdcfb036e365087f1b630628affdbbdee20d1976cb009f32db5f35aadb8117aa02ff2da9bdeaffbcc8bf3412efefeb00365e5f1ea577afd6e1c3585c67ffe1fa120382aa54028dcae9bbd624432a6256687d05483f2611f1ddd14b40f66fdf547e7eba904a79bd27733c9a8fbfb01154dda3457c4eacff8116941777ec570ff040e217d648ea5076588a6417462481eba68ebc59af04ba49b92f70b68a007977fde48b94b0af35475ea19cbec92df6449b065880bf03452cb3b3582f3d1a010e585be6506f3e067226471a94ce46c515f20502b3866553c10f037d9be89ad5858d6b2d2d94c70159247f66958d0e841d1c5b4254809d52475fdf96d087c3c6647b86006147a9ebb3f52ea6f4b89d886725b9e9243efd95e434bd8dd785143c57c06863b68df8f832987eb0c730c8b96634c1f888da2ef420cb0ebacf81f4b25c65962ae40c09ac4b0b2d440e3bdaa7309d87a1fa6af1c2e13e7a63c253fae027ceb2067cef8421b62d205f5d37c7204eaf594b1b43f9d9b67509a6709df48769ab9e1078f9e59d7656ec2132b5ebccf297e757a052835fffe94ae073131ac49c4f4374a1904cd4bf3041b236b73ea19eaa583db577fe35",
+			domain:        "",
+			wantErr:       true,
+			needsMoreData: true,
+		},
+		{
+			name:          "QUIC Chromebook Handshake[3]; packet 1-3",
+			hexData:       "cb0000000108676ef9ec3514fd5f004046001ae0c831dde6ac72f1337c9ca111f5b32afdf102d75c017d3bccb6fa89902b750b00c51bb226afa517754b72e962ff007c1c8c8749a21be1d8d94f7bf73437c010cd60e0bd4489d0a84868f32ecd4bd0d4c95a8a08d60d8303ef02323bdbcd96a33940824d25b9594bd8ae5716b9d043ab27ba03a2593c4d149b923711dd98e45456db19c8ea71e982562ae787c1b6cbe3ca1b03df2df62aa8e3127c5f68bdf80ed90588e7ec1f41f5a6281b87a12348cb17a04e9eaa461fef2e0e3ae70ebdc7bffa15c6b61ab270173e46dec0fd081f935a5fe6338d3b9cd38fcb52cb159edb66d2927238294313990da25c22f40d40e3cd72e76bbd066de731cf8fb6b4b7bc7639efb788c0b108dbf8280845a2cc62fbaf5fb8e1ecbe5ba7791aab94786c1c71c9058d0153b34a3f5bc8903e0d120f353defbe973cd33568bd03609dcdab8af1e8563897f5dd0251c6e6514bf40bd447d376fed21b2c54ebf74680df241bdc2ea5579bc0736cf3257c20d275746e8e6853aa89dcda8c2dbe523438ab92ca1ed1ab4f109e4ea84de57dfb6c544d695a5b710fe2d432f2b58644f8aeb965752d3a1d1a3057c2229192f89b254f5d292c22f1060642729df3667ef39e27691c82da9be847a59a17ba7345d23a37e31ec135633cc5ea84c752f56d4ec75878a2920b93e9b4e091e0114552712e1e50ade42e26ac0266b84043a493e1ce2e80cd57422de16a88deceaa55385dc2a977ffc9063e7c427200b6d8511ef9004f89412587bd6d0057898f5ae284db78b0ec861fed36dfb7c7a9679ad0480eefe71985ba6f731bd0e816a901e0c017dd0cb7fc8a4606dec2091a51aab16d6f9bbdecf3fea177671e68250a84fe19de8df78d711e22b81372bc22ae21ac7208ed41201f6e26cd6748e9d6e2f4884f5acba736b2432536718891638d43991bd97c232829e26be6e6bb303d44849b245ef758eb2813bc87cf21a30f132360111e3015de5d1e4f0c5a98aff159c29f6debed7c2f18f455dfc7f33995a90b7625688507ecef1e7db48e7030ea6c4fa835bbc1dfbea6c0a6c704d658d4866a42b9860b1c8b5b64cb669e102c81e369b5f07b8fa08816a566a99f4d2910f6e8d751d52f1e2889f0ec9acfcb4627e0da5c35452be05c7766eddf3c42ceb6a312044075a4231b4203718c886498a313f3ba12e44e368b04ec3ea6e72d6fed9b6b334cbc0ba89f0aa9a129b1bad5b0ad8690291a344967f58e52415859852c6ca3ea24bc93ec1041fd1dc8a6a181326d3026098db0cddec90b3cd6df1e7638a3703f70c9a3baff8f005b90f362459a275a8b39daa78ff24613434594f96b8023a41a17d815e5c0319a39e07d32841339f14f404030b4a22551b86ba94832a1c49053d63140b503f2f64354ce10abe6c08f6cdaf6d8dc361c3c9d1a8077ad34dccc699b6fe07c16f8f7743d04003d672f82e643b3f1d5e263495504e11e6b2e676c11b3d0033d5f837e6bfd01602584ff181e3cb86f081015a9311eed546b42a8280680aa538353949f89674c554b43241e36536430ae9e0190729ce902e8f06a952d23b62816deb3b62b45375033ede2d8065a8e7b38f5aee0a5c66eb2f21f33fa6795d4b086e6f6ac941ba0c883ccf6e54e52164384045e0b0d74a9361f224303c841ec907be250725ab06cf79dd8bff8f46c08963a409b9b71b5c634c987c5e163f73fc32553be1231c72444c5e2a91189824034a784948fc90000000108676ef9ec3514fd5f004046001ae0c831dde6ac72f1337c9ca111f5b32afdf102d75c017d3bccb6fa89902b750b00c51bb226afa517754b72e962ff007c1c8c8749a21be1d8d94f7bf73437c010cd60e0bd448983eee52163a177650f57b2cd8404bc619b9b59e796f9808bcd549ae6ae30d448c90f2783978bf9314a8038f45c0da5983163bd26f38f559f59447e8cf004f93b6b5c8af7b09603db021d4bdfa641bd83926eae1709a7a427add14df90cb258c6d4663d4d29709da89c90613d2ff9334637d53ca89407804eb863f78e110b866af2734c980705d9f969730a41132e788fc9e426d0f68ed24157aaff0383438d2715262e9b8b03cff850ba88127a05a8b68ac9a5ae5b098bb9ba5eaadd71ae846b3c0f68db728361eb8c8ed899c77725afbdfabf93812c49cbf4ee64047a96ea71258dbe5be3f988029d005fa2d9fc6e1e53fbeb6888074521b972e2ac71b4f22b754fc743e0de21af1e2ab416b2481e03227a1c7d7ea6cac5bc37ee3597d3bf11bf13a688dfa3d9aeff1eb1a7fdfcf8b6c722a4853f7c2b2d31e0b2b691f4273d4793fbb7a00f27a25577bfcba95e60699c9d2a926e71d64f535b633f2fd03320b28fe86c6619c54b34e6caf8f5a71b8a144c9236bf07edaacb486ff8ac63173af099efe7c9d006a5bb756449fb32b1fbff2e315fd5e96b586bb922a9795e29ffe6ead037c556e1bf30e24afb344cf873201007096b6f687f157588e236b71ade4d9245d8f065f2e23b36fad798d0f5504ddf25b828698d0cbdc28478b20d692d2ab605797a67232b0795927d886de798f00b4e7c69517d62b748e62e01d53dd1e77ac9a1605c0408713ff309ad53ff8f2bef17f9074f01134374068bf1f5dc07125180b5ea6902ec2d55c7d6d5f7ed4ef8732f9d34b4627678611fc9579e4321cea012c4e457dee6a11c41bdd1eb965056e885757af389079a558434eb3d59ae56a232302759431172ecc88de1c5400265f0f47e21396e3c38e0ba022c3e55ee4b85527cf49dece94445adc740cd26c18004a1cb984cc1732a138844da1ab003f89c589b6f3cc10c99a1b0d87be763f83e1b12c6fa6938ebc55d2ba33c25ca816dde207f7186f0c70b56b33feb538eb31175fdcfb036e365087f1b630628affdbbdee20d1976cb009f32db5f35aadb8117aa02ff2da9bdeaffbcc8bf3412efefeb00365e5f1ea577afd6e1c3585c67ffe1fa120382aa54028dcae9bbd624432a6256687d05483f2611f1ddd14b40f66fdf547e7eba904a79bd27733c9a8fbfb01154dda3457c4eacff8116941777ec570ff040e217d648ea5076588a6417462481eba68ebc59af04ba49b92f70b68a007977fde48b94b0af35475ea19cbec92df6449b065880bf03452cb3b3582f3d1a010e585be6506f3e067226471a94ce46c515f20502b3866553c10f037d9be89ad5858d6b2d2d94c70159247f66958d0e841d1c5b4254809d52475fdf96d087c3c6647b86006147a9ebb3f52ea6f4b89d886725b9e9243efd95e434bd8dd785143c57c06863b68df8f832987eb0c730c8b96634c1f888da2ef420cb0ebacf81f4b25c65962ae40c09ac4b0b2d440e3bdaa7309d87a1fa6af1c2e13e7a63c253fae027ceb2067cef8421b62d205f5d37c7204eaf594b1b43f9d9b67509a6709df48769ab9e1078f9e59d7656ec2132b5ebccf297e757a052835fffe94ae073131ac49c4f4374a1904cd4bf3041b236b73ea19eaa583db577fe35ca0000000108676ef9ec3514fd5f004046001ae0c831dde6ac72f1337c9ca111f5b32afdf102d75c017d3bccb6fa89902b750b00c51bb226afa517754b72e962ff007c1c8c8749a21be1d8d94f7bf73437c010cd60e0bd4489ea77dbb530c7ba127c66c3d7bbc00c336fd4e09e1775c646dffaa8696f7b8b00bf91261fc5164d57a4b9652b7cff4e301d32224b4e48cbfca535b2070ac46181615358d87e244ba6e369f6719bd5a551ac05dc78c222fd0969d0d943cbfaa3570ec25ab2768e9679d1cd1a3528659d010c409a0719526c44e4d9915dc5b0618ebc9e35f06b31bfd8e01fad99dabe32f6bfa00b3a5db5a01920d6685c34efb958729ffc5acfe46b3605715149b65b2f638007885a0866bbdde6765992b9acce2f527de906443f8643845489f1224fd3bbbb3fa78ca4848fe0167ec7cff8a05a17eb7c7a05a80c3106647e5d9aae350f33d10f3a60ab1c705858323a8f610d98cc68ef3cea66eedbb788b9a3da873bfd44ed632aa952ed7bb2004f4502260cef0596ec6e82e7683bdd2cb1f63b01b3f928ffa86b89cbeee922f1fd192fea0bdd17cf62d14f06f9e27bf5cafec90ab26f103e1dcb96ae4335e444b1fbad294cc395c5dc3a1c0c1fb4078d362eb229c42bc42ff53115c51f137d75596b3e6d3d28974720d6935430054c6b630bade51ad508d31fdfd572bd37f70e3dc06021d2b0ccf91a7975aa501e152d62980f02ce0ee94b547a2fbede47cf1f5c0a541ccc8992dd006f77437ce6a6b1f4f91833914a1cc51acf9336a620c4a22073966cde3ecac3224941dec004e741e05c11b43796dc531ce33e7c9a4fa68fa689880842e37a3a04fb75f3fcee86813388df74d443d1c35d7adea290effa98309b22ceca9bc252ccb4c443733db691adf0af559a5b7565043f84e91c5ed9f79ebf49f0bd60b68a7b8730032574e8e21548204c75321a374bbbf822efb1281ddf32feeced4bfe22bcf7c1a309954c1e356175a8a1a1a074a22f4561acd872d813c88ea9f0f22ac8d7b7b2088bc8565e1c56dfbc84f57aa38c2600ee20e8736076a91ee73f3137e8da3fe3871587b8bdb0a08af40babbe5493f036b45eea837dc15f761d9475d27a512a2d9dfc1ccdb81e2b581f91a5d7fe67cf6955427315a4e9c158806e651e4acff40051cd8a44b0108876c82f7b4d69033bfd8216234de545bf8fb58e489bc74d366db5e48711ba7f317dcdd1708ed5de97468a6026e15bc68ab11efc90f5465b4466bf384a8cc95f9c7fff91d776cccceeae5badebc31c3516c93a7b4682212e5a4902a9fd0327234749d83c141db2eee9688a76f4361f8b6213c88ebde69ebb84488c9ab8f42737da123eaf39373ac687df65f817939296f5477f92ad3fda0effbdd5d0594eb59d80265eef6cfcaf81b386c9d03c205c1b6714bf31be15e8f871b4791aec10884938285d6b8c18a0dfe750b753de88a2d2d855b9d1a0068ac4d2ce3a259bfdd30414380bf8b287abf2a28de442552f1d70a0aeb0867d9c7ed4e9717565ebc6aca21d85d2845faacfd8fadb1a76d9a2cd619413e631666009085bc7dad7492654ec20431e37ddd55588d2cd4d256021547cac768dfe3f7dcc9a18f0c72a743de799e98398b9bb2f216aea727d240b2f52ee269f4df4b8d7bdb439f074e3ef179ae2ae44daba64864fe427574b659a5e79defaf43e45e1357e1ff48e28ba6384c559cd036c9229151f917865b5575cda11e1ee0690bfbdb628b9a17e9c37190102",
+			domain:        "signaler-pa.clients6.google.com",
+			wantErr:       false,
+			needsMoreData: false,
+		},
+		{
+			name:          "QUIC Chromebook Handshake[4]; packet 1",
+			hexData:       "cc0000000108a3e7f3133d37e2970040460094b49b4808cfaa190ce163e91b9d2c0105f36a2c93f670114f7b60598f03d6c596ceb19f410e9660903f590e3f25cf619e5c171001990b1d1b97f789595d3039e666345cc944894c6153ddd936992f160ae349757507f79fd0485766987d986518d9f19270a0021c52bff14e594c074f3c5664cf3de3b761cd36c16acf68565aaaeebf196da581533f19a464b22404b13b46ae3e4819bd4a7a85db6ddf379bb84f8dffcbb412c9ce405d8b4c98d303cb13df2e80a88ca0f09e2e2489c8d0b6d5ba9262b85869f8f989e9b82c4a270592894fda96bd27ce03e0cb4d4a4e130d9655e6da02f4348c949bc9b2aa609fdb4b9a0a3e45be25b18fbde569bb996d6419e98f2d9b7a0ca63f52f054b50771dc7c580596d86b4a94642be9a9b78a01ad2deae4607d8e0e25641aa8ed46b20fe027f4b9f77d1736aa0fec4f837cf5d878b3dcefdf3c6e82eb943dd022e98d623403950e6ea3addc0f93f92a422ed686b7beee437a4040f4a440dfd071d8c09f1344c28545b4488765a455e33e13d17434b9642dedadcb6a13ec35d51c3e7a03ae9a76cca6b1cba8312b7d8bae703e0a378300a17b7483d07893ddd941dd3e545a66faa0fabb4dc967c807665ebf4562fede176719d1a126f228acc0902e7235972a6db4eedd6547c38705629ee2574c5d2dd6c76c5c82e741f33291506e66a8df65ef6d1e7e6628fe4a4f5e141d482fc5f9d26609e64da8061eef5c0fca421d5334b199ca8270612074a1f9fbaad8b98ff7b81f8871f4ada6976f254e47c51e03d4c628beb3471ba375642ae0b41d65dec1419cd31f20ec779f5666717c1e7b4240fdcfa46a774234961083e1915e938ae0d41a66868b91949d856065c4e6813e0cbd9680a916b5eb78655dea9ad0f9c0ad0f5c244a72fcb8b589321519e34f0e6e25e6bb43abfa84a7241bc02555fa9060b9ef55f1e3a9dc3a575e16b23a36aabbd3ddeaf8f2516224179a4039a891e7f29631c2a08745bb184c66ffe98bc960e6c08a14524ae34444433591cdf7adc14419310b74594305f67c3087a2c21733e6e0be748e7af6fb6717946c313fbc0935ad3559e2d6323979cdc3bd48753b5a438605e15832efb8a0c4144060f41ed27a82dd067f2caaea3830abc97d9e080b3fd762aecbd58e8b2b17dae553dacdf3ee44198d2f19c0522b6a1b17923a210cf24902c5590afe808fd22e54e586399665d588a7febd0b402a4e6283679e1f95a2d4d7d3945e2bb8f44225ad8aa07cd07d3323ce94f39ae4c9466c05ceeb0a30981cea022d1bcab8a4b0c8e42e08211ee727728c74d7945f2350a149eb9cb7eb3a280954b64e612b53b19016a4c07427945345ffb86982c113ed797172ded4428d6b95b9ce64b48e98ab96421a179983c4a74b986f3f52d9a2d7fac8ea0955835d241bf4817a42950e2b298e51de20c026df81fdb0d28c68841bf62dfcfb4684def62c13ceddce9a25b446043056006ec8582aea14eee602eb2963f575dedfd2313d7d561c6ceac0d08c94645a222b25b7493542fee52c316f06f583612ab2ec3d420a01a61fe80b099386c2fe647292769d4571239592fe7e27f4324456ef894643f72ac450628cdcc9f376607b85f369a092c64d7d5a0559193e29cbc48e9ed77fa3fa05776d6169fbdbafa507db1e1d33a4550003a3a1a794b266e886f483eba76a8629d17d9596574068ffce61a52b209c21c77f5e7337e5541755c9f1c6b4",
+			domain:        "",
+			wantErr:       true,
+			needsMoreData: true,
+		},
+		{
+			name:          "QUIC Chromebook Handshake[4]; packet 1-2",
+			hexData:       "ca0000000108d799f48baf472fc3004047005411dcdaa24bd4c3cdbef653940a1ea0a671bb8c23222a8502bfcbd0a335af016df330b1190e4b1efd420aa82c4414a7dfd7b1aa63aa7bd0269ec8ed0d24895a467b737fcc514488a8142241b81c4952fb32e9f123f3f8d1be9eecc1340d7fa747c6f4838810209d51ad453fcec084ffaa382f9fed010a0585f8ce73c36dc6c628df940f72fb5b8e3e06f4612128d3b8f87725770d81305489a3a23cd443fcc668fece0ec9a909c82cfdb66819ce031422c3edd49ea72b6216efb940b8c186e2510b0f93d4cf3b6434ed9f5817c5a5a19fa861d24883bd48ba296df81e887fcb9ef18013ab1070df268049f3d35e8ddfffd2b100e4eb687176a02e7975085caa138e9df7cb6f9862356faafba3300f586df09af3b4e3eec15b6d1f14b34fe4eeb8e762ff482f3b7b0595c16d3eb20cf9c892b3f7c6449e51ffa33f3dc877d32e572e10ba4d5a320117110b150bec4a9434103de963aa2de1b22eaa992b59a8583c7a2d4e5743ef98a1b1f5f4aaeb2b49dbe441c331e7cb028e70432ce0890f78d40671f13d5feccc4ab264ae903affaa951897128d598ed8e8542294aa03abb0a2a7ec970ab874387b8777827c4847bb29ff93d0427c1fcc581407465611e4400bfeab39de4c4f65572365156421503706d66138317e514214db27303ad8b5b17eb443e959faad1ccb3d3def5f3843b241dd9a60378cd907a02cc5c6e8527715c7734079cf9143586ed471587690816133fa8f09b8421f2de6ff1f5cecc134ac404e53a367b57fd4f3c85fe7e121e7094fbf93c06d427cec30cd519ee43a6018a8bb8717c05d7660b379101a182bfd3018d485d5b46e81d39445ccd4d8baefdd7590e664f2289f11bbad3d35ea6d70e157aaa7f9e91a692794b85c5b86db33863151468d32792ecfdb2aec52784ded5aa431fa9a7337ddd9e95313a897fe5ca6ef3c7e0cf3d41f7f104506f8695f2ba307715022e5e98472d6ff24125004d14db2c7a4cc71ca39a9874bfb93b64dd54ef451097059bbdfa96aca6c6c01e1f000b8d35bdead1502874e5d80ac00a79593b6d7e2fbee406c2212b4abd7b7e9f0037518de232cd6559443f4e3f0f03c17cef616a74992f65754bb6699b08c0eb2ec59508086e496e070c6239a73f11a9d14a727b10188ca97ebf04851fa475ed1774836a94cfb6543c33888dfc250100e9992b0cca8bd27ae8552541f1b3d81546f15b740e4f07b41af864769fe17290eb7076c0c1f938ce56a45ead6deb6c89164f829543414a1b8cd2361c3d9b22cf85d4ad0d4221dcc87533506e32c1cfdc8240636b669f97f7c6e150ea3753fcb63a7b9eedb5615b257651e090b567a20fdc5c167ad58fa940985572db004db2b14709a6663c1fb79dc045e45cb7228f11eab4c60a48fffc702cd74dcf5aabded8355a5ae1a5e6325a3afff608e53af3aa944437139c438e6200c75bb27c8a8ce7ce9f9ec9723c4423e9e49c807b12484783ed79fc501b544f03e4b29bdf0c74eb055dbac9b78fe87a66efc819f9d2ea637dd478b920b7196232b970ed092050ba0621329aa2b3e26184176137a9c6283e4cc2c03c07e28d2da7b0485da51f131686f4dd6b23735c66316142f48781885c35c9940054a4b9187a20914bedd1c48e94af358994da5c6060dd224b0ba84ddd5e95f395fe941d464e2cccd857a180de756d32407540c3611b649c7a71cbf5a492bf5c8d4e112a743498ce83ea3e94bcaa6c00000000108d799f48baf472fc3004047005411dcdaa24bd4c3cdbef653940a1ea0a671bb8c23222a8502bfcbd0a335af016df330b1190e4b1efd420aa82c4414a7dfd7b1aa63aa7bd0269ec8ed0d24895a467b737fcc514488e7151df796764293639665547941eaaa7d83dfc9d42952583a821611921cba9e0276f9244f197e011b6c2d898255802c81c8792dd68d03cd8982ee6146c8734814e9640e0999312f97e898db60642ceca21700be9e698b5e577062148d1ac840e737f7bc4f18f9ffd13e656fca1517c96d0e0c607b67d7e75795f62131255b44c2178d896192348d5f053060fa21c855236401e853e435fbc71a428c8e126cd8393cb860193fd6304d9576e8a8ce7f6959739afa7d7ffaf86516afb061ade1eef603e8e5c66f002cacbef25546e84b59be707c547837f7b49471a59325ad58a4f189a525a3a354a4be5ffd3db34ce0585ec470f78f0ff6eb807989d5998e2fccc80bd651de654da3581b6c8a858b56c4df47c3041c50d74f0b3a3a5a325882cd356d0c46d6db74559cef934a1655c65a06daff218244f5f4e95b96794e45d371a03afee2c89768fe3d7bc134844f45440620a88d6ddb5d07b7f6c9b2adfbf5743c5c586520504febf14ee4b216f8186ee1bf9802ccebd4dac519bd337a554940a3873cd21ef32f3d4d4fdfd3eaabb172b5314490b3587a9ca2dc12637fa80dcd526859bb83d54f67dedeb173470e052beec9edba4b41444d31253accb3381237179a5381d437fc4d47c0a82f1c9da8c76ad3eee9417bf69acb8d530ac824e65d796b84bee40b14daa9e80c11e466f93233e1768ecc6c0237e71b901f1faa093bbd9e5324b2a160d02f09d4590392279a15c73edc4d1d7501ebad992fc8f1c9dce96c190879225dbbb09d20532f9dcbb845e3484c87cb8c3b06fe892b07bdc60926e3d4b5c9024acde5abed0a72686d546da535a2122cfd6d6488a491dc9612b90f3f6709835e83f59fd612c2259c3ac944fdae87ffd744176a92fbea1efd037565a39d5bc38991cfe6617135b43cd6c6484a3b228e10d3f8184227a7ee63121be20f099c4264461d52aecf4b8ee1a4d0ec41717f9a68e1394544cf3be0a3a171ece35c879b67afdaac49c12731e6dc5ccaa49fa72610901036a7f0752951077cd9f1d77eb6e4f12c16dab08e1a9655fda3ba0e80c34c767f40e61491f706ab9d1b50f48273ca4e37708d075909a3e2c4b173510114d8377b5300994f9a4f794db2781b98c2e9d0056fdbe87b249beb3e7301c86efe6b32242b4c7fabef280a1ca7bdd6abb38624cbebb01b6b75b07d0cd9090b2c296d0e330b9008788dd6f7e1af1dd63b02408f1a67b57be3316152270bf90c36e9f74322c9caba5adab3309e5bd7c44d3c2ac77329e167dafda7395e37313723fb550a6ab96729a9fa8f9e4a3e5957bffa3302617d48fd38196635309928c491ca974a112768de16043fc618001780b49a0bac2ea9fc2607ebd1f25b8ef65a6cab42d16c9184e23af496ac5cfab274d9557006d9c52bb56cd8c019ddf085f260a0582ef465c73f97fedc02271dda53eec20e6aa50503357ed1847f7d976899cb24e5dd42dd87ae48db3c9335b38957fc0f86a6ceee590b1cbee41fc6ace3189886bd86f9b082e66fb263f1a98dd8e564bff9ec412ae79e29fd519ac96e9c5b446b436b78a6ca555c496ca5c5e73c2c1c5837b13f7a953d57738440d4ed60efd4701bbbbcad79e1697b5724695f52dab8bce02e7f",
+			domain:        "play.google.com",
+			wantErr:       false,
+			needsMoreData: false,
+		},
+		{
+			name:          "QUIC Chromebook Handshake[5]; packet 1",
+			hexData:       "c200000001085b15f32cf8fb5a3f00404600f909e38ed514455146c4ab8e53dd225a775dab2a06eaf73c2ec6b36c95c40873910eaa7e424e1b1fcb15892cf9e37a0ad2a1b67e9e8c6ec0c3a99e3d8775afe1e0aac824704489c14d28b48268df096f2db0c040c0ffdfb1817c4e1dd32005e87a74104515069ccd1b12f6fa3f657891bca8f0d27f4bb42b23c8310897ac09241f511888ac2e431e3ba8d9114b3f8bb1470324c8a0815dd1589686d058d03fa2669ad7367dc8877abce4700ae999112eb7cba755b20b7db66918021a36a66c60ecaaeb3e0859e3f50d14c1f8c3f56966043f437bfc16098deeb02e2236cc42d2f2802f4082bec30afc347a75f78c5e7337c52502e8e8d945bb4d792ef69419e57ee4e8f3465de4d0a49955787dff0756f1bcd98268919c112ae5e87ec333d590988e111724627143bf5a0aa69c77ee322b1240a65718e0033c4b70c6a5dc2d3248aef71598d73effa0eb397b79279ce846d9c2556fca28595eb3b196f40f052f0127711abbbc334571b8de67f7d39bd9437f9196bfe0650c4972462473776eccae42418b16edd5f45414e1a5e13300ae6705a49ef68e1748e876ce04fe611c973f94fcbe18b0c1a0ae506ce6eac268021e9744899c33ffe44dabdf1ea5413c20ab1013326255ae6df2d6861a7e914001e231ce4065e0d89fb439afb928d660cea26f99eafe65c9f89c5639f3ba8ffdcdf7a777d7859ca948f123a5c4f1491e22803754373ab0f1b605ac09ca6018c6acca7f52aad786ce96d9ae28d09a77dd88d77f23e2e33475973a23dea914fb049662800cfbed416b61835bd3bc22dace817b3b271c816ccf9603de2209067def5b8747112c49659cf6c5281402bed38a4176c0331e0841592c503d342188ac97266866a102864f76b0ff2adf781e0af84ae725fb6db418545dbb70adde5d4ea6d87f8c9b64b579d4f969830056dc0007cdad648035ccdf2c24264905422dfc1a85ac7f519f475351e046a27268312d4ab6a66ea55be01226fd5dfce06f804cafe85ad997946db3d029ef28ebdd36103c8fc05b522c1d4debe034523595cef576c771f0848a221d76c63dd044ea61a3adcbe5d4f0ebcd0bb631f4db1d88a609a1c2a6cc3de29ccd8a40e8a770d806abdae300cc178a32b4ba979652d0b8849dff252571f0b09935744c5b33628a190ae2eb43543ed8dee8539fd464abfcd3cf826aa18c4e84cd11975c5e3bfd0827f7cd211a2084c8626ed4e32bb9877f4801dabe695132b835e335563cb2f4c3e9377cac57f7766a10620f1c57c9f485d66918613daf8b257035ec91481d0076899c45abdbec38b63745428dee481c1cba81b0ab6e7efd6b0c431e018b6503cb13d4df18dbbff195bad1063d59ca5066e0733d3f499109111d22304066e7656e755518ceb6d862095ae54e532fad82f6c21c0c4d776dfecc516b00fa59e117e79481d3fd386c9b0c4d6fa4ec295a5b5b67207c3db20a206e0e31dad2c8dafb38e35dde331730bea33af32893653763e82565689009265db76b3b142d60f302a9545d82900aa6a017643c5c60583aefae43066ea3908e299612b078d06f102280dce4429461a42d80acdb6279c7aa190f9a8f61b485ffa430cbef199e1732da3d9b96cfac7ecc3b4959b86260eba763abb74c249180f67997967e716c95788bb6c04f182f40b795a929370c7fc72f1785f94cd36e3ddaddc15c7adb226cc131abc1863352caceb541d3924094db9c8a1c21c21640",
+			domain:        "",
+			wantErr:       true,
+			needsMoreData: true,
+		},
+		{
+			name:          "QUIC Chromebook Handshake[5]; packet 1-2",
+			hexData:       "c200000001085b15f32cf8fb5a3f00404600f909e38ed514455146c4ab8e53dd225a775dab2a06eaf73c2ec6b36c95c40873910eaa7e424e1b1fcb15892cf9e37a0ad2a1b67e9e8c6ec0c3a99e3d8775afe1e0aac824704489c14d28b48268df096f2db0c040c0ffdfb1817c4e1dd32005e87a74104515069ccd1b12f6fa3f657891bca8f0d27f4bb42b23c8310897ac09241f511888ac2e431e3ba8d9114b3f8bb1470324c8a0815dd1589686d058d03fa2669ad7367dc8877abce4700ae999112eb7cba755b20b7db66918021a36a66c60ecaaeb3e0859e3f50d14c1f8c3f56966043f437bfc16098deeb02e2236cc42d2f2802f4082bec30afc347a75f78c5e7337c52502e8e8d945bb4d792ef69419e57ee4e8f3465de4d0a49955787dff0756f1bcd98268919c112ae5e87ec333d590988e111724627143bf5a0aa69c77ee322b1240a65718e0033c4b70c6a5dc2d3248aef71598d73effa0eb397b79279ce846d9c2556fca28595eb3b196f40f052f0127711abbbc334571b8de67f7d39bd9437f9196bfe0650c4972462473776eccae42418b16edd5f45414e1a5e13300ae6705a49ef68e1748e876ce04fe611c973f94fcbe18b0c1a0ae506ce6eac268021e9744899c33ffe44dabdf1ea5413c20ab1013326255ae6df2d6861a7e914001e231ce4065e0d89fb439afb928d660cea26f99eafe65c9f89c5639f3ba8ffdcdf7a777d7859ca948f123a5c4f1491e22803754373ab0f1b605ac09ca6018c6acca7f52aad786ce96d9ae28d09a77dd88d77f23e2e33475973a23dea914fb049662800cfbed416b61835bd3bc22dace817b3b271c816ccf9603de2209067def5b8747112c49659cf6c5281402bed38a4176c0331e0841592c503d342188ac97266866a102864f76b0ff2adf781e0af84ae725fb6db418545dbb70adde5d4ea6d87f8c9b64b579d4f969830056dc0007cdad648035ccdf2c24264905422dfc1a85ac7f519f475351e046a27268312d4ab6a66ea55be01226fd5dfce06f804cafe85ad997946db3d029ef28ebdd36103c8fc05b522c1d4debe034523595cef576c771f0848a221d76c63dd044ea61a3adcbe5d4f0ebcd0bb631f4db1d88a609a1c2a6cc3de29ccd8a40e8a770d806abdae300cc178a32b4ba979652d0b8849dff252571f0b09935744c5b33628a190ae2eb43543ed8dee8539fd464abfcd3cf826aa18c4e84cd11975c5e3bfd0827f7cd211a2084c8626ed4e32bb9877f4801dabe695132b835e335563cb2f4c3e9377cac57f7766a10620f1c57c9f485d66918613daf8b257035ec91481d0076899c45abdbec38b63745428dee481c1cba81b0ab6e7efd6b0c431e018b6503cb13d4df18dbbff195bad1063d59ca5066e0733d3f499109111d22304066e7656e755518ceb6d862095ae54e532fad82f6c21c0c4d776dfecc516b00fa59e117e79481d3fd386c9b0c4d6fa4ec295a5b5b67207c3db20a206e0e31dad2c8dafb38e35dde331730bea33af32893653763e82565689009265db76b3b142d60f302a9545d82900aa6a017643c5c60583aefae43066ea3908e299612b078d06f102280dce4429461a42d80acdb6279c7aa190f9a8f61b485ffa430cbef199e1732da3d9b96cfac7ecc3b4959b86260eba763abb74c249180f67997967e716c95788bb6c04f182f40b795a929370c7fc72f1785f94cd36e3ddaddc15c7adb226cc131abc1863352caceb541d3924094db9c8a1c21c21640c900000001085b15f32cf8fb5a3f00404600f909e38ed514455146c4ab8e53dd225a775dab2a06eaf73c2ec6b36c95c40873910eaa7e424e1b1fcb15892cf9e37a0ad2a1b67e9e8c6ec0c3a99e3d8775afe1e0aac8247044898c283466f3b200164ad9b30e17b425e07f6722df94b9a77dd555fbf25e5b0bae4fef254daf03f156b78afd967614c78208deaadef3552040c055487804c047604c5d6846e67d33e5fb5f743a81f688220d6f4c87091a860885af95d2db27e9c5dd2361f8196f5c1ade8fb37e159980547c38c6a6ddd0e055fbbd52bd7615615ffca15a0c144899d25f21156c53cb3922d2ccb83073e26074025a3c39f64a67dc02044ce0d630d9120041b2233bd26282bd2d7d1a81d486b64cab6dba7fb4375e200f53523f714a066b96769f9b1dc7c14353fc1faa51c0aeb99507ff3ae90ad6f4bfbc9b9ea00a87f8bf8e213a84a9efe2ce624e629261d93c83642df97fe146bdef478cc92bba387c9b524ac83cde55ad8f4a4d8fb3c09c8245a50ac16ebb67d651110a10ad1f7dc74ed32b9d644bc4b229c56942072aae5c311059165ef6839e7cfa0717c7032b667b8618527722fdc10a4c0ea900e9b414521b89ca83f253ea414a410a8b0b13da25c4b618f2ccd79e5d2a7579b4c431107d56ab8df16125bc25673181a6bd5abb09941515806fda32659e5281457d8c093314da0087169781b306f348d3994d84bdef936bb11355c41ce02c359174dc2a366509c130c96ddf5f156e0eb7912ac56611cf4f59ff3a8785034e81738a53ebc7fb60aaed709d78980d39822aae7e9a9d985aee6c11252a5e984ff1d167b9d4dc5d02ca8ba1167422dfc0f68b3b5902f3fd032204a5020b14a288ecd845816575fca7ef13c85765385e9964a9f0f6e2e5c4e600b190b275cd91ee8a38ecf73d35bad7371c15fdb73059afb3178786e76750845232ef787767c6985ea9b9ed9ff73430b7afb8e0b66aa210ab1943b606021bb8f50c55534e1014003d947533c1c0bd0c16dfaabf4914497583b818e643a2d8bc32d33a07133b4eecf8bcbd802dfaae894ebd473338e074af1b3672c6f03c55e6c3885848a4379cdb5873d9ff3015f9ddf8d954b3cb4eb9f56f2e8ccb519dcba72c5832146011068d3074520370fc8008b62f3fdd65978865df1a85e58fb62315dc617a3367e6c9564fbf74f5d5015932d435f3aaaaed37bc7d14d974c0e15d899c684f17db3b4790bdeba076624f4f45a0cc1c6c078a527695110842e837ded310f8c6ddf69a18e455f09130d4b4136ca6d02eee0f103b9923adefe8cb36b8fd554a27fa7300c4a6173835ca2c4d38cc11e3849ebbf73c475b7d0713caed6e70f55b34ccffe03978f231d5f92bc1e2da7ce589e2cc2cd76183394469fa537cb927db14a383dc589cf10819eb90dbdb7981cd1eeb3a284c9ce55ed859fbfbe73ca22328073b534bc81d319b5fdb97e66d532b5ffc19516b4c70ecb68f963b053a82915f3f74c8809f082bbc89d97dff9e8c82a65ed4be8e2975b82f0b7c73f34797c61db4ea8ee273116564288563a71747cf31568317363dffdff1d9e159b2f9bcd3fe5be96a9c50ac885493cc16234c58cdf471381664c1e3b54d147ea5c779c9c9b06d5c493231d9c03b50c6cba315a5ee766a6e8578105306e0911270d347e8ade2b354037f507e4993708191d32b51a79f023f4fccabb7d2ac262004745cc528b8a6dc1d8849e9d4a0152ab326b1eab8a505eef65076aca156f7b9",
+			domain:        "optimizationguide-pa.googleapis.com",
+			wantErr:       false,
+			needsMoreData: false,
+		},
+		{
+			name:          "QUIC Chromebook Handshake[6]; packet 1",
+			hexData:       "c500000001087e13dee82c592724000044d0a17c2a188dadf8c82a018cabf25d25211d9987189b2900ad36a8fa366990353230bc8d41ec5543e91e119a0fd35f72d320d670074d02f412a5418c9a3e25489db73b1f5e5ddb8fc8d6c51fd6a12dcade71e1fc8e89d2663e206185247847d218d695793a8a1054afd18d42a4feaa9bb5fae7651eab0bc5e9aa91539c311cbfd17f46d8894ac45eade657bd456ee87b4475f5e84a2c07571b082ecfdafd1a660075692ae22048d163067a60e06cf879eab20a464c6e44b242da94cc6b92e064ee6a52cb34c115056925d4615e51157da4e88f019ae144040827cf2cd2806b3f4018cde5f42e041ef55eab35fe65ff79dba1ddad5aba6221e93d4555510176463888666b1d1f53a2f3c71e8872b05717002717edd3a9c5c651be47a663ee877962623ee92310b2b1dbcd75ec2f31d9e2f0c87affe3ee083aaa0868c03c9b4e78660d8afa4e936f81dfcb2fc33dbc1ed3828195c8de3130a2757641652de23d270c8a25976546c46460d9635f499a650475a4288d1c62241f65ddd346e2bde3f4fb5fec76646f51d829b55e16a0975494c11101abb504f5398a761d59355a4843e14bfeced024239ca06717d27e932df5e050d7c54c9b3cc937f6b0731f0b1dc312b14cf4388bbc0c601abf8ca16ed7d9b597dd414156d75b486ac256f8989a072fe680961ac7446201aca359337ef0e58ffa2aa12bb3c9bd1a9f6237b5c37880cd450d8a95db7c1463c53ac4bca174f278be1a99fb75ded9fe282e0e44a03b51ad943cf8970e4ca7f8567d9a3883d07bc0ff6c11639ebc7614fa88496488cb2a49a158d0f008a6a03caf97d77c3d03a98c5a611b04f865d134e258f4094bd220e00bde789c3b3158e622d509073179c0725c7a14dde1cd76b4c6b61fc7ba87f05742f081a5c42dbe83445132b8ad1539ee36e221a9dc700ccab55e34688b082a1a8edc48335760f3d5fb7e92b548e7a09d11f15b97bda08ebb5ea355e274587720d7c1189e9ffbb00dba3c13da94d646e7742e3641d59aee50a5bd400cd992c5614325d8f1ff3529637c3f60adc1682fa6b5e26f3d52de73236680abde87ead74368e05c600a2fd291a592be00fba64eea78c9e1f5e55e61f691b3eb0ef17b7bd11f06427c89c4c930d18c0b28221a6c918322cae56397c7e2978bf253e7f2d987f4cbe66c44a96b45cddb9d5f6dae47bbc9e1f9dcbe6280e50c5dfc91efb469f408b28fed49c583800009dc8bfb4bc42174175df987a3be833582abd9aa09ba0425973de2ea9a4149a81ae1863e0c9f1b1075c26bf965dcbec2bea47ff6042495ed715b65fdd3266800994463c95960dfb6ceadfa07d58910d329fa7ef7a8f14da4a6d3b09faa5b17cbac8481ea46cbfcfb54f660929e268bcf2f86cd88a1b065dcc27f18110db9efb6fcf1eec62874ed3657b1d43419f39e785c510d239c021b7e97d258d789c90d39b434f1667495bd4f5dc5e0eb97df376d801cced0da3a85aab6ca12893d8622314b5d530f28ead33075891d0ee553d5bedcffb20fce9933ab5e117df816c96398f6a60c9e6f5b9182fd7d58869de01635b2c178ae7738beb81e318934ecd752393129fda6833718d6984d8e1a8d7bf52e9d93ad0902c0fbe3e66ae8305e43363d8996626646a684bebfb1809ac9823be750e84308ef573243b884d09ef294094ef256cfc13cb0fedb1e095ff71687c09a767bff308e562e1a6ce9964014a7afc8db2481d8d07486",
+			domain:        "",
+			wantErr:       true,
+			needsMoreData: true,
+		},
+		{
+			name:          "QUIC Chromebook Handshake[6]; packet 1-2",
+			hexData:       "c500000001087e13dee82c592724000044d0a17c2a188dadf8c82a018cabf25d25211d9987189b2900ad36a8fa366990353230bc8d41ec5543e91e119a0fd35f72d320d670074d02f412a5418c9a3e25489db73b1f5e5ddb8fc8d6c51fd6a12dcade71e1fc8e89d2663e206185247847d218d695793a8a1054afd18d42a4feaa9bb5fae7651eab0bc5e9aa91539c311cbfd17f46d8894ac45eade657bd456ee87b4475f5e84a2c07571b082ecfdafd1a660075692ae22048d163067a60e06cf879eab20a464c6e44b242da94cc6b92e064ee6a52cb34c115056925d4615e51157da4e88f019ae144040827cf2cd2806b3f4018cde5f42e041ef55eab35fe65ff79dba1ddad5aba6221e93d4555510176463888666b1d1f53a2f3c71e8872b05717002717edd3a9c5c651be47a663ee877962623ee92310b2b1dbcd75ec2f31d9e2f0c87affe3ee083aaa0868c03c9b4e78660d8afa4e936f81dfcb2fc33dbc1ed3828195c8de3130a2757641652de23d270c8a25976546c46460d9635f499a650475a4288d1c62241f65ddd346e2bde3f4fb5fec76646f51d829b55e16a0975494c11101abb504f5398a761d59355a4843e14bfeced024239ca06717d27e932df5e050d7c54c9b3cc937f6b0731f0b1dc312b14cf4388bbc0c601abf8ca16ed7d9b597dd414156d75b486ac256f8989a072fe680961ac7446201aca359337ef0e58ffa2aa12bb3c9bd1a9f6237b5c37880cd450d8a95db7c1463c53ac4bca174f278be1a99fb75ded9fe282e0e44a03b51ad943cf8970e4ca7f8567d9a3883d07bc0ff6c11639ebc7614fa88496488cb2a49a158d0f008a6a03caf97d77c3d03a98c5a611b04f865d134e258f4094bd220e00bde789c3b3158e622d509073179c0725c7a14dde1cd76b4c6b61fc7ba87f05742f081a5c42dbe83445132b8ad1539ee36e221a9dc700ccab55e34688b082a1a8edc48335760f3d5fb7e92b548e7a09d11f15b97bda08ebb5ea355e274587720d7c1189e9ffbb00dba3c13da94d646e7742e3641d59aee50a5bd400cd992c5614325d8f1ff3529637c3f60adc1682fa6b5e26f3d52de73236680abde87ead74368e05c600a2fd291a592be00fba64eea78c9e1f5e55e61f691b3eb0ef17b7bd11f06427c89c4c930d18c0b28221a6c918322cae56397c7e2978bf253e7f2d987f4cbe66c44a96b45cddb9d5f6dae47bbc9e1f9dcbe6280e50c5dfc91efb469f408b28fed49c583800009dc8bfb4bc42174175df987a3be833582abd9aa09ba0425973de2ea9a4149a81ae1863e0c9f1b1075c26bf965dcbec2bea47ff6042495ed715b65fdd3266800994463c95960dfb6ceadfa07d58910d329fa7ef7a8f14da4a6d3b09faa5b17cbac8481ea46cbfcfb54f660929e268bcf2f86cd88a1b065dcc27f18110db9efb6fcf1eec62874ed3657b1d43419f39e785c510d239c021b7e97d258d789c90d39b434f1667495bd4f5dc5e0eb97df376d801cced0da3a85aab6ca12893d8622314b5d530f28ead33075891d0ee553d5bedcffb20fce9933ab5e117df816c96398f6a60c9e6f5b9182fd7d58869de01635b2c178ae7738beb81e318934ecd752393129fda6833718d6984d8e1a8d7bf52e9d93ad0902c0fbe3e66ae8305e43363d8996626646a684bebfb1809ac9823be750e84308ef573243b884d09ef294094ef256cfc13cb0fedb1e095ff71687c09a767bff308e562e1a6ce9964014a7afc8db2481d8d07486cd00000001087e13dee82c592724000044d0b2c403d66eaa310a954540668e9edc4b17a321446ac931672ca3d9097b2854efdfa7a8f610be76592b56ef9154b9ab42f4dafc575a9b9572433fa2bba180194a32a72a92a42560ae840508317cf34015b1d7d88a633588ce4333cd12bec1f9d53fe905130eb136852d4f405ef66254a0807640fe415e6d667b9f5e2148826d5a6c36b3c44b822cfb7a1e76954610a522e1bc9703e155f8f1e0c705e411d09c5dec1183c61608174767408558da03290f5536682373a09c762deb829dfe3ee061ac9f509a2b3d20dbb77f262e9ba8a5ff50f895165742c90c4ff48eb0438d5ff8491700f97fbfced20e8e95ab9b67078ece6664527eb8a4e78944c07c6bc5c48776e141418c3b5a0e58d24114b7d65a83619525f5a10be53a55f6e3e65080cf42109aa2ec166fbb9079444ea6c809b5062227fed7cc81609a6d7ea471bc82cd0759a354aa896c7a8242c3d8c845aa52225bbaf7546a0de6510189cd2852f7b70a29687eee6a3a99a3a288f3c3672a72dba2843fcee320e18ea906adf1629cc7f8220b6be890a8d37f4093022717d8c6d76080d07798ba74e9cda1a4c26189c367a6d12da14621b93fbfd2d2365465350b5864e4981955750c6d4038b74644827cd60c8cad0d6a18869f99d61b214becedd8f71a476c2a1a0ea8fade7b15de6ee522b6b90d0cc4e6d40eb85d9b5097e2969e85eae6710285016ae47fbc858d63e13d882721aaef3cbe0a6e4c4910e8b3e465fa66a738d8979a444b4a4804baf5b4f9a5fc8438f4991c32d280c5d273d0a1e0d9eea30d003162cd313780a5b000f70fb7797e6111b354c3deac241cb816328b77d71584852966392cab9b1a3d64ead878a2cfac085452397ba17b5cddf96415c31846a80fa9a5a21fd5f9963324ad75505d4b5c70903ec3b5f91c3460d88a7d1c6b111a5206d11accac8a2115e1ce8e834b01f48e041dcd71585c6fcdd3a2e83ec2ff1a2b85e75134ec966afec023d375a2a8bcd54ef0c42d50e20c6cd9b9fdab63785e62c5a4ceb8451c560b647a6cd87698e56e0be4e2990337f45f1cb4c73f0dbf98da1158d75df6eb60ab7a61d836c7b7f3e5c809b850a5cc5369ddd4e455da5e88179e932311873d177febf6226a378c72324ea710e10ef74f6462e7dba25b7df336cb2947df749ad0b8455f3c5c9ba5c0c8eb1e665fe50451c928ce87cc81a0ae2102e7a4fc297392818db885943112fae3c4547ea48c89ef9cd44c2edba4856dbc72b956e4fc6a875bdac57b1cd2378ddb9322e5a1d1844977ff2a6e94d8a00f4ef0a7ef7949f0840c6cc781252830c70d37df9846a69eb95bc733ec420b7b3724572521496da27bba1fcb73c28eed1eefb094283ab01284ebd82004e0be9977f23fbf135b8162ac41a2bf9e1b941b05cb52c80279775070cf2f851bb0168235c97de47880d2d51f1d5ba8327af33f16f49d44326b0d08d20ca7880ff88a14d3201452d7fd452b24fc3b69b89c5149795bc4d0bf51b6ace2c9146048e5ca0259b4955a069a16d5a73e72248cec44b2ca542dcd326aca3ba53bd48368719f44d53eddbace11ff28c11c7fd90c38966752532d3f81325d1682839b2da3d69acc85275c71ef3b10c4d983cfb0cb464f554d9360b0d6ec8fd25b85824350866207eef9e2c66e43f5d08e86aa6186b36d9ece72f56e06ac8e51a1b53fab4cc496e69307e9810a9b5cf960f306ec54131dd8e917a5861ba92f6885e41993",
+			domain:        "lh3.google.com",
+			wantErr:       false,
+			needsMoreData: false,
+		},
+		{
+			name:          "QUIC Chromebook Handshake[7]; packet 1",
+			hexData:       "c9000000010852e6d0c4f5f177b700404600eae9a1449fd711efdca846f59b6c9975a2189c1430f740e0e0eb4d50be086b798a47e037ee6afe9785b45df6302cfb87d39b9c03d0712f11793adab33e74904249722c4a1544896cd650da62160bdb601194f82a98c06df2546b79b5bab9503eafdbfbcfd1128204b52c9c5dde4d661cb84f2e015b7de9e10109874176362b7f06d4b49d850f2dcc8485aacb82fed8017fe454a1c31cfb82d392d6894081fa3ab1e5f2b71df79bf5a52a68a90d4752cf441220acbb274e3473f65c1a6e4cea3295da23e4a07818d5ba80b0668638c6ecb0b3ee12ecb8bed4ca32e27f4eee7376010b3905b8f7055728b8b1eda2e2707338b86f9a6115a23b29a010769d9a0e19d2bd06b81a507c4775d7215030862a026f168664255912c321669a5eff84ded4fec82af394cee909110758e5ad4de945236001bc0627d8e88ead3c3a6790d7e50887ced96f8380a80b11477147abc24dc4963c1907a07fec13e3cd8d5bab83cabd7cf8bb66af4911dfcdaf0f13aade34865b0740bebe4b4a482f1e3105bb9c3e5fece975187fa4eae5cb8fc868376b8b8329f89e407618aa5265f8ce73437e9f2714d752dad78025a38eaca1ebd6617a9a8a0bdefa8b3d3daad006978ba85d17ce3269da06be92eec61e4c5c99712517f01588b0b7deb4d7a75cadd5643daebc731f4a7bfaf17e8f002721b054a5d6d6ca7a3430c9480daff6adfd0a5480968b4fe0ee616d2e1f2f01268dcda2ee523fa593a0c83cbfc051dd7d503d48b152eb53894f79d4f6d38f05af35b287d16df579575b755f36e87b6df082108fda812195d5f60d2ceb59a54f09bb270d660c1d923348c7fdad97dc081e749a393af83bbcdd3c290efa19bce1a0f68dab0061df9dbee778dffb7754db10cbcc354a4b66c614e29d216a3a45a38594d337f775cb88c940924734ad52f8856606147b14ae2cf2990e1c401d79d27e4d6723afa4047454580698b9108b952b78b6bfd31db3b376f0879b2a0d8949b8443ffb9f7eb84b8024c620680481944312e86d183735effadab2d9f144a72d170fb035ed230f1451c94cb3f39bc28929e7480b22bbf6c906070eda03884cdd7ada9b10b7af27315c3bde8b4a273d46d1f764669aca152120da3e0a4fcf1be84b4f3cdfefe235a16598022cc74ad8f32e78aa06eb74ef61cccfc82ed35bcb70f008368ccdc17a6f64a316fcc9f006f307fa7a1a50f28c343c4c93a39df73a0d0a6dfc6f8ab10e966f738bee331e5a29d91ed993fd2638f0ec9d0ce539552b0a312fb85ed5e9f392fbc76a6164298b9de2c47dcb21a895957e92bc1270dfef3f00f44cc42c5f5005132dd030f9aec804045731c6a3eed3776beebe9451488932a1172b979f371aa370308037e57513a8fc9dd03d63fc2e5f7dcd683de26e116ea11a1d3b5e61fb5bbddc98e4ccd20be9ee71c02cacc95cbb17dd404558f586d4f0334bd12fc0a584d29eef3b4c2ce3f87babc462b6d24ca10aa8f1eb1abbd29d11ce3f1c92426c4950e53ba6c914cb4bf0bb1b44b25452cafbf246b76ce17f829bef3178174fbac4f932e6ac18e579fbbf8790611187c6f01de70fa82a21e979c90eed3c7f7b7e416491a000b5f2216e54858fa61893391b115573b2b960a0f7dc1e2a703a6f38485589c9133b4509fb54b4a602cc7d3341298e8e5da88d5e06aad28738650c08d8c71239735375e5bca7ea91dd78d748d65af598192317fd69e03daeecc99b8b",
+			domain:        "",
+			wantErr:       true,
+			needsMoreData: true,
+		},
+		{
+			name:          "QUIC Chromebook Handshake[7]; packet 1-2",
+			hexData:       "c9000000010852e6d0c4f5f177b700404600eae9a1449fd711efdca846f59b6c9975a2189c1430f740e0e0eb4d50be086b798a47e037ee6afe9785b45df6302cfb87d39b9c03d0712f11793adab33e74904249722c4a1544896cd650da62160bdb601194f82a98c06df2546b79b5bab9503eafdbfbcfd1128204b52c9c5dde4d661cb84f2e015b7de9e10109874176362b7f06d4b49d850f2dcc8485aacb82fed8017fe454a1c31cfb82d392d6894081fa3ab1e5f2b71df79bf5a52a68a90d4752cf441220acbb274e3473f65c1a6e4cea3295da23e4a07818d5ba80b0668638c6ecb0b3ee12ecb8bed4ca32e27f4eee7376010b3905b8f7055728b8b1eda2e2707338b86f9a6115a23b29a010769d9a0e19d2bd06b81a507c4775d7215030862a026f168664255912c321669a5eff84ded4fec82af394cee909110758e5ad4de945236001bc0627d8e88ead3c3a6790d7e50887ced96f8380a80b11477147abc24dc4963c1907a07fec13e3cd8d5bab83cabd7cf8bb66af4911dfcdaf0f13aade34865b0740bebe4b4a482f1e3105bb9c3e5fece975187fa4eae5cb8fc868376b8b8329f89e407618aa5265f8ce73437e9f2714d752dad78025a38eaca1ebd6617a9a8a0bdefa8b3d3daad006978ba85d17ce3269da06be92eec61e4c5c99712517f01588b0b7deb4d7a75cadd5643daebc731f4a7bfaf17e8f002721b054a5d6d6ca7a3430c9480daff6adfd0a5480968b4fe0ee616d2e1f2f01268dcda2ee523fa593a0c83cbfc051dd7d503d48b152eb53894f79d4f6d38f05af35b287d16df579575b755f36e87b6df082108fda812195d5f60d2ceb59a54f09bb270d660c1d923348c7fdad97dc081e749a393af83bbcdd3c290efa19bce1a0f68dab0061df9dbee778dffb7754db10cbcc354a4b66c614e29d216a3a45a38594d337f775cb88c940924734ad52f8856606147b14ae2cf2990e1c401d79d27e4d6723afa4047454580698b9108b952b78b6bfd31db3b376f0879b2a0d8949b8443ffb9f7eb84b8024c620680481944312e86d183735effadab2d9f144a72d170fb035ed230f1451c94cb3f39bc28929e7480b22bbf6c906070eda03884cdd7ada9b10b7af27315c3bde8b4a273d46d1f764669aca152120da3e0a4fcf1be84b4f3cdfefe235a16598022cc74ad8f32e78aa06eb74ef61cccfc82ed35bcb70f008368ccdc17a6f64a316fcc9f006f307fa7a1a50f28c343c4c93a39df73a0d0a6dfc6f8ab10e966f738bee331e5a29d91ed993fd2638f0ec9d0ce539552b0a312fb85ed5e9f392fbc76a6164298b9de2c47dcb21a895957e92bc1270dfef3f00f44cc42c5f5005132dd030f9aec804045731c6a3eed3776beebe9451488932a1172b979f371aa370308037e57513a8fc9dd03d63fc2e5f7dcd683de26e116ea11a1d3b5e61fb5bbddc98e4ccd20be9ee71c02cacc95cbb17dd404558f586d4f0334bd12fc0a584d29eef3b4c2ce3f87babc462b6d24ca10aa8f1eb1abbd29d11ce3f1c92426c4950e53ba6c914cb4bf0bb1b44b25452cafbf246b76ce17f829bef3178174fbac4f932e6ac18e579fbbf8790611187c6f01de70fa82a21e979c90eed3c7f7b7e416491a000b5f2216e54858fa61893391b115573b2b960a0f7dc1e2a703a6f38485589c9133b4509fb54b4a602cc7d3341298e8e5da88d5e06aad28738650c08d8c71239735375e5bca7ea91dd78d748d65af598192317fd69e03daeecc99b8bc4000000010852e6d0c4f5f177b700404600eae9a1449fd711efdca846f59b6c9975a2189c1430f740e0e0eb4d50be086b798a47e037ee6afe9785b45df6302cfb87d39b9c03d0712f11793adab33e74904249722c4a1544898bcc839c7364f9518287bbf01c06e9fd67f74096cab78bc885ad264ca9151a48420ea11d5b9e3bc899cc0d663509c926bee5ef2a389a9945f5919677472b3245a2a68ab91654ba5f75026ae738a9e10b6b7439503961bedbfa2494099a9bba3b9595f70cacd8950abd5d3b8a85ac61e6482847e0ac71cbd63df462f4978afc7084ec5c9e65f3b57ad22f802d699c94f260212a61db6e6958ed60356bf991d3af9582cd1724a90f08e869ebd7f29fc3fb9e1198819a967096de1bdeea692fade6229b41c5efe6cdae313014db328e99bae1f323584a308f575b923a11185634b24c8cc1d608303c8ca5c1ae3d54b8b7ecb689d5e0e22323c5e47d8f9093080bcf1553f7fa238e156658ef50281f633f184e47992645c82ab9985b9b13f97f0bbd9db94285c131fff5870ea38691ade2e017ee6417a118a9b31f5b85ba2c76163f8668d90d448976d9d37238605d36b0b7e7abfb0e9c2866bb11b128bb70f003aeb77f439c6148d28719a4f336f4d622140faff82595233cff94906695e402b9115ba7b99f7d832f55d8de481af808ed9d48a493c3301d2b633cdcdc7a64acefaa9408b99a52768edeb9824cdb49257c6d3ea3f23763f70b74fc46252a97f7b3e173a93e81cca50fb12e8b0ea1083f9262e1607156296b5ff85e1531335441c90b442aa5dc616ed7b520bc040502280a0bdb011d6e9dac154587f033b3e9434cef567b724bf5203c315ef5e283028ec72ff33736499b8d326cd643e3a37d53e70b9a2384ac6037f488075eef8b2e507774d3d450ea4b1b65c1587eb2a60c6aad0ae20745a2c50f8acd8bc1e25740b4e7ab4b03a59731ccc487831b46ca0211264f4fd4a498e145aca0d7339663d29a7f32a14fc2b62a32f6354abf2d7de5ed9d7e0a1d6dbbfe14af25ca8c927dc8eeb2618f308eac81405552f1bafcaaede51f560fe5eb6aa78b8650ae97040b46469503c85994ebcf7ffa0222905657111325f861d380935c2a5b9ad26094e85b92327f79f66b4a2f8cd674344f931f0e056ba58a084a1026bc422b80ec11b17de1ca965e8ac9ede1464588303986ba8fabb395b55de5580131ae3bf61822e4e2817dacf765e034542e435c4e9ebc58f21cfa7901dfbcc2b2be98cc55fa6d9e0030e17a32abf84d551a74f7391dd204847c25ee6382f6374b8ecc5b29b598b9ba562e0a6f25ebb932570ae8ab7ef7d06e444fdf79845e88b3132ffb6e1f330e3424272da082486aba357bd254ef0738bb7f5c9db73d2a9ba0c9afeb34e09ff0e20bd44ba1a46ad3081db2f750d00b647756dec1bb41032e1aaf56f58d7046102aef6ae40517f9cbc148692401ad06ea4ff6ed3e5c8a0cff8f9466a3530a99cfb9b5a857a967675df0cfbe3b798fdc2d929fa4c86e3b3e3c45b75fa5db6c15953f25bcd025d7efc3172b2206a200128f6d8caca97154b2608511b35b0cba9a550d8f791552faed64036cfb8498dc60492207ab81c3f3edeafd9d3acf5bca2f2735117a273c70345d3b7e289b9948edda3d5ebb8adde7de2451fe2d942d92ab383dc9a9adb6fb9e8cbc0b73d852f176e0265a6107e6a59746e2f2e7203fd445e5fe278d02cd5dac1b7988e205c37bc5f35dc27572743810453b9b27e55c",
+			domain:        "",
+			wantErr:       true,
+			needsMoreData: true,
+		},
+		{
+			name:          "QUIC Chromebook Handshake[7]; packet 1-3",
+			hexData:       "c9000000010852e6d0c4f5f177b700404600eae9a1449fd711efdca846f59b6c9975a2189c1430f740e0e0eb4d50be086b798a47e037ee6afe9785b45df6302cfb87d39b9c03d0712f11793adab33e74904249722c4a1544896cd650da62160bdb601194f82a98c06df2546b79b5bab9503eafdbfbcfd1128204b52c9c5dde4d661cb84f2e015b7de9e10109874176362b7f06d4b49d850f2dcc8485aacb82fed8017fe454a1c31cfb82d392d6894081fa3ab1e5f2b71df79bf5a52a68a90d4752cf441220acbb274e3473f65c1a6e4cea3295da23e4a07818d5ba80b0668638c6ecb0b3ee12ecb8bed4ca32e27f4eee7376010b3905b8f7055728b8b1eda2e2707338b86f9a6115a23b29a010769d9a0e19d2bd06b81a507c4775d7215030862a026f168664255912c321669a5eff84ded4fec82af394cee909110758e5ad4de945236001bc0627d8e88ead3c3a6790d7e50887ced96f8380a80b11477147abc24dc4963c1907a07fec13e3cd8d5bab83cabd7cf8bb66af4911dfcdaf0f13aade34865b0740bebe4b4a482f1e3105bb9c3e5fece975187fa4eae5cb8fc868376b8b8329f89e407618aa5265f8ce73437e9f2714d752dad78025a38eaca1ebd6617a9a8a0bdefa8b3d3daad006978ba85d17ce3269da06be92eec61e4c5c99712517f01588b0b7deb4d7a75cadd5643daebc731f4a7bfaf17e8f002721b054a5d6d6ca7a3430c9480daff6adfd0a5480968b4fe0ee616d2e1f2f01268dcda2ee523fa593a0c83cbfc051dd7d503d48b152eb53894f79d4f6d38f05af35b287d16df579575b755f36e87b6df082108fda812195d5f60d2ceb59a54f09bb270d660c1d923348c7fdad97dc081e749a393af83bbcdd3c290efa19bce1a0f68dab0061df9dbee778dffb7754db10cbcc354a4b66c614e29d216a3a45a38594d337f775cb88c940924734ad52f8856606147b14ae2cf2990e1c401d79d27e4d6723afa4047454580698b9108b952b78b6bfd31db3b376f0879b2a0d8949b8443ffb9f7eb84b8024c620680481944312e86d183735effadab2d9f144a72d170fb035ed230f1451c94cb3f39bc28929e7480b22bbf6c906070eda03884cdd7ada9b10b7af27315c3bde8b4a273d46d1f764669aca152120da3e0a4fcf1be84b4f3cdfefe235a16598022cc74ad8f32e78aa06eb74ef61cccfc82ed35bcb70f008368ccdc17a6f64a316fcc9f006f307fa7a1a50f28c343c4c93a39df73a0d0a6dfc6f8ab10e966f738bee331e5a29d91ed993fd2638f0ec9d0ce539552b0a312fb85ed5e9f392fbc76a6164298b9de2c47dcb21a895957e92bc1270dfef3f00f44cc42c5f5005132dd030f9aec804045731c6a3eed3776beebe9451488932a1172b979f371aa370308037e57513a8fc9dd03d63fc2e5f7dcd683de26e116ea11a1d3b5e61fb5bbddc98e4ccd20be9ee71c02cacc95cbb17dd404558f586d4f0334bd12fc0a584d29eef3b4c2ce3f87babc462b6d24ca10aa8f1eb1abbd29d11ce3f1c92426c4950e53ba6c914cb4bf0bb1b44b25452cafbf246b76ce17f829bef3178174fbac4f932e6ac18e579fbbf8790611187c6f01de70fa82a21e979c90eed3c7f7b7e416491a000b5f2216e54858fa61893391b115573b2b960a0f7dc1e2a703a6f38485589c9133b4509fb54b4a602cc7d3341298e8e5da88d5e06aad28738650c08d8c71239735375e5bca7ea91dd78d748d65af598192317fd69e03daeecc99b8bc4000000010852e6d0c4f5f177b700404600eae9a1449fd711efdca846f59b6c9975a2189c1430f740e0e0eb4d50be086b798a47e037ee6afe9785b45df6302cfb87d39b9c03d0712f11793adab33e74904249722c4a1544898bcc839c7364f9518287bbf01c06e9fd67f74096cab78bc885ad264ca9151a48420ea11d5b9e3bc899cc0d663509c926bee5ef2a389a9945f5919677472b3245a2a68ab91654ba5f75026ae738a9e10b6b7439503961bedbfa2494099a9bba3b9595f70cacd8950abd5d3b8a85ac61e6482847e0ac71cbd63df462f4978afc7084ec5c9e65f3b57ad22f802d699c94f260212a61db6e6958ed60356bf991d3af9582cd1724a90f08e869ebd7f29fc3fb9e1198819a967096de1bdeea692fade6229b41c5efe6cdae313014db328e99bae1f323584a308f575b923a11185634b24c8cc1d608303c8ca5c1ae3d54b8b7ecb689d5e0e22323c5e47d8f9093080bcf1553f7fa238e156658ef50281f633f184e47992645c82ab9985b9b13f97f0bbd9db94285c131fff5870ea38691ade2e017ee6417a118a9b31f5b85ba2c76163f8668d90d448976d9d37238605d36b0b7e7abfb0e9c2866bb11b128bb70f003aeb77f439c6148d28719a4f336f4d622140faff82595233cff94906695e402b9115ba7b99f7d832f55d8de481af808ed9d48a493c3301d2b633cdcdc7a64acefaa9408b99a52768edeb9824cdb49257c6d3ea3f23763f70b74fc46252a97f7b3e173a93e81cca50fb12e8b0ea1083f9262e1607156296b5ff85e1531335441c90b442aa5dc616ed7b520bc040502280a0bdb011d6e9dac154587f033b3e9434cef567b724bf5203c315ef5e283028ec72ff33736499b8d326cd643e3a37d53e70b9a2384ac6037f488075eef8b2e507774d3d450ea4b1b65c1587eb2a60c6aad0ae20745a2c50f8acd8bc1e25740b4e7ab4b03a59731ccc487831b46ca0211264f4fd4a498e145aca0d7339663d29a7f32a14fc2b62a32f6354abf2d7de5ed9d7e0a1d6dbbfe14af25ca8c927dc8eeb2618f308eac81405552f1bafcaaede51f560fe5eb6aa78b8650ae97040b46469503c85994ebcf7ffa0222905657111325f861d380935c2a5b9ad26094e85b92327f79f66b4a2f8cd674344f931f0e056ba58a084a1026bc422b80ec11b17de1ca965e8ac9ede1464588303986ba8fabb395b55de5580131ae3bf61822e4e2817dacf765e034542e435c4e9ebc58f21cfa7901dfbcc2b2be98cc55fa6d9e0030e17a32abf84d551a74f7391dd204847c25ee6382f6374b8ecc5b29b598b9ba562e0a6f25ebb932570ae8ab7ef7d06e444fdf79845e88b3132ffb6e1f330e3424272da082486aba357bd254ef0738bb7f5c9db73d2a9ba0c9afeb34e09ff0e20bd44ba1a46ad3081db2f750d00b647756dec1bb41032e1aaf56f58d7046102aef6ae40517f9cbc148692401ad06ea4ff6ed3e5c8a0cff8f9466a3530a99cfb9b5a857a967675df0cfbe3b798fdc2d929fa4c86e3b3e3c45b75fa5db6c15953f25bcd025d7efc3172b2206a200128f6d8caca97154b2608511b35b0cba9a550d8f791552faed64036cfb8498dc60492207ab81c3f3edeafd9d3acf5bca2f2735117a273c70345d3b7e289b9948edda3d5ebb8adde7de2451fe2d942d92ab383dc9a9adb6fb9e8cbc0b73d852f176e0265a6107e6a59746e2f2e7203fd445e5fe278d02cd5dac1b7988e205c37bc5f35dc27572743810453b9b27e55cc5000000010852e6d0c4f5f177b700404600eae9a1449fd711efdca846f59b6c9975a2189c1430f740e0e0eb4d50be086b798a47e037ee6afe9785b45df6302cfb87d39b9c03d0712f11793adab33e74904249722c4a1544894fb2a6f735bea394066ea4ab5d3ef6f419c4bb099bcea8fd7e36d8ec14fae027d0c84ba8c38a5ea1e2e9ff24ec334dee8085d1fa9d88df2c5ce3dddd981f7b2a68011f2d4034f8e4c6f43e645fc71e19927aec56045f0ef72d9da1942dbe3e42248c2f695525c8d8fcf6dbc970c2eb5d607e07dce5c8c66d4de07de6b2c35bd3bfa12cd4e4fcd4cdda3e0b2ff7575d406db96502f1ec4d9b5748215fe2a4018c7dbdb5ead1ddfc06da5233ce359e4f3924f2af1b80c7af9d13437e0107f7e240e485458a3a656e31a543bc5a80f6a598dcbbd87ff9cb4ce6842abadb72d62ae03e6d12b7f43ac1805e408d738148fa3a5c34deae7378d7d7309a7e09f5bac848f4c031693fbe3382a2de66a9d007420512e24b8a78a9489b30794c7cc51dd751c1cdeb2870b7c4a9b9606547f843c1a16d9be986b2f3e3d2f73f89c8e15da9de3dfdf7a667ced977332c5c62fd83d3c9a5e9718643e716db8f1b6fb58904ca17c24c9a4a191ec42be4c405fb00e443429582ff712dfdbadf1bb7e2d2abb0cc14f39c13a3b7013c62fd99488f043a6aec3ed7998b943ee24905fc915e3144c54393fa67ff34fdce2e48bba044f13ee1cd9c4f59a1a41f7fb7bdd8daee73461234f7cce5d54b078c3ad2b0aa37850ed4bb24f4d310d4ce75ede546ed6e73c0ee495ff8ce4b7256e8f43949539bf9df6e8d0fbf066fb506020c5a72e5e8b686641b78b365474c65fe9d8dd41133e27326fe82744b45b6ad1170433f3746647a68b824e94a213cda4c02f78465acbccdccb5bad1c70806d5a5c98c94338f88bf980b05b72cb82a4fd5b2a8586a5e5c5f2760115df595091809cfd12829f09622b53ca1d3809060aa7ab5d1f3640b3c2792a55c58fc3e80ac5d7f39ab5774a80fa1fc70461d396fa70dad1f90598244ce4197cb3ea42dce4afd61ca8ef93c8bc254d347872db21edcc3857bcb8dbe627508aa4856bd7d46e512db071905b3db100f425ba9f7181f0cce005cee2a95ffc190ddc1939e7049e58791b0e186433b0409f5a49e4e3262690a5160f8267c9099afdc58182236833fe7f825dfca34b08801345c1592bbab4964b34d7efa6c9d92e0106ede9a10fbf2a1be32f61f914211c3caa8b4c14edec5f9c139ee14789fe7d6634ede9bf9789caa60f5bf30b092e65ff95d3b32cbdc3e5842e3b16b935d31a3a0963bb0fe60f41efb6590f24eaf5e84006b28b3c755203113237e43fa70a37a009f71da49ea3f8097914d6128ee2b18adac49b5111fd3d18db9fd61ef8a2202fac5cfce646ccbea7eaaa81df0f1b7243465de15a3900143f479852f0e40bfad434b96eea3941f527b0d31c3d8f43188b911140766b5d7146feb93bf4da1ec47023dcd8f89863e487ba25c3105a4e43c4ea90f479eb0f774f3aa044b817f7e69b5dd1b3954e7dcdb2a6c4d191d5b9178262449413310f3876dd93145716781cb077025deb37d23c35e6fdf867d5353d10303b9e60efa50e9ecd013cd3f5270fc0e117a19ffb63038c594190018bd9c1c18a799f548c08a3e6f768de0de344cff160689fed73aa7fc4edc26f77413145775745c25fc2c9da5b62e24eab9b21895cfcda6e6457ae9fdfa6c54b49b0d160dad0aa7f8cbd3820a3098",
+			domain:        "ogads-pa.clients6.google.com",
+			wantErr:       false,
+			needsMoreData: false,
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			pkt, err := hex.DecodeString(tt.hexData)
+			if err != nil {
+				t.Fatalf("failed to decode hex string: %v", err)
+			}
+			quicHdr, err := quic.SniffQUIC(pkt)
+			if (err != nil) != tt.wantErr {
+				t.Errorf("SniffQUIC() error = %v, wantErr %v", err, tt.wantErr)
+				return
+			}
+			if (errors.Is(err, protocol.ErrProtoNeedMoreData)) != tt.needsMoreData {
+				t.Errorf("SniffQUIC() error = %v, expectsNoClue %v", err, tt.needsMoreData)
+				return
+			}
+			if err == nil && quicHdr.Domain() != tt.domain {
+				t.Errorf("SniffQUIC() domain = %v, want %v", quicHdr.Domain(), tt.domain)
+			}
+		})
+	}
+}
+
+func TestSniffQUICPackets_2(t *testing.T) {
+	//2 packets
+	pkt, err := hex.DecodeString("ca0000000108d799f48baf472fc3004047005411dcdaa24bd4c3cdbef653940a1ea0a671bb8c23222a8502bfcbd0a335af016df330b1190e4b1efd420aa82c4414a7dfd7b1aa63aa7bd0269ec8ed0d24895a467b737fcc514488a8142241b81c4952fb32e9f123f3f8d1be9eecc1340d7fa747c6f4838810209d51ad453fcec084ffaa382f9fed010a0585f8ce73c36dc6c628df940f72fb5b8e3e06f4612128d3b8f87725770d81305489a3a23cd443fcc668fece0ec9a909c82cfdb66819ce031422c3edd49ea72b6216efb940b8c186e2510b0f93d4cf3b6434ed9f5817c5a5a19fa861d24883bd48ba296df81e887fcb9ef18013ab1070df268049f3d35e8ddfffd2b100e4eb687176a02e7975085caa138e9df7cb6f9862356faafba3300f586df09af3b4e3eec15b6d1f14b34fe4eeb8e762ff482f3b7b0595c16d3eb20cf9c892b3f7c6449e51ffa33f3dc877d32e572e10ba4d5a320117110b150bec4a9434103de963aa2de1b22eaa992b59a8583c7a2d4e5743ef98a1b1f5f4aaeb2b49dbe441c331e7cb028e70432ce0890f78d40671f13d5feccc4ab264ae903affaa951897128d598ed8e8542294aa03abb0a2a7ec970ab874387b8777827c4847bb29ff93d0427c1fcc581407465611e4400bfeab39de4c4f65572365156421503706d66138317e514214db27303ad8b5b17eb443e959faad1ccb3d3def5f3843b241dd9a60378cd907a02cc5c6e8527715c7734079cf9143586ed471587690816133fa8f09b8421f2de6ff1f5cecc134ac404e53a367b57fd4f3c85fe7e121e7094fbf93c06d427cec30cd519ee43a6018a8bb8717c05d7660b379101a182bfd3018d485d5b46e81d39445ccd4d8baefdd7590e664f2289f11bbad3d35ea6d70e157aaa7f9e91a692794b85c5b86db33863151468d32792ecfdb2aec52784ded5aa431fa9a7337ddd9e95313a897fe5ca6ef3c7e0cf3d41f7f104506f8695f2ba307715022e5e98472d6ff24125004d14db2c7a4cc71ca39a9874bfb93b64dd54ef451097059bbdfa96aca6c6c01e1f000b8d35bdead1502874e5d80ac00a79593b6d7e2fbee406c2212b4abd7b7e9f0037518de232cd6559443f4e3f0f03c17cef616a74992f65754bb6699b08c0eb2ec59508086e496e070c6239a73f11a9d14a727b10188ca97ebf04851fa475ed1774836a94cfb6543c33888dfc250100e9992b0cca8bd27ae8552541f1b3d81546f15b740e4f07b41af864769fe17290eb7076c0c1f938ce56a45ead6deb6c89164f829543414a1b8cd2361c3d9b22cf85d4ad0d4221dcc87533506e32c1cfdc8240636b669f97f7c6e150ea3753fcb63a7b9eedb5615b257651e090b567a20fdc5c167ad58fa940985572db004db2b14709a6663c1fb79dc045e45cb7228f11eab4c60a48fffc702cd74dcf5aabded8355a5ae1a5e6325a3afff608e53af3aa944437139c438e6200c75bb27c8a8ce7ce9f9ec9723c4423e9e49c807b12484783ed79fc501b544f03e4b29bdf0c74eb055dbac9b78fe87a66efc819f9d2ea637dd478b920b7196232b970ed092050ba0621329aa2b3e26184176137a9c6283e4cc2c03c07e28d2da7b0485da51f131686f4dd6b23735c66316142f48781885c35c9940054a4b9187a20914bedd1c48e94af358994da5c6060dd224b0ba84ddd5e95f395fe941d464e2cccd857a180de756d32407540c3611b649c7a71cbf5a492bf5c8d4e112a743498ce83ea3e94bcaa6c00000000108d799f48baf472fc3004047005411dcdaa24bd4c3cdbef653940a1ea0a671bb8c23222a8502bfcbd0a335af016df330b1190e4b1efd420aa82c4414a7dfd7b1aa63aa7bd0269ec8ed0d24895a467b737fcc514488e7151df796764293639665547941eaaa7d83dfc9d42952583a821611921cba9e0276f9244f197e011b6c2d898255802c81c8792dd68d03cd8982ee6146c8734814e9640e0999312f97e898db60642ceca21700be9e698b5e577062148d1ac840e737f7bc4f18f9ffd13e656fca1517c96d0e0c607b67d7e75795f62131255b44c2178d896192348d5f053060fa21c855236401e853e435fbc71a428c8e126cd8393cb860193fd6304d9576e8a8ce7f6959739afa7d7ffaf86516afb061ade1eef603e8e5c66f002cacbef25546e84b59be707c547837f7b49471a59325ad58a4f189a525a3a354a4be5ffd3db34ce0585ec470f78f0ff6eb807989d5998e2fccc80bd651de654da3581b6c8a858b56c4df47c3041c50d74f0b3a3a5a325882cd356d0c46d6db74559cef934a1655c65a06daff218244f5f4e95b96794e45d371a03afee2c89768fe3d7bc134844f45440620a88d6ddb5d07b7f6c9b2adfbf5743c5c586520504febf14ee4b216f8186ee1bf9802ccebd4dac519bd337a554940a3873cd21ef32f3d4d4fdfd3eaabb172b5314490b3587a9ca2dc12637fa80dcd526859bb83d54f67dedeb173470e052beec9edba4b41444d31253accb3381237179a5381d437fc4d47c0a82f1c9da8c76ad3eee9417bf69acb8d530ac824e65d796b84bee40b14daa9e80c11e466f93233e1768ecc6c0237e71b901f1faa093bbd9e5324b2a160d02f09d4590392279a15c73edc4d1d7501ebad992fc8f1c9dce96c190879225dbbb09d20532f9dcbb845e3484c87cb8c3b06fe892b07bdc60926e3d4b5c9024acde5abed0a72686d546da535a2122cfd6d6488a491dc9612b90f3f6709835e83f59fd612c2259c3ac944fdae87ffd744176a92fbea1efd037565a39d5bc38991cfe6617135b43cd6c6484a3b228e10d3f8184227a7ee63121be20f099c4264461d52aecf4b8ee1a4d0ec41717f9a68e1394544cf3be0a3a171ece35c879b67afdaac49c12731e6dc5ccaa49fa72610901036a7f0752951077cd9f1d77eb6e4f12c16dab08e1a9655fda3ba0e80c34c767f40e61491f706ab9d1b50f48273ca4e37708d075909a3e2c4b173510114d8377b5300994f9a4f794db2781b98c2e9d0056fdbe87b249beb3e7301c86efe6b32242b4c7fabef280a1ca7bdd6abb38624cbebb01b6b75b07d0cd9090b2c296d0e330b9008788dd6f7e1af1dd63b02408f1a67b57be3316152270bf90c36e9f74322c9caba5adab3309e5bd7c44d3c2ac77329e167dafda7395e37313723fb550a6ab96729a9fa8f9e4a3e5957bffa3302617d48fd38196635309928c491ca974a112768de16043fc618001780b49a0bac2ea9fc2607ebd1f25b8ef65a6cab42d16c9184e23af496ac5cfab274d9557006d9c52bb56cd8c019ddf085f260a0582ef465c73f97fedc02271dda53eec20e6aa50503357ed1847f7d976899cb24e5dd42dd87ae48db3c9335b38957fc0f86a6ceee590b1cbee41fc6ace3189886bd86f9b082e66fb263f1a98dd8e564bff9ec412ae79e29fd519ac96e9c5b446b436b78a6ca555c496ca5c5e73c2c1c5837b13f7a953d57738440d4ed60efd4701bbbbcad79e1697b5724695f52dab8bce02e7f")
+	common.Must(err)
+	pkts := make([]byte, len(pkt))
+	copy(pkts, pkt)
+	quicHdr, err := quic.SniffQUIC(pkt)
+	if err != nil || quicHdr.Domain() != "play.google.com" {
+		t.Error("failed")
+		return
+	}
+	pkt1 := make([]byte, 1250)
+	copy(pkt1, pkts)
+	quicHdr, err = quic.SniffQUIC(pkt1)
+	if !errors.Is(err, protocol.ErrProtoNeedMoreData) {
path: common/protocol/quic/sniff_test.go
user: login: j2rong4cn
body: ~先别合并，同样的代码在v2ray 测试里直接得到了域名，我懵逼了~
~可能v2ray的有bug~
xray没有把buf放回pool所以这里一直都是获取到空的buf（因bug得福）
而v2ray可以把buf放回pool然后获取之前的buf（因没bug祸从天降）
created_at: 2025-04-23T10:26:31Z
author_association: CONTRIBUTOR
diff_hunk: @@ -61,8 +64,10 @@ func SniffQUIC(b []byte) (resultReturn *SniffHeader, errorReturn error) {
 
 	// Crypto data separated across packets
 	cryptoLen := 0
-	cryptoData := bytespool.Alloc(int32(len(b)))
-	defer bytespool.Free(cryptoData)
+	cryptoDataBuf := buf.NewWithSize(32767)
+	defer cryptoDataBuf.Release()
path: common/protocol/quic/sniff.go
user: login: j2rong4cn
body: ~xray这里没有把buf放回pool所以这里一直都是获取到空的buf（因bug得福）
而v2ray可以把buf放回pool然后获取之前的buf（因没bug祸从天降）
@RPRX 怎么整~

整好了
created_at: 2025-04-23T11:15:34Z
author_association: CONTRIBUTOR
diff_hunk: @@ -147,44 +141,34 @@ func SniffQUIC(b []byte) (resultReturn *SniffHeader, errorReturn error) {
 			return nil, err
 		}
 
-		cache := buf.New()
-		defer cache.Release()
-
+		cache.Clear()
 		mask := cache.Extend(int32(block.BlockSize()))
 		block.Encrypt(mask, b[hdrLen+4:hdrLen+4+16])
 		b[0] ^= mask[0] & 0xf
-		for i := range b[hdrLen : hdrLen+4] {
+		packetNumberLength := int(b[0]&0x3 + 1)
+		for i := range packetNumberLength {
 			b[hdrLen+i] ^= mask[i+1]
 		}
-		packetNumberLength := b[0]&0x3 + 1
-		if packetNumberLength != 1 {
-			return nil, errNotQuicInitial
-		}
-		var packetNumber uint32
-		{
-			n, err := buffer.ReadByte()
-			if err != nil {
-				return nil, err
-			}
-			packetNumber = uint32(n)
-		}
-
-		extHdrLen := hdrLen + int(packetNumberLength)
-		copy(b[extHdrLen:hdrLen+4], origPNBytes[packetNumberLength:])
-		data := b[extHdrLen : int(packetLen)+hdrLen]
 
 		key := hkdfExpandLabel(crypto.SHA256, secret, []byte{}, "quic key", 16)
 		iv := hkdfExpandLabel(crypto.SHA256, secret, []byte{}, "quic iv", 12)
 		cipher := AEADAESGCMTLS13(key, iv)
+
 		nonce := cache.Extend(int32(cipher.NonceSize()))
path: common/protocol/quic/sniff.go
user: login: j2rong4cn
body: @RPRX 这行下面需要添加这个
```
wipeBytes(nonce[:len(nonce)-packetNumberLength])
```
created_at: 2025-04-28T10:16:41Z
author_association: CONTRIBUTOR
diff_hunk: @@ -147,44 +141,34 @@ func SniffQUIC(b []byte) (resultReturn *SniffHeader, errorReturn error) {
 			return nil, err
 		}
 
-		cache := buf.New()
-		defer cache.Release()
-
+		cache.Clear()
 		mask := cache.Extend(int32(block.BlockSize()))
 		block.Encrypt(mask, b[hdrLen+4:hdrLen+4+16])
 		b[0] ^= mask[0] & 0xf
-		for i := range b[hdrLen : hdrLen+4] {
+		packetNumberLength := int(b[0]&0x3 + 1)
+		for i := range packetNumberLength {
 			b[hdrLen+i] ^= mask[i+1]
 		}
-		packetNumberLength := b[0]&0x3 + 1
-		if packetNumberLength != 1 {
-			return nil, errNotQuicInitial
-		}
-		var packetNumber uint32
-		{
-			n, err := buffer.ReadByte()
-			if err != nil {
-				return nil, err
-			}
-			packetNumber = uint32(n)
-		}
-
-		extHdrLen := hdrLen + int(packetNumberLength)
-		copy(b[extHdrLen:hdrLen+4], origPNBytes[packetNumberLength:])
-		data := b[extHdrLen : int(packetLen)+hdrLen]
 
 		key := hkdfExpandLabel(crypto.SHA256, secret, []byte{}, "quic key", 16)
 		iv := hkdfExpandLabel(crypto.SHA256, secret, []byte{}, "quic iv", 12)
 		cipher := AEADAESGCMTLS13(key, iv)
+
 		nonce := cache.Extend(int32(cipher.NonceSize()))
-		binary.BigEndian.PutUint64(nonce[len(nonce)-8:], uint64(packetNumber))
+		_, err = buffer.Read(nonce[len(nonce)-packetNumberLength:])
path: common/protocol/quic/sniff.go
user: login: j2rong4cn
body: @RPRX 因为这里把数据读取到nonce末尾
created_at: 2025-04-28T10:49:21Z
author_association: CONTRIBUTOR
diff_hunk: @@ -147,44 +141,34 @@ func SniffQUIC(b []byte) (resultReturn *SniffHeader, errorReturn error) {
 			return nil, err
 		}
 
-		cache := buf.New()
-		defer cache.Release()
-
+		cache.Clear()
 		mask := cache.Extend(int32(block.BlockSize()))
 		block.Encrypt(mask, b[hdrLen+4:hdrLen+4+16])
 		b[0] ^= mask[0] & 0xf
-		for i := range b[hdrLen : hdrLen+4] {
+		packetNumberLength := int(b[0]&0x3 + 1)
+		for i := range packetNumberLength {
 			b[hdrLen+i] ^= mask[i+1]
 		}
-		packetNumberLength := b[0]&0x3 + 1
-		if packetNumberLength != 1 {
-			return nil, errNotQuicInitial
-		}
-		var packetNumber uint32
-		{
-			n, err := buffer.ReadByte()
-			if err != nil {
-				return nil, err
-			}
-			packetNumber = uint32(n)
-		}
-
-		extHdrLen := hdrLen + int(packetNumberLength)
-		copy(b[extHdrLen:hdrLen+4], origPNBytes[packetNumberLength:])
-		data := b[extHdrLen : int(packetLen)+hdrLen]
 
 		key := hkdfExpandLabel(crypto.SHA256, secret, []byte{}, "quic key", 16)
 		iv := hkdfExpandLabel(crypto.SHA256, secret, []byte{}, "quic iv", 12)
 		cipher := AEADAESGCMTLS13(key, iv)
+
 		nonce := cache.Extend(int32(cipher.NonceSize()))
-		binary.BigEndian.PutUint64(nonce[len(nonce)-8:], uint64(packetNumber))
+		_, err = buffer.Read(nonce[len(nonce)-packetNumberLength:])
path: common/protocol/quic/sniff.go
user: login: j2rong4cn
body: 原本的代码就有这个潜在bug
created_at: 2025-04-28T10:50:51Z
author_association: CONTRIBUTOR
diff_hunk: @@ -147,44 +141,34 @@ func SniffQUIC(b []byte) (resultReturn *SniffHeader, errorReturn error) {
 			return nil, err
 		}
 
-		cache := buf.New()
-		defer cache.Release()
-
+		cache.Clear()
 		mask := cache.Extend(int32(block.BlockSize()))
 		block.Encrypt(mask, b[hdrLen+4:hdrLen+4+16])
 		b[0] ^= mask[0] & 0xf
-		for i := range b[hdrLen : hdrLen+4] {
+		packetNumberLength := int(b[0]&0x3 + 1)
+		for i := range packetNumberLength {
 			b[hdrLen+i] ^= mask[i+1]
 		}
-		packetNumberLength := b[0]&0x3 + 1
-		if packetNumberLength != 1 {
-			return nil, errNotQuicInitial
-		}
-		var packetNumber uint32
-		{
-			n, err := buffer.ReadByte()
-			if err != nil {
-				return nil, err
-			}
-			packetNumber = uint32(n)
-		}
-
-		extHdrLen := hdrLen + int(packetNumberLength)
-		copy(b[extHdrLen:hdrLen+4], origPNBytes[packetNumberLength:])
-		data := b[extHdrLen : int(packetLen)+hdrLen]
 
 		key := hkdfExpandLabel(crypto.SHA256, secret, []byte{}, "quic key", 16)
 		iv := hkdfExpandLabel(crypto.SHA256, secret, []byte{}, "quic iv", 12)
 		cipher := AEADAESGCMTLS13(key, iv)
+
 		nonce := cache.Extend(int32(cipher.NonceSize()))
-		binary.BigEndian.PutUint64(nonce[len(nonce)-8:], uint64(packetNumber))
+		_, err = buffer.Read(nonce[len(nonce)-packetNumberLength:])
path: common/protocol/quic/sniff.go
user: login: RPRX
body: 这个 buffer.Read 没问题吧，上面 cache.Extend 可能有问题
created_at: 2025-04-28T11:23:12Z
author_association: MEMBER

PR comments:
user: login: RPRX
created_at: 2025-04-23T02:52:53Z
body: 整个 QUIC sniffer 的代码都是从 v2fly 那边搬来的，你要搬就全搬了
author_association: MEMBER
user: login: j2rong4cn
created_at: 2025-04-23T02:55:44Z
body: > 整个 QUIC sniffer 的代码都是从 v2fly 那边搬来的，你要搬就全搬了

好
author_association: CONTRIBUTOR
user: login: ddatsh
created_at: 2025-04-23T03:09:07Z
body: 想提个问题请教啊，测试数据里那些hexData，有没办法是用代码来生成呀
author_association: CONTRIBUTOR
user: login: RPRX
created_at: 2025-04-23T03:13:05Z
body: > 想提个问题请教啊，测试数据里那些hexData，有没办法是用代码来生成呀

~~说实话我没看过~~
author_association: MEMBER
user: login: j2rong4cn
created_at: 2025-04-23T03:14:37Z
body: > 想提个问题请教啊，测试数据里那些hexData，有没办法是用代码来生成呀

我是在手机的xray加个出站到电脑端得到的
author_association: CONTRIBUTOR
user: login: RPRX
created_at: 2025-04-23T03:20:06Z
body: @j2rong4cn 你现在有空完善这个 PR 吗？我可以等等然后很快合并
author_association: MEMBER
user: login: j2rong4cn
created_at: 2025-04-23T03:31:59Z
body: > @j2rong4cn 你现在有空完善这个 PR 吗？我可以等等然后很快合并

现在身边没电脑
author_association: CONTRIBUTOR
user: login: Fangliding
created_at: 2025-04-23T03:56:24Z
body: > 想提个问题请教啊，测试数据里那些hexData，有没办法是用代码来生成呀

可以的 丢个fake conn给QUIC就行了 但是好像不是很有必要 加之奇奇怪怪的QUIC包主要来自chrome的chaos protection 要生成它们就有点麻烦了(
author_association: MEMBER
user: login: j2rong4cn
created_at: 2025-04-23T04:19:43Z
body: @RPRX 好了
author_association: CONTRIBUTOR
user: login: j2rong4cn
created_at: 2025-04-23T13:13:19Z
body: 应该没bug了
author_association: CONTRIBUTOR
user: login: Fangliding
created_at: 2025-04-23T13:43:06Z
body: 最好全部搬过来然后移除掉那个defer recover
author_association: MEMBER
user: login: j2rong4cn
created_at: 2025-04-23T13:46:16Z
body: > 最好全部搬过来然后移除掉那个defer recover

搬完了
author_association: CONTRIBUTOR
user: login: RPRX
created_at: 2025-04-28T08:55:01Z
body: 看了下修改后的 buffer.go，用标识 bytespools 取代 `if cap(p) == Size {` 是合理的，NewWithSize() Alloc 的也能正确 Free 了

潜在 bug 是 NewExisted() 会把 unmanaged 和 bytespools 转为 managed，然后在 Release() 中被 `pool.Put(p)`，以前有判断还好

但看了下 NewExisted() 只有 gRPC 传输层有两处调用，随便吧懒得再往上追了，gRPC 传输层都快成弃子了，~~交给众测~~
author_association: MEMBER
user: login: j2rong4cn
created_at: 2025-04-28T09:13:16Z
body: > 潜在 bug 是 NewExisted() 会把 unmanaged 和 bytespools 转为 managed，然后在 Release() 中被 `pool.Put(p)`，以前有判断还好

是直接从v2ray搬来的，没修改这个文件就没怎么看代码
author_association: CONTRIBUTOR
user: login: RPRX
created_at: 2025-04-28T09:16:16Z
body: @j2rong4cn 我不确定你这项新的修改合不合适，根据之前的代码，我感觉 NewExisted() 的本意可能就是复用 New() 的 buffer？不然和 FromBytes() 的区别就只剩确保了 capacity
author_association: MEMBER
user: login: RPRX
created_at: 2025-04-28T09:18:32Z
body: @j2rong4cn 此外 `if cap(p) == Size {` 这个判断应该没必要加回来了，能 New 的就那五个函数，我之前看了一遍逻辑没有冲突
author_association: MEMBER
user: login: j2rong4cn
created_at: 2025-04-28T09:20:30Z
body: > @j2rong4cn 我不确定你这项新的修改合不合适，根据之前的代码，我感觉 NewExisted() 的本意可能就是复用 New() 的 buffer？不然和 FromBytes() 的区别就只剩确保了 capacity

~buffer.New之后不都会buffer.Release，除非忘记了Release，应该没问题吧，我去看看代码~

感觉只加 if cap(p) == Size  判断最合适了
author_association: CONTRIBUTOR
user: login: RPRX
created_at: 2025-04-28T09:35:49Z
body: > 感觉只加 if cap(p) == Size 判断最合适了

这样也行，走原逻辑，~~至少 buffer.go 这种最重要的基础设施之一别改出啥问题~~

至于 QUIC sniffer 的部分我是没有看的，交给众测，以及我计划把针对 UDP/443 的默认 block 扩展至更大范围，还没定插哪合适

这个 PR 的 title 需要 rename 一下以匹配现在的 files changed，不用提及 buffer.go
author_association: MEMBER
user: login: j2rong4cn
created_at: 2025-04-28T09:39:15Z
body: > 这个 PR 的 title 需要 rename 一下以匹配现在的 files changed，不用提及 buffer.go

你改吧
author_association: CONTRIBUTOR
user: login: RPRX
created_at: 2025-04-28T09:40:00Z
body: ~~我没看 QUIC sniffer 的相关 changes 所以改不了，你改吧~~
author_association: MEMBER
user: login: j2rong4cn
created_at: 2025-04-28T09:41:42Z
body: > 至于 QUIC sniffer 的部分我是没有看的，交给众测

我在安卓设备上测试了几个chrome内核的主流浏览器都都可以识别了
author_association: CONTRIBUTOR
user: login: RPRX
created_at: 2025-04-28T10:03:21Z
body: 感谢 PR，以及 v2fly 的三位贡献者
author_association: MEMBER
user: login: j2rong4cn
created_at: 2025-04-28T10:11:41Z
body: > 感谢 PR，以及 v2fly 的三位贡献者

又发现潜在bug了😅emm
author_association: CONTRIBUTOR
user: login: RPRX
created_at: 2025-04-28T10:26:14Z
body: 其实之前我还是简单对比了一下的，我发现 v2fly 的代码没有你这里加的 wipeBytes()，看到你是在 "perf" 那个 commit 加的就没有说什么，而且你给 v2fly 那边也提了一个 PR，所以与它的 main 代码不一致也正常？所以就没提出

你再看看代码，可以开个 PR 修 bug，~~如果没把握的话就改成和 v2fly 的 main 保持一致吧~~
author_association: MEMBER
user: login: j2rong4cn
created_at: 2025-04-28T10:29:48Z
body: > 其实之前我还是简单对比了一下的，我发现 v2fly 的代码没有你这里加的 wipeBytes()，看到你是在 "perf" 那个 commit 加的就没有说什么，而且你给 v2fly 那边也提了一个 PR，所以与它的 main 代码不一致也正常？所以就没提出
> 
> 你再看看代码，可以开个 PR 修 bug，~如果没把握的话就改成和 v2fly 的 main 保持一致吧~

是buffer.New()得到了有数据buf，导致数据错乱
author_association: CONTRIBUTOR
user: login: RPRX
created_at: 2025-04-28T10:41:05Z
body: > 是buffer.New()得到了有数据buf，导致数据错乱

按理来说 buf.New() 不是默认 length 0、capacity 8k 吗？为什么还会得到有数据的 buf
author_association: MEMBER
user: login: j2rong4cn
created_at: 2025-04-28T10:44:09Z
body: > > 是buffer.New()得到了有数据buf，导致数据错乱
> 
> 按理来说 buf.New() 不是默认 length 0、capacity 8k 吗？为什么还会得到有数据的 buf

因为buf是从pool里拿出来的，有时候会得到有数据的buf
author_association: CONTRIBUTOR
user: login: RPRX
created_at: 2025-04-28T10:45:51Z
body: > 因为buf是从pool里拿出来的，有时候会得到有数据的buf

只要 length 0，capacity 有数据也无所谓啊，~~难道 extend 加的是 length~~
author_association: MEMBER
user: login: RPRX
created_at: 2025-04-28T11:24:00Z
body: ~~我看了下 buf.Extend() 真就是只加 length，坏了~~
author_association: MEMBER