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 }