github.com/sagernet/quic-go@v0.43.1-beta.1/internal/wire/frame_parser.go (about) 1 package wire 2 3 import ( 4 "bytes" 5 "errors" 6 "fmt" 7 "reflect" 8 9 "github.com/sagernet/quic-go/internal/protocol" 10 "github.com/sagernet/quic-go/internal/qerr" 11 "github.com/sagernet/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 }