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 }