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 }