github.com/metacubex/quic-go@v0.44.1-0.20240520163451-20b689a59136/internal/wire/stream_frame.go (about) 1 package wire 2 3 import ( 4 "errors" 5 "io" 6 7 "github.com/metacubex/quic-go/internal/protocol" 8 "github.com/metacubex/quic-go/quicvarint" 9 ) 10 11 // A StreamFrame of QUIC 12 type StreamFrame struct { 13 StreamID protocol.StreamID 14 Offset protocol.ByteCount 15 Data []byte 16 Fin bool 17 DataLenPresent bool 18 19 fromPool bool 20 } 21 22 func parseStreamFrame(b []byte, typ uint64, _ protocol.Version) (*StreamFrame, int, error) { 23 startLen := len(b) 24 hasOffset := typ&0b100 > 0 25 fin := typ&0b1 > 0 26 hasDataLen := typ&0b10 > 0 27 28 streamID, l, err := quicvarint.Parse(b) 29 if err != nil { 30 return nil, 0, replaceUnexpectedEOF(err) 31 } 32 b = b[l:] 33 var offset uint64 34 if hasOffset { 35 offset, l, err = quicvarint.Parse(b) 36 if err != nil { 37 return nil, 0, replaceUnexpectedEOF(err) 38 } 39 b = b[l:] 40 } 41 42 var dataLen uint64 43 if hasDataLen { 44 var err error 45 var l int 46 dataLen, l, err = quicvarint.Parse(b) 47 if err != nil { 48 return nil, 0, replaceUnexpectedEOF(err) 49 } 50 b = b[l:] 51 if dataLen > uint64(len(b)) { 52 return nil, 0, io.EOF 53 } 54 } else { 55 // The rest of the packet is data 56 dataLen = uint64(len(b)) 57 } 58 59 var frame *StreamFrame 60 if dataLen < protocol.MinStreamFrameBufferSize { 61 frame = &StreamFrame{Data: make([]byte, dataLen)} 62 } else { 63 frame = GetStreamFrame() 64 // The STREAM frame can't be larger than the StreamFrame we obtained from the buffer, 65 // since those StreamFrames have a buffer length of the maximum packet size. 66 if dataLen > uint64(cap(frame.Data)) { 67 return nil, 0, io.EOF 68 } 69 frame.Data = frame.Data[:dataLen] 70 } 71 72 frame.StreamID = protocol.StreamID(streamID) 73 frame.Offset = protocol.ByteCount(offset) 74 frame.Fin = fin 75 frame.DataLenPresent = hasDataLen 76 77 if dataLen != 0 { 78 copy(frame.Data, b) 79 } 80 if frame.Offset+frame.DataLen() > protocol.MaxByteCount { 81 return nil, 0, errors.New("stream data overflows maximum offset") 82 } 83 return frame, startLen - len(b) + int(dataLen), nil 84 } 85 86 func (f *StreamFrame) Append(b []byte, _ protocol.Version) ([]byte, error) { 87 if len(f.Data) == 0 && !f.Fin { 88 return nil, errors.New("StreamFrame: attempting to write empty frame without FIN") 89 } 90 91 typ := byte(0x8) 92 if f.Fin { 93 typ ^= 0b1 94 } 95 hasOffset := f.Offset != 0 96 if f.DataLenPresent { 97 typ ^= 0b10 98 } 99 if hasOffset { 100 typ ^= 0b100 101 } 102 b = append(b, typ) 103 b = quicvarint.Append(b, uint64(f.StreamID)) 104 if hasOffset { 105 b = quicvarint.Append(b, uint64(f.Offset)) 106 } 107 if f.DataLenPresent { 108 b = quicvarint.Append(b, uint64(f.DataLen())) 109 } 110 b = append(b, f.Data...) 111 return b, nil 112 } 113 114 // Length returns the total length of the STREAM frame 115 func (f *StreamFrame) Length(protocol.Version) protocol.ByteCount { 116 length := 1 + quicvarint.Len(uint64(f.StreamID)) 117 if f.Offset != 0 { 118 length += quicvarint.Len(uint64(f.Offset)) 119 } 120 if f.DataLenPresent { 121 length += quicvarint.Len(uint64(f.DataLen())) 122 } 123 return protocol.ByteCount(length) + f.DataLen() 124 } 125 126 // DataLen gives the length of data in bytes 127 func (f *StreamFrame) DataLen() protocol.ByteCount { 128 return protocol.ByteCount(len(f.Data)) 129 } 130 131 // MaxDataLen returns the maximum data length 132 // If 0 is returned, writing will fail (a STREAM frame must contain at least 1 byte of data). 133 func (f *StreamFrame) MaxDataLen(maxSize protocol.ByteCount, _ protocol.Version) protocol.ByteCount { 134 headerLen := 1 + protocol.ByteCount(quicvarint.Len(uint64(f.StreamID))) 135 if f.Offset != 0 { 136 headerLen += protocol.ByteCount(quicvarint.Len(uint64(f.Offset))) 137 } 138 if f.DataLenPresent { 139 // Pretend that the data size will be 1 byte. 140 // If it turns out that varint encoding the length will consume 2 bytes, we need to adjust the data length afterward 141 headerLen++ 142 } 143 if headerLen > maxSize { 144 return 0 145 } 146 maxDataLen := maxSize - headerLen 147 if f.DataLenPresent && quicvarint.Len(uint64(maxDataLen)) != 1 { 148 maxDataLen-- 149 } 150 return maxDataLen 151 } 152 153 // MaybeSplitOffFrame splits a frame such that it is not bigger than n bytes. 154 // It returns if the frame was actually split. 155 // The frame might not be split if: 156 // * the size is large enough to fit the whole frame 157 // * the size is too small to fit even a 1-byte frame. In that case, the frame returned is nil. 158 func (f *StreamFrame) MaybeSplitOffFrame(maxSize protocol.ByteCount, version protocol.Version) (*StreamFrame, bool /* was splitting required */) { 159 if maxSize >= f.Length(version) { 160 return nil, false 161 } 162 163 n := f.MaxDataLen(maxSize, version) 164 if n == 0 { 165 return nil, true 166 } 167 168 new := GetStreamFrame() 169 new.StreamID = f.StreamID 170 new.Offset = f.Offset 171 new.Fin = false 172 new.DataLenPresent = f.DataLenPresent 173 174 // swap the data slices 175 new.Data, f.Data = f.Data, new.Data 176 new.fromPool, f.fromPool = f.fromPool, new.fromPool 177 178 f.Data = f.Data[:protocol.ByteCount(len(new.Data))-n] 179 copy(f.Data, new.Data[n:]) 180 new.Data = new.Data[:n] 181 f.Offset += n 182 183 return new, true 184 } 185 186 func (f *StreamFrame) PutBack() { 187 putStreamFrame(f) 188 }