QUICHE team | fd50a40 | 2018-12-07 22:54:05 -0500 | [diff] [blame] | 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 | |
QUICHE team | 5be974e | 2020-12-29 18:35:24 -0500 | [diff] [blame] | 5 | #include "http2/decoder/payload_decoders/settings_payload_decoder.h" |
QUICHE team | fd50a40 | 2018-12-07 22:54:05 -0500 | [diff] [blame] | 6 | |
QUICHE team | 5be974e | 2020-12-29 18:35:24 -0500 | [diff] [blame] | 7 | #include "http2/decoder/decode_buffer.h" |
| 8 | #include "http2/decoder/http2_frame_decoder_listener.h" |
| 9 | #include "http2/http2_constants.h" |
| 10 | #include "http2/http2_structures.h" |
| 11 | #include "http2/platform/api/http2_logging.h" |
QUICHE team | fd50a40 | 2018-12-07 22:54:05 -0500 | [diff] [blame] | 12 | |
| 13 | namespace http2 { |
| 14 | |
| 15 | DecodeStatus SettingsPayloadDecoder::StartDecodingPayload( |
| 16 | FrameDecoderState* state, |
| 17 | DecodeBuffer* db) { |
| 18 | const Http2FrameHeader& frame_header = state->frame_header(); |
| 19 | const uint32_t total_length = frame_header.payload_length; |
| 20 | |
QUICHE team | 61940b4 | 2019-03-07 23:32:27 -0500 | [diff] [blame] | 21 | HTTP2_DVLOG(2) << "SettingsPayloadDecoder::StartDecodingPayload: " |
| 22 | << frame_header; |
vasilvv | afcc317 | 2021-02-02 12:01:07 -0800 | [diff] [blame] | 23 | QUICHE_DCHECK_EQ(Http2FrameType::SETTINGS, frame_header.type); |
| 24 | QUICHE_DCHECK_LE(db->Remaining(), total_length); |
| 25 | QUICHE_DCHECK_EQ(0, frame_header.flags & ~(Http2FrameFlag::ACK)); |
QUICHE team | fd50a40 | 2018-12-07 22:54:05 -0500 | [diff] [blame] | 26 | |
| 27 | if (frame_header.IsAck()) { |
| 28 | if (total_length == 0) { |
| 29 | state->listener()->OnSettingsAck(frame_header); |
| 30 | return DecodeStatus::kDecodeDone; |
| 31 | } else { |
| 32 | state->InitializeRemainders(); |
| 33 | return state->ReportFrameSizeError(); |
| 34 | } |
| 35 | } else { |
| 36 | state->InitializeRemainders(); |
| 37 | state->listener()->OnSettingsStart(frame_header); |
| 38 | return StartDecodingSettings(state, db); |
| 39 | } |
| 40 | } |
| 41 | |
| 42 | DecodeStatus SettingsPayloadDecoder::ResumeDecodingPayload( |
| 43 | FrameDecoderState* state, |
| 44 | DecodeBuffer* db) { |
QUICHE team | 61940b4 | 2019-03-07 23:32:27 -0500 | [diff] [blame] | 45 | HTTP2_DVLOG(2) << "SettingsPayloadDecoder::ResumeDecodingPayload" |
| 46 | << " remaining_payload=" << state->remaining_payload() |
| 47 | << " db->Remaining=" << db->Remaining(); |
vasilvv | afcc317 | 2021-02-02 12:01:07 -0800 | [diff] [blame] | 48 | QUICHE_DCHECK_EQ(Http2FrameType::SETTINGS, state->frame_header().type); |
| 49 | QUICHE_DCHECK_LE(db->Remaining(), state->frame_header().payload_length); |
QUICHE team | fd50a40 | 2018-12-07 22:54:05 -0500 | [diff] [blame] | 50 | |
| 51 | DecodeStatus status = |
| 52 | state->ResumeDecodingStructureInPayload(&setting_fields_, db); |
| 53 | if (status == DecodeStatus::kDecodeDone) { |
| 54 | state->listener()->OnSetting(setting_fields_); |
| 55 | return StartDecodingSettings(state, db); |
| 56 | } |
| 57 | return HandleNotDone(state, db, status); |
| 58 | } |
| 59 | |
| 60 | DecodeStatus SettingsPayloadDecoder::StartDecodingSettings( |
| 61 | FrameDecoderState* state, |
| 62 | DecodeBuffer* db) { |
QUICHE team | 61940b4 | 2019-03-07 23:32:27 -0500 | [diff] [blame] | 63 | HTTP2_DVLOG(2) << "SettingsPayloadDecoder::StartDecodingSettings" |
| 64 | << " remaining_payload=" << state->remaining_payload() |
| 65 | << " db->Remaining=" << db->Remaining(); |
QUICHE team | fd50a40 | 2018-12-07 22:54:05 -0500 | [diff] [blame] | 66 | while (state->remaining_payload() > 0) { |
| 67 | DecodeStatus status = |
| 68 | state->StartDecodingStructureInPayload(&setting_fields_, db); |
| 69 | if (status == DecodeStatus::kDecodeDone) { |
| 70 | state->listener()->OnSetting(setting_fields_); |
| 71 | continue; |
| 72 | } |
| 73 | return HandleNotDone(state, db, status); |
| 74 | } |
QUICHE team | 61940b4 | 2019-03-07 23:32:27 -0500 | [diff] [blame] | 75 | HTTP2_DVLOG(2) << "LEAVING SettingsPayloadDecoder::StartDecodingSettings" |
| 76 | << "\n\tdb->Remaining=" << db->Remaining() |
| 77 | << "\n\t remaining_payload=" << state->remaining_payload(); |
QUICHE team | fd50a40 | 2018-12-07 22:54:05 -0500 | [diff] [blame] | 78 | state->listener()->OnSettingsEnd(); |
| 79 | return DecodeStatus::kDecodeDone; |
| 80 | } |
| 81 | |
| 82 | DecodeStatus SettingsPayloadDecoder::HandleNotDone(FrameDecoderState* state, |
| 83 | DecodeBuffer* db, |
| 84 | DecodeStatus status) { |
| 85 | // Not done decoding the structure. Either we've got more payload to decode, |
| 86 | // or we've run out because the payload is too short, in which case |
| 87 | // OnFrameSizeError will have already been called. |
vasilvv | afcc317 | 2021-02-02 12:01:07 -0800 | [diff] [blame] | 88 | QUICHE_DCHECK( |
QUICHE team | fd50a40 | 2018-12-07 22:54:05 -0500 | [diff] [blame] | 89 | (status == DecodeStatus::kDecodeInProgress && |
| 90 | state->remaining_payload() > 0) || |
| 91 | (status == DecodeStatus::kDecodeError && state->remaining_payload() == 0)) |
| 92 | << "\n status=" << status |
| 93 | << "; remaining_payload=" << state->remaining_payload() |
| 94 | << "; db->Remaining=" << db->Remaining(); |
| 95 | return status; |
| 96 | } |
| 97 | |
| 98 | } // namespace http2 |