| OLD | NEW |
| (Empty) |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "net/http2/decoder/http2_frame_decoder.h" | |
| 6 | |
| 7 #include "net/http2/http2_constants.h" | |
| 8 | |
| 9 namespace net { | |
| 10 | |
| 11 std::ostream& operator<<(std::ostream& out, Http2FrameDecoder::State v) { | |
| 12 switch (v) { | |
| 13 case Http2FrameDecoder::State::kStartDecodingHeader: | |
| 14 return out << "kStartDecodingHeader"; | |
| 15 case Http2FrameDecoder::State::kResumeDecodingHeader: | |
| 16 return out << "kResumeDecodingHeader"; | |
| 17 case Http2FrameDecoder::State::kResumeDecodingPayload: | |
| 18 return out << "kResumeDecodingPayload"; | |
| 19 case Http2FrameDecoder::State::kDiscardPayload: | |
| 20 return out << "kDiscardPayload"; | |
| 21 } | |
| 22 return out << static_cast<int>(v); | |
| 23 } | |
| 24 | |
| 25 Http2FrameDecoder::Http2FrameDecoder(Http2FrameDecoderListener* listener) | |
| 26 : state_(State::kStartDecodingHeader), | |
| 27 maximum_payload_size_(Http2SettingsInfo::DefaultMaxFrameSize()) { | |
| 28 set_listener(listener); | |
| 29 } | |
| 30 | |
| 31 void Http2FrameDecoder::set_listener(Http2FrameDecoderListener* listener) { | |
| 32 if (listener == nullptr) { | |
| 33 listener = &no_op_listener_; | |
| 34 } | |
| 35 frame_decoder_state_.set_listener(listener); | |
| 36 } | |
| 37 | |
| 38 Http2FrameDecoderListener* Http2FrameDecoder::listener() const { | |
| 39 return frame_decoder_state_.listener(); | |
| 40 } | |
| 41 | |
| 42 DecodeStatus Http2FrameDecoder::DecodeFrame(DecodeBuffer* db) { | |
| 43 DVLOG(2) << "Http2FrameDecoder::DecodeFrame state=" << state_; | |
| 44 switch (state_) { | |
| 45 case State::kStartDecodingHeader: | |
| 46 if (frame_decoder_state_.StartDecodingFrameHeader(db)) { | |
| 47 return StartDecodingPayload(db); | |
| 48 } | |
| 49 state_ = State::kResumeDecodingHeader; | |
| 50 return DecodeStatus::kDecodeInProgress; | |
| 51 | |
| 52 case State::kResumeDecodingHeader: | |
| 53 if (frame_decoder_state_.ResumeDecodingFrameHeader(db)) { | |
| 54 return StartDecodingPayload(db); | |
| 55 } | |
| 56 return DecodeStatus::kDecodeInProgress; | |
| 57 | |
| 58 case State::kResumeDecodingPayload: | |
| 59 return ResumeDecodingPayload(db); | |
| 60 | |
| 61 case State::kDiscardPayload: | |
| 62 return DiscardPayload(db); | |
| 63 } | |
| 64 | |
| 65 NOTREACHED(); | |
| 66 return DecodeStatus::kDecodeError; | |
| 67 } | |
| 68 | |
| 69 size_t Http2FrameDecoder::remaining_payload() const { | |
| 70 return frame_decoder_state_.remaining_payload(); | |
| 71 } | |
| 72 | |
| 73 uint32_t Http2FrameDecoder::remaining_padding() const { | |
| 74 return frame_decoder_state_.remaining_padding(); | |
| 75 } | |
| 76 | |
| 77 DecodeStatus Http2FrameDecoder::StartDecodingPayload(DecodeBuffer* db) { | |
| 78 const Http2FrameHeader& header = frame_header(); | |
| 79 | |
| 80 // TODO(jamessynge): Remove OnFrameHeader once done with supporting | |
| 81 // SpdyFramer's exact states. | |
| 82 if (!listener()->OnFrameHeader(header)) { | |
| 83 DVLOG(2) << "OnFrameHeader rejected the frame, will discard; header: " | |
| 84 << header; | |
| 85 state_ = State::kDiscardPayload; | |
| 86 frame_decoder_state_.InitializeRemainders(); | |
| 87 return DecodeStatus::kDecodeError; | |
| 88 } | |
| 89 | |
| 90 if (header.payload_length > maximum_payload_size_) { | |
| 91 DVLOG(2) << "Payload length is greater than allowed: " | |
| 92 << header.payload_length << " > " << maximum_payload_size_ | |
| 93 << "\n header: " << header; | |
| 94 state_ = State::kDiscardPayload; | |
| 95 frame_decoder_state_.InitializeRemainders(); | |
| 96 listener()->OnFrameSizeError(header); | |
| 97 return DecodeStatus::kDecodeError; | |
| 98 } | |
| 99 | |
| 100 // The decode buffer can extend across many frames. Make sure that the | |
| 101 // buffer we pass to the start method that is specific to the frame type | |
| 102 // does not exend beyond this frame. | |
| 103 DecodeBufferSubset subset(db, header.payload_length); | |
| 104 DecodeStatus status; | |
| 105 switch (header.type) { | |
| 106 case Http2FrameType::DATA: | |
| 107 status = StartDecodingDataPayload(&subset); | |
| 108 break; | |
| 109 | |
| 110 case Http2FrameType::HEADERS: | |
| 111 status = StartDecodingHeadersPayload(&subset); | |
| 112 break; | |
| 113 | |
| 114 case Http2FrameType::PRIORITY: | |
| 115 status = StartDecodingPriorityPayload(&subset); | |
| 116 break; | |
| 117 | |
| 118 case Http2FrameType::RST_STREAM: | |
| 119 status = StartDecodingRstStreamPayload(&subset); | |
| 120 break; | |
| 121 | |
| 122 case Http2FrameType::SETTINGS: | |
| 123 status = StartDecodingSettingsPayload(&subset); | |
| 124 break; | |
| 125 | |
| 126 case Http2FrameType::PUSH_PROMISE: | |
| 127 status = StartDecodingPushPromisePayload(&subset); | |
| 128 break; | |
| 129 | |
| 130 case Http2FrameType::PING: | |
| 131 status = StartDecodingPingPayload(&subset); | |
| 132 break; | |
| 133 | |
| 134 case Http2FrameType::GOAWAY: | |
| 135 status = StartDecodingGoAwayPayload(&subset); | |
| 136 break; | |
| 137 | |
| 138 case Http2FrameType::WINDOW_UPDATE: | |
| 139 status = StartDecodingWindowUpdatePayload(&subset); | |
| 140 break; | |
| 141 | |
| 142 case Http2FrameType::CONTINUATION: | |
| 143 status = StartDecodingContinuationPayload(&subset); | |
| 144 break; | |
| 145 | |
| 146 case Http2FrameType::ALTSVC: | |
| 147 status = StartDecodingAltSvcPayload(&subset); | |
| 148 break; | |
| 149 | |
| 150 default: | |
| 151 status = StartDecodingUnknownPayload(&subset); | |
| 152 break; | |
| 153 } | |
| 154 | |
| 155 if (status == DecodeStatus::kDecodeDone) { | |
| 156 state_ = State::kStartDecodingHeader; | |
| 157 return status; | |
| 158 } else if (status == DecodeStatus::kDecodeInProgress) { | |
| 159 state_ = State::kResumeDecodingPayload; | |
| 160 return status; | |
| 161 } else { | |
| 162 state_ = State::kDiscardPayload; | |
| 163 return status; | |
| 164 } | |
| 165 } | |
| 166 | |
| 167 DecodeStatus Http2FrameDecoder::ResumeDecodingPayload(DecodeBuffer* db) { | |
| 168 // The decode buffer can extend across many frames. Make sure that the | |
| 169 // buffer we pass to the start method that is specific to the frame type | |
| 170 // does not exend beyond this frame. | |
| 171 size_t remaining = frame_decoder_state_.remaining_total_payload(); | |
| 172 DCHECK_LE(remaining, frame_header().payload_length); | |
| 173 DecodeBufferSubset subset(db, remaining); | |
| 174 DecodeStatus status; | |
| 175 switch (frame_header().type) { | |
| 176 case Http2FrameType::DATA: | |
| 177 status = ResumeDecodingDataPayload(&subset); | |
| 178 break; | |
| 179 | |
| 180 case Http2FrameType::HEADERS: | |
| 181 status = ResumeDecodingHeadersPayload(&subset); | |
| 182 break; | |
| 183 | |
| 184 case Http2FrameType::PRIORITY: | |
| 185 status = ResumeDecodingPriorityPayload(&subset); | |
| 186 break; | |
| 187 | |
| 188 case Http2FrameType::RST_STREAM: | |
| 189 status = ResumeDecodingRstStreamPayload(&subset); | |
| 190 break; | |
| 191 | |
| 192 case Http2FrameType::SETTINGS: | |
| 193 status = ResumeDecodingSettingsPayload(&subset); | |
| 194 break; | |
| 195 | |
| 196 case Http2FrameType::PUSH_PROMISE: | |
| 197 status = ResumeDecodingPushPromisePayload(&subset); | |
| 198 break; | |
| 199 | |
| 200 case Http2FrameType::PING: | |
| 201 status = ResumeDecodingPingPayload(&subset); | |
| 202 break; | |
| 203 | |
| 204 case Http2FrameType::GOAWAY: | |
| 205 status = ResumeDecodingGoAwayPayload(&subset); | |
| 206 break; | |
| 207 | |
| 208 case Http2FrameType::WINDOW_UPDATE: | |
| 209 status = ResumeDecodingWindowUpdatePayload(&subset); | |
| 210 break; | |
| 211 | |
| 212 case Http2FrameType::CONTINUATION: | |
| 213 status = ResumeDecodingContinuationPayload(&subset); | |
| 214 break; | |
| 215 | |
| 216 case Http2FrameType::ALTSVC: | |
| 217 status = ResumeDecodingAltSvcPayload(&subset); | |
| 218 break; | |
| 219 | |
| 220 default: | |
| 221 status = ResumeDecodingUnknownPayload(&subset); | |
| 222 break; | |
| 223 } | |
| 224 | |
| 225 if (status == DecodeStatus::kDecodeDone) { | |
| 226 state_ = State::kStartDecodingHeader; | |
| 227 return status; | |
| 228 } else if (status == DecodeStatus::kDecodeInProgress) { | |
| 229 return status; | |
| 230 } else { | |
| 231 state_ = State::kDiscardPayload; | |
| 232 return status; | |
| 233 } | |
| 234 } | |
| 235 | |
| 236 // Clear any of the flags in the frame header that aren't set in valid_flags. | |
| 237 void Http2FrameDecoder::RetainFlags(uint8_t valid_flags) { | |
| 238 frame_decoder_state_.RetainFlags(valid_flags); | |
| 239 } | |
| 240 | |
| 241 // Clear all of the flags in the frame header; for use with frame types that | |
| 242 // don't define any flags, such as WINDOW_UPDATE. | |
| 243 void Http2FrameDecoder::ClearFlags() { | |
| 244 frame_decoder_state_.ClearFlags(); | |
| 245 } | |
| 246 | |
| 247 DecodeStatus Http2FrameDecoder::StartDecodingAltSvcPayload(DecodeBuffer* db) { | |
| 248 ClearFlags(); | |
| 249 return altsvc_payload_decoder_.StartDecodingPayload(&frame_decoder_state_, | |
| 250 db); | |
| 251 } | |
| 252 DecodeStatus Http2FrameDecoder::ResumeDecodingAltSvcPayload(DecodeBuffer* db) { | |
| 253 // The frame is not paddable. | |
| 254 DCHECK_EQ(frame_decoder_state_.remaining_total_payload(), | |
| 255 frame_decoder_state_.remaining_payload()); | |
| 256 return altsvc_payload_decoder_.ResumeDecodingPayload(&frame_decoder_state_, | |
| 257 db); | |
| 258 } | |
| 259 | |
| 260 DecodeStatus Http2FrameDecoder::StartDecodingContinuationPayload( | |
| 261 DecodeBuffer* db) { | |
| 262 RetainFlags(Http2FrameFlag::FLAG_END_HEADERS); | |
| 263 return continuation_payload_decoder_.StartDecodingPayload( | |
| 264 &frame_decoder_state_, db); | |
| 265 } | |
| 266 DecodeStatus Http2FrameDecoder::ResumeDecodingContinuationPayload( | |
| 267 DecodeBuffer* db) { | |
| 268 // The frame is not paddable. | |
| 269 DCHECK_EQ(frame_decoder_state_.remaining_total_payload(), | |
| 270 frame_decoder_state_.remaining_payload()); | |
| 271 return continuation_payload_decoder_.ResumeDecodingPayload( | |
| 272 &frame_decoder_state_, db); | |
| 273 } | |
| 274 | |
| 275 DecodeStatus Http2FrameDecoder::StartDecodingDataPayload(DecodeBuffer* db) { | |
| 276 RetainFlags(Http2FrameFlag::FLAG_END_STREAM | Http2FrameFlag::FLAG_PADDED); | |
| 277 return data_payload_decoder_.StartDecodingPayload(&frame_decoder_state_, db); | |
| 278 } | |
| 279 DecodeStatus Http2FrameDecoder::ResumeDecodingDataPayload(DecodeBuffer* db) { | |
| 280 return data_payload_decoder_.ResumeDecodingPayload(&frame_decoder_state_, db); | |
| 281 } | |
| 282 | |
| 283 DecodeStatus Http2FrameDecoder::StartDecodingGoAwayPayload(DecodeBuffer* db) { | |
| 284 ClearFlags(); | |
| 285 return goaway_payload_decoder_.StartDecodingPayload(&frame_decoder_state_, | |
| 286 db); | |
| 287 } | |
| 288 DecodeStatus Http2FrameDecoder::ResumeDecodingGoAwayPayload(DecodeBuffer* db) { | |
| 289 // The frame is not paddable. | |
| 290 DCHECK_EQ(frame_decoder_state_.remaining_total_payload(), | |
| 291 frame_decoder_state_.remaining_payload()); | |
| 292 return goaway_payload_decoder_.ResumeDecodingPayload(&frame_decoder_state_, | |
| 293 db); | |
| 294 } | |
| 295 | |
| 296 DecodeStatus Http2FrameDecoder::StartDecodingHeadersPayload(DecodeBuffer* db) { | |
| 297 RetainFlags(Http2FrameFlag::FLAG_END_STREAM | | |
| 298 Http2FrameFlag::FLAG_END_HEADERS | Http2FrameFlag::FLAG_PADDED | | |
| 299 Http2FrameFlag::FLAG_PRIORITY); | |
| 300 return headers_payload_decoder_.StartDecodingPayload(&frame_decoder_state_, | |
| 301 db); | |
| 302 } | |
| 303 DecodeStatus Http2FrameDecoder::ResumeDecodingHeadersPayload(DecodeBuffer* db) { | |
| 304 DCHECK_LE(frame_decoder_state_.remaining_payload_and_padding(), | |
| 305 frame_header().payload_length); | |
| 306 return headers_payload_decoder_.ResumeDecodingPayload(&frame_decoder_state_, | |
| 307 db); | |
| 308 } | |
| 309 | |
| 310 DecodeStatus Http2FrameDecoder::StartDecodingPingPayload(DecodeBuffer* db) { | |
| 311 RetainFlags(Http2FrameFlag::FLAG_ACK); | |
| 312 return ping_payload_decoder_.StartDecodingPayload(&frame_decoder_state_, db); | |
| 313 } | |
| 314 DecodeStatus Http2FrameDecoder::ResumeDecodingPingPayload(DecodeBuffer* db) { | |
| 315 // The frame is not paddable. | |
| 316 DCHECK_EQ(frame_decoder_state_.remaining_total_payload(), | |
| 317 frame_decoder_state_.remaining_payload()); | |
| 318 return ping_payload_decoder_.ResumeDecodingPayload(&frame_decoder_state_, db); | |
| 319 } | |
| 320 | |
| 321 DecodeStatus Http2FrameDecoder::StartDecodingPriorityPayload(DecodeBuffer* db) { | |
| 322 ClearFlags(); | |
| 323 return priority_payload_decoder_.StartDecodingPayload(&frame_decoder_state_, | |
| 324 db); | |
| 325 } | |
| 326 DecodeStatus Http2FrameDecoder::ResumeDecodingPriorityPayload( | |
| 327 DecodeBuffer* db) { | |
| 328 // The frame is not paddable. | |
| 329 DCHECK_EQ(frame_decoder_state_.remaining_total_payload(), | |
| 330 frame_decoder_state_.remaining_payload()); | |
| 331 return priority_payload_decoder_.ResumeDecodingPayload(&frame_decoder_state_, | |
| 332 db); | |
| 333 } | |
| 334 | |
| 335 DecodeStatus Http2FrameDecoder::StartDecodingPushPromisePayload( | |
| 336 DecodeBuffer* db) { | |
| 337 RetainFlags(Http2FrameFlag::FLAG_END_HEADERS | Http2FrameFlag::FLAG_PADDED); | |
| 338 return push_promise_payload_decoder_.StartDecodingPayload( | |
| 339 &frame_decoder_state_, db); | |
| 340 } | |
| 341 DecodeStatus Http2FrameDecoder::ResumeDecodingPushPromisePayload( | |
| 342 DecodeBuffer* db) { | |
| 343 DCHECK_LE(frame_decoder_state_.remaining_payload_and_padding(), | |
| 344 frame_header().payload_length); | |
| 345 return push_promise_payload_decoder_.ResumeDecodingPayload( | |
| 346 &frame_decoder_state_, db); | |
| 347 } | |
| 348 | |
| 349 DecodeStatus Http2FrameDecoder::StartDecodingRstStreamPayload( | |
| 350 DecodeBuffer* db) { | |
| 351 ClearFlags(); | |
| 352 return rst_stream_payload_decoder_.StartDecodingPayload(&frame_decoder_state_, | |
| 353 db); | |
| 354 } | |
| 355 DecodeStatus Http2FrameDecoder::ResumeDecodingRstStreamPayload( | |
| 356 DecodeBuffer* db) { | |
| 357 // The frame is not paddable. | |
| 358 DCHECK_EQ(frame_decoder_state_.remaining_total_payload(), | |
| 359 frame_decoder_state_.remaining_payload()); | |
| 360 return rst_stream_payload_decoder_.ResumeDecodingPayload( | |
| 361 &frame_decoder_state_, db); | |
| 362 } | |
| 363 | |
| 364 DecodeStatus Http2FrameDecoder::StartDecodingSettingsPayload(DecodeBuffer* db) { | |
| 365 RetainFlags(Http2FrameFlag::FLAG_ACK); | |
| 366 return settings_payload_decoder_.StartDecodingPayload(&frame_decoder_state_, | |
| 367 db); | |
| 368 } | |
| 369 DecodeStatus Http2FrameDecoder::ResumeDecodingSettingsPayload( | |
| 370 DecodeBuffer* db) { | |
| 371 // The frame is not paddable. | |
| 372 DCHECK_EQ(frame_decoder_state_.remaining_total_payload(), | |
| 373 frame_decoder_state_.remaining_payload()); | |
| 374 return settings_payload_decoder_.ResumeDecodingPayload(&frame_decoder_state_, | |
| 375 db); | |
| 376 } | |
| 377 | |
| 378 DecodeStatus Http2FrameDecoder::StartDecodingUnknownPayload(DecodeBuffer* db) { | |
| 379 // We don't known what type of frame this is, so we don't know which flags | |
| 380 // are valid, so we don't touch them. | |
| 381 return unknown_payload_decoder_.StartDecodingPayload(&frame_decoder_state_, | |
| 382 db); | |
| 383 } | |
| 384 DecodeStatus Http2FrameDecoder::ResumeDecodingUnknownPayload(DecodeBuffer* db) { | |
| 385 // We don't known what type of frame this is, so we treat it as not paddable. | |
| 386 DCHECK_EQ(frame_decoder_state_.remaining_total_payload(), | |
| 387 frame_decoder_state_.remaining_payload()); | |
| 388 return unknown_payload_decoder_.ResumeDecodingPayload(&frame_decoder_state_, | |
| 389 db); | |
| 390 } | |
| 391 | |
| 392 DecodeStatus Http2FrameDecoder::StartDecodingWindowUpdatePayload( | |
| 393 DecodeBuffer* db) { | |
| 394 ClearFlags(); | |
| 395 return window_update_payload_decoder_.StartDecodingPayload( | |
| 396 &frame_decoder_state_, db); | |
| 397 } | |
| 398 DecodeStatus Http2FrameDecoder::ResumeDecodingWindowUpdatePayload( | |
| 399 DecodeBuffer* db) { | |
| 400 // The frame is not paddable. | |
| 401 DCHECK_EQ(frame_decoder_state_.remaining_total_payload(), | |
| 402 frame_decoder_state_.remaining_payload()); | |
| 403 return window_update_payload_decoder_.ResumeDecodingPayload( | |
| 404 &frame_decoder_state_, db); | |
| 405 } | |
| 406 | |
| 407 DecodeStatus Http2FrameDecoder::DiscardPayload(DecodeBuffer* db) { | |
| 408 DVLOG(2) << "remaining_payload=" << frame_decoder_state_.remaining_payload_ | |
| 409 << "; remaining_padding=" << frame_decoder_state_.remaining_padding_; | |
| 410 frame_decoder_state_.remaining_payload_ += | |
| 411 frame_decoder_state_.remaining_padding_; | |
| 412 frame_decoder_state_.remaining_padding_ = 0; | |
| 413 const size_t avail = frame_decoder_state_.AvailablePayload(db); | |
| 414 DVLOG(2) << "avail=" << avail; | |
| 415 if (avail > 0) { | |
| 416 frame_decoder_state_.ConsumePayload(avail); | |
| 417 db->AdvanceCursor(avail); | |
| 418 } | |
| 419 if (frame_decoder_state_.remaining_payload_ == 0) { | |
| 420 state_ = State::kStartDecodingHeader; | |
| 421 return DecodeStatus::kDecodeDone; | |
| 422 } | |
| 423 return DecodeStatus::kDecodeInProgress; | |
| 424 } | |
| 425 | |
| 426 } // namespace net | |
| OLD | NEW |