/** @file

  A brief file description

  @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.
 */

/****************************************************************************

   Http1ClientSession.cc

   Description:


 ****************************************************************************/

#include "tscore/ink_resolver.h"
#include "Http1ClientSession.h"
#include "Http1Transaction.h"
#include "HttpSM.h"
#include "HttpDebugNames.h"
#include "Plugin.h"
#include "PoolableSession.h"

#include "P_SSLNetVConnection.h"

#define HttpSsnDebug(fmt, ...) SsnDebug(this, "http_cs", fmt, __VA_ARGS__)

#define STATE_ENTER(state_name, event, vio)                                                             \
  do {                                                                                                  \
    /*ink_assert (magic == HTTP_SM_MAGIC_ALIVE);  REMEMBER (event, NULL, reentrancy_count); */          \
    HttpSsnDebug("[%" PRId64 "] [%s, %s]", con_id, #state_name, HttpDebugNames::get_event_name(event)); \
  } while (0)

#ifdef USE_HTTP_DEBUG_LISTS

// We have debugging list that we can use to find stuck
//  client sessions
DList(Http1ClientSession, debug_link) debug_cs_list;
ink_mutex debug_cs_list_mutex;

#endif /* USE_HTTP_DEBUG_LISTS */

ClassAllocator<Http1ClientSession, true> http1ClientSessionAllocator("http1ClientSessionAllocator");

Http1ClientSession::Http1ClientSession() : super(), trans(this) {}

void
Http1ClientSession::destroy()
{
  if (read_state != HCS_CLOSED) {
    return;
  }
  if (!in_destroy) {
    in_destroy = true;

    HttpSsnDebug("[%" PRId64 "] session destroy", con_id);
    ink_assert(read_buffer);
    ink_release_assert(transact_count == released_transactions);
    do_api_callout(TS_HTTP_SSN_CLOSE_HOOK);
  } else {
    Warning("http1: Attempt to double ssn close");
  }
}

void
Http1ClientSession::release_transaction()
{
  released_transactions++;
  if (transact_count == released_transactions) {
    // Make sure we previously called release() or do_io_close() on the session
    ink_release_assert(read_state != HCS_INIT);
    if (read_state == HCS_ACTIVE_READER) {
      // (in)active timeout
      do_io_close(HTTP_ERRNO);
    } else {
      destroy();
    }
  }
}

void
Http1ClientSession::free()
{
  magic = HTTP_CS_MAGIC_DEAD;
  if (read_buffer) {
    free_MIOBuffer(read_buffer);
    read_buffer = nullptr;
  }

#ifdef USE_HTTP_DEBUG_LISTS
  ink_mutex_acquire(&debug_cs_list_mutex);
  debug_cs_list.remove(this);
  ink_mutex_release(&debug_cs_list_mutex);
#endif

  if (conn_decrease) {
    HTTP_DECREMENT_DYN_STAT(http_current_client_connections_stat);
    conn_decrease = false;
  }

  if (_vc) {
    _vc->do_io_close();
    _vc = nullptr;
  }

  THREAD_FREE(this, http1ClientSessionAllocator, this_thread());
}

void
Http1ClientSession::new_connection(NetVConnection *new_vc, MIOBuffer *iobuf, IOBufferReader *reader)
{
  ink_assert(new_vc != nullptr);
  ink_assert(_vc == nullptr);
  _vc         = new_vc;
  magic       = HTTP_CS_MAGIC_ALIVE;
  mutex       = new_vc->mutex;
  trans.mutex = mutex; // Share this mutex with the transaction
  in_destroy  = false;

  SSLNetVConnection *ssl_vc = dynamic_cast<SSLNetVConnection *>(new_vc);
  if (ssl_vc != nullptr) {
    read_from_early_data = ssl_vc->read_from_early_data;
    Debug("ssl_early_data", "read_from_early_data = %" PRId64, read_from_early_data);
  }

  MUTEX_TRY_LOCK(lock, mutex, this_ethread());
  ink_assert(lock.is_locked());

  // Unique client session identifier.
  con_id = ProxySession::next_connection_id();

  schedule_event = nullptr;

  HTTP_INCREMENT_DYN_STAT(http_current_client_connections_stat);
  conn_decrease = true;
  HTTP_INCREMENT_DYN_STAT(http_total_client_connections_stat);
  if (static_cast<HttpProxyPort::TransportType>(new_vc->attributes) == HttpProxyPort::TRANSPORT_SSL) {
    HTTP_INCREMENT_DYN_STAT(https_total_client_connections_stat);
  }

  /* inbound requests stat should be incremented here, not after the
   * header has been read */
  HTTP_INCREMENT_DYN_STAT(http_total_incoming_connections_stat);

  // check what type of socket address we just accepted
  // by looking at the address family value of sockaddr_storage
  // and logging to stat system
  switch (new_vc->get_remote_addr()->sa_family) {
  case AF_INET:
    HTTP_INCREMENT_DYN_STAT(http_total_client_connections_ipv4_stat);
    break;
  case AF_INET6:
    HTTP_INCREMENT_DYN_STAT(http_total_client_connections_ipv6_stat);
    break;
  default:
    // don't do anything if the address family is not ipv4 or ipv6
    // (there are many other address families in <sys/socket.h>
    // but we don't have a need to report on all the others today)
    break;
  }

#ifdef USE_HTTP_DEBUG_LISTS
  ink_mutex_acquire(&debug_cs_list_mutex);
  debug_cs_list.push(this);
  ink_mutex_release(&debug_cs_list_mutex);
#endif

  HttpSsnDebug("[%" PRId64 "] session born, netvc %p", con_id, new_vc);

  _vc->set_tcp_congestion_control(CLIENT_SIDE);

  read_buffer = iobuf ? iobuf : new_MIOBuffer(HTTP_HEADER_BUFFER_SIZE_INDEX);
  _reader     = reader ? reader : read_buffer->alloc_reader();
  trans.set_reader(_reader);

  _handle_if_ssl(new_vc);

  // INKqa11186: Use a local pointer to the mutex as
  // when we return from do_api_callout, the ClientSession may
  // have already been deallocated.
  EThread *ethis         = this_ethread();
  Ptr<ProxyMutex> lmutex = this->mutex;
  MUTEX_TAKE_LOCK(lmutex, ethis);
  do_api_callout(TS_HTTP_SSN_START_HOOK);
  MUTEX_UNTAKE_LOCK(lmutex, ethis);
  lmutex.clear();
}

void
Http1ClientSession::do_io_close(int alerrno)
{
  if (read_state == HCS_CLOSED) {
    return; // Don't double call session close
  }
  if (read_state == HCS_ACTIVE_READER) {
    clear_session_active();
  }

  // Prevent double closing
  ink_release_assert(read_state != HCS_CLOSED);

  // If we have an attached server session, release
  //   it back to our shared pool
  if (bound_ss) {
    bound_ss->release(nullptr);
    bound_ss     = nullptr;
    slave_ka_vio = nullptr;
  }
  // Completed the last transaction.  Just shutdown already
  // Or the do_io_close is due to a network error
  if (transact_count == released_transactions || alerrno == HTTP_ERRNO) {
    half_close = false;
  }

  if (half_close && this->trans.get_sm()) {
    read_state = HCS_HALF_CLOSED;
    SET_HANDLER(&Http1ClientSession::state_wait_for_close);
    HttpSsnDebug("[%" PRId64 "] session half close", con_id);

    if (_vc) {
      _vc->do_io_shutdown(IO_SHUTDOWN_WRITE);

      ka_vio = _vc->do_io_read(this, INT64_MAX, read_buffer);
      ink_assert(slave_ka_vio != ka_vio);

      // Set the active timeout to the same as the inactive time so
      //   that this connection does not hang around forever if
      //   the ua hasn't closed
      _vc->set_active_timeout(HRTIME_SECONDS(trans.get_sm()->t_state.txn_conf->keep_alive_no_activity_timeout_in));
    }

    // [bug 2610799] Drain any data read.
    // If the buffer is full and the client writes again, we will not receive a
    // READ_READY event.
    _reader->consume(_reader->read_avail());
  } else {
    HttpSsnDebug("[%" PRId64 "] session closed", con_id);
    HTTP_SUM_DYN_STAT(http_transactions_per_client_con, transact_count);
    read_state = HCS_CLOSED;

    // Can go ahead and close the netvc now, but keeping around the session object
    // until all the transactions are closed
    if (_vc) {
      _vc->do_io_close();
      _vc = nullptr;
    }
  }
  if (transact_count == released_transactions) {
    this->destroy();
  }
}

int
Http1ClientSession::state_wait_for_close(int event, void *data)
{
  STATE_ENTER(&Http1ClientSession::state_wait_for_close, event, data);

  ink_assert(data == ka_vio);
  ink_assert(read_state == HCS_HALF_CLOSED);

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

  switch (event) {
  case VC_EVENT_EOS:
  case VC_EVENT_ERROR:
  case VC_EVENT_ACTIVE_TIMEOUT:
  case VC_EVENT_INACTIVITY_TIMEOUT:
    half_close = false;
    this->do_io_close(EHTTP_ERROR);
    break;
  case VC_EVENT_READ_READY:
    // Drain any data read
    _reader->consume(_reader->read_avail());
    break;

  default:
    ink_release_assert(0);
    break;
  }

  return 0;
}

int
Http1ClientSession::state_slave_keep_alive(int event, void *data)
{
  STATE_ENTER(&Http1ClientSession::state_slave_keep_alive, event, data);

  ink_assert(data == slave_ka_vio);

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

  switch (event) {
  default:
  case VC_EVENT_READ_COMPLETE:
    // These events are bogus
    ink_assert(0);
  /* Fall Through */
  case VC_EVENT_ERROR:
  case VC_EVENT_READ_READY:
  case VC_EVENT_EOS:
    // The server session closed or something is amiss
    bound_ss->do_io_close();
    bound_ss     = nullptr;
    slave_ka_vio = nullptr;
    break;

  case VC_EVENT_ACTIVE_TIMEOUT:
  case VC_EVENT_INACTIVITY_TIMEOUT:
    // Timeout - place the session on the shared pool
    bound_ss->release(nullptr);
    bound_ss     = nullptr;
    slave_ka_vio = nullptr;
    break;
  }

  return 0;
}

int
Http1ClientSession::state_keep_alive(int event, void *data)
{
  // Route the event.  It is either for vc or
  //  the origin server slave vc
  if (data && data == slave_ka_vio) {
    return state_slave_keep_alive(event, data);
  } else {
    ink_assert(data && data == ka_vio);
    ink_assert(read_state == HCS_KEEP_ALIVE);
  }

  STATE_ENTER(&Http1ClientSession::state_keep_alive, event, data);

  switch (event) {
  case VC_EVENT_READ_READY:
    // New transaction, need to spawn of new sm to process
    // request
    new_transaction();
    break;

  case VC_EVENT_EOS:
    this->do_io_close(EHTTP_ERROR);
    break;

  case VC_EVENT_READ_COMPLETE:
  default:
    // These events are bogus
    ink_assert(0);
  // Fall through
  case VC_EVENT_ERROR:
  case VC_EVENT_ACTIVE_TIMEOUT:
  case VC_EVENT_INACTIVITY_TIMEOUT:
    // Keep-alive timed out
    this->do_io_close(EHTTP_ERROR);
    break;
  }

  return 0;
}

// Called from the Http1Transaction::release
void
Http1ClientSession::release(ProxyTransaction *trans)
{
  ink_assert(read_state == HCS_ACTIVE_READER || read_state == HCS_INIT);

  // When release is called from start() to read the first transaction, get_sm()
  // will return null.
  HttpSM *sm                = trans->get_sm();
  Http1Transaction *h1trans = static_cast<Http1Transaction *>(trans);
  if (sm) {
    MgmtInt ka_in = trans->get_sm()->t_state.txn_conf->keep_alive_no_activity_timeout_in;
    set_inactivity_timeout(HRTIME_SECONDS(ka_in));

    this->clear_session_active();

    // Timeout events should be delivered to the session
    this->do_io_write(this, 0, nullptr);
  }

  // Check to see there is remaining data in the
  //  buffer.  If there is, spin up a new state
  //  machine to process it.  Otherwise, issue an
  //  IO to wait for new data
  bool more_to_read = this->_reader->is_read_avail_more_than(0);
  if (more_to_read) {
    h1trans->reset();
    HttpSsnDebug("[%" PRId64 "] data already in buffer, starting new transaction", con_id);
    new_transaction();
  } else {
    HttpSsnDebug("[%" PRId64 "] initiating io for next header", con_id);
    read_state = HCS_KEEP_ALIVE;
    SET_HANDLER(&Http1ClientSession::state_keep_alive);
    ka_vio = this->do_io_read(this, INT64_MAX, read_buffer);
    ink_assert(slave_ka_vio != ka_vio);

    if (_vc) {
      _vc->cancel_active_timeout();
      _vc->add_to_keep_alive_queue();
    }
    h1trans->reset();
  }
}

void
Http1ClientSession::new_transaction()
{
  // If the client connection terminated during API callouts we're done.
  if (nullptr == _vc) {
    this->do_io_close(); // calls the SSN_CLOSE hooks to match the SSN_START hooks.
    return;
  }

  if (!_vc->add_to_active_queue()) {
    // no room in the active queue close the connection
    this->do_io_close();
    return;
  }

  // Defensive programming, make sure nothing persists across
  // connection re-use
  half_close = false;

  read_state = HCS_ACTIVE_READER;

  transact_count++;

  trans.new_transaction(read_from_early_data > 0 ? true : false);
}

bool
Http1ClientSession::attach_server_session(PoolableSession *ssession, bool transaction_done)
{
  if (ssession) {
    ink_assert(bound_ss == nullptr);
    ssession->state = PoolableSession::KA_RESERVED;
    bound_ss        = ssession;
    HttpSsnDebug("[%" PRId64 "] attaching server session [%" PRId64 "] as slave", con_id, ssession->connection_id());
    ink_assert(ssession->get_netvc() != this->get_netvc());

    // handling potential keep-alive here
    clear_session_active();

    // Since this our slave, issue an IO to detect a close and
    //  have it call the client session back.  This IO also prevent
    //  the server net conneciton from calling back a dead sm
    SET_HANDLER(&Http1ClientSession::state_keep_alive);
    slave_ka_vio = ssession->do_io_read(this, 0, nullptr);
    ink_assert(slave_ka_vio != ka_vio);

    // Transfer control of the write side as well
    ssession->do_io_write(this, 0, nullptr);

    if (transaction_done) {
      ssession->set_inactivity_timeout(HRTIME_SECONDS(trans.get_sm()->t_state.txn_conf->keep_alive_no_activity_timeout_out));
      ssession->cancel_active_timeout();
    } else {
      // we are serving from the cache - this could take a while.
      ssession->cancel_inactivity_timeout();
      ssession->cancel_active_timeout();
    }
  } else {
    ink_assert(bound_ss != nullptr);
    bound_ss     = nullptr;
    slave_ka_vio = nullptr;
  }
  return true;
}

void
Http1ClientSession::increment_current_active_connections_stat()
{
  HTTP_INCREMENT_DYN_STAT(http_current_active_client_connections_stat);
}
void
Http1ClientSession::decrement_current_active_connections_stat()
{
  HTTP_DECREMENT_DYN_STAT(http_current_active_client_connections_stat);
}

void
Http1ClientSession::start()
{
  // Troll for data to get a new transaction
  this->release(&trans);
}

bool
Http1ClientSession::allow_half_open() const
{
  // Only allow half open connections if the not over TLS
  return (_vc && dynamic_cast<SSLNetVConnection *>(_vc) == nullptr);
}

void
Http1ClientSession::set_half_close_flag(bool flag)
{
  half_close = flag;
}

bool
Http1ClientSession::get_half_close_flag() const
{
  return half_close;
}

bool
Http1ClientSession::is_chunked_encoding_supported() const
{
  return true;
}

int
Http1ClientSession::get_transact_count() const
{
  return transact_count;
}

bool
Http1ClientSession::is_outbound_transparent() const
{
  return f_outbound_transparent;
}

PoolableSession *
Http1ClientSession::get_server_session() const
{
  return bound_ss;
}

const char *
Http1ClientSession::get_protocol_string() const
{
  return "http";
}
