github.com/tumi8/quic-go@v0.37.4-tum/noninternal/wire/frame_parser.go (about)

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