1package wire 2 3import ( 4 "bytes" 5 6 "github.com/ooni/psiphon/oopsi/github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/quic/gquic-go/internal/protocol" 7 "github.com/ooni/psiphon/oopsi/github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/quic/gquic-go/internal/utils" 8) 9 10// A MaxDataFrame carries flow control information for the connection 11type MaxDataFrame struct { 12 ByteOffset protocol.ByteCount 13} 14 15// parseMaxDataFrame parses a MAX_DATA frame 16func parseMaxDataFrame(r *bytes.Reader, version protocol.VersionNumber) (*MaxDataFrame, error) { 17 // read the TypeByte 18 if _, err := r.ReadByte(); err != nil { 19 return nil, err 20 } 21 22 frame := &MaxDataFrame{} 23 byteOffset, err := utils.ReadVarInt(r) 24 if err != nil { 25 return nil, err 26 } 27 frame.ByteOffset = protocol.ByteCount(byteOffset) 28 return frame, nil 29} 30 31//Write writes a MAX_STREAM_DATA frame 32func (f *MaxDataFrame) Write(b *bytes.Buffer, version protocol.VersionNumber) error { 33 if !version.UsesIETFFrameFormat() { 34 // write a gQUIC WINDOW_UPDATE frame (with stream ID 0, which means connection-level there) 35 return (&windowUpdateFrame{ 36 StreamID: 0, 37 ByteOffset: f.ByteOffset, 38 }).Write(b, version) 39 } 40 b.WriteByte(0x4) 41 utils.WriteVarInt(b, uint64(f.ByteOffset)) 42 return nil 43} 44 45// Length of a written frame 46func (f *MaxDataFrame) Length(version protocol.VersionNumber) protocol.ByteCount { 47 if !version.UsesIETFFrameFormat() { // writing this frame would result in a gQUIC WINDOW_UPDATE being written, which is longer 48 return 1 + 4 + 8 49 } 50 return 1 + utils.VarIntLen(uint64(f.ByteOffset)) 51} 52