// 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 <cstdint>

#include "net/third_party/quiche/src/quic/core/http/http_frames.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 {

HttpDecoder::HttpDecoder(Visitor* visitor)
    : visitor_(visitor),
      state_(STATE_READING_FRAME_TYPE),
      current_frame_type_(0),
      current_length_field_length_(0),
      remaining_length_field_length_(0),
      current_frame_length_(0),
      remaining_frame_length_(0),
      current_type_field_length_(0),
      remaining_type_field_length_(0),
      current_push_id_length_(0),
      remaining_push_id_length_(0),
      error_(QUIC_NO_ERROR),
      error_detail_("") {
  DCHECK(visitor_);
}

HttpDecoder::~HttpDecoder() {}

QuicByteCount HttpDecoder::ProcessInput(const char* data, QuicByteCount len) {
  DCHECK_EQ(QUIC_NO_ERROR, error_);
  DCHECK_NE(STATE_ERROR, state_);

  QuicDataReader reader(data, len);
  bool continue_processing = true;
  while (continue_processing &&
         (reader.BytesRemaining() != 0 || state_ == STATE_FINISH_PARSING)) {
    // |continue_processing| must have been set to false upon error.
    DCHECK_EQ(QUIC_NO_ERROR, error_);
    DCHECK_NE(STATE_ERROR, state_);

    switch (state_) {
      case STATE_READING_FRAME_TYPE:
        ReadFrameType(&reader);
        break;
      case STATE_READING_FRAME_LENGTH:
        continue_processing = ReadFrameLength(&reader);
        break;
      case STATE_READING_FRAME_PAYLOAD:
        continue_processing = ReadFramePayload(&reader);
        break;
      case STATE_FINISH_PARSING:
        continue_processing = FinishParsing();
        break;
      case STATE_ERROR:
        break;
      default:
        QUIC_BUG << "Invalid state: " << state_;
    }
  }

  return len - reader.BytesRemaining();
}

void HttpDecoder::ReadFrameType(QuicDataReader* reader) {
  DCHECK_NE(0u, reader->BytesRemaining());
  if (current_type_field_length_ == 0) {
    // A new frame is coming.
    current_type_field_length_ = reader->PeekVarInt62Length();
    DCHECK_NE(0u, current_type_field_length_);
    if (current_type_field_length_ > reader->BytesRemaining()) {
      // Buffer a new type field.
      remaining_type_field_length_ = current_type_field_length_;
      BufferFrameType(reader);
      return;
    }
    // The reader has all type data needed, so no need to buffer.
    bool success = reader->ReadVarInt62(&current_frame_type_);
    DCHECK(success);
  } else {
    // Buffer the existing type field.
    BufferFrameType(reader);
    // The frame is still not buffered completely.
    if (remaining_type_field_length_ != 0) {
      return;
    }
    QuicDataReader type_reader(type_buffer_.data(), current_type_field_length_);
    bool success = type_reader.ReadVarInt62(&current_frame_type_);
    DCHECK(success);
  }

  state_ = STATE_READING_FRAME_LENGTH;
}

bool HttpDecoder::ReadFrameLength(QuicDataReader* reader) {
  DCHECK_NE(0u, reader->BytesRemaining());
  if (current_length_field_length_ == 0) {
    // A new frame is coming.
    current_length_field_length_ = reader->PeekVarInt62Length();
    DCHECK_NE(0u, current_length_field_length_);
    if (current_length_field_length_ > reader->BytesRemaining()) {
      // Buffer a new length field.
      remaining_length_field_length_ = current_length_field_length_;
      BufferFrameLength(reader);
      return true;
    }
    // The reader has all length data needed, so no need to buffer.
    bool success = reader->ReadVarInt62(&current_frame_length_);
    DCHECK(success);
  } else {
    // Buffer the existing length field.
    BufferFrameLength(reader);
    // The frame is still not buffered completely.
    if (remaining_length_field_length_ != 0) {
      return true;
    }
    QuicDataReader length_reader(length_buffer_.data(),
                                 current_length_field_length_);
    bool success = length_reader.ReadVarInt62(&current_frame_length_);
    DCHECK(success);
  }

  if (current_frame_length_ > MaxFrameLength(current_frame_type_)) {
    // TODO(b/124216424): Use HTTP_EXCESSIVE_LOAD.
    RaiseError(QUIC_INVALID_FRAME_DATA, "Frame is too large");
    return false;
  }

  // Calling the following visitor methods does not require parsing of any
  // frame payload.
  bool continue_processing = true;
  const QuicByteCount header_length =
      current_length_field_length_ + current_type_field_length_;

  switch (current_frame_type_) {
    case static_cast<uint64_t>(HttpFrameType::DATA):
      continue_processing = visitor_->OnDataFrameStart(header_length);
      break;
    case static_cast<uint64_t>(HttpFrameType::HEADERS):
      continue_processing = visitor_->OnHeadersFrameStart(header_length);
      break;
    case static_cast<uint64_t>(HttpFrameType::PRIORITY):
      continue_processing = visitor_->OnPriorityFrameStart(header_length);
      break;
    case static_cast<uint64_t>(HttpFrameType::CANCEL_PUSH):
      break;
    case static_cast<uint64_t>(HttpFrameType::SETTINGS):
      continue_processing = visitor_->OnSettingsFrameStart(header_length);
      break;
    case static_cast<uint64_t>(HttpFrameType::PUSH_PROMISE):
      if (current_frame_length_ == 0) {
        RaiseError(QUIC_INVALID_FRAME_DATA, "Corrupt PUSH_PROMISE frame.");
        return false;
      }
      break;
    case static_cast<uint64_t>(HttpFrameType::GOAWAY):
      break;
    case static_cast<uint64_t>(HttpFrameType::MAX_PUSH_ID):
      break;
    case static_cast<uint64_t>(HttpFrameType::DUPLICATE_PUSH):
      break;
    default:
      continue_processing =
          visitor_->OnUnknownFrameStart(current_frame_type_, header_length);
      break;
  }

  remaining_frame_length_ = current_frame_length_;
  state_ = (remaining_frame_length_ == 0) ? STATE_FINISH_PARSING
                                          : STATE_READING_FRAME_PAYLOAD;
  return continue_processing;
}

bool HttpDecoder::ReadFramePayload(QuicDataReader* reader) {
  DCHECK_NE(0u, reader->BytesRemaining());
  DCHECK_NE(0u, remaining_frame_length_);

  bool continue_processing = true;

  switch (current_frame_type_) {
    case static_cast<uint64_t>(HttpFrameType::DATA): {
      QuicByteCount bytes_to_read = std::min<QuicByteCount>(
          remaining_frame_length_, reader->BytesRemaining());
      QuicStringPiece payload;
      bool success = reader->ReadStringPiece(&payload, bytes_to_read);
      DCHECK(success);
      DCHECK(!payload.empty());
      continue_processing = visitor_->OnDataFramePayload(payload);
      remaining_frame_length_ -= payload.length();
      break;
    }
    case static_cast<uint64_t>(HttpFrameType::HEADERS): {
      QuicByteCount bytes_to_read = std::min<QuicByteCount>(
          remaining_frame_length_, reader->BytesRemaining());
      QuicStringPiece payload;
      bool success = reader->ReadStringPiece(&payload, bytes_to_read);
      DCHECK(success);
      DCHECK(!payload.empty());
      continue_processing = visitor_->OnHeadersFramePayload(payload);
      remaining_frame_length_ -= payload.length();
      break;
    }
    case static_cast<uint64_t>(HttpFrameType::PRIORITY): {
      // TODO(rch): avoid buffering if the entire frame is present, and
      // instead parse directly out of |reader|.
      BufferFramePayload(reader);
      break;
    }
    case static_cast<uint64_t>(HttpFrameType::CANCEL_PUSH): {
      BufferFramePayload(reader);
      break;
    }
    case static_cast<uint64_t>(HttpFrameType::SETTINGS): {
      BufferFramePayload(reader);
      break;
    }
    case static_cast<uint64_t>(HttpFrameType::PUSH_PROMISE): {
      PushId push_id;
      if (current_frame_length_ == remaining_frame_length_) {
        // A new Push Promise frame just arrived.
        DCHECK_EQ(0u, current_push_id_length_);
        current_push_id_length_ = reader->PeekVarInt62Length();
        if (current_push_id_length_ > remaining_frame_length_) {
          RaiseError(QUIC_INVALID_FRAME_DATA, "PUSH_PROMISE frame malformed.");
          return false;
        }
        if (current_push_id_length_ > reader->BytesRemaining()) {
          // Not all bytes of push id is present yet, buffer push id.
          DCHECK_EQ(0u, remaining_push_id_length_);
          remaining_push_id_length_ = current_push_id_length_;
          BufferPushId(reader);
          break;
        }
        bool success = reader->ReadVarInt62(&push_id);
        DCHECK(success);
        remaining_frame_length_ -= current_push_id_length_;
        if (!visitor_->OnPushPromiseFrameStart(
                push_id,
                current_length_field_length_ + current_type_field_length_,
                current_push_id_length_)) {
          continue_processing = false;
          current_push_id_length_ = 0;
          break;
        }
        current_push_id_length_ = 0;
      } else if (remaining_push_id_length_ > 0) {
        // Waiting for more bytes on push id.
        BufferPushId(reader);
        if (remaining_push_id_length_ != 0) {
          break;
        }
        QuicDataReader push_id_reader(push_id_buffer_.data(),
                                      current_push_id_length_);

        bool success = push_id_reader.ReadVarInt62(&push_id);
        DCHECK(success);
        if (!visitor_->OnPushPromiseFrameStart(
                push_id,
                current_length_field_length_ + current_type_field_length_,
                current_push_id_length_)) {
          continue_processing = false;
          current_push_id_length_ = 0;
          break;
        }
        current_push_id_length_ = 0;
      }

      // Read Push Promise headers.
      DCHECK_LT(remaining_frame_length_, current_frame_length_);
      QuicByteCount bytes_to_read = std::min<QuicByteCount>(
          remaining_frame_length_, reader->BytesRemaining());
      if (bytes_to_read == 0) {
        break;
      }
      QuicStringPiece payload;
      bool success = reader->ReadStringPiece(&payload, bytes_to_read);
      DCHECK(success);
      DCHECK(!payload.empty());
      continue_processing = visitor_->OnPushPromiseFramePayload(payload);
      remaining_frame_length_ -= payload.length();
      break;
    }
    case static_cast<uint64_t>(HttpFrameType::GOAWAY): {
      BufferFramePayload(reader);
      break;
    }
    case static_cast<uint64_t>(HttpFrameType::MAX_PUSH_ID): {
      BufferFramePayload(reader);
      break;
    }
    case static_cast<uint64_t>(HttpFrameType::DUPLICATE_PUSH): {
      BufferFramePayload(reader);
      break;
    }
    default: {
      QuicByteCount bytes_to_read = std::min<QuicByteCount>(
          remaining_frame_length_, reader->BytesRemaining());
      QuicStringPiece payload;
      bool success = reader->ReadStringPiece(&payload, bytes_to_read);
      DCHECK(success);
      DCHECK(!payload.empty());
      continue_processing = visitor_->OnUnknownFramePayload(payload);
      remaining_frame_length_ -= payload.length();
      break;
    }
  }

  if (remaining_frame_length_ == 0) {
    state_ = STATE_FINISH_PARSING;
  }

  return continue_processing;
}

bool HttpDecoder::FinishParsing() {
  DCHECK_EQ(0u, remaining_frame_length_);

  bool continue_processing = true;

  switch (current_frame_type_) {
    case static_cast<uint64_t>(HttpFrameType::DATA): {
      continue_processing = visitor_->OnDataFrameEnd();
      break;
    }
    case static_cast<uint64_t>(HttpFrameType::HEADERS): {
      continue_processing = visitor_->OnHeadersFrameEnd();
      break;
    }
    case static_cast<uint64_t>(HttpFrameType::PRIORITY): {
      // TODO(rch): avoid buffering if the entire frame is present, and
      // instead parse directly out of |reader|.
      PriorityFrame frame;
      QuicDataReader reader(buffer_.data(), current_frame_length_);
      if (!ParsePriorityFrame(&reader, &frame)) {
        return false;
      }
      continue_processing = visitor_->OnPriorityFrame(frame);
      break;
    }
    case static_cast<uint64_t>(HttpFrameType::CANCEL_PUSH): {
      CancelPushFrame frame;
      QuicDataReader reader(buffer_.data(), current_frame_length_);
      if (!reader.ReadVarInt62(&frame.push_id)) {
        // TODO(b/124216424): Use HTTP_MALFORMED_FRAME.
        RaiseError(QUIC_INVALID_FRAME_DATA, "Unable to read push_id");
        return false;
      }
      if (!reader.IsDoneReading()) {
        RaiseError(QUIC_INVALID_FRAME_DATA,
                   "Superfluous data in CANCEL_PUSH frame.");
        return false;
      }
      continue_processing = visitor_->OnCancelPushFrame(frame);
      break;
    }
    case static_cast<uint64_t>(HttpFrameType::SETTINGS): {
      SettingsFrame frame;
      QuicDataReader reader(buffer_.data(), current_frame_length_);
      if (!ParseSettingsFrame(&reader, &frame)) {
        return false;
      }
      continue_processing = visitor_->OnSettingsFrame(frame);
      break;
    }
    case static_cast<uint64_t>(HttpFrameType::PUSH_PROMISE): {
      continue_processing = visitor_->OnPushPromiseFrameEnd();
      break;
    }
    case static_cast<uint64_t>(HttpFrameType::GOAWAY): {
      QuicDataReader reader(buffer_.data(), current_frame_length_);
      GoAwayFrame frame;
      static_assert(!std::is_same<decltype(frame.stream_id), uint64_t>::value,
                    "Please remove local |stream_id| variable and pass "
                    "&frame.stream_id directly to ReadVarInt62() when changing "
                    "QuicStreamId from uint32_t to uint64_t.");
      uint64_t stream_id;
      if (!reader.ReadVarInt62(&stream_id)) {
        // TODO(b/124216424): Use HTTP_MALFORMED_FRAME.
        RaiseError(QUIC_INVALID_FRAME_DATA, "Unable to read GOAWAY stream_id");
        return false;
      }
      if (!reader.IsDoneReading()) {
        RaiseError(QUIC_INVALID_FRAME_DATA,
                   "Superfluous data in GOAWAY frame.");
        return false;
      }
      frame.stream_id = static_cast<QuicStreamId>(stream_id);
      continue_processing = visitor_->OnGoAwayFrame(frame);
      break;
    }
    case static_cast<uint64_t>(HttpFrameType::MAX_PUSH_ID): {
      QuicDataReader reader(buffer_.data(), current_frame_length_);
      MaxPushIdFrame frame;
      if (!reader.ReadVarInt62(&frame.push_id)) {
        // TODO(b/124216424): Use HTTP_MALFORMED_FRAME.
        RaiseError(QUIC_INVALID_FRAME_DATA, "Unable to read push_id");
        return false;
      }
      if (!reader.IsDoneReading()) {
        RaiseError(QUIC_INVALID_FRAME_DATA,
                   "Superfluous data in MAX_PUSH_ID frame.");
        return false;
      }
      continue_processing = visitor_->OnMaxPushIdFrame(frame);
      break;
    }
    case static_cast<uint64_t>(HttpFrameType::DUPLICATE_PUSH): {
      QuicDataReader reader(buffer_.data(), current_frame_length_);
      DuplicatePushFrame frame;
      if (!reader.ReadVarInt62(&frame.push_id)) {
        // TODO(b/124216424): Use HTTP_MALFORMED_FRAME.
        RaiseError(QUIC_INVALID_FRAME_DATA, "Unable to read push_id");
        return false;
      }
      if (!reader.IsDoneReading()) {
        RaiseError(QUIC_INVALID_FRAME_DATA,
                   "Superfluous data in DUPLICATE_PUSH frame.");
        return false;
      }
      continue_processing = visitor_->OnDuplicatePushFrame(frame);
      break;
    }
    default: {
      continue_processing = visitor_->OnUnknownFrameEnd();
      break;
    }
  }

  current_length_field_length_ = 0;
  current_type_field_length_ = 0;
  state_ = STATE_READING_FRAME_TYPE;
  return continue_processing;
}

void HttpDecoder::DiscardFramePayload(QuicDataReader* reader) {
  QuicByteCount bytes_to_read = std::min<QuicByteCount>(
      remaining_frame_length_, reader->BytesRemaining());
  QuicStringPiece payload;
  bool success = reader->ReadStringPiece(&payload, bytes_to_read);
  DCHECK(success);
  remaining_frame_length_ -= payload.length();
  if (remaining_frame_length_ == 0) {
    state_ = STATE_READING_FRAME_TYPE;
    current_length_field_length_ = 0;
    current_type_field_length_ = 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());
  bool success = reader->ReadBytes(
      &(buffer_[0]) + current_frame_length_ - remaining_frame_length_,
      bytes_to_read);
  DCHECK(success);
  remaining_frame_length_ -= bytes_to_read;
}

void HttpDecoder::BufferFrameLength(QuicDataReader* reader) {
  QuicByteCount bytes_to_read = std::min<QuicByteCount>(
      remaining_length_field_length_, reader->BytesRemaining());
  bool success =
      reader->ReadBytes(length_buffer_.data() + current_length_field_length_ -
                            remaining_length_field_length_,
                        bytes_to_read);
  DCHECK(success);
  remaining_length_field_length_ -= bytes_to_read;
}

void HttpDecoder::BufferFrameType(QuicDataReader* reader) {
  QuicByteCount bytes_to_read = std::min<QuicByteCount>(
      remaining_type_field_length_, reader->BytesRemaining());
  bool success =
      reader->ReadBytes(type_buffer_.data() + current_type_field_length_ -
                            remaining_type_field_length_,
                        bytes_to_read);
  DCHECK(success);
  remaining_type_field_length_ -= bytes_to_read;
}

void HttpDecoder::BufferPushId(QuicDataReader* reader) {
  DCHECK_LE(remaining_push_id_length_, current_frame_length_);
  QuicByteCount bytes_to_read = std::min<QuicByteCount>(
      reader->BytesRemaining(), remaining_push_id_length_);
  bool success =
      reader->ReadBytes(push_id_buffer_.data() + current_push_id_length_ -
                            remaining_push_id_length_,
                        bytes_to_read);
  DCHECK(success);
  remaining_push_id_length_ -= bytes_to_read;
  remaining_frame_length_ -= bytes_to_read;
}

void HttpDecoder::RaiseError(QuicErrorCode error, std::string error_detail) {
  state_ = STATE_ERROR;
  error_ = error;
  error_detail_ = std::move(error_detail);
  visitor_->OnError(this);
}

bool HttpDecoder::ParsePriorityFrame(QuicDataReader* reader,
                                     PriorityFrame* frame) {
  uint8_t flags;
  if (!reader->ReadUInt8(&flags)) {
    // TODO(b/124216424): Use HTTP_MALFORMED_FRAME.
    RaiseError(QUIC_INVALID_FRAME_DATA, "Unable to read PRIORITY frame flags.");
    return false;
  }

  // Assign two most significant bits to prioritized_type.
  frame->prioritized_type = static_cast<PriorityElementType>((flags >> 6) & 3);
  // Assign the next two most significant bits to dependency type.
  frame->dependency_type = static_cast<PriorityElementType>((flags >> 4) & 3);
  frame->exclusive = flags & kPriorityExclusiveBit;
  // TODO(bnc): Close connection with HTTP_MALFORMED_FRAME
  // if lowest three bits are not all zero.

  if (frame->prioritized_type != ROOT_OF_TREE &&
      !reader->ReadVarInt62(&frame->prioritized_element_id)) {
    // TODO(b/124216424): Use HTTP_MALFORMED_FRAME.
    RaiseError(QUIC_INVALID_FRAME_DATA,
               "Unable to read prioritized_element_id.");
    return false;
  }
  if (frame->dependency_type != ROOT_OF_TREE &&
      !reader->ReadVarInt62(&frame->element_dependency_id)) {
    // TODO(b/124216424): Use HTTP_MALFORMED_FRAME.
    RaiseError(QUIC_INVALID_FRAME_DATA,
               "Unable to read element_dependency_id.");
    return false;
  }
  if (!reader->ReadUInt8(&frame->weight)) {
    // TODO(b/124216424): Use HTTP_MALFORMED_FRAME.
    RaiseError(QUIC_INVALID_FRAME_DATA,
               "Unable to read PRIORITY frame weight.");
    return false;
  }
  if (!reader->IsDoneReading()) {
    // TODO(b/124216424): Use HTTP_MALFORMED_FRAME.
    RaiseError(QUIC_INVALID_FRAME_DATA, "Superfluous data in PRIORITY frame.");
    return false;
  }
  return true;
}

bool HttpDecoder::ParseSettingsFrame(QuicDataReader* reader,
                                     SettingsFrame* frame) {
  while (!reader->IsDoneReading()) {
    uint64_t id;
    if (!reader->ReadVarInt62(&id)) {
      // TODO(b/124216424): Use HTTP_MALFORMED_FRAME.
      RaiseError(QUIC_INVALID_FRAME_DATA,
                 "Unable to read settings frame identifier");
      return false;
    }
    uint64_t content;
    if (!reader->ReadVarInt62(&content)) {
      // TODO(b/124216424): Use HTTP_MALFORMED_FRAME.
      RaiseError(QUIC_INVALID_FRAME_DATA,
                 "Unable to read settings frame content");
      return false;
    }
    auto result = frame->values.insert({id, content});
    if (!result.second) {
      // TODO(b/124216424): Use HTTP_SETTINGS_ERROR.
      RaiseError(QUIC_INVALID_FRAME_DATA, "Duplicate SETTINGS identifier.");
      return false;
    }
  }
  return true;
}

QuicByteCount HttpDecoder::MaxFrameLength(uint64_t frame_type) {
  switch (frame_type) {
    case static_cast<uint64_t>(HttpFrameType::PRIORITY):
      return kPriorityFirstByteLength + VARIABLE_LENGTH_INTEGER_LENGTH_8 * 2 +
             kPriorityWeightLength;
    case static_cast<uint64_t>(HttpFrameType::CANCEL_PUSH):
      return sizeof(PushId);
    case static_cast<uint64_t>(HttpFrameType::SETTINGS):
      // This limit is arbitrary.
      return 1024 * 1024;
    case static_cast<uint64_t>(HttpFrameType::GOAWAY):
      return sizeof(QuicStreamId);
    case static_cast<uint64_t>(HttpFrameType::MAX_PUSH_ID):
      return sizeof(PushId);
    case static_cast<uint64_t>(HttpFrameType::DUPLICATE_PUSH):
      return sizeof(PushId);
    default:
      // Other frames require no data buffering, so it's safe to have no limit.
      return std::numeric_limits<QuicByteCount>::max();
  }
}

}  // namespace quic
