Project import generated by Copybara.

PiperOrigin-RevId: 237361882
Change-Id: I109a68f44db867b20f8c6a7732b0ce657133e52a
diff --git a/quic/core/http/http_decoder.cc b/quic/core/http/http_decoder.cc
new file mode 100644
index 0000000..e697821
--- /dev/null
+++ b/quic/core/http/http_decoder.cc
@@ -0,0 +1,411 @@
+// Copyright (c) 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/third_party/quiche/src/quic/core/http/http_decoder.h"
+#include "net/third_party/quiche/src/quic/core/quic_data_reader.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_fallthrough.h"
+
+namespace quic {
+
+namespace {
+
+// Create a mask that sets the last |num_bits| to 1 and the rest to 0.
+inline uint8_t GetMaskFromNumBits(uint8_t num_bits) {
+  return (1u << num_bits) - 1;
+}
+
+// Extract |num_bits| from |flags| offset by |offset|.
+uint8_t ExtractBits(uint8_t flags, uint8_t num_bits, uint8_t offset) {
+  return (flags >> offset) & GetMaskFromNumBits(num_bits);
+}
+
+// Length of the type field of HTTP/3 frames.
+static const QuicByteCount kFrameTypeLength = 1;
+
+}  // namespace
+
+HttpDecoder::HttpDecoder()
+    : visitor_(nullptr),
+      state_(STATE_READING_FRAME_LENGTH),
+      current_frame_type_(0),
+      current_length_field_size_(0),
+      remaining_length_field_length_(0),
+      current_frame_length_(0),
+      remaining_frame_length_(0),
+      error_(QUIC_NO_ERROR),
+      error_detail_(""),
+      has_payload_(false) {}
+
+HttpDecoder::~HttpDecoder() {}
+
+QuicByteCount HttpDecoder::ProcessInput(const char* data, QuicByteCount len) {
+  has_payload_ = false;
+  QuicDataReader reader(data, len);
+  while (error_ == QUIC_NO_ERROR && reader.BytesRemaining() != 0) {
+    switch (state_) {
+      case STATE_READING_FRAME_LENGTH:
+        ReadFrameLength(&reader);
+        break;
+      case STATE_READING_FRAME_TYPE:
+        ReadFrameType(&reader);
+        break;
+      case STATE_READING_FRAME_PAYLOAD:
+        ReadFramePayload(&reader);
+        break;
+      case STATE_ERROR:
+        break;
+      default:
+        QUIC_BUG << "Invalid state: " << state_;
+    }
+  }
+
+  if (error_ != QUIC_NO_ERROR) {
+    return 0;
+  }
+
+  return len - reader.BytesRemaining();
+}
+
+void HttpDecoder::ReadFrameLength(QuicDataReader* reader) {
+  DCHECK_NE(0u, reader->BytesRemaining());
+  BufferFrameLength(reader);
+  if (remaining_length_field_length_ != 0) {
+    return;
+  }
+  QuicDataReader length_reader(length_buffer_.data(),
+                               current_length_field_size_);
+  if (!length_reader.ReadVarInt62(&current_frame_length_)) {
+    RaiseError(QUIC_INTERNAL_ERROR, "Unable to read frame length");
+    visitor_->OnError(this);
+    return;
+  }
+
+  state_ = STATE_READING_FRAME_TYPE;
+  remaining_frame_length_ = current_frame_length_;
+}
+
+void HttpDecoder::ReadFrameType(QuicDataReader* reader) {
+  DCHECK_NE(0u, reader->BytesRemaining());
+  if (!reader->ReadUInt8(&current_frame_type_)) {
+    RaiseError(QUIC_INTERNAL_ERROR, "Unable to read frame type");
+    return;
+  }
+
+  state_ = STATE_READING_FRAME_PAYLOAD;
+}
+
+void HttpDecoder::ReadFramePayload(QuicDataReader* reader) {
+  DCHECK_NE(0u, reader->BytesRemaining());
+  switch (current_frame_type_) {
+    case 0x0: {  // DATA
+      if (current_frame_length_ == remaining_frame_length_) {
+        visitor_->OnDataFrameStart(
+            Http3FrameLengths(current_length_field_size_ + kFrameTypeLength,
+                              current_frame_length_));
+      }
+      QuicByteCount bytes_to_read = std::min<QuicByteCount>(
+          remaining_frame_length_, reader->BytesRemaining());
+      QuicStringPiece payload;
+      if (!reader->ReadStringPiece(&payload, bytes_to_read)) {
+        RaiseError(QUIC_INTERNAL_ERROR, "Unable to read data");
+        return;
+      }
+      has_payload_ = true;
+      visitor_->OnDataFramePayload(payload);
+      remaining_frame_length_ -= payload.length();
+      if (remaining_frame_length_ == 0) {
+        state_ = STATE_READING_FRAME_LENGTH;
+        current_length_field_size_ = 0;
+        visitor_->OnDataFrameEnd();
+      }
+      return;
+    }
+    case 0x1: {  // HEADERS
+      if (current_frame_length_ == remaining_frame_length_) {
+        visitor_->OnHeadersFrameStart();
+      }
+      QuicByteCount bytes_to_read = std::min<QuicByteCount>(
+          remaining_frame_length_, reader->BytesRemaining());
+      QuicStringPiece payload;
+      if (!reader->ReadStringPiece(&payload, bytes_to_read)) {
+        RaiseError(QUIC_INTERNAL_ERROR, "Unable to read data");
+        return;
+      }
+      visitor_->OnHeadersFramePayload(payload);
+      remaining_frame_length_ -= payload.length();
+      if (remaining_frame_length_ == 0) {
+        state_ = STATE_READING_FRAME_LENGTH;
+        current_length_field_size_ = 0;
+        visitor_->OnHeadersFrameEnd(current_frame_length_);
+      }
+      return;
+    }
+    case 0x2: {  // PRIORITY
+      // TODO(rch): avoid buffering if the entire frame is present, and
+      // instead parse directly out of |reader|.
+      BufferFramePayload(reader);
+      if (remaining_frame_length_ == 0) {
+        PriorityFrame frame;
+        QuicDataReader reader(buffer_.data(), current_frame_length_);
+        if (!ParsePriorityFrame(&reader, &frame)) {
+          return;
+        }
+        visitor_->OnPriorityFrame(frame);
+        state_ = STATE_READING_FRAME_LENGTH;
+        current_length_field_size_ = 0;
+      }
+      return;
+    }
+    case 0x3: {  // CANCEL_PUSH
+      // TODO(rch): Handle partial delivery.
+      BufferFramePayload(reader);
+      if (remaining_frame_length_ == 0) {
+        CancelPushFrame frame;
+        QuicDataReader reader(buffer_.data(), current_frame_length_);
+        if (!reader.ReadVarInt62(&frame.push_id)) {
+          RaiseError(QUIC_INTERNAL_ERROR, "Unable to read push_id");
+          return;
+        }
+        visitor_->OnCancelPushFrame(frame);
+        state_ = STATE_READING_FRAME_LENGTH;
+        current_length_field_size_ = 0;
+      }
+      return;
+    }
+    case 0x4: {  // SETTINGS
+      // TODO(rch): Handle overly large SETTINGS frames. Either:
+      // 1. Impose a limit on SETTINGS frame size, and close the connection if
+      //    exceeded
+      // 2. Implement a streaming parsing mode.
+      BufferFramePayload(reader);
+      if (remaining_frame_length_ == 0) {
+        SettingsFrame frame;
+        QuicDataReader reader(buffer_.data(), current_frame_length_);
+        if (!ParseSettingsFrame(&reader, &frame)) {
+          return;
+        }
+        visitor_->OnSettingsFrame(frame);
+        state_ = STATE_READING_FRAME_LENGTH;
+        current_length_field_size_ = 0;
+      }
+      return;
+    }
+    case 0x5: {  // PUSH_PROMISE
+      if (current_frame_length_ == remaining_frame_length_) {
+        QuicByteCount bytes_remaining = reader->BytesRemaining();
+        PushId push_id;
+        // TODO(rch): Handle partial delivery of this field.
+        if (!reader->ReadVarInt62(&push_id)) {
+          RaiseError(QUIC_INTERNAL_ERROR, "Unable to read push_id");
+          return;
+        }
+        remaining_frame_length_ -= bytes_remaining - reader->BytesRemaining();
+        visitor_->OnPushPromiseFrameStart(push_id);
+      }
+      QuicByteCount bytes_to_read = std::min<QuicByteCount>(
+          remaining_frame_length_, reader->BytesRemaining());
+      if (bytes_to_read == 0) {
+        return;
+      }
+      QuicStringPiece payload;
+      if (!reader->ReadStringPiece(&payload, bytes_to_read)) {
+        RaiseError(QUIC_INTERNAL_ERROR, "Unable to read data");
+        return;
+      }
+      visitor_->OnPushPromiseFramePayload(payload);
+      remaining_frame_length_ -= payload.length();
+      if (remaining_frame_length_ == 0) {
+        state_ = STATE_READING_FRAME_LENGTH;
+        current_length_field_size_ = 0;
+        visitor_->OnPushPromiseFrameEnd();
+      }
+      return;
+    }
+    case 0x7: {  // GOAWAY
+      BufferFramePayload(reader);
+      if (remaining_frame_length_ == 0) {
+        GoAwayFrame frame;
+        QuicDataReader reader(buffer_.data(), current_frame_length_);
+        uint64_t stream_id;
+        if (!reader.ReadVarInt62(&stream_id)) {
+          RaiseError(QUIC_INTERNAL_ERROR, "Unable to read GOAWAY stream_id");
+          return;
+        }
+        frame.stream_id = stream_id;
+        visitor_->OnGoAwayFrame(frame);
+        state_ = STATE_READING_FRAME_LENGTH;
+        current_length_field_size_ = 0;
+      }
+      return;
+    }
+
+    case 0xD: {  // MAX_PUSH_ID
+      // TODO(rch): Handle partial delivery.
+      BufferFramePayload(reader);
+      if (remaining_frame_length_ == 0) {
+        QuicDataReader reader(buffer_.data(), current_frame_length_);
+        MaxPushIdFrame frame;
+        if (!reader.ReadVarInt62(&frame.push_id)) {
+          RaiseError(QUIC_INTERNAL_ERROR, "Unable to read push_id");
+          return;
+        }
+        visitor_->OnMaxPushIdFrame(frame);
+        state_ = STATE_READING_FRAME_LENGTH;
+        current_length_field_size_ = 0;
+      }
+      return;
+    }
+
+    case 0xE: {  // DUPLICATE_PUSH
+      BufferFramePayload(reader);
+      if (remaining_frame_length_ != 0) {
+        return;
+      }
+      QuicDataReader reader(buffer_.data(), current_frame_length_);
+      DuplicatePushFrame frame;
+      if (!reader.ReadVarInt62(&frame.push_id)) {
+        RaiseError(QUIC_INTERNAL_ERROR, "Unable to read push_id");
+        return;
+      }
+      visitor_->OnDuplicatePushFrame(frame);
+      state_ = STATE_READING_FRAME_LENGTH;
+      current_length_field_size_ = 0;
+      return;
+    }
+    // Reserved frame types.
+    // TODO(rch): Since these are actually the same behavior as the
+    // default, we probably don't need to special case them here?
+    case 0xB:
+      QUIC_FALLTHROUGH_INTENDED;
+    case 0xB + 0x1F:
+      QUIC_FALLTHROUGH_INTENDED;
+    case 0xB + 0x1F * 2:
+      QUIC_FALLTHROUGH_INTENDED;
+    case 0xB + 0x1F * 3:
+      QUIC_FALLTHROUGH_INTENDED;
+    case 0xB + 0x1F * 4:
+      QUIC_FALLTHROUGH_INTENDED;
+    case 0xB + 0x1F * 5:
+      QUIC_FALLTHROUGH_INTENDED;
+    case 0xB + 0x1F * 6:
+      QUIC_FALLTHROUGH_INTENDED;
+    case 0xB + 0x1F * 7:
+      QUIC_FALLTHROUGH_INTENDED;
+    default:
+      DiscardFramePayload(reader);
+  }
+}
+
+void HttpDecoder::DiscardFramePayload(QuicDataReader* reader) {
+  QuicByteCount bytes_to_read = std::min<QuicByteCount>(
+      remaining_frame_length_, reader->BytesRemaining());
+  QuicStringPiece payload;
+  if (!reader->ReadStringPiece(&payload, bytes_to_read)) {
+    RaiseError(QUIC_INTERNAL_ERROR, "Unable to read frame payload");
+    return;
+  }
+  remaining_frame_length_ -= payload.length();
+  if (remaining_frame_length_ == 0) {
+    state_ = STATE_READING_FRAME_LENGTH;
+    current_length_field_size_ = 0;
+  }
+}
+
+void HttpDecoder::BufferFramePayload(QuicDataReader* reader) {
+  if (current_frame_length_ == remaining_frame_length_) {
+    buffer_.erase(buffer_.size());
+    buffer_.reserve(current_frame_length_);
+  }
+  QuicByteCount bytes_to_read = std::min<QuicByteCount>(
+      remaining_frame_length_, reader->BytesRemaining());
+  if (!reader->ReadBytes(
+          &(buffer_[0]) + current_frame_length_ - remaining_frame_length_,
+          bytes_to_read)) {
+    RaiseError(QUIC_INTERNAL_ERROR, "Unable to read frame payload");
+    return;
+  }
+  remaining_frame_length_ -= bytes_to_read;
+}
+
+void HttpDecoder::BufferFrameLength(QuicDataReader* reader) {
+  if (current_length_field_size_ == 0) {
+    current_length_field_size_ = reader->PeekVarInt62Length();
+    if (current_length_field_size_ == 0) {
+      RaiseError(QUIC_INTERNAL_ERROR, "Unable to read frame length");
+      visitor_->OnError(this);
+      return;
+    }
+    remaining_length_field_length_ = current_length_field_size_;
+  }
+  if (current_length_field_size_ == remaining_length_field_length_) {
+    length_buffer_.erase(length_buffer_.size());
+    length_buffer_.reserve(current_length_field_size_);
+  }
+  QuicByteCount bytes_to_read = std::min<QuicByteCount>(
+      remaining_length_field_length_, reader->BytesRemaining());
+  if (!reader->ReadBytes(&(length_buffer_[0]) + current_length_field_size_ -
+                             remaining_length_field_length_,
+                         bytes_to_read)) {
+    RaiseError(QUIC_INTERNAL_ERROR, "Unable to read frame length");
+    visitor_->OnError(this);
+    return;
+  }
+  remaining_length_field_length_ -= bytes_to_read;
+}
+
+void HttpDecoder::RaiseError(QuicErrorCode error, QuicString error_detail) {
+  state_ = STATE_ERROR;
+  error_ = error;
+  error_detail_ = std::move(error_detail);
+}
+
+bool HttpDecoder::ParsePriorityFrame(QuicDataReader* reader,
+                                     PriorityFrame* frame) {
+  uint8_t flags;
+  if (!reader->ReadUInt8(&flags)) {
+    RaiseError(QUIC_INTERNAL_ERROR, "Unable to read priority frame flags");
+    return false;
+  }
+
+  frame->prioritized_type =
+      static_cast<PriorityElementType>(ExtractBits(flags, 2, 6));
+  frame->dependency_type =
+      static_cast<PriorityElementType>(ExtractBits(flags, 2, 4));
+  frame->exclusive = flags % 2 == 1;
+  if (!reader->ReadVarInt62(&frame->prioritized_element_id)) {
+    RaiseError(QUIC_INTERNAL_ERROR, "Unable to read prioritized_element_id");
+    return false;
+  }
+  if (!reader->ReadVarInt62(&frame->element_dependency_id)) {
+    RaiseError(QUIC_INTERNAL_ERROR, "Unable to read element_dependency_id");
+    return false;
+  }
+  if (!reader->ReadUInt8(&frame->weight)) {
+    RaiseError(QUIC_INTERNAL_ERROR, "Unable to read priority frame weight");
+    return false;
+  }
+  return true;
+}
+
+bool HttpDecoder::ParseSettingsFrame(QuicDataReader* reader,
+                                     SettingsFrame* frame) {
+  while (!reader->IsDoneReading()) {
+    uint16_t id;
+    if (!reader->ReadUInt16(&id)) {
+      RaiseError(QUIC_INTERNAL_ERROR,
+                 "Unable to read settings frame identifier");
+      return false;
+    }
+    uint64_t content;
+    if (!reader->ReadVarInt62(&content)) {
+      RaiseError(QUIC_INTERNAL_ERROR, "Unable to read settings frame content");
+      return false;
+    }
+    frame->values[id] = content;
+  }
+  return true;
+}
+
+}  // namespace quic