/** @file

  ProxySession - Base class for protocol client sessions.

  @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 "HttpConfig.h"
#include "HttpDebugNames.h"
#include "ProxySession.h"
#include "P_SSLNetVConnection.h"

ProxySession::ProxySession() : VConnection(nullptr) {}

ProxySession::ProxySession(NetVConnection *vc) : VConnection(nullptr), _vc(vc) {}

void
ProxySession::set_session_active()
{
  if (!m_active) {
    m_active = true;
    this->increment_current_active_client_connections_stat();
  }
}

void
ProxySession::clear_session_active()
{
  if (m_active) {
    m_active = false;
    this->decrement_current_active_client_connections_stat();
  }
}

static const TSEvent eventmap[TS_HTTP_LAST_HOOK + 1] = {
  TS_EVENT_HTTP_READ_REQUEST_HDR,      // TS_HTTP_READ_REQUEST_HDR_HOOK
  TS_EVENT_HTTP_OS_DNS,                // TS_HTTP_OS_DNS_HOOK
  TS_EVENT_HTTP_SEND_REQUEST_HDR,      // TS_HTTP_SEND_REQUEST_HDR_HOOK
  TS_EVENT_HTTP_READ_CACHE_HDR,        // TS_HTTP_READ_CACHE_HDR_HOOK
  TS_EVENT_HTTP_READ_RESPONSE_HDR,     // TS_HTTP_READ_RESPONSE_HDR_HOOK
  TS_EVENT_HTTP_SEND_RESPONSE_HDR,     // TS_HTTP_SEND_RESPONSE_HDR_HOOK
  TS_EVENT_HTTP_REQUEST_TRANSFORM,     // TS_HTTP_REQUEST_TRANSFORM_HOOK
  TS_EVENT_HTTP_RESPONSE_TRANSFORM,    // TS_HTTP_RESPONSE_TRANSFORM_HOOK
  TS_EVENT_HTTP_SELECT_ALT,            // TS_HTTP_SELECT_ALT_HOOK
  TS_EVENT_HTTP_TXN_START,             // TS_HTTP_TXN_START_HOOK
  TS_EVENT_HTTP_TXN_CLOSE,             // TS_HTTP_TXN_CLOSE_HOOK
  TS_EVENT_HTTP_SSN_START,             // TS_HTTP_SSN_START_HOOK
  TS_EVENT_HTTP_SSN_CLOSE,             // TS_HTTP_SSN_CLOSE_HOOK
  TS_EVENT_HTTP_CACHE_LOOKUP_COMPLETE, // TS_HTTP_CACHE_LOOKUP_COMPLETE_HOOK
  TS_EVENT_HTTP_PRE_REMAP,             // TS_HTTP_PRE_REMAP_HOOK
  TS_EVENT_HTTP_POST_REMAP,            // TS_HTTP_POST_REMAP_HOOK
  TS_EVENT_NONE,                       // TS_HTTP_RESPONSE_CLIENT_HOOK
  TS_EVENT_NONE,                       // TS_HTTP_LAST_HOOK
};

void
ProxySession::free()
{
  if (schedule_event) {
    schedule_event->cancel();
    schedule_event = nullptr;
  }
  this->api_hooks.clear();
  this->mutex.clear();
  this->acl.clear();
  this->_ssl.reset();
}

int
ProxySession::state_api_callout(int event, void *data)
{
  Event *e = static_cast<Event *>(data);
  if (e == schedule_event) {
    schedule_event = nullptr;
  }

  switch (event) {
  case EVENT_NONE:
  case EVENT_INTERVAL:
  case TS_EVENT_HTTP_CONTINUE:
    if (nullptr == cur_hook) {
      /// Get the next hook to invoke from HttpHookState
      cur_hook = hook_state.getNext();
    }
    if (nullptr != cur_hook) {
      APIHook const *hook = cur_hook;

      WEAK_MUTEX_TRY_LOCK(lock, hook->m_cont->mutex, mutex->thread_holding);

      // Have a mutex but didn't get the lock, reschedule
      if (!lock.is_locked()) {
        SET_HANDLER(&ProxySession::state_api_callout);
        if (!schedule_event) { // Don't bother if there is already one
          schedule_event = mutex->thread_holding->schedule_in(this, HRTIME_MSECONDS(10));
        }
        return -1;
      }

      cur_hook = nullptr; // mark current callback at dispatched.
      hook->invoke(eventmap[hook_state.id()], this);

      return 0;
    }

    handle_api_return(event);
    break;

  case TS_EVENT_HTTP_ERROR:
    this->handle_api_return(event);
    break;

  // coverity[unterminated_default]
  default:
    ink_release_assert(false);
  }

  return 0;
}

int
ProxySession::do_api_callout(TSHttpHookID id)
{
  ink_assert(id == TS_HTTP_SSN_START_HOOK || id == TS_HTTP_SSN_CLOSE_HOOK);
  hook_state.init(id, http_global_hooks, &api_hooks);
  /// Verify if there is any hook to invoke
  cur_hook = hook_state.getNext();
  if (nullptr != cur_hook) {
    SET_HANDLER(&ProxySession::state_api_callout);
    return this->state_api_callout(EVENT_NONE, nullptr);
  } else {
    this->handle_api_return(TS_EVENT_HTTP_CONTINUE);
  }
  return 0;
}

void
ProxySession::handle_api_return(int event)
{
  TSHttpHookID hookid = hook_state.id();

  SET_HANDLER(&ProxySession::state_api_callout);

  cur_hook = nullptr;

  switch (hookid) {
  case TS_HTTP_SSN_START_HOOK:
    if (event == TS_EVENT_HTTP_ERROR) {
      this->do_io_close();
    } else {
      this->start();
    }
    break;
  case TS_HTTP_SSN_CLOSE_HOOK: {
    free(); // You can now clean things up
    break;
  }
  default:
    Fatal("received invalid session hook %s (%d)", HttpDebugNames::get_api_hook_name(hookid), hookid);
    break;
  }
}

bool
ProxySession::is_chunked_encoding_supported() const
{
  return false;
}

// Override if your session protocol cares.
void
ProxySession::set_half_close_flag(bool flag)
{
}

bool
ProxySession::get_half_close_flag() const
{
  return false;
}

int64_t
ProxySession::connection_id() const
{
  return con_id;
}

void
ProxySession::attach_server_session(Http1ServerSession *ssession, bool transaction_done)
{
}

Http1ServerSession *
ProxySession::get_server_session() const
{
  return nullptr;
}

void
ProxySession::set_active_timeout(ink_hrtime timeout_in)
{
  if (_vc) {
    _vc->set_active_timeout(timeout_in);
  }
}

void
ProxySession::set_inactivity_timeout(ink_hrtime timeout_in)
{
  if (_vc) {
    _vc->set_inactivity_timeout(timeout_in);
  }
}

void
ProxySession::cancel_inactivity_timeout()
{
  if (_vc) {
    _vc->cancel_inactivity_timeout();
  }
}

int
ProxySession::populate_protocol(std::string_view *result, int size) const
{
  return _vc ? _vc->populate_protocol(result, size) : 0;
}

const char *
ProxySession::protocol_contains(std::string_view tag_prefix) const
{
  return _vc ? _vc->protocol_contains(tag_prefix) : nullptr;
}

sockaddr const *
ProxySession::get_client_addr()
{
  return _vc ? _vc->get_remote_addr() : nullptr;
}

sockaddr const *
ProxySession::get_local_addr()
{
  return _vc ? _vc->get_local_addr() : nullptr;
}

void
ProxySession::_handle_if_ssl(NetVConnection *new_vc)
{
  auto ssl_vc = dynamic_cast<SSLNetVConnection *>(new_vc);
  if (ssl_vc) {
    _ssl = std::make_unique<SSLProxySession>();
    _ssl.get()->init(*ssl_vc);
  }
}

VIO *
ProxySession::do_io_read(Continuation *c, int64_t nbytes, MIOBuffer *buf)
{
  return _vc ? this->_vc->do_io_read(c, nbytes, buf) : nullptr;
}

VIO *
ProxySession::do_io_write(Continuation *c, int64_t nbytes, IOBufferReader *buf, bool owner)
{
  return _vc ? this->_vc->do_io_write(c, nbytes, buf, owner) : nullptr;
}

void
ProxySession::do_io_shutdown(ShutdownHowTo_t howto)
{
  this->_vc->do_io_shutdown(howto);
}

void
ProxySession::reenable(VIO *vio)
{
  this->_vc->reenable(vio);
}

bool
ProxySession::support_sni() const
{
  return _vc ? _vc->support_sni() : false;
}
