github.com/metacubex/quic-go@v0.44.1-0.20240520163451-20b689a59136/internal/wire/frame_parser.go (about)

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