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

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