diff --git a/analyzer/udp/internal/quic/payload.go b/analyzer/udp/internal/quic/payload.go index e31d4d6..9a2fa26 100644 --- a/analyzer/udp/internal/quic/payload.go +++ b/analyzer/udp/internal/quic/payload.go @@ -270,6 +270,11 @@ func extractCryptoFrames(r *bytes.Reader) ([]CryptoFrame, error) { return nil, err } default: + // Unknown/extension frame type: if we already collected CRYPTO + // frames, return them instead of failing hard. + if len(frames) > 0 { + return frames, nil + } return nil, fmt.Errorf("unsupported frame type: %d", typ) } } diff --git a/analyzer/udp/internal/quic/payload_test.go b/analyzer/udp/internal/quic/payload_test.go index e409c73..d44fb4f 100644 --- a/analyzer/udp/internal/quic/payload_test.go +++ b/analyzer/udp/internal/quic/payload_test.go @@ -37,3 +37,21 @@ func TestExtractCryptoFrames_UnsupportedFrame(t *testing.T) { t.Fatal("extractCryptoFrames() error = nil, want non-nil") } } + +func TestExtractCryptoFrames_UnknownAfterCrypto(t *testing.T) { + // CRYPTO(offset=0,"abc"), then unknown frame type 0x20. + payload := []byte{ + 0x06, 0x00, 0x03, 'a', 'b', 'c', + 0x20, + } + frames, err := extractCryptoFrames(bytes.NewReader(payload)) + if err != nil { + t.Fatalf("extractCryptoFrames() error = %v", err) + } + if len(frames) != 1 { + t.Fatalf("extractCryptoFrames() len = %d, want 1", len(frames)) + } + if frames[0].Offset != 0 || string(frames[0].Data) != "abc" { + t.Fatalf("frame0 = %+v, want offset=0 data=abc", frames[0]) + } +} diff --git a/analyzer/udp/quic.go b/analyzer/udp/quic.go index 15a8e1d..1e02313 100644 --- a/analyzer/udp/quic.go +++ b/analyzer/udp/quic.go @@ -59,6 +59,7 @@ func (s *quicStream) Feed(rev bool, data []byte) (u *analyzer.PropUpdate, done b s.invalidCount++ return nil, s.invalidCount >= quicInvalidCountThreshold } + s.invalidCount = 0 for _, f := range frs { s.mergeFrame(f.Offset, f.Data) } diff --git a/analyzer/udp/quic_test.go b/analyzer/udp/quic_test.go index bec384e..2421e3d 100644 --- a/analyzer/udp/quic_test.go +++ b/analyzer/udp/quic_test.go @@ -56,3 +56,13 @@ func TestQuicStreamParsing_ClientHello(t *testing.T) { t.Errorf("%d B parsed = %v, want %v", len(clientHello), got, want) } } + +func TestQuicStreamContiguousPayloadFromZero(t *testing.T) { + s := &quicStream{} + s.mergeFrame(3, []byte("de")) + s.mergeFrame(0, []byte("abc")) + got := s.contiguousPayloadFromZero() + if string(got) != "abcde" { + t.Fatalf("contiguousPayloadFromZero() = %q, want %q", string(got), "abcde") + } +}