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