github.com/danielpfeifer02/quic-go-prio-packs@v0.41.0-28/internal/wire/stream_frame.go (about)

     1  package wire
     2  
     3  import (
     4  	"bytes"
     5  	"errors"
     6  	"io"
     7  
     8  	"github.com/danielpfeifer02/quic-go-prio-packs/internal/protocol"
     9  	"github.com/danielpfeifer02/quic-go-prio-packs/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  }