Files
quic-go/http3/qlog/frame.go
2025-11-14 04:04:40 +03:00

212 lines
5.7 KiB
Go

package qlog
import (
"git.geeks-team.ru/gr1ffon/quic-go"
"git.geeks-team.ru/gr1ffon/quic-go/qlogwriter/jsontext"
)
// Frame represents an HTTP/3 frame.
type Frame struct {
Frame any
}
func (f Frame) encode(enc *jsontext.Encoder) error {
switch frame := f.Frame.(type) {
case DataFrame:
return frame.encode(enc)
case HeadersFrame:
return frame.encode(enc)
case GoAwayFrame:
return frame.encode(enc)
case SettingsFrame:
return frame.encode(enc)
case PushPromiseFrame:
return frame.encode(enc)
case CancelPushFrame:
return frame.encode(enc)
case MaxPushIDFrame:
return frame.encode(enc)
case ReservedFrame:
return frame.encode(enc)
case UnknownFrame:
return frame.encode(enc)
}
// This shouldn't happen if the code is correctly logging frames.
// Write a null token to produce valid JSON.
return enc.WriteToken(jsontext.Null)
}
// A DataFrame is a DATA frame
type DataFrame struct{}
func (f *DataFrame) encode(enc *jsontext.Encoder) error {
h := encoderHelper{enc: enc}
h.WriteToken(jsontext.BeginObject)
h.WriteToken(jsontext.String("frame_type"))
h.WriteToken(jsontext.String("data"))
h.WriteToken(jsontext.EndObject)
return h.err
}
type HeaderField struct {
Name string
Value string
}
// A HeadersFrame is a HEADERS frame
type HeadersFrame struct {
HeaderFields []HeaderField
}
func (f *HeadersFrame) encode(enc *jsontext.Encoder) error {
h := encoderHelper{enc: enc}
h.WriteToken(jsontext.BeginObject)
h.WriteToken(jsontext.String("frame_type"))
h.WriteToken(jsontext.String("headers"))
if len(f.HeaderFields) > 0 {
h.WriteToken(jsontext.String("header_fields"))
h.WriteToken(jsontext.BeginArray)
for _, f := range f.HeaderFields {
h.WriteToken(jsontext.BeginObject)
h.WriteToken(jsontext.String("name"))
h.WriteToken(jsontext.String(f.Name))
h.WriteToken(jsontext.String("value"))
h.WriteToken(jsontext.String(f.Value))
h.WriteToken(jsontext.EndObject)
}
h.WriteToken(jsontext.EndArray)
}
h.WriteToken(jsontext.EndObject)
return h.err
}
// A GoAwayFrame is a GOAWAY frame
type GoAwayFrame struct {
StreamID quic.StreamID
}
func (f *GoAwayFrame) encode(enc *jsontext.Encoder) error {
h := encoderHelper{enc: enc}
h.WriteToken(jsontext.BeginObject)
h.WriteToken(jsontext.String("frame_type"))
h.WriteToken(jsontext.String("goaway"))
h.WriteToken(jsontext.String("id"))
h.WriteToken(jsontext.Uint(uint64(f.StreamID)))
h.WriteToken(jsontext.EndObject)
return h.err
}
type SettingsFrame struct {
Datagram *bool
ExtendedConnect *bool
Other map[uint64]uint64
}
func (f *SettingsFrame) encode(enc *jsontext.Encoder) error {
h := encoderHelper{enc: enc}
h.WriteToken(jsontext.BeginObject)
h.WriteToken(jsontext.String("frame_type"))
h.WriteToken(jsontext.String("settings"))
h.WriteToken(jsontext.String("settings"))
h.WriteToken(jsontext.BeginArray)
if f.Datagram != nil {
h.WriteToken(jsontext.BeginObject)
h.WriteToken(jsontext.String("name"))
h.WriteToken(jsontext.String("settings_h3_datagram"))
h.WriteToken(jsontext.String("value"))
h.WriteToken(jsontext.Bool(*f.Datagram))
h.WriteToken(jsontext.EndObject)
}
if f.ExtendedConnect != nil {
h.WriteToken(jsontext.BeginObject)
h.WriteToken(jsontext.String("name"))
h.WriteToken(jsontext.String("settings_enable_connect_protocol"))
h.WriteToken(jsontext.String("value"))
h.WriteToken(jsontext.Bool(*f.ExtendedConnect))
h.WriteToken(jsontext.EndObject)
}
if len(f.Other) > 0 {
for k, v := range f.Other {
h.WriteToken(jsontext.BeginObject)
h.WriteToken(jsontext.String("name"))
h.WriteToken(jsontext.String("unknown"))
h.WriteToken(jsontext.String("name_bytes"))
h.WriteToken(jsontext.Uint(k))
h.WriteToken(jsontext.String("value"))
h.WriteToken(jsontext.Uint(v))
h.WriteToken(jsontext.EndObject)
}
}
h.WriteToken(jsontext.EndArray)
h.WriteToken(jsontext.EndObject)
return h.err
}
// A PushPromiseFrame is a PUSH_PROMISE frame
type PushPromiseFrame struct{}
func (f *PushPromiseFrame) encode(enc *jsontext.Encoder) error {
h := encoderHelper{enc: enc}
h.WriteToken(jsontext.BeginObject)
h.WriteToken(jsontext.String("frame_type"))
h.WriteToken(jsontext.String("push_promise"))
h.WriteToken(jsontext.EndObject)
return h.err
}
// A CancelPushFrame is a CANCEL_PUSH frame
type CancelPushFrame struct{}
func (f *CancelPushFrame) encode(enc *jsontext.Encoder) error {
h := encoderHelper{enc: enc}
h.WriteToken(jsontext.BeginObject)
h.WriteToken(jsontext.String("frame_type"))
h.WriteToken(jsontext.String("cancel_push"))
h.WriteToken(jsontext.EndObject)
return h.err
}
// A MaxPushIDFrame is a MAX_PUSH_ID frame
type MaxPushIDFrame struct{}
func (f *MaxPushIDFrame) encode(enc *jsontext.Encoder) error {
h := encoderHelper{enc: enc}
h.WriteToken(jsontext.BeginObject)
h.WriteToken(jsontext.String("frame_type"))
h.WriteToken(jsontext.String("max_push_id"))
h.WriteToken(jsontext.EndObject)
return h.err
}
// A ReservedFrame is one of the reserved frame types
type ReservedFrame struct {
Type uint64
}
func (f *ReservedFrame) encode(enc *jsontext.Encoder) error {
h := encoderHelper{enc: enc}
h.WriteToken(jsontext.BeginObject)
h.WriteToken(jsontext.String("frame_type"))
h.WriteToken(jsontext.String("reserved"))
h.WriteToken(jsontext.String("frame_type_bytes"))
h.WriteToken(jsontext.Uint(f.Type))
h.WriteToken(jsontext.EndObject)
return h.err
}
// An UnknownFrame is an unknown frame type
type UnknownFrame struct {
Type uint64
}
func (f *UnknownFrame) encode(enc *jsontext.Encoder) error {
h := encoderHelper{enc: enc}
h.WriteToken(jsontext.BeginObject)
h.WriteToken(jsontext.String("frame_type"))
h.WriteToken(jsontext.String("unknown"))
h.WriteToken(jsontext.String("frame_type_bytes"))
h.WriteToken(jsontext.Uint(f.Type))
h.WriteToken(jsontext.EndObject)
return h.err
}