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