github.com/daeuniverse/quic-go@v0.0.0-20240413031024-943f218e0810/internal/wire/datagram_frame.go (about) 1 package wire 2 3 import ( 4 "bytes" 5 "io" 6 7 "github.com/daeuniverse/quic-go/internal/protocol" 8 "github.com/daeuniverse/quic-go/quicvarint" 9 ) 10 11 // MaxDatagramSize is the maximum size of a DATAGRAM frame (RFC 9221). 12 // By setting it to a large value, we allow all datagrams that fit into a QUIC packet. 13 // The value is chosen such that it can still be encoded as a 2 byte varint. 14 // This is a var and not a const so it can be set in tests. 15 var MaxDatagramSize protocol.ByteCount = 1200 16 17 // A DatagramFrame is a DATAGRAM frame 18 type DatagramFrame struct { 19 DataLenPresent bool 20 Data []byte 21 } 22 23 func parseDatagramFrame(r *bytes.Reader, typ uint64, _ protocol.Version) (*DatagramFrame, error) { 24 f := &DatagramFrame{} 25 f.DataLenPresent = typ&0x1 > 0 26 27 var length uint64 28 if f.DataLenPresent { 29 var err error 30 len, err := quicvarint.Read(r) 31 if err != nil { 32 return nil, err 33 } 34 if len > uint64(r.Len()) { 35 return nil, io.EOF 36 } 37 length = len 38 } else { 39 length = uint64(r.Len()) 40 } 41 f.Data = make([]byte, length) 42 if _, err := io.ReadFull(r, f.Data); err != nil { 43 return nil, err 44 } 45 return f, nil 46 } 47 48 func (f *DatagramFrame) Append(b []byte, _ protocol.Version) ([]byte, error) { 49 typ := uint8(0x30) 50 if f.DataLenPresent { 51 typ ^= 0b1 52 } 53 b = append(b, typ) 54 if f.DataLenPresent { 55 b = quicvarint.Append(b, uint64(len(f.Data))) 56 } 57 b = append(b, f.Data...) 58 return b, nil 59 } 60 61 // MaxDataLen returns the maximum data length 62 func (f *DatagramFrame) MaxDataLen(maxSize protocol.ByteCount, version protocol.Version) protocol.ByteCount { 63 headerLen := protocol.ByteCount(1) 64 if f.DataLenPresent { 65 // pretend that the data size will be 1 bytes 66 // if it turns out that varint encoding the length will consume 2 bytes, we need to adjust the data length afterwards 67 headerLen++ 68 } 69 if headerLen > maxSize { 70 return 0 71 } 72 maxDataLen := maxSize - headerLen 73 if f.DataLenPresent && quicvarint.Len(uint64(maxDataLen)) != 1 { 74 maxDataLen-- 75 } 76 return maxDataLen 77 } 78 79 // Length of a written frame 80 func (f *DatagramFrame) Length(_ protocol.Version) protocol.ByteCount { 81 length := 1 + protocol.ByteCount(len(f.Data)) 82 if f.DataLenPresent { 83 length += quicvarint.Len(uint64(len(f.Data))) 84 } 85 return length 86 }