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