// 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, std::string 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
