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