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 | dfabdfb | 2020-01-17 17:46:40 -0800 | [diff] [blame] | 131 | RaiseError(QUIC_HTTP_FRAME_TOO_LARGE, "Frame is too large."); |
bnc | b9d07d9 | 2019-06-25 17:43:49 -0700 | [diff] [blame] | 132 | return false; |
renjietang | 4ab9d9f | 2019-04-10 14:30:26 -0700 | [diff] [blame] | 133 | } |
| 134 | |
renjietang | 7d4f913 | 2019-06-20 15:04:34 -0700 | [diff] [blame] | 135 | // Calling the following visitor methods does not require parsing of any |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 136 | // frame payload. |
bnc | b9d07d9 | 2019-06-25 17:43:49 -0700 | [diff] [blame] | 137 | bool continue_processing = true; |
bnc | a2b13be | 2019-07-31 12:04:20 -0700 | [diff] [blame] | 138 | const QuicByteCount header_length = |
| 139 | current_length_field_length_ + current_type_field_length_; |
bnc | bf3dbe5 | 2019-07-17 05:17:41 -0700 | [diff] [blame] | 140 | |
| 141 | switch (current_frame_type_) { |
bnc | 95fb6b6 | 2019-07-21 11:20:47 -0700 | [diff] [blame] | 142 | case static_cast<uint64_t>(HttpFrameType::DATA): |
bnc | a2b13be | 2019-07-31 12:04:20 -0700 | [diff] [blame] | 143 | continue_processing = visitor_->OnDataFrameStart(header_length); |
bnc | bf3dbe5 | 2019-07-17 05:17:41 -0700 | [diff] [blame] | 144 | break; |
bnc | 95fb6b6 | 2019-07-21 11:20:47 -0700 | [diff] [blame] | 145 | case static_cast<uint64_t>(HttpFrameType::HEADERS): |
bnc | a2b13be | 2019-07-31 12:04:20 -0700 | [diff] [blame] | 146 | continue_processing = visitor_->OnHeadersFrameStart(header_length); |
bnc | bf3dbe5 | 2019-07-17 05:17:41 -0700 | [diff] [blame] | 147 | break; |
bnc | 95fb6b6 | 2019-07-21 11:20:47 -0700 | [diff] [blame] | 148 | case static_cast<uint64_t>(HttpFrameType::CANCEL_PUSH): |
bnc | bf3dbe5 | 2019-07-17 05:17:41 -0700 | [diff] [blame] | 149 | break; |
bnc | 95fb6b6 | 2019-07-21 11:20:47 -0700 | [diff] [blame] | 150 | case static_cast<uint64_t>(HttpFrameType::SETTINGS): |
bnc | a2b13be | 2019-07-31 12:04:20 -0700 | [diff] [blame] | 151 | continue_processing = visitor_->OnSettingsFrameStart(header_length); |
bnc | bf3dbe5 | 2019-07-17 05:17:41 -0700 | [diff] [blame] | 152 | break; |
bnc | 95fb6b6 | 2019-07-21 11:20:47 -0700 | [diff] [blame] | 153 | case static_cast<uint64_t>(HttpFrameType::PUSH_PROMISE): |
bnc | f0db654 | 2019-09-23 11:18:28 -0700 | [diff] [blame] | 154 | // This edge case needs to be handled here, because ReadFramePayload() |
| 155 | // does not get called if |current_frame_length_| is zero. |
bnc | fcd4235 | 2019-09-20 17:55:47 -0700 | [diff] [blame] | 156 | if (current_frame_length_ == 0) { |
bnc | dfabdfb | 2020-01-17 17:46:40 -0800 | [diff] [blame] | 157 | RaiseError(QUIC_HTTP_FRAME_ERROR, |
| 158 | "PUSH_PROMISE frame with empty payload."); |
bnc | fcd4235 | 2019-09-20 17:55:47 -0700 | [diff] [blame] | 159 | return false; |
| 160 | } |
bnc | f0db654 | 2019-09-23 11:18:28 -0700 | [diff] [blame] | 161 | continue_processing = visitor_->OnPushPromiseFrameStart(header_length); |
bnc | bf3dbe5 | 2019-07-17 05:17:41 -0700 | [diff] [blame] | 162 | break; |
bnc | 95fb6b6 | 2019-07-21 11:20:47 -0700 | [diff] [blame] | 163 | case static_cast<uint64_t>(HttpFrameType::GOAWAY): |
bnc | bf3dbe5 | 2019-07-17 05:17:41 -0700 | [diff] [blame] | 164 | break; |
bnc | 95fb6b6 | 2019-07-21 11:20:47 -0700 | [diff] [blame] | 165 | case static_cast<uint64_t>(HttpFrameType::MAX_PUSH_ID): |
bnc | bf3dbe5 | 2019-07-17 05:17:41 -0700 | [diff] [blame] | 166 | break; |
bnc | 95fb6b6 | 2019-07-21 11:20:47 -0700 | [diff] [blame] | 167 | case static_cast<uint64_t>(HttpFrameType::DUPLICATE_PUSH): |
bnc | bf3dbe5 | 2019-07-17 05:17:41 -0700 | [diff] [blame] | 168 | break; |
bnc | 51e8962 | 2020-01-10 10:40:32 -0800 | [diff] [blame] | 169 | case static_cast<uint64_t>(HttpFrameType::PRIORITY_UPDATE): |
| 170 | continue_processing = visitor_->OnPriorityUpdateFrameStart(header_length); |
| 171 | break; |
bnc | bf3dbe5 | 2019-07-17 05:17:41 -0700 | [diff] [blame] | 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::CANCEL_PUSH): { |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 214 | BufferFramePayload(reader); |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 215 | break; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 216 | } |
bnc | 95fb6b6 | 2019-07-21 11:20:47 -0700 | [diff] [blame] | 217 | case static_cast<uint64_t>(HttpFrameType::SETTINGS): { |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 218 | BufferFramePayload(reader); |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 219 | break; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 220 | } |
bnc | 95fb6b6 | 2019-07-21 11:20:47 -0700 | [diff] [blame] | 221 | case static_cast<uint64_t>(HttpFrameType::PUSH_PROMISE): { |
renjietang | 857362b | 2019-08-09 09:52:35 -0700 | [diff] [blame] | 222 | PushId push_id; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 223 | if (current_frame_length_ == remaining_frame_length_) { |
renjietang | 857362b | 2019-08-09 09:52:35 -0700 | [diff] [blame] | 224 | // A new Push Promise frame just arrived. |
| 225 | DCHECK_EQ(0u, current_push_id_length_); |
| 226 | current_push_id_length_ = reader->PeekVarInt62Length(); |
| 227 | if (current_push_id_length_ > remaining_frame_length_) { |
bnc | dfabdfb | 2020-01-17 17:46:40 -0800 | [diff] [blame] | 228 | RaiseError(QUIC_HTTP_FRAME_ERROR, |
| 229 | "Unable to read PUSH_PROMISE push_id."); |
bnc | b9d07d9 | 2019-06-25 17:43:49 -0700 | [diff] [blame] | 230 | return false; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 231 | } |
renjietang | 857362b | 2019-08-09 09:52:35 -0700 | [diff] [blame] | 232 | if (current_push_id_length_ > reader->BytesRemaining()) { |
| 233 | // Not all bytes of push id is present yet, buffer push id. |
| 234 | DCHECK_EQ(0u, remaining_push_id_length_); |
| 235 | remaining_push_id_length_ = current_push_id_length_; |
| 236 | BufferPushId(reader); |
bnc | b9d07d9 | 2019-06-25 17:43:49 -0700 | [diff] [blame] | 237 | break; |
renjietang | 546a628 | 2019-06-03 10:21:21 -0700 | [diff] [blame] | 238 | } |
renjietang | 857362b | 2019-08-09 09:52:35 -0700 | [diff] [blame] | 239 | bool success = reader->ReadVarInt62(&push_id); |
| 240 | DCHECK(success); |
| 241 | remaining_frame_length_ -= current_push_id_length_; |
bnc | f0db654 | 2019-09-23 11:18:28 -0700 | [diff] [blame] | 242 | if (!visitor_->OnPushPromiseFramePushId(push_id, |
| 243 | current_push_id_length_)) { |
renjietang | 857362b | 2019-08-09 09:52:35 -0700 | [diff] [blame] | 244 | continue_processing = false; |
| 245 | current_push_id_length_ = 0; |
| 246 | break; |
| 247 | } |
| 248 | current_push_id_length_ = 0; |
| 249 | } else if (remaining_push_id_length_ > 0) { |
| 250 | // Waiting for more bytes on push id. |
| 251 | BufferPushId(reader); |
| 252 | if (remaining_push_id_length_ != 0) { |
| 253 | break; |
| 254 | } |
| 255 | QuicDataReader push_id_reader(push_id_buffer_.data(), |
| 256 | current_push_id_length_); |
| 257 | |
| 258 | bool success = push_id_reader.ReadVarInt62(&push_id); |
| 259 | DCHECK(success); |
bnc | f0db654 | 2019-09-23 11:18:28 -0700 | [diff] [blame] | 260 | if (!visitor_->OnPushPromiseFramePushId(push_id, |
| 261 | current_push_id_length_)) { |
renjietang | 857362b | 2019-08-09 09:52:35 -0700 | [diff] [blame] | 262 | continue_processing = false; |
| 263 | current_push_id_length_ = 0; |
| 264 | break; |
| 265 | } |
| 266 | current_push_id_length_ = 0; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 267 | } |
renjietang | 857362b | 2019-08-09 09:52:35 -0700 | [diff] [blame] | 268 | |
| 269 | // Read Push Promise headers. |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 270 | DCHECK_LT(remaining_frame_length_, current_frame_length_); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 271 | QuicByteCount bytes_to_read = std::min<QuicByteCount>( |
| 272 | remaining_frame_length_, reader->BytesRemaining()); |
| 273 | if (bytes_to_read == 0) { |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 274 | break; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 275 | } |
dmcardle | ba2fb7e | 2019-12-13 07:44:34 -0800 | [diff] [blame] | 276 | quiche::QuicheStringPiece payload; |
bnc | 4368e7f | 2019-06-24 12:15:48 -0700 | [diff] [blame] | 277 | bool success = reader->ReadStringPiece(&payload, bytes_to_read); |
| 278 | DCHECK(success); |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 279 | DCHECK(!payload.empty()); |
bnc | b9d07d9 | 2019-06-25 17:43:49 -0700 | [diff] [blame] | 280 | continue_processing = visitor_->OnPushPromiseFramePayload(payload); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 281 | remaining_frame_length_ -= payload.length(); |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 282 | break; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 283 | } |
bnc | 95fb6b6 | 2019-07-21 11:20:47 -0700 | [diff] [blame] | 284 | case static_cast<uint64_t>(HttpFrameType::GOAWAY): { |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 285 | BufferFramePayload(reader); |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 286 | break; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 287 | } |
bnc | 95fb6b6 | 2019-07-21 11:20:47 -0700 | [diff] [blame] | 288 | case static_cast<uint64_t>(HttpFrameType::MAX_PUSH_ID): { |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 289 | BufferFramePayload(reader); |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 290 | break; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 291 | } |
bnc | 95fb6b6 | 2019-07-21 11:20:47 -0700 | [diff] [blame] | 292 | case static_cast<uint64_t>(HttpFrameType::DUPLICATE_PUSH): { |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 293 | BufferFramePayload(reader); |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 294 | break; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 295 | } |
bnc | 51e8962 | 2020-01-10 10:40:32 -0800 | [diff] [blame] | 296 | case static_cast<uint64_t>(HttpFrameType::PRIORITY_UPDATE): { |
| 297 | // TODO(bnc): Avoid buffering if the entire frame is present, and |
| 298 | // instead parse directly out of |reader|. |
| 299 | BufferFramePayload(reader); |
| 300 | break; |
| 301 | } |
bnc | bf3dbe5 | 2019-07-17 05:17:41 -0700 | [diff] [blame] | 302 | default: { |
| 303 | QuicByteCount bytes_to_read = std::min<QuicByteCount>( |
| 304 | remaining_frame_length_, reader->BytesRemaining()); |
dmcardle | ba2fb7e | 2019-12-13 07:44:34 -0800 | [diff] [blame] | 305 | quiche::QuicheStringPiece payload; |
bnc | bf3dbe5 | 2019-07-17 05:17:41 -0700 | [diff] [blame] | 306 | bool success = reader->ReadStringPiece(&payload, bytes_to_read); |
| 307 | DCHECK(success); |
| 308 | DCHECK(!payload.empty()); |
| 309 | continue_processing = visitor_->OnUnknownFramePayload(payload); |
| 310 | remaining_frame_length_ -= payload.length(); |
| 311 | break; |
| 312 | } |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 313 | } |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 314 | |
| 315 | if (remaining_frame_length_ == 0) { |
| 316 | state_ = STATE_FINISH_PARSING; |
| 317 | } |
bnc | b9d07d9 | 2019-06-25 17:43:49 -0700 | [diff] [blame] | 318 | |
| 319 | return continue_processing; |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 320 | } |
| 321 | |
bnc | b9d07d9 | 2019-06-25 17:43:49 -0700 | [diff] [blame] | 322 | bool HttpDecoder::FinishParsing() { |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 323 | DCHECK_EQ(0u, remaining_frame_length_); |
bnc | b9d07d9 | 2019-06-25 17:43:49 -0700 | [diff] [blame] | 324 | |
| 325 | bool continue_processing = true; |
| 326 | |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 327 | switch (current_frame_type_) { |
bnc | 95fb6b6 | 2019-07-21 11:20:47 -0700 | [diff] [blame] | 328 | case static_cast<uint64_t>(HttpFrameType::DATA): { |
bnc | b9d07d9 | 2019-06-25 17:43:49 -0700 | [diff] [blame] | 329 | continue_processing = visitor_->OnDataFrameEnd(); |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 330 | break; |
| 331 | } |
bnc | 95fb6b6 | 2019-07-21 11:20:47 -0700 | [diff] [blame] | 332 | case static_cast<uint64_t>(HttpFrameType::HEADERS): { |
bnc | b9d07d9 | 2019-06-25 17:43:49 -0700 | [diff] [blame] | 333 | continue_processing = visitor_->OnHeadersFrameEnd(); |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 334 | break; |
| 335 | } |
bnc | 95fb6b6 | 2019-07-21 11:20:47 -0700 | [diff] [blame] | 336 | case static_cast<uint64_t>(HttpFrameType::CANCEL_PUSH): { |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 337 | CancelPushFrame frame; |
| 338 | QuicDataReader reader(buffer_.data(), current_frame_length_); |
| 339 | if (!reader.ReadVarInt62(&frame.push_id)) { |
bnc | dfabdfb | 2020-01-17 17:46:40 -0800 | [diff] [blame] | 340 | RaiseError(QUIC_HTTP_FRAME_ERROR, |
| 341 | "Unable to read CANCEL_PUSH push_id."); |
bnc | b9d07d9 | 2019-06-25 17:43:49 -0700 | [diff] [blame] | 342 | return false; |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 343 | } |
bnc | 01918c0 | 2019-08-08 07:08:47 -0700 | [diff] [blame] | 344 | if (!reader.IsDoneReading()) { |
bnc | dfabdfb | 2020-01-17 17:46:40 -0800 | [diff] [blame] | 345 | RaiseError(QUIC_HTTP_FRAME_ERROR, |
bnc | 01918c0 | 2019-08-08 07:08:47 -0700 | [diff] [blame] | 346 | "Superfluous data in CANCEL_PUSH frame."); |
| 347 | return false; |
| 348 | } |
bnc | b9d07d9 | 2019-06-25 17:43:49 -0700 | [diff] [blame] | 349 | continue_processing = visitor_->OnCancelPushFrame(frame); |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 350 | break; |
| 351 | } |
bnc | 95fb6b6 | 2019-07-21 11:20:47 -0700 | [diff] [blame] | 352 | case static_cast<uint64_t>(HttpFrameType::SETTINGS): { |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 353 | SettingsFrame frame; |
| 354 | QuicDataReader reader(buffer_.data(), current_frame_length_); |
| 355 | if (!ParseSettingsFrame(&reader, &frame)) { |
bnc | b9d07d9 | 2019-06-25 17:43:49 -0700 | [diff] [blame] | 356 | return false; |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 357 | } |
bnc | b9d07d9 | 2019-06-25 17:43:49 -0700 | [diff] [blame] | 358 | continue_processing = visitor_->OnSettingsFrame(frame); |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 359 | break; |
| 360 | } |
bnc | 95fb6b6 | 2019-07-21 11:20:47 -0700 | [diff] [blame] | 361 | case static_cast<uint64_t>(HttpFrameType::PUSH_PROMISE): { |
bnc | b9d07d9 | 2019-06-25 17:43:49 -0700 | [diff] [blame] | 362 | continue_processing = visitor_->OnPushPromiseFrameEnd(); |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 363 | break; |
| 364 | } |
bnc | 95fb6b6 | 2019-07-21 11:20:47 -0700 | [diff] [blame] | 365 | case static_cast<uint64_t>(HttpFrameType::GOAWAY): { |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 366 | QuicDataReader reader(buffer_.data(), current_frame_length_); |
| 367 | GoAwayFrame frame; |
| 368 | static_assert(!std::is_same<decltype(frame.stream_id), uint64_t>::value, |
| 369 | "Please remove local |stream_id| variable and pass " |
| 370 | "&frame.stream_id directly to ReadVarInt62() when changing " |
| 371 | "QuicStreamId from uint32_t to uint64_t."); |
| 372 | uint64_t stream_id; |
| 373 | if (!reader.ReadVarInt62(&stream_id)) { |
bnc | dfabdfb | 2020-01-17 17:46:40 -0800 | [diff] [blame] | 374 | RaiseError(QUIC_HTTP_FRAME_ERROR, "Unable to read GOAWAY stream_id."); |
bnc | b9d07d9 | 2019-06-25 17:43:49 -0700 | [diff] [blame] | 375 | return false; |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 376 | } |
bnc | 01918c0 | 2019-08-08 07:08:47 -0700 | [diff] [blame] | 377 | if (!reader.IsDoneReading()) { |
bnc | dfabdfb | 2020-01-17 17:46:40 -0800 | [diff] [blame] | 378 | RaiseError(QUIC_HTTP_FRAME_ERROR, "Superfluous data in GOAWAY frame."); |
bnc | 01918c0 | 2019-08-08 07:08:47 -0700 | [diff] [blame] | 379 | return false; |
| 380 | } |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 381 | frame.stream_id = static_cast<QuicStreamId>(stream_id); |
bnc | b9d07d9 | 2019-06-25 17:43:49 -0700 | [diff] [blame] | 382 | continue_processing = visitor_->OnGoAwayFrame(frame); |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 383 | break; |
| 384 | } |
bnc | 95fb6b6 | 2019-07-21 11:20:47 -0700 | [diff] [blame] | 385 | case static_cast<uint64_t>(HttpFrameType::MAX_PUSH_ID): { |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 386 | QuicDataReader reader(buffer_.data(), current_frame_length_); |
| 387 | MaxPushIdFrame frame; |
| 388 | if (!reader.ReadVarInt62(&frame.push_id)) { |
bnc | dfabdfb | 2020-01-17 17:46:40 -0800 | [diff] [blame] | 389 | RaiseError(QUIC_HTTP_FRAME_ERROR, |
| 390 | "Unable to read MAX_PUSH_ID push_id."); |
bnc | b9d07d9 | 2019-06-25 17:43:49 -0700 | [diff] [blame] | 391 | return false; |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 392 | } |
bnc | 01918c0 | 2019-08-08 07:08:47 -0700 | [diff] [blame] | 393 | if (!reader.IsDoneReading()) { |
bnc | dfabdfb | 2020-01-17 17:46:40 -0800 | [diff] [blame] | 394 | RaiseError(QUIC_HTTP_FRAME_ERROR, |
bnc | 01918c0 | 2019-08-08 07:08:47 -0700 | [diff] [blame] | 395 | "Superfluous data in MAX_PUSH_ID frame."); |
| 396 | return false; |
| 397 | } |
bnc | b9d07d9 | 2019-06-25 17:43:49 -0700 | [diff] [blame] | 398 | continue_processing = visitor_->OnMaxPushIdFrame(frame); |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 399 | break; |
| 400 | } |
bnc | 95fb6b6 | 2019-07-21 11:20:47 -0700 | [diff] [blame] | 401 | case static_cast<uint64_t>(HttpFrameType::DUPLICATE_PUSH): { |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 402 | QuicDataReader reader(buffer_.data(), current_frame_length_); |
| 403 | DuplicatePushFrame frame; |
| 404 | if (!reader.ReadVarInt62(&frame.push_id)) { |
bnc | dfabdfb | 2020-01-17 17:46:40 -0800 | [diff] [blame] | 405 | RaiseError(QUIC_HTTP_FRAME_ERROR, |
| 406 | "Unable to read DUPLICATE_PUSH push_id."); |
bnc | b9d07d9 | 2019-06-25 17:43:49 -0700 | [diff] [blame] | 407 | return false; |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 408 | } |
bnc | 01918c0 | 2019-08-08 07:08:47 -0700 | [diff] [blame] | 409 | if (!reader.IsDoneReading()) { |
bnc | dfabdfb | 2020-01-17 17:46:40 -0800 | [diff] [blame] | 410 | RaiseError(QUIC_HTTP_FRAME_ERROR, |
bnc | 01918c0 | 2019-08-08 07:08:47 -0700 | [diff] [blame] | 411 | "Superfluous data in DUPLICATE_PUSH frame."); |
| 412 | return false; |
| 413 | } |
bnc | b9d07d9 | 2019-06-25 17:43:49 -0700 | [diff] [blame] | 414 | continue_processing = visitor_->OnDuplicatePushFrame(frame); |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 415 | break; |
| 416 | } |
bnc | 51e8962 | 2020-01-10 10:40:32 -0800 | [diff] [blame] | 417 | case static_cast<uint64_t>(HttpFrameType::PRIORITY_UPDATE): { |
| 418 | // TODO(bnc): Avoid buffering if the entire frame is present, and |
| 419 | // instead parse directly out of |reader|. |
| 420 | PriorityUpdateFrame frame; |
| 421 | QuicDataReader reader(buffer_.data(), current_frame_length_); |
| 422 | if (!ParsePriorityUpdateFrame(&reader, &frame)) { |
| 423 | return false; |
| 424 | } |
| 425 | continue_processing = visitor_->OnPriorityUpdateFrame(frame); |
| 426 | break; |
| 427 | } |
bnc | bf3dbe5 | 2019-07-17 05:17:41 -0700 | [diff] [blame] | 428 | default: { |
| 429 | continue_processing = visitor_->OnUnknownFrameEnd(); |
| 430 | break; |
| 431 | } |
bnc | 7091426 | 2019-03-16 12:49:50 -0700 | [diff] [blame] | 432 | } |
| 433 | |
renjietang | bb98cbc | 2019-04-23 13:13:56 -0700 | [diff] [blame] | 434 | current_length_field_length_ = 0; |
renjietang | 2d475cf | 2019-04-18 17:03:37 -0700 | [diff] [blame] | 435 | current_type_field_length_ = 0; |
renjietang | fcd91c0 | 2019-04-22 10:40:35 -0700 | [diff] [blame] | 436 | state_ = STATE_READING_FRAME_TYPE; |
bnc | b9d07d9 | 2019-06-25 17:43:49 -0700 | [diff] [blame] | 437 | return continue_processing; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 438 | } |
| 439 | |
| 440 | void HttpDecoder::DiscardFramePayload(QuicDataReader* reader) { |
| 441 | QuicByteCount bytes_to_read = std::min<QuicByteCount>( |
| 442 | remaining_frame_length_, reader->BytesRemaining()); |
dmcardle | ba2fb7e | 2019-12-13 07:44:34 -0800 | [diff] [blame] | 443 | quiche::QuicheStringPiece payload; |
bnc | 4368e7f | 2019-06-24 12:15:48 -0700 | [diff] [blame] | 444 | bool success = reader->ReadStringPiece(&payload, bytes_to_read); |
| 445 | DCHECK(success); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 446 | remaining_frame_length_ -= payload.length(); |
| 447 | if (remaining_frame_length_ == 0) { |
renjietang | fcd91c0 | 2019-04-22 10:40:35 -0700 | [diff] [blame] | 448 | state_ = STATE_READING_FRAME_TYPE; |
renjietang | bb98cbc | 2019-04-23 13:13:56 -0700 | [diff] [blame] | 449 | current_length_field_length_ = 0; |
renjietang | 2d475cf | 2019-04-18 17:03:37 -0700 | [diff] [blame] | 450 | current_type_field_length_ = 0; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 451 | } |
| 452 | } |
| 453 | |
| 454 | void HttpDecoder::BufferFramePayload(QuicDataReader* reader) { |
| 455 | if (current_frame_length_ == remaining_frame_length_) { |
| 456 | buffer_.erase(buffer_.size()); |
| 457 | buffer_.reserve(current_frame_length_); |
| 458 | } |
| 459 | QuicByteCount bytes_to_read = std::min<QuicByteCount>( |
| 460 | remaining_frame_length_, reader->BytesRemaining()); |
bnc | 4368e7f | 2019-06-24 12:15:48 -0700 | [diff] [blame] | 461 | bool success = reader->ReadBytes( |
| 462 | &(buffer_[0]) + current_frame_length_ - remaining_frame_length_, |
| 463 | bytes_to_read); |
| 464 | DCHECK(success); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 465 | remaining_frame_length_ -= bytes_to_read; |
| 466 | } |
| 467 | |
| 468 | void HttpDecoder::BufferFrameLength(QuicDataReader* reader) { |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 469 | QuicByteCount bytes_to_read = std::min<QuicByteCount>( |
| 470 | remaining_length_field_length_, reader->BytesRemaining()); |
bnc | 4368e7f | 2019-06-24 12:15:48 -0700 | [diff] [blame] | 471 | bool success = |
| 472 | reader->ReadBytes(length_buffer_.data() + current_length_field_length_ - |
| 473 | remaining_length_field_length_, |
| 474 | bytes_to_read); |
| 475 | DCHECK(success); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 476 | remaining_length_field_length_ -= bytes_to_read; |
| 477 | } |
| 478 | |
renjietang | 2d475cf | 2019-04-18 17:03:37 -0700 | [diff] [blame] | 479 | void HttpDecoder::BufferFrameType(QuicDataReader* reader) { |
renjietang | 2d475cf | 2019-04-18 17:03:37 -0700 | [diff] [blame] | 480 | QuicByteCount bytes_to_read = std::min<QuicByteCount>( |
| 481 | remaining_type_field_length_, reader->BytesRemaining()); |
bnc | 4368e7f | 2019-06-24 12:15:48 -0700 | [diff] [blame] | 482 | bool success = |
| 483 | reader->ReadBytes(type_buffer_.data() + current_type_field_length_ - |
| 484 | remaining_type_field_length_, |
| 485 | bytes_to_read); |
| 486 | DCHECK(success); |
renjietang | 2d475cf | 2019-04-18 17:03:37 -0700 | [diff] [blame] | 487 | remaining_type_field_length_ -= bytes_to_read; |
| 488 | } |
| 489 | |
renjietang | 857362b | 2019-08-09 09:52:35 -0700 | [diff] [blame] | 490 | void HttpDecoder::BufferPushId(QuicDataReader* reader) { |
| 491 | DCHECK_LE(remaining_push_id_length_, current_frame_length_); |
| 492 | QuicByteCount bytes_to_read = std::min<QuicByteCount>( |
| 493 | reader->BytesRemaining(), remaining_push_id_length_); |
| 494 | bool success = |
| 495 | reader->ReadBytes(push_id_buffer_.data() + current_push_id_length_ - |
| 496 | remaining_push_id_length_, |
| 497 | bytes_to_read); |
| 498 | DCHECK(success); |
| 499 | remaining_push_id_length_ -= bytes_to_read; |
| 500 | remaining_frame_length_ -= bytes_to_read; |
| 501 | } |
| 502 | |
vasilvv | c48c871 | 2019-03-11 13:38:16 -0700 | [diff] [blame] | 503 | void HttpDecoder::RaiseError(QuicErrorCode error, std::string error_detail) { |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 504 | state_ = STATE_ERROR; |
| 505 | error_ = error; |
| 506 | error_detail_ = std::move(error_detail); |
bnc | 8983c0f | 2019-08-08 06:12:10 -0700 | [diff] [blame] | 507 | visitor_->OnError(this); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 508 | } |
| 509 | |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 510 | bool HttpDecoder::ParseSettingsFrame(QuicDataReader* reader, |
| 511 | SettingsFrame* frame) { |
| 512 | while (!reader->IsDoneReading()) { |
renjietang | 3b3e3b3 | 2019-04-22 18:01:20 -0700 | [diff] [blame] | 513 | uint64_t id; |
| 514 | if (!reader->ReadVarInt62(&id)) { |
bnc | dfabdfb | 2020-01-17 17:46:40 -0800 | [diff] [blame] | 515 | RaiseError(QUIC_HTTP_FRAME_ERROR, "Unable to read setting identifier."); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 516 | return false; |
| 517 | } |
| 518 | uint64_t content; |
| 519 | if (!reader->ReadVarInt62(&content)) { |
bnc | dfabdfb | 2020-01-17 17:46:40 -0800 | [diff] [blame] | 520 | RaiseError(QUIC_HTTP_FRAME_ERROR, "Unable to read setting value."); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 521 | return false; |
| 522 | } |
bnc | 93ea18d | 2019-08-22 09:57:43 -0700 | [diff] [blame] | 523 | auto result = frame->values.insert({id, content}); |
| 524 | if (!result.second) { |
bnc | dfabdfb | 2020-01-17 17:46:40 -0800 | [diff] [blame] | 525 | RaiseError(QUIC_HTTP_FRAME_ERROR, "Duplicate setting identifier."); |
bnc | 93ea18d | 2019-08-22 09:57:43 -0700 | [diff] [blame] | 526 | return false; |
| 527 | } |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 528 | } |
| 529 | return true; |
| 530 | } |
| 531 | |
bnc | 51e8962 | 2020-01-10 10:40:32 -0800 | [diff] [blame] | 532 | bool HttpDecoder::ParsePriorityUpdateFrame(QuicDataReader* reader, |
| 533 | PriorityUpdateFrame* frame) { |
| 534 | uint8_t prioritized_element_type; |
| 535 | if (!reader->ReadUInt8(&prioritized_element_type)) { |
bnc | dfabdfb | 2020-01-17 17:46:40 -0800 | [diff] [blame] | 536 | RaiseError(QUIC_HTTP_FRAME_ERROR, |
bnc | 51e8962 | 2020-01-10 10:40:32 -0800 | [diff] [blame] | 537 | "Unable to read prioritized element type."); |
| 538 | return false; |
| 539 | } |
| 540 | |
| 541 | if (prioritized_element_type != REQUEST_STREAM && |
| 542 | prioritized_element_type != PUSH_STREAM) { |
bnc | dfabdfb | 2020-01-17 17:46:40 -0800 | [diff] [blame] | 543 | RaiseError(QUIC_HTTP_FRAME_ERROR, "Invalid prioritized element type."); |
bnc | 51e8962 | 2020-01-10 10:40:32 -0800 | [diff] [blame] | 544 | return false; |
| 545 | } |
| 546 | |
| 547 | frame->prioritized_element_type = |
| 548 | static_cast<PrioritizedElementType>(prioritized_element_type); |
| 549 | |
| 550 | if (!reader->ReadVarInt62(&frame->prioritized_element_id)) { |
bnc | dfabdfb | 2020-01-17 17:46:40 -0800 | [diff] [blame] | 551 | RaiseError(QUIC_HTTP_FRAME_ERROR, "Unable to read prioritized element id."); |
bnc | 51e8962 | 2020-01-10 10:40:32 -0800 | [diff] [blame] | 552 | return false; |
| 553 | } |
| 554 | |
| 555 | quiche::QuicheStringPiece priority_field_value = |
| 556 | reader->ReadRemainingPayload(); |
| 557 | frame->priority_field_value = |
| 558 | std::string(priority_field_value.data(), priority_field_value.size()); |
| 559 | |
| 560 | return true; |
| 561 | } |
| 562 | |
bnc | 95fb6b6 | 2019-07-21 11:20:47 -0700 | [diff] [blame] | 563 | QuicByteCount HttpDecoder::MaxFrameLength(uint64_t frame_type) { |
renjietang | 4ab9d9f | 2019-04-10 14:30:26 -0700 | [diff] [blame] | 564 | switch (frame_type) { |
bnc | 95fb6b6 | 2019-07-21 11:20:47 -0700 | [diff] [blame] | 565 | case static_cast<uint64_t>(HttpFrameType::CANCEL_PUSH): |
renjietang | 4ab9d9f | 2019-04-10 14:30:26 -0700 | [diff] [blame] | 566 | return sizeof(PushId); |
bnc | 95fb6b6 | 2019-07-21 11:20:47 -0700 | [diff] [blame] | 567 | case static_cast<uint64_t>(HttpFrameType::SETTINGS): |
renjietang | 4ab9d9f | 2019-04-10 14:30:26 -0700 | [diff] [blame] | 568 | // This limit is arbitrary. |
| 569 | return 1024 * 1024; |
bnc | 95fb6b6 | 2019-07-21 11:20:47 -0700 | [diff] [blame] | 570 | case static_cast<uint64_t>(HttpFrameType::GOAWAY): |
renjietang | 5843bfd | 2019-10-10 13:24:57 -0700 | [diff] [blame] | 571 | return VARIABLE_LENGTH_INTEGER_LENGTH_8; |
bnc | 95fb6b6 | 2019-07-21 11:20:47 -0700 | [diff] [blame] | 572 | case static_cast<uint64_t>(HttpFrameType::MAX_PUSH_ID): |
renjietang | 4ab9d9f | 2019-04-10 14:30:26 -0700 | [diff] [blame] | 573 | return sizeof(PushId); |
bnc | 95fb6b6 | 2019-07-21 11:20:47 -0700 | [diff] [blame] | 574 | case static_cast<uint64_t>(HttpFrameType::DUPLICATE_PUSH): |
renjietang | 4ab9d9f | 2019-04-10 14:30:26 -0700 | [diff] [blame] | 575 | return sizeof(PushId); |
bnc | 51e8962 | 2020-01-10 10:40:32 -0800 | [diff] [blame] | 576 | case static_cast<uint64_t>(HttpFrameType::PRIORITY_UPDATE): |
| 577 | // This limit is arbitrary. |
| 578 | return 1024 * 1024; |
renjietang | 4ab9d9f | 2019-04-10 14:30:26 -0700 | [diff] [blame] | 579 | default: |
| 580 | // Other frames require no data buffering, so it's safe to have no limit. |
| 581 | return std::numeric_limits<QuicByteCount>::max(); |
| 582 | } |
| 583 | } |
| 584 | |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 585 | } // namespace quic |