1package wire 2 3import ( 4 "bytes" 5 "io" 6 7 "github.com/lucas-clemente/quic-go/internal/protocol" 8 "github.com/lucas-clemente/quic-go/quicvarint" 9) 10 11// A DatagramFrame is a DATAGRAM frame 12type DatagramFrame struct { 13 DataLenPresent bool 14 Data []byte 15} 16 17func parseDatagramFrame(r *bytes.Reader, _ protocol.VersionNumber) (*DatagramFrame, error) { 18 typeByte, err := r.ReadByte() 19 if err != nil { 20 return nil, err 21 } 22 23 f := &DatagramFrame{} 24 f.DataLenPresent = typeByte&0x1 > 0 25 26 var length uint64 27 if f.DataLenPresent { 28 var err error 29 len, err := quicvarint.Read(r) 30 if err != nil { 31 return nil, err 32 } 33 if len > uint64(r.Len()) { 34 return nil, io.EOF 35 } 36 length = len 37 } else { 38 length = uint64(r.Len()) 39 } 40 f.Data = make([]byte, length) 41 if _, err := io.ReadFull(r, f.Data); err != nil { 42 return nil, err 43 } 44 return f, nil 45} 46 47func (f *DatagramFrame) Write(b *bytes.Buffer, _ protocol.VersionNumber) error { 48 typeByte := uint8(0x30) 49 if f.DataLenPresent { 50 typeByte ^= 0x1 51 } 52 b.WriteByte(typeByte) 53 if f.DataLenPresent { 54 quicvarint.Write(b, uint64(len(f.Data))) 55 } 56 b.Write(f.Data) 57 return nil 58} 59 60// MaxDataLen returns the maximum data length 61func (f *DatagramFrame) MaxDataLen(maxSize protocol.ByteCount, version protocol.VersionNumber) protocol.ByteCount { 62 headerLen := protocol.ByteCount(1) 63 if f.DataLenPresent { 64 // pretend that the data size will be 1 bytes 65 // if it turns out that varint encoding the length will consume 2 bytes, we need to adjust the data length afterwards 66 headerLen++ 67 } 68 if headerLen > maxSize { 69 return 0 70 } 71 maxDataLen := maxSize - headerLen 72 if f.DataLenPresent && quicvarint.Len(uint64(maxDataLen)) != 1 { 73 maxDataLen-- 74 } 75 return maxDataLen 76} 77 78// Length of a written frame 79func (f *DatagramFrame) Length(_ protocol.VersionNumber) protocol.ByteCount { 80 length := 1 + protocol.ByteCount(len(f.Data)) 81 if f.DataLenPresent { 82 length += quicvarint.Len(uint64(len(f.Data))) 83 } 84 return length 85} 86