diff --git a/qlog/frame.go b/qlog/frame.go index 2f844975..4cfb6c89 100644 --- a/qlog/frame.go +++ b/qlog/frame.go @@ -130,8 +130,7 @@ func marshalCryptoFrame(enc *gojay.Encoder, f *logging.CryptoFrame) { func marshalNewTokenFrame(enc *gojay.Encoder, f *logging.NewTokenFrame) { enc.StringKey("frame_type", "new_token") - enc.IntKey("length", len(f.Token)) - enc.StringKey("token", fmt.Sprintf("%x", f.Token)) + enc.ObjectKey("token", &token{Raw: f.Token}) } func marshalStreamFrame(enc *gojay.Encoder, f *logging.StreamFrame) { diff --git a/qlog/frame_test.go b/qlog/frame_test.go index f2235e86..b773e137 100644 --- a/qlog/frame_test.go +++ b/qlog/frame_test.go @@ -149,8 +149,7 @@ var _ = Describe("Frames", func() { }, map[string]interface{}{ "frame_type": "new_token", - "length": 4, - "token": "deadbeef", + "token": map[string]interface{}{"data": "deadbeef"}, }, ) }) diff --git a/qlog/packet_header.go b/qlog/packet_header.go index da714f0f..e45c9af9 100644 --- a/qlog/packet_header.go +++ b/qlog/packet_header.go @@ -1,6 +1,8 @@ package qlog import ( + "fmt" + "github.com/lucas-clemente/quic-go/internal/protocol" "github.com/lucas-clemente/quic-go/internal/wire" "github.com/lucas-clemente/quic-go/logging" @@ -25,10 +27,22 @@ func getPacketTypeFromEncryptionLevel(encLevel protocol.EncryptionLevel) packetT return packetType(t) } +type token struct { + Raw []byte +} + +var _ gojay.MarshalerJSONObject = &token{} + +func (t token) IsNil() bool { return false } +func (t token) MarshalJSONObject(enc *gojay.Encoder) { + enc.StringKey("data", fmt.Sprintf("%x", t.Raw)) +} + // PacketHeader is a QUIC packet header. type packetHeader struct { PacketType logging.PacketType + KeyPhaseBit logging.KeyPhaseBit PacketNumber logging.PacketNumber PayloadLength logging.ByteCount // Size of the QUIC packet (QUIC header + payload). @@ -39,17 +53,21 @@ type packetHeader struct { SrcConnectionID logging.ConnectionID DestConnectionID logging.ConnectionID - KeyPhaseBit logging.KeyPhaseBit + Token *token } func transformHeader(hdr *wire.Header) *packetHeader { - return &packetHeader{ + h := &packetHeader{ PacketType: logging.PacketTypeFromHeader(hdr), PayloadLength: hdr.Length, SrcConnectionID: hdr.SrcConnectionID, DestConnectionID: hdr.DestConnectionID, Version: hdr.Version, } + if len(hdr.Token) > 0 { + h.Token = &token{Raw: hdr.Token} + } + return h } func transformExtendedHeader(hdr *wire.ExtendedHeader) *packetHeader { @@ -82,4 +100,7 @@ func (h packetHeader) MarshalJSONObject(enc *gojay.Encoder) { if h.KeyPhaseBit == logging.KeyPhaseZero || h.KeyPhaseBit == logging.KeyPhaseOne { enc.StringKey("key_phase_bit", h.KeyPhaseBit.String()) } + if h.Token != nil { + enc.ObjectKey("token", h.Token) + } } diff --git a/qlog/packet_header_test.go b/qlog/packet_header_test.go index 1227f0b8..68e81d58 100644 --- a/qlog/packet_header_test.go +++ b/qlog/packet_header_test.go @@ -69,6 +69,52 @@ var _ = Describe("Packet Header", func() { ) }) + It("marshals an Initial with a token", func() { + check( + &wire.ExtendedHeader{ + PacketNumber: 4242, + Header: wire.Header{ + IsLongHeader: true, + Type: protocol.PacketTypeInitial, + Length: 123, + Version: protocol.VersionNumber(0xdecafbad), + Token: []byte{0xde, 0xad, 0xbe, 0xef}, + }, + }, + map[string]interface{}{ + "packet_type": "initial", + "packet_number": 4242, + "payload_length": 123, + "dcil": 0, + "scil": 0, + "version": "decafbad", + "token": map[string]interface{}{"data": "deadbeef"}, + }, + ) + }) + + It("marshals a Retry packet", func() { + check( + &wire.ExtendedHeader{ + Header: wire.Header{ + IsLongHeader: true, + Type: protocol.PacketTypeRetry, + SrcConnectionID: protocol.ConnectionID{0x11, 0x22, 0x33, 0x44}, + Version: protocol.VersionNumber(0xdecafbad), + Token: []byte{0xde, 0xad, 0xbe, 0xef}, + }, + }, + map[string]interface{}{ + "packet_type": "retry", + "dcil": 0, + "scil": 4, + "scid": "11223344", + "token": map[string]interface{}{"data": "deadbeef"}, + "version": "decafbad", + }, + ) + }) + It("marshals a packet with packet number 0", func() { check( &wire.ExtendedHeader{ diff --git a/qlog/qlog_suite_test.go b/qlog/qlog_suite_test.go index 420b8a6c..73f4917e 100644 --- a/qlog/qlog_suite_test.go +++ b/qlog/qlog_suite_test.go @@ -33,12 +33,10 @@ func checkEncoding(data []byte, expected map[string]interface{}) { ExpectWithOffset(1, m).To(HaveLen(len(expected))) for key, value := range expected { switch v := value.(type) { - case string: + case bool, string, map[string]interface{}: ExpectWithOffset(1, m).To(HaveKeyWithValue(key, v)) case int: ExpectWithOffset(1, m).To(HaveKeyWithValue(key, float64(v))) - case bool: - ExpectWithOffset(1, m).To(HaveKeyWithValue(key, v)) case [][]float64: // used in the ACK frame ExpectWithOffset(1, m).To(HaveKey(key)) for i, l := range v { diff --git a/qlog/qlog_test.go b/qlog/qlog_test.go index 311ca1ce..671ec211 100644 --- a/qlog/qlog_test.go +++ b/qlog/qlog_test.go @@ -357,6 +357,7 @@ var _ = Describe("Tracing", func() { Type: protocol.PacketTypeInitial, DestConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8}, SrcConnectionID: protocol.ConnectionID{4, 3, 2, 1}, + Token: []byte{0xde, 0xad, 0xbe, 0xef}, Version: protocol.VersionTLS, }, PacketNumber: 1337, @@ -377,6 +378,9 @@ var _ = Describe("Tracing", func() { Expect(hdr).To(HaveKeyWithValue("packet_size", float64(789))) Expect(hdr).To(HaveKeyWithValue("packet_number", float64(1337))) Expect(hdr).To(HaveKeyWithValue("scid", "04030201")) + Expect(hdr).To(HaveKey("token")) + token := hdr["token"].(map[string]interface{}) + Expect(token).To(HaveKeyWithValue("data", "deadbeef")) Expect(ev).To(HaveKey("frames")) Expect(ev["frames"].([]interface{})).To(HaveLen(2)) }) @@ -388,6 +392,7 @@ var _ = Describe("Tracing", func() { Type: protocol.PacketTypeRetry, DestConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8}, SrcConnectionID: protocol.ConnectionID{4, 3, 2, 1}, + Token: []byte{0xde, 0xad, 0xbe, 0xef}, Version: protocol.VersionTLS, }, ) @@ -396,12 +401,15 @@ var _ = Describe("Tracing", func() { Expect(entry.Name).To(Equal("transport:packet_received")) ev := entry.Event Expect(ev).To(HaveKey("header")) - header := ev["header"] + header := ev["header"].(map[string]interface{}) Expect(header).To(HaveKeyWithValue("packet_type", "retry")) Expect(header).ToNot(HaveKey("packet_number")) Expect(header).To(HaveKey("version")) Expect(header).To(HaveKey("dcid")) Expect(header).To(HaveKey("scid")) + Expect(header).To(HaveKey("token")) + token := header["token"].(map[string]interface{}) + Expect(token).To(HaveKeyWithValue("data", "deadbeef")) Expect(ev).ToNot(HaveKey("frames")) }) diff --git a/qlog/types_test.go b/qlog/types_test.go index 276ff712..cd47d6f4 100644 --- a/qlog/types_test.go +++ b/qlog/types_test.go @@ -3,7 +3,7 @@ package qlog import ( "go/ast" "go/parser" - "go/token" + gotoken "go/token" "path" "runtime" "strconv" @@ -96,7 +96,7 @@ var _ = Describe("Types", func() { panic("Failed to get current frame") } filename := path.Join(path.Dir(thisfile), "../internal/qerr/error_codes.go") - fileAst, err := parser.ParseFile(token.NewFileSet(), filename, nil, 0) + fileAst, err := parser.ParseFile(gotoken.NewFileSet(), filename, nil, 0) Expect(err).NotTo(HaveOccurred()) constSpecs := fileAst.Decls[2].(*ast.GenDecl).Specs Expect(len(constSpecs)).To(BeNumerically(">", 4)) // at time of writing