// 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 size_t 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() {}

size_t HttpDecoder::ProcessInput(const char* data, size_t len) {
  has_payload_ = false;
  QuicDataReader reader(data, len, NETWORK_BYTE_ORDER);
  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_, NETWORK_BYTE_ORDER);
  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_));
      }
      size_t bytes_to_read =
          std::min<size_t>(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();
      }
      size_t bytes_to_read =
          std::min<size_t>(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();
      }
      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_,
                              NETWORK_BYTE_ORDER);
        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_,
                              NETWORK_BYTE_ORDER);
        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_,
                              NETWORK_BYTE_ORDER);
        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_) {
        size_t 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);
      }
      size_t bytes_to_read =
          std::min<size_t>(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_,
                              NETWORK_BYTE_ORDER);
        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_,
                              NETWORK_BYTE_ORDER);
        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_,
                            NETWORK_BYTE_ORDER);
      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) {
  size_t bytes_to_read =
      std::min<size_t>(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_);
  }
  size_t bytes_to_read =
      std::min<size_t>(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_);
  }
  size_t bytes_to_read = std::min<size_t>(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
