/** @file

  Http2CommonSession.cc

  @section license License

  Licensed to the Apache Software Foundation (ASF) under one
  or more contributor license agreements.  See the NOTICE file
  distributed with this work for additional information
  regarding copyright ownership.  The ASF licenses this file
  to you under the Apache License, Version 2.0 (the
  "License"); you may not use this file except in compliance
  with the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
 */

#include "proxy/http2/Http2CommonSession.h"
#include "proxy/http/HttpDebugNames.h"

namespace
{
DbgCtl dbg_ctl_http2_cs{"http2_cs"};

#define REMEMBER(e, r)                          \
  {                                             \
    this->remember(MakeSourceLocation(), e, r); \
  }

#define STATE_ENTER(state_name, event)                                                      \
  do {                                                                                      \
    REMEMBER(event, this->recursion)                                                        \
    Dbg(dbg_ctl_http2_cs, "[%" PRId64 "] [%s, %s]", this->get_connection_id(), #state_name, \
        HttpDebugNames::get_event_name(event));                                             \
  } while (0)

#define Http2SsnDebug(fmt, ...) Dbg(dbg_ctl_http2_cs, "[%" PRId64 "] " fmt, this->get_connection_id(), ##__VA_ARGS__)

#define HTTP2_SET_SESSION_HANDLER(handler) \
  do {                                     \
    REMEMBER(NO_EVENT, this->recursion);   \
    this->session_handler = (handler);     \
  } while (0)

// memcpy the requested bytes from the IOBufferReader, returning how many were
// actually copied.
inline unsigned
copy_from_buffer_reader(void *dst, IOBufferReader *reader, unsigned nbytes)
{
  char *end;

  end = reader->memcpy(dst, nbytes, 0 /* offset */);
  return end - static_cast<char *>(dst);
}

} // end anonymous namespace

void
Http2CommonSession::remember(const SourceLocation &location, int event, int reentrant)
{
  this->_history.push_back(location, event, reentrant);
}

bool
Http2CommonSession::common_free(ProxySession *ssn)
{
  if (this->_reenable_event) {
    this->_reenable_event->cancel();
    this->_reenable_event = nullptr;
  }

  // Make sure the we are at the bottom of the stack
  if (this->connection_state.is_recursing() || this->recursion != 0) {
    // Note that we are ready to be cleaned up
    // One of the event handlers will catch it
    this->kill_me = true;
    return false;
  }

  REMEMBER(NO_EVENT, this->recursion)
  Http2SsnDebug("session free");

  // Don't free active ProxySession
  ink_release_assert(ssn->is_active() == false);

  this->_milestones.mark(Http2SsnMilestone::CLOSE);
  ink_hrtime total_time = this->_milestones.elapsed(Http2SsnMilestone::OPEN, Http2SsnMilestone::CLOSE);

  // Slow Log
  if (Http2::con_slow_log_threshold != 0 && ink_hrtime_from_msec(Http2::con_slow_log_threshold) < total_time) {
    Error("[%" PRIu64 "] Slow H2 Connection: open: %" PRIu64 " close: %.3f", ssn->connection_id(),
          ink_hrtime_to_msec(this->_milestones[Http2SsnMilestone::OPEN]),
          this->_milestones.difference_sec(Http2SsnMilestone::OPEN, Http2SsnMilestone::CLOSE));
  }

  // Update stats on how we died.  May want to eliminate this.  Was useful for
  // tracking down which cases we were having problems cleaning up.  But for general
  // use probably not worth the effort
  if (cause_of_death != Http2SessionCod::NOT_PROVIDED) {
    switch (cause_of_death) {
    case Http2SessionCod::HIGH_ERROR_RATE:
      Metrics::Counter::increment(http2_rsb.session_die_high_error_rate);
      break;
    case Http2SessionCod::NOT_PROVIDED:
      // Can't happen but this case is here to not have default case.
      Metrics::Counter::increment(http2_rsb.session_die_other);
      break;
    }
  } else {
    switch (dying_event) {
    case VC_EVENT_NONE:
      Metrics::Counter::increment(http2_rsb.session_die_default);
      break;
    case VC_EVENT_ACTIVE_TIMEOUT:
      Metrics::Counter::increment(http2_rsb.session_die_active);
      break;
    case VC_EVENT_INACTIVITY_TIMEOUT:
      Metrics::Counter::increment(http2_rsb.session_die_inactive);
      break;
    case VC_EVENT_ERROR:
      Metrics::Counter::increment(http2_rsb.session_die_error);
      break;
    case VC_EVENT_EOS:
      Metrics::Counter::increment(http2_rsb.session_die_eos);
      break;
    default:
      Metrics::Counter::increment(http2_rsb.session_die_other);
      break;
    }
  }

  delete _h2_pushed_urls;
  _h2_pushed_urls = nullptr;
  this->connection_state.destroy();

  free_MIOBuffer(this->read_buffer);
  this->read_buffer = nullptr;
  free_MIOBuffer(this->write_buffer);
  this->write_buffer = nullptr;
  return true;
}

void
Http2CommonSession::set_half_close_local_flag(bool flag)
{
  if (!half_close_local && flag) {
    Http2SsnDebug("session half-close local");
  }
  half_close_local = flag;
}

int64_t
Http2CommonSession::xmit(const Http2TxFrame &frame, bool flush)
{
  int64_t len                       = frame.write_to(this->write_buffer);
  this->_pending_sending_data_size += len;
  if (!flush) {
    // Flush if we already use half of the buffer to avoid adding a new block to the chain.
    // A frame size can be 16MB at maximum so blocks can be added, but that's fine.
    if (this->_pending_sending_data_size >= this->_write_size_threshold) {
      flush = true;
    } else {
      // Observe that schedule_transmit will only schedule the first time we
      // don't flush because the threshold is not met.
      this->connection_state.schedule_retransmit(HRTIME_MSECONDS(Http2::write_time_threshold));
    }
  }
  if (flush) {
    this->flush();
  }

  return len;
}

void
Http2CommonSession::flush()
{
  this->connection_state.cancel_retransmit();
  if (this->_pending_sending_data_size > 0) {
    this->_pending_sending_data_size = 0;
    this->_write_buffer_last_flush   = ink_get_hrtime();
    write_reenable();
  }
}

int
Http2CommonSession::state_read_connection_preface(int event, void *edata)
{
  VIO *vio = static_cast<VIO *>(edata);

  STATE_ENTER(&Http2CommonSession::state_read_connection_preface, event);
  ink_assert(event == VC_EVENT_READ_COMPLETE || event == VC_EVENT_READ_READY);

  if (this->_read_buffer_reader->read_avail() >= static_cast<int64_t>(HTTP2_CONNECTION_PREFACE_LEN)) {
    char     buf[HTTP2_CONNECTION_PREFACE_LEN];
    unsigned nbytes;

    nbytes = copy_from_buffer_reader(buf, this->_read_buffer_reader, sizeof(buf));
    ink_release_assert(nbytes == HTTP2_CONNECTION_PREFACE_LEN);

    if (memcmp(HTTP2_CONNECTION_PREFACE, buf, nbytes) != 0) {
      Http2SsnDebug("invalid connection preface");
      this->get_proxy_session()->do_io_close();
      return 0;
    }

    // Check whether data is read from early data
    if (this->read_from_early_data > 0) {
      this->read_from_early_data -= this->read_from_early_data > nbytes ? nbytes : this->read_from_early_data;
    }

    Http2SsnDebug("received connection preface");
    this->_read_buffer_reader->consume(nbytes);
    HTTP2_SET_SESSION_HANDLER(&Http2CommonSession::state_start_frame_read);

    this->get_netvc()->set_inactivity_timeout(HRTIME_SECONDS(Http2::no_activity_timeout_in));
    this->get_netvc()->set_active_timeout(HRTIME_SECONDS(Http2::active_timeout_in));

    // XXX start the write VIO ...

    // If we have unconsumed data, start tranferring frames now.
    if (this->_read_buffer_reader->is_read_avail_more_than(0)) {
      return this->get_proxy_session()->handleEvent(VC_EVENT_READ_READY, vio);
    }
  }

  // XXX We don't have enough data to check the connection preface. We should
  // reset the accept inactivity
  // timeout. We should have a maximum timeout to get the session started
  // though.

  vio->reenable();
  return 0;
}

int
Http2CommonSession::state_start_frame_read(int event, void *edata)
{
  VIO *vio = static_cast<VIO *>(edata);

  STATE_ENTER(&Http2CommonSession::state_start_frame_read, event);
  ink_assert(event == VC_EVENT_READ_COMPLETE || event == VC_EVENT_READ_READY);
  return do_process_frame_read(event, vio, false);
}

int
Http2CommonSession::do_start_frame_read(Http2ErrorCode &ret_error)
{
  ret_error = Http2ErrorCode::HTTP2_ERROR_NO_ERROR;
  ink_release_assert(this->_read_buffer_reader->read_avail() >= (int64_t)HTTP2_FRAME_HEADER_LEN);

  uint8_t  buf[HTTP2_FRAME_HEADER_LEN];
  unsigned nbytes;

  Http2SsnDebug("receiving frame header");
  nbytes = copy_from_buffer_reader(buf, this->_read_buffer_reader, sizeof(buf));

  this->cur_frame_from_early_data = false;
  if (!http2_parse_frame_header(make_iovec(buf), this->current_hdr)) {
    Http2SsnDebug("frame header parse failure");
    this->get_proxy_session()->do_io_close();
    return -1;
  }

  // Check whether data is read from early data
  if (this->read_from_early_data > 0) {
    this->read_from_early_data      -= this->read_from_early_data > nbytes ? nbytes : this->read_from_early_data;
    this->cur_frame_from_early_data  = true;
  }

  Http2SsnDebug("frame header length=%u, type=%u, flags=0x%x, streamid=%u, early_data=%d", (unsigned)this->current_hdr.length,
                (unsigned)this->current_hdr.type, (unsigned)this->current_hdr.flags, this->current_hdr.streamid,
                this->cur_frame_from_early_data);

  this->_read_buffer_reader->consume(nbytes);

  if (!http2_frame_header_is_valid(this->current_hdr, this->connection_state.local_settings.get(HTTP2_SETTINGS_MAX_FRAME_SIZE))) {
    ret_error = Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR;
    return -1;
  }

  // If we know up front that the payload is too long, nuke this connection.
  if (this->current_hdr.length > this->connection_state.local_settings.get(HTTP2_SETTINGS_MAX_FRAME_SIZE)) {
    ret_error = Http2ErrorCode::HTTP2_ERROR_FRAME_SIZE_ERROR;
    return -1;
  }

  // CONTINUATIONs MUST follow behind HEADERS which doesn't have END_HEADERS
  Http2StreamId continued_stream_id = this->connection_state.get_continued_stream_id();

  if (continued_stream_id != 0 &&
      (continued_stream_id != this->current_hdr.streamid || this->current_hdr.type != HTTP2_FRAME_TYPE_CONTINUATION)) {
    ret_error = Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR;
    return -1;
  }
  return 0;
}

int
Http2CommonSession::state_complete_frame_read(int event, void *edata)
{
  VIO *vio = static_cast<VIO *>(edata);
  STATE_ENTER(&Http2CommonSession::state_complete_frame_read, event);
  ink_assert(event == VC_EVENT_READ_COMPLETE || event == VC_EVENT_READ_READY);
  if (this->_read_buffer_reader->read_avail() < this->current_hdr.length) {
    if (this->_should_do_something_else()) {
      if (this->_reenable_event == nullptr) {
        vio->disable();
        this->_reenable_event = this->get_mutex()->thread_holding->schedule_in(this->get_proxy_session(), HRTIME_MSECONDS(1),
                                                                               HTTP2_SESSION_EVENT_REENABLE, vio);
      } else {
        vio->reenable();
      }
    } else {
      vio->reenable();
    }
    return 0;
  }
  Http2SsnDebug("completed frame read, %" PRId64 " bytes available", this->_read_buffer_reader->read_avail());

  return do_process_frame_read(event, vio, true);
}

int
Http2CommonSession::do_complete_frame_read()
{
  // XXX parse the frame and handle it ...
  ink_release_assert(this->_read_buffer_reader->read_avail() >= this->current_hdr.length);

  Http2Frame frame(this->current_hdr, this->_read_buffer_reader, this->cur_frame_from_early_data);
  this->_count_received_frames(frame.header().type);
  connection_state.rcv_frame(&frame);

  // Check whether data is read from early data
  if (this->read_from_early_data > 0) {
    this->read_from_early_data -=
      this->read_from_early_data > this->current_hdr.length ? this->current_hdr.length : this->read_from_early_data;
  }
  this->_read_buffer_reader->consume(this->current_hdr.length);
  ++(this->_n_frame_read);

  // Set the event handler if there is no more data to process a new frame
  HTTP2_SET_SESSION_HANDLER(&Http2CommonSession::state_start_frame_read);

  return 0;
}

int
Http2CommonSession::do_process_frame_read(int /* event ATS_UNUSED */, VIO *vio, bool inside_frame)
{
  Http2SsnDebug("do_process_frame_read %" PRId64 " bytes ready", this->_read_buffer_reader->read_avail());

  if (inside_frame) {
    do_complete_frame_read();
  }

  while (this->_read_buffer_reader->read_avail() >= static_cast<int64_t>(HTTP2_FRAME_HEADER_LEN)) {
    // Cancel reading if there was an error or connection is closed
    if (connection_state.tx_error_code.code != static_cast<uint32_t>(Http2ErrorCode::HTTP2_ERROR_NO_ERROR) ||
        connection_state.is_state_closed()) {
      Http2SsnDebug("reading a frame has been canceled (%u)", connection_state.tx_error_code.code);
      break;
    }

    Http2ErrorCode err = Http2ErrorCode::HTTP2_ERROR_NO_ERROR;
    if (this->connection_state.get_stream_error_rate() > std::min(1.0, Http2::stream_error_rate_threshold * 2.0)) {
      ip_port_text_buffer ipb;
      const char         *peer_ip = ats_ip_ntop(this->get_proxy_session()->get_remote_addr(), ipb, sizeof(ipb));
      SiteThrottledWarning("HTTP/2 session error peer_ip=%s session_id=%" PRId64
                           " closing a connection, because its stream error rate (%f) exceeded the threshold (%f)",
                           peer_ip, this->get_connection_id(), this->connection_state.get_stream_error_rate(),
                           Http2::stream_error_rate_threshold);
      err = Http2ErrorCode::HTTP2_ERROR_ENHANCE_YOUR_CALM;
    }

    // Return if there was an error
    if (err > Http2ErrorCode::HTTP2_ERROR_NO_ERROR || do_start_frame_read(err) < 0) {
      // send an error if specified.  Otherwise, just go away
      this->connection_state.restart_receiving(nullptr);
      if (err > Http2ErrorCode::HTTP2_ERROR_NO_ERROR) {
        if (!this->connection_state.is_state_closed()) {
          this->connection_state.send_goaway_frame(this->connection_state.get_latest_stream_id_in(), err);
          this->set_half_close_local_flag(true);
        }
      }
      return 0;
    }

    // If there is no more data to finish the frame, set up the event handler and reenable
    if (this->_read_buffer_reader->read_avail() < this->current_hdr.length) {
      HTTP2_SET_SESSION_HANDLER(&Http2CommonSession::state_complete_frame_read);
      break;
    }
    do_complete_frame_read();

    if (this->_should_do_something_else()) {
      if (this->_reenable_event == nullptr) {
        this->connection_state.restart_receiving(nullptr);
        vio->disable();
        this->_reenable_event = this->get_mutex()->thread_holding->schedule_in(this->get_proxy_session(), HRTIME_MSECONDS(1),
                                                                               HTTP2_SESSION_EVENT_REENABLE, vio);
        return 0;
      }
    }
  }

  // If the client hasn't shut us down, reenable
  if (!this->get_proxy_session()->is_peer_closed()) {
    vio->reenable();
  }
  return 0;
}

bool
Http2CommonSession::_should_do_something_else()
{
  if (this->get_proxy_session()->is_peer_closed()) {
    return false;
  }
  if (this->_interrupt_reading_frames) {
    this->_interrupt_reading_frames = false;
    return true;
  }
  // Do something else every 128 incoming frames if connection state isn't closed
  return (this->_n_frame_read & 0x7F) == 0 && !connection_state.is_state_closed();
}

void
Http2CommonSession::interrupt_reading_frames()
{
  this->_interrupt_reading_frames = true;
}

int64_t
Http2CommonSession::write_avail()
{
  return this->write_buffer->write_avail();
}

bool
Http2CommonSession::is_write_high_water() const
{
  return this->write_buffer->high_water();
}

void
Http2CommonSession::write_reenable()
{
  if (write_vio) {
    // Grab the lock for the write_vio.  Holding the lock is
    // checked eventually via the reenable logic
    SCOPED_MUTEX_LOCK(lock, write_vio->mutex, this_ethread());
    write_vio->reenable();
  }
}

void
Http2CommonSession::add_url_to_pushed_table(const char *url, int url_len)
{
  // Delay std::unordered_set allocation until when it used
  if (_h2_pushed_urls == nullptr) {
    this->_h2_pushed_urls = new std::unordered_set<std::string>();
    this->_h2_pushed_urls->reserve(Http2::push_diary_size);
  }

  if (_h2_pushed_urls->size() < Http2::push_diary_size) {
    _h2_pushed_urls->emplace(url, url_len);
  }
}

void
Http2CommonSession::add_session()
{
}

bool
Http2CommonSession::is_outbound() const
{
  return false;
}

void
Http2CommonSession::_count_received_frames(uint32_t type)
{
  if (type > HTTP2_FRAME_TYPE_MAX) {
    type = HTTP2_FRAME_TYPE_MAX;
  }
  // Global counter
  Metrics::Counter::increment(http2_frame_metrics_in[type]);
  // Local counter
  this->_frame_counts_in[type]++;
}
