github.com/quic-go/quic-go@v0.42.0/internal/wire/frame_parser.go (about)

     1  package wire
     2  
     3  import (
     4  	"bytes"
     5  	"errors"
     6  	"fmt"
     7  	"reflect"
     8  
     9  	"github.com/quic-go/quic-go/internal/protocol"
    10  	"github.com/quic-go/quic-go/internal/qerr"
    11  	"github.com/quic-go/quic-go/quicvarint"
    12  )
    13  
    14  const (
    15  	pingFrameType               = 0x1
    16  	ackFrameType                = 0x2
    17  	ackECNFrameType             = 0x3
    18  	resetStreamFrameType        = 0x4
    19  	stopSendingFrameType        = 0x5
    20  	cryptoFrameType             = 0x6
    21  	newTokenFrameType           = 0x7
    22  	maxDataFrameType            = 0x10
    23  	maxStreamDataFrameType      = 0x11
    24  	bidiMaxStreamsFrameType     = 0x12
    25  	uniMaxStreamsFrameType      = 0x13
    26  	dataBlockedFrameType        = 0x14
    27  	streamDataBlockedFrameType  = 0x15
    28  	bidiStreamBlockedFrameType  = 0x16
    29  	uniStreamBlockedFrameType   = 0x17
    30  	newConnectionIDFrameType    = 0x18
    31  	retireConnectionIDFrameType = 0x19
    32  	pathChallengeFrameType      = 0x1a
    33  	pathResponseFrameType       = 0x1b
    34  	connectionCloseFrameType    = 0x1c
    35  	applicationCloseFrameType   = 0x1d
    36  	handshakeDoneFrameType      = 0x1e
    37  )
    38  
    39  // The FrameParser parses QUIC frames, one by one.
    40  type FrameParser struct {
    41  	r bytes.Reader // cached bytes.Reader, so we don't have to repeatedly allocate them
    42  
    43  	ackDelayExponent  uint8
    44  	supportsDatagrams bool
    45  
    46  	// To avoid allocating when parsing, keep a single ACK frame struct.
    47  	// It is used over and over again.
    48  	ackFrame *AckFrame
    49  }
    50  
    51  // NewFrameParser creates a new frame parser.
    52  func NewFrameParser(supportsDatagrams bool) *FrameParser {
    53  	return &FrameParser{
    54  		r:                 *bytes.NewReader(nil),
    55  		supportsDatagrams: supportsDatagrams,
    56  		ackFrame:          &AckFrame{},
    57  	}
    58  }
    59  
    60  // ParseNext parses the next frame.
    61  // It skips PADDING frames.
    62  func (p *FrameParser) ParseNext(data []byte, encLevel protocol.EncryptionLevel, v protocol.Version) (int, Frame, error) {
    63  	startLen := len(data)
    64  	p.r.Reset(data)
    65  	frame, err := p.parseNext(&p.r, encLevel, v)
    66  	n := startLen - p.r.Len()
    67  	p.r.Reset(nil)
    68  	return n, frame, err
    69  }
    70  
    71  func (p *FrameParser) parseNext(r *bytes.Reader, encLevel protocol.EncryptionLevel, v protocol.Version) (Frame, error) {
    72  	for r.Len() != 0 {
    73  		typ, err := quicvarint.Read(r)
    74  		if err != nil {
    75  			return nil, &qerr.TransportError{
    76  				ErrorCode:    qerr.FrameEncodingError,
    77  				ErrorMessage: err.Error(),
    78  			}
    79  		}
    80  		if typ == 0x0 { // skip PADDING frames
    81  			continue
    82  		}
    83  
    84  		f, err := p.parseFrame(r, typ, encLevel, v)
    85  		if err != nil {
    86  			return nil, &qerr.TransportError{
    87  				FrameType:    typ,
    88  				ErrorCode:    qerr.FrameEncodingError,
    89  				ErrorMessage: err.Error(),
    90  			}
    91  		}
    92  		return f, nil
    93  	}
    94  	return nil, nil
    95  }
    96  
    97  func (p *FrameParser) parseFrame(r *bytes.Reader, typ uint64, encLevel protocol.EncryptionLevel, v protocol.Version) (Frame, error) {
    98  	var frame Frame
    99  	var err error
   100  	if typ&0xf8 == 0x8 {
   101  		frame, err = parseStreamFrame(r, typ, v)
   102  	} else {
   103  		switch typ {
   104  		case pingFrameType:
   105  			frame = &PingFrame{}
   106  		case ackFrameType, ackECNFrameType:
   107  			ackDelayExponent := p.ackDelayExponent
   108  			if encLevel != protocol.Encryption1RTT {
   109  				ackDelayExponent = protocol.DefaultAckDelayExponent
   110  			}
   111  			p.ackFrame.Reset()
   112  			err = parseAckFrame(p.ackFrame, r, typ, ackDelayExponent, v)
   113  			frame = p.ackFrame
   114  		case resetStreamFrameType:
   115  			frame, err = parseResetStreamFrame(r, v)
   116  		case stopSendingFrameType:
   117  			frame, err = parseStopSendingFrame(r, v)
   118  		case cryptoFrameType:
   119  			frame, err = parseCryptoFrame(r, v)
   120  		case newTokenFrameType:
   121  			frame, err = parseNewTokenFrame(r, v)
   122  		case maxDataFrameType:
   123  			frame, err = parseMaxDataFrame(r, v)
   124  		case maxStreamDataFrameType:
   125  			frame, err = parseMaxStreamDataFrame(r, v)
   126  		case bidiMaxStreamsFrameType, uniMaxStreamsFrameType:
   127  			frame, err = parseMaxStreamsFrame(r, typ, v)
   128  		case dataBlockedFrameType:
   129  			frame, err = parseDataBlockedFrame(r, v)
   130  		case streamDataBlockedFrameType:
   131  			frame, err = parseStreamDataBlockedFrame(r, v)
   132  		case bidiStreamBlockedFrameType, uniStreamBlockedFrameType:
   133  			frame, err = parseStreamsBlockedFrame(r, typ, v)
   134  		case newConnectionIDFrameType:
   135  			frame, err = parseNewConnectionIDFrame(r, v)
   136  		case retireConnectionIDFrameType:
   137  			frame, err = parseRetireConnectionIDFrame(r, v)
   138  		case pathChallengeFrameType:
   139  			frame, err = parsePathChallengeFrame(r, v)
   140  		case pathResponseFrameType:
   141  			frame, err = parsePathResponseFrame(r, v)
   142  		case connectionCloseFrameType, applicationCloseFrameType:
   143  			frame, err = parseConnectionCloseFrame(r, typ, v)
   144  		case handshakeDoneFrameType:
   145  			frame = &HandshakeDoneFrame{}
   146  		case 0x30, 0x31:
   147  			if p.supportsDatagrams {
   148  				frame, err = parseDatagramFrame(r, typ, v)
   149  				break
   150  			}
   151  			fallthrough
   152  		default:
   153  			err = errors.New("unknown frame type")
   154  		}
   155  	}
   156  	if err != nil {
   157  		return nil, err
   158  	}
   159  	if !p.isAllowedAtEncLevel(frame, encLevel) {
   160  		return nil, fmt.Errorf("%s not allowed at encryption level %s", reflect.TypeOf(frame).Elem().Name(), encLevel)
   161  	}
   162  	return frame, nil
   163  }
   164  
   165  func (p *FrameParser) isAllowedAtEncLevel(f Frame, encLevel protocol.EncryptionLevel) bool {
   166  	switch encLevel {
   167  	case protocol.EncryptionInitial, protocol.EncryptionHandshake:
   168  		switch f.(type) {
   169  		case *CryptoFrame, *AckFrame, *ConnectionCloseFrame, *PingFrame:
   170  			return true
   171  		default:
   172  			return false
   173  		}
   174  	case protocol.Encryption0RTT:
   175  		switch f.(type) {
   176  		case *CryptoFrame, *AckFrame, *ConnectionCloseFrame, *NewTokenFrame, *PathResponseFrame, *RetireConnectionIDFrame:
   177  			return false
   178  		default:
   179  			return true
   180  		}
   181  	case protocol.Encryption1RTT:
   182  		return true
   183  	default:
   184  		panic("unknown encryption level")
   185  	}
   186  }
   187  
   188  // SetAckDelayExponent sets the acknowledgment delay exponent (sent in the transport parameters).
   189  // This value is used to scale the ACK Delay field in the ACK frame.
   190  func (p *FrameParser) SetAckDelayExponent(exp uint8) {
   191  	p.ackDelayExponent = exp
   192  }