QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 1 | // Copyright (c) 2018 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/third_party/quiche/src/quic/core/http/http_decoder.h" |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 6 | |
renjietang | 3a76c89 | 2019-07-17 10:03:53 -0700 | [diff] [blame] | 7 | #include <cstdint> |
| 8 | |
| 9 | #include "net/third_party/quiche/src/quic/core/http/http_frames.h" |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 10 | #include "net/third_party/quiche/src/quic/core/quic_data_reader.h" |
renjietang | 5843bfd | 2019-10-10 13:24:57 -0700 | [diff] [blame] | 11 | #include "net/third_party/quiche/src/quic/core/quic_types.h" |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 12 | #include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h" |
| 13 | #include "net/third_party/quiche/src/quic/platform/api/quic_fallthrough.h" |
dmcardle | ba2fb7e | 2019-12-13 07:44:34 -0800 | [diff] [blame] | 14 | #include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h" |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 15 | |
| 16 | namespace quic { |
| 17 | |
bnc | a9bb469 | 2019-07-09 17:29:48 -0700 | [diff] [blame] | 18 | HttpDecoder::HttpDecoder(Visitor* visitor) |
| 19 | : visitor_(visitor), |
renjietang | fcd91c0 | 2019-04-22 10:40:35 -0700 | [diff] [blame] | 20 | state_(STATE_READING_FRAME_TYPE), |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 21 | current_frame_type_(0), |
renjietang | bb98cbc | 2019-04-23 13:13:56 -0700 | [diff] [blame] | 22 | current_length_field_length_(0), |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 23 | remaining_length_field_length_(0), |
| 24 | current_frame_length_(0), |
| 25 | remaining_frame_length_(0), |
renjietang | 2d475cf | 2019-04-18 17:03:37 -0700 | [diff] [blame] | 26 | current_type_field_length_(0), |
| 27 | remaining_type_field_length_(0), |
renjietang | 857362b | 2019-08-09 09:52:35 -0700 | [diff] [blame] | 28 | current_push_id_length_(0), |
| 29 | remaining_push_id_length_(0), |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 30 | error_(QUIC_NO_ERROR), |
bnc | a9bb469 | 2019-07-09 17:29:48 -0700 | [diff] [blame] | 31 | error_detail_("") { |
| 32 | DCHECK(visitor_); |
| 33 | } |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 34 | |
| 35 | HttpDecoder::~HttpDecoder() {} |
| 36 | |
| 37 | QuicByteCount HttpDecoder::ProcessInput(const char* data, QuicByteCount len) { |
bnc | 620095a | 2019-06-26 05:31:05 -0700 | [diff] [blame] | 38 | DCHECK_EQ(QUIC_NO_ERROR, error_); |
| 39 | DCHECK_NE(STATE_ERROR, state_); |
| 40 | |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 41 | QuicDataReader reader(data, len); |
bnc | b9d07d9 | 2019-06-25 17:43:49 -0700 | [diff] [blame] | 42 | bool continue_processing = true; |
bnc | 620095a | 2019-06-26 05:31:05 -0700 | [diff] [blame] | 43 | while (continue_processing && |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 44 | (reader.BytesRemaining() != 0 || state_ == STATE_FINISH_PARSING)) { |
bnc | 620095a | 2019-06-26 05:31:05 -0700 | [diff] [blame] | 45 | // |continue_processing| must have been set to false upon error. |
| 46 | DCHECK_EQ(QUIC_NO_ERROR, error_); |
| 47 | DCHECK_NE(STATE_ERROR, state_); |
| 48 | |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 49 | switch (state_) { |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 50 | case STATE_READING_FRAME_TYPE: |
| 51 | ReadFrameType(&reader); |
| 52 | break; |
renjietang | fcd91c0 | 2019-04-22 10:40:35 -0700 | [diff] [blame] | 53 | case STATE_READING_FRAME_LENGTH: |
bnc | b9d07d9 | 2019-06-25 17:43:49 -0700 | [diff] [blame] | 54 | continue_processing = ReadFrameLength(&reader); |
renjietang | fcd91c0 | 2019-04-22 10:40:35 -0700 | [diff] [blame] | 55 | break; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 56 | case STATE_READING_FRAME_PAYLOAD: |
bnc | b9d07d9 | 2019-06-25 17:43:49 -0700 | [diff] [blame] | 57 | continue_processing = ReadFramePayload(&reader); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 58 | break; |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 59 | case STATE_FINISH_PARSING: |
bnc | b9d07d9 | 2019-06-25 17:43:49 -0700 | [diff] [blame] | 60 | continue_processing = FinishParsing(); |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 61 | break; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 62 | case STATE_ERROR: |
| 63 | break; |
| 64 | default: |
| 65 | QUIC_BUG << "Invalid state: " << state_; |
| 66 | } |
| 67 | } |
| 68 | |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 69 | return len - reader.BytesRemaining(); |
| 70 | } |
| 71 | |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 72 | void HttpDecoder::ReadFrameType(QuicDataReader* reader) { |
| 73 | DCHECK_NE(0u, reader->BytesRemaining()); |
renjietang | 2d475cf | 2019-04-18 17:03:37 -0700 | [diff] [blame] | 74 | if (current_type_field_length_ == 0) { |
| 75 | // A new frame is coming. |
| 76 | current_type_field_length_ = reader->PeekVarInt62Length(); |
bnc | 4368e7f | 2019-06-24 12:15:48 -0700 | [diff] [blame] | 77 | DCHECK_NE(0u, current_type_field_length_); |
| 78 | if (current_type_field_length_ > reader->BytesRemaining()) { |
renjietang | 2d475cf | 2019-04-18 17:03:37 -0700 | [diff] [blame] | 79 | // Buffer a new type field. |
| 80 | remaining_type_field_length_ = current_type_field_length_; |
| 81 | BufferFrameType(reader); |
| 82 | return; |
| 83 | } |
bnc | 4368e7f | 2019-06-24 12:15:48 -0700 | [diff] [blame] | 84 | // The reader has all type data needed, so no need to buffer. |
| 85 | bool success = reader->ReadVarInt62(¤t_frame_type_); |
| 86 | DCHECK(success); |
renjietang | 2d475cf | 2019-04-18 17:03:37 -0700 | [diff] [blame] | 87 | } else { |
| 88 | // Buffer the existing type field. |
| 89 | BufferFrameType(reader); |
| 90 | // The frame is still not buffered completely. |
| 91 | if (remaining_type_field_length_ != 0) { |
| 92 | return; |
| 93 | } |
| 94 | QuicDataReader type_reader(type_buffer_.data(), current_type_field_length_); |
bnc | 4368e7f | 2019-06-24 12:15:48 -0700 | [diff] [blame] | 95 | bool success = type_reader.ReadVarInt62(¤t_frame_type_); |
| 96 | DCHECK(success); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 97 | } |
| 98 | |
renjietang | fcd91c0 | 2019-04-22 10:40:35 -0700 | [diff] [blame] | 99 | state_ = STATE_READING_FRAME_LENGTH; |
| 100 | } |
| 101 | |
bnc | b9d07d9 | 2019-06-25 17:43:49 -0700 | [diff] [blame] | 102 | bool HttpDecoder::ReadFrameLength(QuicDataReader* reader) { |
renjietang | fcd91c0 | 2019-04-22 10:40:35 -0700 | [diff] [blame] | 103 | DCHECK_NE(0u, reader->BytesRemaining()); |
renjietang | bb98cbc | 2019-04-23 13:13:56 -0700 | [diff] [blame] | 104 | if (current_length_field_length_ == 0) { |
| 105 | // A new frame is coming. |
| 106 | current_length_field_length_ = reader->PeekVarInt62Length(); |
bnc | 4368e7f | 2019-06-24 12:15:48 -0700 | [diff] [blame] | 107 | DCHECK_NE(0u, current_length_field_length_); |
| 108 | if (current_length_field_length_ > reader->BytesRemaining()) { |
renjietang | bb98cbc | 2019-04-23 13:13:56 -0700 | [diff] [blame] | 109 | // Buffer a new length field. |
| 110 | remaining_length_field_length_ = current_length_field_length_; |
| 111 | BufferFrameLength(reader); |
bnc | b9d07d9 | 2019-06-25 17:43:49 -0700 | [diff] [blame] | 112 | return true; |
renjietang | bb98cbc | 2019-04-23 13:13:56 -0700 | [diff] [blame] | 113 | } |
bnc | 4368e7f | 2019-06-24 12:15:48 -0700 | [diff] [blame] | 114 | // The reader has all length data needed, so no need to buffer. |
| 115 | bool success = reader->ReadVarInt62(¤t_frame_length_); |
| 116 | DCHECK(success); |
renjietang | bb98cbc | 2019-04-23 13:13:56 -0700 | [diff] [blame] | 117 | } else { |
| 118 | // Buffer the existing length field. |
| 119 | BufferFrameLength(reader); |
| 120 | // The frame is still not buffered completely. |
| 121 | if (remaining_length_field_length_ != 0) { |
bnc | b9d07d9 | 2019-06-25 17:43:49 -0700 | [diff] [blame] | 122 | return true; |
renjietang | bb98cbc | 2019-04-23 13:13:56 -0700 | [diff] [blame] | 123 | } |
| 124 | QuicDataReader length_reader(length_buffer_.data(), |
| 125 | current_length_field_length_); |
bnc | 4368e7f | 2019-06-24 12:15:48 -0700 | [diff] [blame] | 126 | bool success = length_reader.ReadVarInt62(¤t_frame_length_); |
| 127 | DCHECK(success); |
renjietang | fcd91c0 | 2019-04-22 10:40:35 -0700 | [diff] [blame] | 128 | } |
| 129 | |
renjietang | 4ab9d9f | 2019-04-10 14:30:26 -0700 | [diff] [blame] | 130 | if (current_frame_length_ > MaxFrameLength(current_frame_type_)) { |
bnc | e7f6796 | 2019-08-08 06:34:35 -0700 | [diff] [blame] | 131 | // TODO(b/124216424): Use HTTP_EXCESSIVE_LOAD. |
| 132 | RaiseError(QUIC_INVALID_FRAME_DATA, "Frame is too large"); |
bnc | b9d07d9 | 2019-06-25 17:43:49 -0700 | [diff] [blame] | 133 | return false; |
renjietang | 4ab9d9f | 2019-04-10 14:30:26 -0700 | [diff] [blame] | 134 | } |
| 135 | |
renjietang | 7d4f913 | 2019-06-20 15:04:34 -0700 | [diff] [blame] | 136 | // Calling the following visitor methods does not require parsing of any |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 137 | // frame payload. |
bnc | b9d07d9 | 2019-06-25 17:43:49 -0700 | [diff] [blame] | 138 | bool continue_processing = true; |
bnc | a2b13be | 2019-07-31 12:04:20 -0700 | [diff] [blame] | 139 | const QuicByteCount header_length = |
| 140 | current_length_field_length_ + current_type_field_length_; |
bnc | bf3dbe5 | 2019-07-17 05:17:41 -0700 | [diff] [blame] | 141 | |
| 142 | switch (current_frame_type_) { |
bnc | 95fb6b6 | 2019-07-21 11:20:47 -0700 | [diff] [blame] | 143 | case static_cast<uint64_t>(HttpFrameType::DATA): |
bnc | a2b13be | 2019-07-31 12:04:20 -0700 | [diff] [blame] | 144 | continue_processing = visitor_->OnDataFrameStart(header_length); |
bnc | bf3dbe5 | 2019-07-17 05:17:41 -0700 | [diff] [blame] | 145 | break; |
bnc | 95fb6b6 | 2019-07-21 11:20:47 -0700 | [diff] [blame] | 146 | case static_cast<uint64_t>(HttpFrameType::HEADERS): |
bnc | a2b13be | 2019-07-31 12:04:20 -0700 | [diff] [blame] | 147 | continue_processing = visitor_->OnHeadersFrameStart(header_length); |
bnc | bf3dbe5 | 2019-07-17 05:17:41 -0700 | [diff] [blame] | 148 | break; |
bnc | 95fb6b6 | 2019-07-21 11:20:47 -0700 | [diff] [blame] | 149 | case static_cast<uint64_t>(HttpFrameType::PRIORITY): |
bnc | a2b13be | 2019-07-31 12:04:20 -0700 | [diff] [blame] | 150 | continue_processing = visitor_->OnPriorityFrameStart(header_length); |
bnc | bf3dbe5 | 2019-07-17 05:17:41 -0700 | [diff] [blame] | 151 | break; |
bnc | 95fb6b6 | 2019-07-21 11:20:47 -0700 | [diff] [blame] | 152 | case static_cast<uint64_t>(HttpFrameType::CANCEL_PUSH): |
bnc | bf3dbe5 | 2019-07-17 05:17:41 -0700 | [diff] [blame] | 153 | break; |
bnc | 95fb6b6 | 2019-07-21 11:20:47 -0700 | [diff] [blame] | 154 | case static_cast<uint64_t>(HttpFrameType::SETTINGS): |
bnc | a2b13be | 2019-07-31 12:04:20 -0700 | [diff] [blame] | 155 | continue_processing = visitor_->OnSettingsFrameStart(header_length); |
bnc | bf3dbe5 | 2019-07-17 05:17:41 -0700 | [diff] [blame] | 156 | break; |
bnc | 95fb6b6 | 2019-07-21 11:20:47 -0700 | [diff] [blame] | 157 | case static_cast<uint64_t>(HttpFrameType::PUSH_PROMISE): |
bnc | f0db654 | 2019-09-23 11:18:28 -0700 | [diff] [blame] | 158 | // This edge case needs to be handled here, because ReadFramePayload() |
| 159 | // does not get called if |current_frame_length_| is zero. |
bnc | fcd4235 | 2019-09-20 17:55:47 -0700 | [diff] [blame] | 160 | if (current_frame_length_ == 0) { |
| 161 | RaiseError(QUIC_INVALID_FRAME_DATA, "Corrupt PUSH_PROMISE frame."); |
| 162 | return false; |
| 163 | } |
bnc | f0db654 | 2019-09-23 11:18:28 -0700 | [diff] [blame] | 164 | continue_processing = visitor_->OnPushPromiseFrameStart(header_length); |
bnc | bf3dbe5 | 2019-07-17 05:17:41 -0700 | [diff] [blame] | 165 | break; |
bnc | 95fb6b6 | 2019-07-21 11:20:47 -0700 | [diff] [blame] | 166 | case static_cast<uint64_t>(HttpFrameType::GOAWAY): |
bnc | bf3dbe5 | 2019-07-17 05:17:41 -0700 | [diff] [blame] | 167 | break; |
bnc | 95fb6b6 | 2019-07-21 11:20:47 -0700 | [diff] [blame] | 168 | case static_cast<uint64_t>(HttpFrameType::MAX_PUSH_ID): |
bnc | bf3dbe5 | 2019-07-17 05:17:41 -0700 | [diff] [blame] | 169 | break; |
bnc | 95fb6b6 | 2019-07-21 11:20:47 -0700 | [diff] [blame] | 170 | case static_cast<uint64_t>(HttpFrameType::DUPLICATE_PUSH): |
bnc | bf3dbe5 | 2019-07-17 05:17:41 -0700 | [diff] [blame] | 171 | break; |
| 172 | default: |
| 173 | continue_processing = |
bnc | a2b13be | 2019-07-31 12:04:20 -0700 | [diff] [blame] | 174 | visitor_->OnUnknownFrameStart(current_frame_type_, header_length); |
bnc | bf3dbe5 | 2019-07-17 05:17:41 -0700 | [diff] [blame] | 175 | break; |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 176 | } |
| 177 | |
renjietang | fcd91c0 | 2019-04-22 10:40:35 -0700 | [diff] [blame] | 178 | remaining_frame_length_ = current_frame_length_; |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 179 | state_ = (remaining_frame_length_ == 0) ? STATE_FINISH_PARSING |
| 180 | : STATE_READING_FRAME_PAYLOAD; |
bnc | b9d07d9 | 2019-06-25 17:43:49 -0700 | [diff] [blame] | 181 | return continue_processing; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 182 | } |
| 183 | |
bnc | b9d07d9 | 2019-06-25 17:43:49 -0700 | [diff] [blame] | 184 | bool HttpDecoder::ReadFramePayload(QuicDataReader* reader) { |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 185 | DCHECK_NE(0u, reader->BytesRemaining()); |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 186 | DCHECK_NE(0u, remaining_frame_length_); |
bnc | b9d07d9 | 2019-06-25 17:43:49 -0700 | [diff] [blame] | 187 | |
| 188 | bool continue_processing = true; |
| 189 | |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 190 | switch (current_frame_type_) { |
bnc | 95fb6b6 | 2019-07-21 11:20:47 -0700 | [diff] [blame] | 191 | case static_cast<uint64_t>(HttpFrameType::DATA): { |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 192 | QuicByteCount bytes_to_read = std::min<QuicByteCount>( |
| 193 | remaining_frame_length_, reader->BytesRemaining()); |
dmcardle | ba2fb7e | 2019-12-13 07:44:34 -0800 | [diff] [blame] | 194 | quiche::QuicheStringPiece payload; |
bnc | 4368e7f | 2019-06-24 12:15:48 -0700 | [diff] [blame] | 195 | bool success = reader->ReadStringPiece(&payload, bytes_to_read); |
| 196 | DCHECK(success); |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 197 | DCHECK(!payload.empty()); |
bnc | b9d07d9 | 2019-06-25 17:43:49 -0700 | [diff] [blame] | 198 | continue_processing = visitor_->OnDataFramePayload(payload); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 199 | remaining_frame_length_ -= payload.length(); |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 200 | break; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 201 | } |
bnc | 95fb6b6 | 2019-07-21 11:20:47 -0700 | [diff] [blame] | 202 | case static_cast<uint64_t>(HttpFrameType::HEADERS): { |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 203 | QuicByteCount bytes_to_read = std::min<QuicByteCount>( |
| 204 | remaining_frame_length_, reader->BytesRemaining()); |
dmcardle | ba2fb7e | 2019-12-13 07:44:34 -0800 | [diff] [blame] | 205 | quiche::QuicheStringPiece payload; |
bnc | 4368e7f | 2019-06-24 12:15:48 -0700 | [diff] [blame] | 206 | bool success = reader->ReadStringPiece(&payload, bytes_to_read); |
| 207 | DCHECK(success); |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 208 | DCHECK(!payload.empty()); |
bnc | b9d07d9 | 2019-06-25 17:43:49 -0700 | [diff] [blame] | 209 | continue_processing = visitor_->OnHeadersFramePayload(payload); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 210 | remaining_frame_length_ -= payload.length(); |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 211 | break; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 212 | } |
bnc | 95fb6b6 | 2019-07-21 11:20:47 -0700 | [diff] [blame] | 213 | case static_cast<uint64_t>(HttpFrameType::PRIORITY): { |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 214 | // TODO(rch): avoid buffering if the entire frame is present, and |
| 215 | // instead parse directly out of |reader|. |
| 216 | BufferFramePayload(reader); |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 217 | break; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 218 | } |
bnc | 95fb6b6 | 2019-07-21 11:20:47 -0700 | [diff] [blame] | 219 | case static_cast<uint64_t>(HttpFrameType::CANCEL_PUSH): { |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 220 | BufferFramePayload(reader); |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 221 | break; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 222 | } |
bnc | 95fb6b6 | 2019-07-21 11:20:47 -0700 | [diff] [blame] | 223 | case static_cast<uint64_t>(HttpFrameType::SETTINGS): { |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 224 | BufferFramePayload(reader); |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 225 | break; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 226 | } |
bnc | 95fb6b6 | 2019-07-21 11:20:47 -0700 | [diff] [blame] | 227 | case static_cast<uint64_t>(HttpFrameType::PUSH_PROMISE): { |
renjietang | 857362b | 2019-08-09 09:52:35 -0700 | [diff] [blame] | 228 | PushId push_id; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 229 | if (current_frame_length_ == remaining_frame_length_) { |
renjietang | 857362b | 2019-08-09 09:52:35 -0700 | [diff] [blame] | 230 | // A new Push Promise frame just arrived. |
| 231 | DCHECK_EQ(0u, current_push_id_length_); |
| 232 | current_push_id_length_ = reader->PeekVarInt62Length(); |
| 233 | if (current_push_id_length_ > remaining_frame_length_) { |
| 234 | RaiseError(QUIC_INVALID_FRAME_DATA, "PUSH_PROMISE frame malformed."); |
bnc | b9d07d9 | 2019-06-25 17:43:49 -0700 | [diff] [blame] | 235 | return false; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 236 | } |
renjietang | 857362b | 2019-08-09 09:52:35 -0700 | [diff] [blame] | 237 | if (current_push_id_length_ > reader->BytesRemaining()) { |
| 238 | // Not all bytes of push id is present yet, buffer push id. |
| 239 | DCHECK_EQ(0u, remaining_push_id_length_); |
| 240 | remaining_push_id_length_ = current_push_id_length_; |
| 241 | BufferPushId(reader); |
bnc | b9d07d9 | 2019-06-25 17:43:49 -0700 | [diff] [blame] | 242 | break; |
renjietang | 546a628 | 2019-06-03 10:21:21 -0700 | [diff] [blame] | 243 | } |
renjietang | 857362b | 2019-08-09 09:52:35 -0700 | [diff] [blame] | 244 | bool success = reader->ReadVarInt62(&push_id); |
| 245 | DCHECK(success); |
| 246 | remaining_frame_length_ -= current_push_id_length_; |
bnc | f0db654 | 2019-09-23 11:18:28 -0700 | [diff] [blame] | 247 | if (!visitor_->OnPushPromiseFramePushId(push_id, |
| 248 | current_push_id_length_)) { |
renjietang | 857362b | 2019-08-09 09:52:35 -0700 | [diff] [blame] | 249 | continue_processing = false; |
| 250 | current_push_id_length_ = 0; |
| 251 | break; |
| 252 | } |
| 253 | current_push_id_length_ = 0; |
| 254 | } else if (remaining_push_id_length_ > 0) { |
| 255 | // Waiting for more bytes on push id. |
| 256 | BufferPushId(reader); |
| 257 | if (remaining_push_id_length_ != 0) { |
| 258 | break; |
| 259 | } |
| 260 | QuicDataReader push_id_reader(push_id_buffer_.data(), |
| 261 | current_push_id_length_); |
| 262 | |
| 263 | bool success = push_id_reader.ReadVarInt62(&push_id); |
| 264 | DCHECK(success); |
bnc | f0db654 | 2019-09-23 11:18:28 -0700 | [diff] [blame] | 265 | if (!visitor_->OnPushPromiseFramePushId(push_id, |
| 266 | current_push_id_length_)) { |
renjietang | 857362b | 2019-08-09 09:52:35 -0700 | [diff] [blame] | 267 | continue_processing = false; |
| 268 | current_push_id_length_ = 0; |
| 269 | break; |
| 270 | } |
| 271 | current_push_id_length_ = 0; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 272 | } |
renjietang | 857362b | 2019-08-09 09:52:35 -0700 | [diff] [blame] | 273 | |
| 274 | // Read Push Promise headers. |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 275 | DCHECK_LT(remaining_frame_length_, current_frame_length_); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 276 | QuicByteCount bytes_to_read = std::min<QuicByteCount>( |
| 277 | remaining_frame_length_, reader->BytesRemaining()); |
| 278 | if (bytes_to_read == 0) { |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 279 | break; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 280 | } |
dmcardle | ba2fb7e | 2019-12-13 07:44:34 -0800 | [diff] [blame] | 281 | quiche::QuicheStringPiece payload; |
bnc | 4368e7f | 2019-06-24 12:15:48 -0700 | [diff] [blame] | 282 | bool success = reader->ReadStringPiece(&payload, bytes_to_read); |
| 283 | DCHECK(success); |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 284 | DCHECK(!payload.empty()); |
bnc | b9d07d9 | 2019-06-25 17:43:49 -0700 | [diff] [blame] | 285 | continue_processing = visitor_->OnPushPromiseFramePayload(payload); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 286 | remaining_frame_length_ -= payload.length(); |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 287 | break; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 288 | } |
bnc | 95fb6b6 | 2019-07-21 11:20:47 -0700 | [diff] [blame] | 289 | case static_cast<uint64_t>(HttpFrameType::GOAWAY): { |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 290 | BufferFramePayload(reader); |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 291 | break; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 292 | } |
bnc | 95fb6b6 | 2019-07-21 11:20:47 -0700 | [diff] [blame] | 293 | case static_cast<uint64_t>(HttpFrameType::MAX_PUSH_ID): { |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 294 | BufferFramePayload(reader); |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 295 | break; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 296 | } |
bnc | 95fb6b6 | 2019-07-21 11:20:47 -0700 | [diff] [blame] | 297 | case static_cast<uint64_t>(HttpFrameType::DUPLICATE_PUSH): { |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 298 | BufferFramePayload(reader); |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 299 | break; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 300 | } |
bnc | bf3dbe5 | 2019-07-17 05:17:41 -0700 | [diff] [blame] | 301 | default: { |
| 302 | QuicByteCount bytes_to_read = std::min<QuicByteCount>( |
| 303 | remaining_frame_length_, reader->BytesRemaining()); |
dmcardle | ba2fb7e | 2019-12-13 07:44:34 -0800 | [diff] [blame] | 304 | quiche::QuicheStringPiece payload; |
bnc | bf3dbe5 | 2019-07-17 05:17:41 -0700 | [diff] [blame] | 305 | bool success = reader->ReadStringPiece(&payload, bytes_to_read); |
| 306 | DCHECK(success); |
| 307 | DCHECK(!payload.empty()); |
| 308 | continue_processing = visitor_->OnUnknownFramePayload(payload); |
| 309 | remaining_frame_length_ -= payload.length(); |
| 310 | break; |
| 311 | } |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 312 | } |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 313 | |
| 314 | if (remaining_frame_length_ == 0) { |
| 315 | state_ = STATE_FINISH_PARSING; |
| 316 | } |
bnc | b9d07d9 | 2019-06-25 17:43:49 -0700 | [diff] [blame] | 317 | |
| 318 | return continue_processing; |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 319 | } |
| 320 | |
bnc | b9d07d9 | 2019-06-25 17:43:49 -0700 | [diff] [blame] | 321 | bool HttpDecoder::FinishParsing() { |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 322 | DCHECK_EQ(0u, remaining_frame_length_); |
bnc | b9d07d9 | 2019-06-25 17:43:49 -0700 | [diff] [blame] | 323 | |
| 324 | bool continue_processing = true; |
| 325 | |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 326 | switch (current_frame_type_) { |
bnc | 95fb6b6 | 2019-07-21 11:20:47 -0700 | [diff] [blame] | 327 | case static_cast<uint64_t>(HttpFrameType::DATA): { |
bnc | b9d07d9 | 2019-06-25 17:43:49 -0700 | [diff] [blame] | 328 | continue_processing = visitor_->OnDataFrameEnd(); |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 329 | break; |
| 330 | } |
bnc | 95fb6b6 | 2019-07-21 11:20:47 -0700 | [diff] [blame] | 331 | case static_cast<uint64_t>(HttpFrameType::HEADERS): { |
bnc | b9d07d9 | 2019-06-25 17:43:49 -0700 | [diff] [blame] | 332 | continue_processing = visitor_->OnHeadersFrameEnd(); |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 333 | break; |
| 334 | } |
bnc | 95fb6b6 | 2019-07-21 11:20:47 -0700 | [diff] [blame] | 335 | case static_cast<uint64_t>(HttpFrameType::PRIORITY): { |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 336 | // TODO(rch): avoid buffering if the entire frame is present, and |
| 337 | // instead parse directly out of |reader|. |
| 338 | PriorityFrame frame; |
| 339 | QuicDataReader reader(buffer_.data(), current_frame_length_); |
| 340 | if (!ParsePriorityFrame(&reader, &frame)) { |
bnc | b9d07d9 | 2019-06-25 17:43:49 -0700 | [diff] [blame] | 341 | return false; |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 342 | } |
bnc | b9d07d9 | 2019-06-25 17:43:49 -0700 | [diff] [blame] | 343 | continue_processing = visitor_->OnPriorityFrame(frame); |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 344 | break; |
| 345 | } |
bnc | 95fb6b6 | 2019-07-21 11:20:47 -0700 | [diff] [blame] | 346 | case static_cast<uint64_t>(HttpFrameType::CANCEL_PUSH): { |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 347 | CancelPushFrame frame; |
| 348 | QuicDataReader reader(buffer_.data(), current_frame_length_); |
| 349 | if (!reader.ReadVarInt62(&frame.push_id)) { |
bnc | e7f6796 | 2019-08-08 06:34:35 -0700 | [diff] [blame] | 350 | // TODO(b/124216424): Use HTTP_MALFORMED_FRAME. |
| 351 | RaiseError(QUIC_INVALID_FRAME_DATA, "Unable to read push_id"); |
bnc | b9d07d9 | 2019-06-25 17:43:49 -0700 | [diff] [blame] | 352 | return false; |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 353 | } |
bnc | 01918c0 | 2019-08-08 07:08:47 -0700 | [diff] [blame] | 354 | if (!reader.IsDoneReading()) { |
| 355 | RaiseError(QUIC_INVALID_FRAME_DATA, |
| 356 | "Superfluous data in CANCEL_PUSH frame."); |
| 357 | return false; |
| 358 | } |
bnc | b9d07d9 | 2019-06-25 17:43:49 -0700 | [diff] [blame] | 359 | continue_processing = visitor_->OnCancelPushFrame(frame); |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 360 | break; |
| 361 | } |
bnc | 95fb6b6 | 2019-07-21 11:20:47 -0700 | [diff] [blame] | 362 | case static_cast<uint64_t>(HttpFrameType::SETTINGS): { |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 363 | SettingsFrame frame; |
| 364 | QuicDataReader reader(buffer_.data(), current_frame_length_); |
| 365 | if (!ParseSettingsFrame(&reader, &frame)) { |
bnc | b9d07d9 | 2019-06-25 17:43:49 -0700 | [diff] [blame] | 366 | return false; |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 367 | } |
bnc | b9d07d9 | 2019-06-25 17:43:49 -0700 | [diff] [blame] | 368 | continue_processing = visitor_->OnSettingsFrame(frame); |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 369 | break; |
| 370 | } |
bnc | 95fb6b6 | 2019-07-21 11:20:47 -0700 | [diff] [blame] | 371 | case static_cast<uint64_t>(HttpFrameType::PUSH_PROMISE): { |
bnc | b9d07d9 | 2019-06-25 17:43:49 -0700 | [diff] [blame] | 372 | continue_processing = visitor_->OnPushPromiseFrameEnd(); |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 373 | break; |
| 374 | } |
bnc | 95fb6b6 | 2019-07-21 11:20:47 -0700 | [diff] [blame] | 375 | case static_cast<uint64_t>(HttpFrameType::GOAWAY): { |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 376 | QuicDataReader reader(buffer_.data(), current_frame_length_); |
| 377 | GoAwayFrame frame; |
| 378 | static_assert(!std::is_same<decltype(frame.stream_id), uint64_t>::value, |
| 379 | "Please remove local |stream_id| variable and pass " |
| 380 | "&frame.stream_id directly to ReadVarInt62() when changing " |
| 381 | "QuicStreamId from uint32_t to uint64_t."); |
| 382 | uint64_t stream_id; |
| 383 | if (!reader.ReadVarInt62(&stream_id)) { |
bnc | e7f6796 | 2019-08-08 06:34:35 -0700 | [diff] [blame] | 384 | // TODO(b/124216424): Use HTTP_MALFORMED_FRAME. |
| 385 | RaiseError(QUIC_INVALID_FRAME_DATA, "Unable to read GOAWAY stream_id"); |
bnc | b9d07d9 | 2019-06-25 17:43:49 -0700 | [diff] [blame] | 386 | return false; |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 387 | } |
bnc | 01918c0 | 2019-08-08 07:08:47 -0700 | [diff] [blame] | 388 | if (!reader.IsDoneReading()) { |
| 389 | RaiseError(QUIC_INVALID_FRAME_DATA, |
| 390 | "Superfluous data in GOAWAY frame."); |
| 391 | return false; |
| 392 | } |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 393 | frame.stream_id = static_cast<QuicStreamId>(stream_id); |
bnc | b9d07d9 | 2019-06-25 17:43:49 -0700 | [diff] [blame] | 394 | continue_processing = visitor_->OnGoAwayFrame(frame); |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 395 | break; |
| 396 | } |
bnc | 95fb6b6 | 2019-07-21 11:20:47 -0700 | [diff] [blame] | 397 | case static_cast<uint64_t>(HttpFrameType::MAX_PUSH_ID): { |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 398 | QuicDataReader reader(buffer_.data(), current_frame_length_); |
| 399 | MaxPushIdFrame frame; |
| 400 | if (!reader.ReadVarInt62(&frame.push_id)) { |
bnc | e7f6796 | 2019-08-08 06:34:35 -0700 | [diff] [blame] | 401 | // TODO(b/124216424): Use HTTP_MALFORMED_FRAME. |
| 402 | RaiseError(QUIC_INVALID_FRAME_DATA, "Unable to read push_id"); |
bnc | b9d07d9 | 2019-06-25 17:43:49 -0700 | [diff] [blame] | 403 | return false; |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 404 | } |
bnc | 01918c0 | 2019-08-08 07:08:47 -0700 | [diff] [blame] | 405 | if (!reader.IsDoneReading()) { |
| 406 | RaiseError(QUIC_INVALID_FRAME_DATA, |
| 407 | "Superfluous data in MAX_PUSH_ID frame."); |
| 408 | return false; |
| 409 | } |
bnc | b9d07d9 | 2019-06-25 17:43:49 -0700 | [diff] [blame] | 410 | continue_processing = visitor_->OnMaxPushIdFrame(frame); |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 411 | break; |
| 412 | } |
bnc | 95fb6b6 | 2019-07-21 11:20:47 -0700 | [diff] [blame] | 413 | case static_cast<uint64_t>(HttpFrameType::DUPLICATE_PUSH): { |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 414 | QuicDataReader reader(buffer_.data(), current_frame_length_); |
| 415 | DuplicatePushFrame frame; |
| 416 | if (!reader.ReadVarInt62(&frame.push_id)) { |
bnc | e7f6796 | 2019-08-08 06:34:35 -0700 | [diff] [blame] | 417 | // TODO(b/124216424): Use HTTP_MALFORMED_FRAME. |
| 418 | RaiseError(QUIC_INVALID_FRAME_DATA, "Unable to read push_id"); |
bnc | b9d07d9 | 2019-06-25 17:43:49 -0700 | [diff] [blame] | 419 | return false; |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 420 | } |
bnc | 01918c0 | 2019-08-08 07:08:47 -0700 | [diff] [blame] | 421 | if (!reader.IsDoneReading()) { |
| 422 | RaiseError(QUIC_INVALID_FRAME_DATA, |
| 423 | "Superfluous data in DUPLICATE_PUSH frame."); |
| 424 | return false; |
| 425 | } |
bnc | b9d07d9 | 2019-06-25 17:43:49 -0700 | [diff] [blame] | 426 | continue_processing = visitor_->OnDuplicatePushFrame(frame); |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 427 | break; |
| 428 | } |
bnc | bf3dbe5 | 2019-07-17 05:17:41 -0700 | [diff] [blame] | 429 | default: { |
| 430 | continue_processing = visitor_->OnUnknownFrameEnd(); |
| 431 | break; |
| 432 | } |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 433 | } |
| 434 | |
renjietang | bb98cbc | 2019-04-23 13:13:56 -0700 | [diff] [blame] | 435 | current_length_field_length_ = 0; |
renjietang | 2d475cf | 2019-04-18 17:03:37 -0700 | [diff] [blame] | 436 | current_type_field_length_ = 0; |
renjietang | fcd91c0 | 2019-04-22 10:40:35 -0700 | [diff] [blame] | 437 | state_ = STATE_READING_FRAME_TYPE; |
bnc | b9d07d9 | 2019-06-25 17:43:49 -0700 | [diff] [blame] | 438 | return continue_processing; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 439 | } |
| 440 | |
| 441 | void HttpDecoder::DiscardFramePayload(QuicDataReader* reader) { |
| 442 | QuicByteCount bytes_to_read = std::min<QuicByteCount>( |
| 443 | remaining_frame_length_, reader->BytesRemaining()); |
dmcardle | ba2fb7e | 2019-12-13 07:44:34 -0800 | [diff] [blame] | 444 | quiche::QuicheStringPiece payload; |
bnc | 4368e7f | 2019-06-24 12:15:48 -0700 | [diff] [blame] | 445 | bool success = reader->ReadStringPiece(&payload, bytes_to_read); |
| 446 | DCHECK(success); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 447 | remaining_frame_length_ -= payload.length(); |
| 448 | if (remaining_frame_length_ == 0) { |
renjietang | fcd91c0 | 2019-04-22 10:40:35 -0700 | [diff] [blame] | 449 | state_ = STATE_READING_FRAME_TYPE; |
renjietang | bb98cbc | 2019-04-23 13:13:56 -0700 | [diff] [blame] | 450 | current_length_field_length_ = 0; |
renjietang | 2d475cf | 2019-04-18 17:03:37 -0700 | [diff] [blame] | 451 | current_type_field_length_ = 0; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 452 | } |
| 453 | } |
| 454 | |
| 455 | void HttpDecoder::BufferFramePayload(QuicDataReader* reader) { |
| 456 | if (current_frame_length_ == remaining_frame_length_) { |
| 457 | buffer_.erase(buffer_.size()); |
| 458 | buffer_.reserve(current_frame_length_); |
| 459 | } |
| 460 | QuicByteCount bytes_to_read = std::min<QuicByteCount>( |
| 461 | remaining_frame_length_, reader->BytesRemaining()); |
bnc | 4368e7f | 2019-06-24 12:15:48 -0700 | [diff] [blame] | 462 | bool success = reader->ReadBytes( |
| 463 | &(buffer_[0]) + current_frame_length_ - remaining_frame_length_, |
| 464 | bytes_to_read); |
| 465 | DCHECK(success); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 466 | remaining_frame_length_ -= bytes_to_read; |
| 467 | } |
| 468 | |
| 469 | void HttpDecoder::BufferFrameLength(QuicDataReader* reader) { |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 470 | QuicByteCount bytes_to_read = std::min<QuicByteCount>( |
| 471 | remaining_length_field_length_, reader->BytesRemaining()); |
bnc | 4368e7f | 2019-06-24 12:15:48 -0700 | [diff] [blame] | 472 | bool success = |
| 473 | reader->ReadBytes(length_buffer_.data() + current_length_field_length_ - |
| 474 | remaining_length_field_length_, |
| 475 | bytes_to_read); |
| 476 | DCHECK(success); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 477 | remaining_length_field_length_ -= bytes_to_read; |
| 478 | } |
| 479 | |
renjietang | 2d475cf | 2019-04-18 17:03:37 -0700 | [diff] [blame] | 480 | void HttpDecoder::BufferFrameType(QuicDataReader* reader) { |
renjietang | 2d475cf | 2019-04-18 17:03:37 -0700 | [diff] [blame] | 481 | QuicByteCount bytes_to_read = std::min<QuicByteCount>( |
| 482 | remaining_type_field_length_, reader->BytesRemaining()); |
bnc | 4368e7f | 2019-06-24 12:15:48 -0700 | [diff] [blame] | 483 | bool success = |
| 484 | reader->ReadBytes(type_buffer_.data() + current_type_field_length_ - |
| 485 | remaining_type_field_length_, |
| 486 | bytes_to_read); |
| 487 | DCHECK(success); |
renjietang | 2d475cf | 2019-04-18 17:03:37 -0700 | [diff] [blame] | 488 | remaining_type_field_length_ -= bytes_to_read; |
| 489 | } |
| 490 | |
renjietang | 857362b | 2019-08-09 09:52:35 -0700 | [diff] [blame] | 491 | void HttpDecoder::BufferPushId(QuicDataReader* reader) { |
| 492 | DCHECK_LE(remaining_push_id_length_, current_frame_length_); |
| 493 | QuicByteCount bytes_to_read = std::min<QuicByteCount>( |
| 494 | reader->BytesRemaining(), remaining_push_id_length_); |
| 495 | bool success = |
| 496 | reader->ReadBytes(push_id_buffer_.data() + current_push_id_length_ - |
| 497 | remaining_push_id_length_, |
| 498 | bytes_to_read); |
| 499 | DCHECK(success); |
| 500 | remaining_push_id_length_ -= bytes_to_read; |
| 501 | remaining_frame_length_ -= bytes_to_read; |
| 502 | } |
| 503 | |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame] | 504 | void HttpDecoder::RaiseError(QuicErrorCode error, std::string error_detail) { |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 505 | state_ = STATE_ERROR; |
| 506 | error_ = error; |
| 507 | error_detail_ = std::move(error_detail); |
bnc | 8983c0f | 2019-08-08 06:12:10 -0700 | [diff] [blame] | 508 | visitor_->OnError(this); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 509 | } |
| 510 | |
| 511 | bool HttpDecoder::ParsePriorityFrame(QuicDataReader* reader, |
| 512 | PriorityFrame* frame) { |
| 513 | uint8_t flags; |
bnc | 8dfeebd | 2019-07-16 11:41:29 -0700 | [diff] [blame] | 514 | if (!reader->ReadUInt8(&flags)) { |
| 515 | // TODO(b/124216424): Use HTTP_MALFORMED_FRAME. |
| 516 | RaiseError(QUIC_INVALID_FRAME_DATA, "Unable to read PRIORITY frame flags."); |
| 517 | return false; |
| 518 | } |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 519 | |
renjietang | 3a76c89 | 2019-07-17 10:03:53 -0700 | [diff] [blame] | 520 | // Assign two most significant bits to prioritized_type. |
| 521 | frame->prioritized_type = static_cast<PriorityElementType>((flags >> 6) & 3); |
| 522 | // Assign the next two most significant bits to dependency type. |
| 523 | frame->dependency_type = static_cast<PriorityElementType>((flags >> 4) & 3); |
bnc | efbda66 | 2019-07-17 17:01:13 -0700 | [diff] [blame] | 524 | frame->exclusive = flags & kPriorityExclusiveBit; |
| 525 | // TODO(bnc): Close connection with HTTP_MALFORMED_FRAME |
| 526 | // if lowest three bits are not all zero. |
| 527 | |
renjietang | ec09576 | 2019-06-19 14:35:02 -0700 | [diff] [blame] | 528 | if (frame->prioritized_type != ROOT_OF_TREE && |
| 529 | !reader->ReadVarInt62(&frame->prioritized_element_id)) { |
bnc | 8dfeebd | 2019-07-16 11:41:29 -0700 | [diff] [blame] | 530 | // TODO(b/124216424): Use HTTP_MALFORMED_FRAME. |
| 531 | RaiseError(QUIC_INVALID_FRAME_DATA, |
| 532 | "Unable to read prioritized_element_id."); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 533 | return false; |
| 534 | } |
renjietang | ec09576 | 2019-06-19 14:35:02 -0700 | [diff] [blame] | 535 | if (frame->dependency_type != ROOT_OF_TREE && |
| 536 | !reader->ReadVarInt62(&frame->element_dependency_id)) { |
bnc | 8dfeebd | 2019-07-16 11:41:29 -0700 | [diff] [blame] | 537 | // TODO(b/124216424): Use HTTP_MALFORMED_FRAME. |
| 538 | RaiseError(QUIC_INVALID_FRAME_DATA, |
| 539 | "Unable to read element_dependency_id."); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 540 | return false; |
| 541 | } |
| 542 | if (!reader->ReadUInt8(&frame->weight)) { |
bnc | 8dfeebd | 2019-07-16 11:41:29 -0700 | [diff] [blame] | 543 | // TODO(b/124216424): Use HTTP_MALFORMED_FRAME. |
| 544 | RaiseError(QUIC_INVALID_FRAME_DATA, |
bnc | 01918c0 | 2019-08-08 07:08:47 -0700 | [diff] [blame] | 545 | "Unable to read PRIORITY frame weight."); |
bnc | 8dfeebd | 2019-07-16 11:41:29 -0700 | [diff] [blame] | 546 | return false; |
| 547 | } |
| 548 | if (!reader->IsDoneReading()) { |
| 549 | // TODO(b/124216424): Use HTTP_MALFORMED_FRAME. |
bnc | 01918c0 | 2019-08-08 07:08:47 -0700 | [diff] [blame] | 550 | RaiseError(QUIC_INVALID_FRAME_DATA, "Superfluous data in PRIORITY frame."); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 551 | return false; |
| 552 | } |
| 553 | return true; |
| 554 | } |
| 555 | |
| 556 | bool HttpDecoder::ParseSettingsFrame(QuicDataReader* reader, |
| 557 | SettingsFrame* frame) { |
| 558 | while (!reader->IsDoneReading()) { |
renjietang | 3b3e3b3 | 2019-04-22 18:01:20 -0700 | [diff] [blame] | 559 | uint64_t id; |
| 560 | if (!reader->ReadVarInt62(&id)) { |
bnc | e7f6796 | 2019-08-08 06:34:35 -0700 | [diff] [blame] | 561 | // TODO(b/124216424): Use HTTP_MALFORMED_FRAME. |
| 562 | RaiseError(QUIC_INVALID_FRAME_DATA, |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 563 | "Unable to read settings frame identifier"); |
| 564 | return false; |
| 565 | } |
| 566 | uint64_t content; |
| 567 | if (!reader->ReadVarInt62(&content)) { |
bnc | e7f6796 | 2019-08-08 06:34:35 -0700 | [diff] [blame] | 568 | // TODO(b/124216424): Use HTTP_MALFORMED_FRAME. |
| 569 | RaiseError(QUIC_INVALID_FRAME_DATA, |
| 570 | "Unable to read settings frame content"); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 571 | return false; |
| 572 | } |
bnc | 93ea18d | 2019-08-22 09:57:43 -0700 | [diff] [blame] | 573 | auto result = frame->values.insert({id, content}); |
| 574 | if (!result.second) { |
| 575 | // TODO(b/124216424): Use HTTP_SETTINGS_ERROR. |
| 576 | RaiseError(QUIC_INVALID_FRAME_DATA, "Duplicate SETTINGS identifier."); |
| 577 | return false; |
| 578 | } |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 579 | } |
| 580 | return true; |
| 581 | } |
| 582 | |
bnc | 95fb6b6 | 2019-07-21 11:20:47 -0700 | [diff] [blame] | 583 | QuicByteCount HttpDecoder::MaxFrameLength(uint64_t frame_type) { |
renjietang | 4ab9d9f | 2019-04-10 14:30:26 -0700 | [diff] [blame] | 584 | switch (frame_type) { |
bnc | 95fb6b6 | 2019-07-21 11:20:47 -0700 | [diff] [blame] | 585 | case static_cast<uint64_t>(HttpFrameType::PRIORITY): |
renjietang | 4ab9d9f | 2019-04-10 14:30:26 -0700 | [diff] [blame] | 586 | return kPriorityFirstByteLength + VARIABLE_LENGTH_INTEGER_LENGTH_8 * 2 + |
| 587 | kPriorityWeightLength; |
bnc | 95fb6b6 | 2019-07-21 11:20:47 -0700 | [diff] [blame] | 588 | case static_cast<uint64_t>(HttpFrameType::CANCEL_PUSH): |
renjietang | 4ab9d9f | 2019-04-10 14:30:26 -0700 | [diff] [blame] | 589 | return sizeof(PushId); |
bnc | 95fb6b6 | 2019-07-21 11:20:47 -0700 | [diff] [blame] | 590 | case static_cast<uint64_t>(HttpFrameType::SETTINGS): |
renjietang | 4ab9d9f | 2019-04-10 14:30:26 -0700 | [diff] [blame] | 591 | // This limit is arbitrary. |
| 592 | return 1024 * 1024; |
bnc | 95fb6b6 | 2019-07-21 11:20:47 -0700 | [diff] [blame] | 593 | case static_cast<uint64_t>(HttpFrameType::GOAWAY): |
renjietang | 5843bfd | 2019-10-10 13:24:57 -0700 | [diff] [blame] | 594 | return VARIABLE_LENGTH_INTEGER_LENGTH_8; |
bnc | 95fb6b6 | 2019-07-21 11:20:47 -0700 | [diff] [blame] | 595 | case static_cast<uint64_t>(HttpFrameType::MAX_PUSH_ID): |
renjietang | 4ab9d9f | 2019-04-10 14:30:26 -0700 | [diff] [blame] | 596 | return sizeof(PushId); |
bnc | 95fb6b6 | 2019-07-21 11:20:47 -0700 | [diff] [blame] | 597 | case static_cast<uint64_t>(HttpFrameType::DUPLICATE_PUSH): |
renjietang | 4ab9d9f | 2019-04-10 14:30:26 -0700 | [diff] [blame] | 598 | return sizeof(PushId); |
| 599 | default: |
| 600 | // Other frames require no data buffering, so it's safe to have no limit. |
| 601 | return std::numeric_limits<QuicByteCount>::max(); |
| 602 | } |
| 603 | } |
| 604 | |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 605 | } // namespace quic |