/** @file

  Http2ServerSession.

  @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/Http2ServerSession.h"
#include "iocore/net/NetVConnection.h"
#include "iocore/net/TLSSNISupport.h"
#include "proxy/http/HttpDebugNames.h"
#include "tscore/ink_base64.h"
#include "proxy/http2/Http2CommonSessionInternal.h"
#include "proxy/http/HttpSessionManager.h"

ClassAllocator<Http2ServerSession, false> http2ServerSessionAllocator("http2ServerSessionAllocator");

static int
send_connection_event(Continuation *cont, int event, void *edata)
{
  SCOPED_MUTEX_LOCK(lock, cont->mutex, this_ethread());
  return cont->handleEvent(event, edata);
}

Http2ServerSession::Http2ServerSession() = default;

void
Http2ServerSession::destroy()
{
  if (!in_destroy) {
    in_destroy = true;
    write_vio  = nullptr;
    this->remove_session();
    this->release_outbound_connection_tracking();
    REMEMBER(NO_EVENT, this->recursion)
    Http2SsnDebug("session destroy");
    if (_vc) {
      _vc->do_io_close();
      _vc = nullptr;
    }
    free();
  }
}

void
Http2ServerSession::free()
{
  auto mutex_thread = this->mutex->thread_holding;
  if (Http2CommonSession::common_free(this)) {
    Metrics::Gauge::decrement(http2_rsb.current_server_session_count);
    THREAD_FREE(this, http2ServerSessionAllocator, mutex_thread);
  }
}

void
Http2ServerSession::start()
{
  SCOPED_MUTEX_LOCK(lock, this->mutex, this_ethread());

  SET_HANDLER(&Http2ServerSession::main_event_handler);
  HTTP2_SET_SESSION_HANDLER(&Http2ServerSession::state_start_frame_read);

  _vc->set_inactivity_timeout(HRTIME_SECONDS(Http2::accept_no_activity_timeout));

  VIO *read_vio = this->do_io_read(this, INT64_MAX, this->read_buffer);
  write_vio     = this->do_io_write(this, INT64_MAX, this->_write_buffer_reader);

  this->connection_state.init(this);

  // 3.5 HTTP/2 Connection Preface. Upon establishment of a TCP connection and
  // determination that HTTP/2 will be used by both peers, each endpoint MUST
  // send a connection preface as a final confirmation ...
  // This is the preface string sent by the client
  this->write_buffer->write(HTTP2_CONNECTION_PREFACE, HTTP2_CONNECTION_PREFACE_LEN);
  write_reenable();
  this->connection_state.send_connection_preface();
  Http2SsnDebug("Sent Connection Preface");

  this->handleEvent(VC_EVENT_READ_READY, read_vio);
}

void
Http2ServerSession::new_connection(NetVConnection *new_vc, MIOBuffer *iobuf, IOBufferReader *reader)
{
  ink_assert(new_vc->mutex->thread_holding == this_ethread());

  Metrics::Gauge::increment(http2_rsb.current_server_session_count);
  Metrics::Counter::increment(http2_rsb.total_server_connection_count);
  this->_milestones.mark(Http2SsnMilestone::OPEN);

  // Unique client session identifier.
  this->con_id         = ProxySession::next_connection_id();
  this->_vc            = new_vc;
  this->schedule_event = nullptr;
  this->mutex          = new_vc->mutex;

  this->connection_state.mutex = this->mutex;

  // Since we're functioning as a client, we do not need to worry about
  // TLSEarlyDataSupport.

  Http2SsnDebug("session born, netvc %p", this->_vc);

  this->_vc->set_tcp_congestion_control(NetVConnection::tcp_congestion_control_side::CLIENT_SIDE);

  this->read_buffer             = iobuf ? iobuf : new_MIOBuffer(HTTP2_HEADER_BUFFER_SIZE_INDEX);
  this->read_buffer->water_mark = connection_state.local_settings.get(HTTP2_SETTINGS_MAX_FRAME_SIZE);
  this->_read_buffer_reader     = reader ? reader : this->read_buffer->alloc_reader();

  // Set write buffer size to max size of TLS record (16KB)
  // This block size is the buffer size that we pass to SSLWriteBuffer
  auto buffer_block_size_index = iobuffer_size_to_index(Http2::write_buffer_block_size, MAX_BUFFER_SIZE_INDEX);
  this->write_buffer           = new_MIOBuffer(buffer_block_size_index);
  this->_write_buffer_reader   = this->write_buffer->alloc_reader();
  this->_write_size_threshold  = index_to_buffer_size(buffer_block_size_index) * Http2::write_size_threshold;

  uint32_t buffer_water_mark;
  if (auto snis = this->_vc->get_service<TLSSNISupport>(); snis && snis->hints_from_sni.http2_buffer_water_mark.has_value()) {
    buffer_water_mark = snis->hints_from_sni.http2_buffer_water_mark.value();
  } else {
    buffer_water_mark = Http2::buffer_water_mark;
  }
  this->write_buffer->water_mark = buffer_water_mark;

  this->_handle_if_ssl(new_vc);

  if (has_session_hook(TS_HTTP_SSN_START_HOOK)) {
    _vc->cancel_inactivity_timeout();
  }
  do_api_callout(TS_HTTP_SSN_START_HOOK);

  this->add_session();
}

// implement that. After we send a GOAWAY, there
// are scenarios where we would like to complete the outstanding streams.

void
Http2ServerSession::do_io_close(int /* alerrno ATS_UNUSED */)
{
  REMEMBER(NO_EVENT, this->recursion)

  if (!this->connection_state.is_state_closed()) {
    Http2SsnDebug("session closed");
    this->remove_session();

    ink_assert(this->mutex->thread_holding == this_ethread());
    send_connection_event(&this->connection_state, HTTP2_SESSION_EVENT_FINI, this);

    // Destroy will be called from connection_state.release_stream() once the number of active streams goes to 0
  }
}

int
Http2ServerSession::main_event_handler(int event, void *edata)
{
  ink_assert(this->mutex->thread_holding == this_ethread());
  int retval;

  recursion++;

  Event *e = static_cast<Event *>(edata);
  if (e == schedule_event) {
    schedule_event = nullptr;
  }

  Http2SsnDebug("main_event_handler=%d edata=%p", event, edata);

  switch (event) {
  case VC_EVENT_READ_COMPLETE:
  case VC_EVENT_READ_READY: {
    bool is_zombie = connection_state.get_zombie_event() != nullptr;
    retval         = (this->*session_handler)(event, edata);
    if (is_zombie && connection_state.get_zombie_event() != nullptr) {
      Warning("Processed read event for zombie session %" PRId64, connection_id());
    }
    break;
  }

  case HTTP2_SESSION_EVENT_REENABLE:
    // VIO will be reenableed in this handler
    retval = (this->*session_handler)(VC_EVENT_READ_READY, static_cast<VIO *>(e->cookie));
    // Clear the event after calling session_handler to not reschedule REENABLE in it
    this->_reenable_event = nullptr;
    break;

  case VC_EVENT_ACTIVE_TIMEOUT:
  case VC_EVENT_INACTIVITY_TIMEOUT:
  case VC_EVENT_ERROR:
  case VC_EVENT_EOS:
    Http2SsnDebug("Closing event: %s", HttpDebugNames::get_event_name(event));
    this->set_dying_event(event);
    this->do_io_close();
    retval = 0;
    break;

  case VC_EVENT_WRITE_READY:
  case VC_EVENT_WRITE_COMPLETE:
    this->connection_state.restart_streams();
    if ((ink_get_hrtime() >= this->_write_buffer_last_flush + HRTIME_MSECONDS(this->_write_time_threshold))) {
      this->flush();
    }

    retval = 0;
    break;

  case HTTP2_SESSION_EVENT_PRIO:
  default:
    Http2SsnDebug("unexpected event=%d edata=%p", event, edata);
    ink_release_assert(0);
    retval = 0;
    break;
  }

  if (!this->is_draining() && this->connection_state.get_shutdown_reason() == Http2ErrorCode::HTTP2_ERROR_MAX) {
    this->connection_state.set_shutdown_state(HTTP2_SHUTDOWN_NONE);
  }

  if (this->connection_state.get_shutdown_state() == HTTP2_SHUTDOWN_NONE) {
    if (this->is_draining()) { // For a case we already checked Connection header and it didn't exist
      Http2SsnDebug("Preparing for graceful shutdown because of draining state");
      this->connection_state.set_shutdown_state(HTTP2_SHUTDOWN_NOT_INITIATED);
    } /*else if (this->connection_state.get_stream_error_rate() >
               Http2::stream_error_rate_threshold) { // For a case many stream errors happened
      ip_port_text_buffer ipb;
      const char *client_ip = ats_ip_ntop(get_remote_addr(), ipb, sizeof(ipb));
      SiteThrottledWarning("HTTP/2 session error origin_ip=%s session_id=%" PRId64
              " closing a connection, because its stream error rate (%f) exceeded the threshold (%f)",
              client_ip, connection_id(), this->connection_state.get_stream_error_rate(), Http2::stream_error_rate_threshold);
      Http2SsnDebug("Preparing for graceful shutdown because of a high stream error rate");
      cause_of_death = Http2SessionCod::HIGH_ERROR_RATE;
      this->connection_state.set_shutdown_state(HTTP2_SHUTDOWN_NOT_INITIATED, Http2ErrorCode::HTTP2_ERROR_ENHANCE_YOUR_CALM);
    } */
  }

  if (this->connection_state.get_shutdown_state() == HTTP2_SHUTDOWN_NOT_INITIATED) {
    send_connection_event(&this->connection_state, HTTP2_SESSION_EVENT_SHUTDOWN_INIT, this);
  }

  recursion--;
  if (!connection_state.is_recursing() && this->recursion == 0 && kill_me) {
    this->free();
  }
  return retval;
}

sockaddr const *
Http2ServerSession::get_remote_addr() const
{
  return _vc ? _vc->get_remote_addr() : &cached_client_addr.sa;
}

sockaddr const *
Http2ServerSession::get_local_addr()
{
  return _vc ? _vc->get_local_addr() : &cached_local_addr.sa;
}

int
Http2ServerSession::get_transact_count() const
{
  return connection_state.get_stream_requests();
}

const char *
Http2ServerSession::get_protocol_string() const
{
  return "http/2";
}

void
Http2ServerSession::release(ProxyTransaction * /* trans ATS_UNUSED */)
{
}

int
Http2ServerSession::populate_protocol(std::string_view *result, int size) const
{
  int retval = 0;
  if (size > retval) {
    result[retval++] = IP_PROTO_TAG_HTTP_2_0;
    if (size > retval) {
      retval += super::populate_protocol(result + retval, size - retval);
    }
  }
  return retval;
}

const char *
Http2ServerSession::protocol_contains(std::string_view prefix) const
{
  const char *retval = nullptr;

  if (prefix.size() <= IP_PROTO_TAG_HTTP_2_0.size() && strncmp(IP_PROTO_TAG_HTTP_2_0.data(), prefix.data(), prefix.size()) == 0) {
    retval = IP_PROTO_TAG_HTTP_2_0.data();
  } else {
    retval = super::protocol_contains(prefix);
  }
  return retval;
}

ProxySession *
Http2ServerSession::get_proxy_session()
{
  return this;
}

ProxyTransaction *
Http2ServerSession::new_transaction()
{
  this->set_session_active();

  // Create a new stream/transaction
  Http2Error   error(Http2ErrorClass::HTTP2_ERROR_CLASS_NONE);
  Http2Stream *stream = connection_state.create_initiating_stream(error);

  if (!stream || connection_state.is_peer_concurrent_stream_ub()) {
    if (error.cls != Http2ErrorClass::HTTP2_ERROR_CLASS_NONE) {
      Error("HTTP/2 stream error code=0x%02x %s", static_cast<int>(error.code), error.msg);
    }

    remove_session();
  }

  return stream;
}

void
Http2ServerSession::add_session()
{
  if (this->in_session_table) {
    return;
  }
  Http2SsnDebug("Add session to pool");
  EThread           *ethread = this_ethread();
  ServerSessionPool *pool    = ethread->server_session_pool;
  MUTEX_TRY_LOCK(lock, pool->mutex, ethread);
  if (lock.is_locked()) {
    pool->addSession(this);
    this->in_session_table = true;
  }
}

void
Http2ServerSession::remove_session()
{
  if (!this->in_session_table) {
    return;
  }
  Http2SsnDebug("Remove session from pool");
  EThread           *ethread = this_ethread();
  ServerSessionPool *pool    = ethread->server_session_pool;
  MUTEX_TRY_LOCK(lock, pool->mutex, ethread);
  if (lock.is_locked()) {
    pool->removeSession(this);
    in_session_table = false;
  } else {
    ink_release_assert(!"How did we not get the pool lock?");
  }
}

bool
Http2ServerSession::is_multiplexing() const
{
  return true;
}

bool
Http2ServerSession::is_outbound() const
{
  return true;
}

void
Http2ServerSession::set_netvc(NetVConnection *netvc)
{
  super::set_netvc(netvc);
  if (netvc == nullptr) {
    write_vio = nullptr;
  }
}

void
Http2ServerSession::set_no_activity_timeout()
{
  // Only set if not previously set
  if (this->_vc->get_inactivity_timeout() == 0) {
    this->set_inactivity_timeout(HRTIME_SECONDS(Http2::no_activity_timeout_out));
  }
}

HTTPVersion
Http2ServerSession::get_version(HTTPHdr & /* hdr ATS_UNUSED */) const
{
  return HTTP_2_0;
}

IOBufferReader *
Http2ServerSession::get_remote_reader()
{
  return _read_buffer_reader;
}

bool
Http2ServerSession::is_protocol_framed() const
{
  return true;
}

uint64_t
Http2ServerSession::get_received_frame_count(uint64_t type) const
{
  if (type > HTTP2_FRAME_TYPE_MAX) {
    type = HTTP2_FRAME_TYPE_MAX;
  }
  return this->_frame_counts_in[type];
}

std::function<PoolableSession *()> create_h2_server_session = []() -> PoolableSession * {
  return http2ServerSessionAllocator.alloc();
};
