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

#include "QUICHandshake.h"

#include <utility>

#include "QUICEvents.h"
#include "QUICGlobals.h"
#include "QUICHandshakeProtocol.h"
#include "QUICPacketFactory.h"
#include "QUICVersionNegotiator.h"
#include "QUICConfig.h"

#define QUICHSDebug(fmt, ...) Debug("quic_handshake", "[%s] " fmt, this->_qc->cids().data(), ##__VA_ARGS__)

#define QUICVHSDebug(fmt, ...) Debug("v_quic_handshake", "[%s] " fmt, this->_qc->cids().data(), ##__VA_ARGS__)

#define I_WANNA_DUMP_THIS_BUF(buf, len)                                                                                            \
  {                                                                                                                                \
    static constexpr char dump_tag[] = "v_quic_handshake_dump_pkt";                                                                \
    int i;                                                                                                                         \
    Debug(dump_tag, "len=%" PRId64 "\n", len);                                                                                     \
    for (i = 0; i < len / 8; i++) {                                                                                                \
      Debug(dump_tag, "%02x %02x %02x %02x %02x %02x %02x %02x ", buf[i * 8 + 0], buf[i * 8 + 1], buf[i * 8 + 2], buf[i * 8 + 3],  \
            buf[i * 8 + 4], buf[i * 8 + 5], buf[i * 8 + 6], buf[i * 8 + 7]);                                                       \
    }                                                                                                                              \
    switch (len % 8) {                                                                                                             \
    case 1:                                                                                                                        \
      Debug(dump_tag, "%02x", buf[i * 8 + 0]);                                                                                     \
      break;                                                                                                                       \
    case 2:                                                                                                                        \
      Debug(dump_tag, "%02x %02x", buf[i * 8 + 0], buf[i * 8 + 1]);                                                                \
                                                                                                                                   \
      break;                                                                                                                       \
    case 3:                                                                                                                        \
      Debug(dump_tag, "%02x %02x %02x", buf[i * 8 + 0], buf[i * 8 + 1], buf[i * 8 + 2]);                                           \
                                                                                                                                   \
      break;                                                                                                                       \
    case 4:                                                                                                                        \
      Debug(dump_tag, "%02x %02x %02x %02x", buf[i * 8 + 0], buf[i * 8 + 1], buf[i * 8 + 2], buf[i * 8 + 3]);                      \
                                                                                                                                   \
      break;                                                                                                                       \
    case 5:                                                                                                                        \
      Debug(dump_tag, "%02x %02x %02x %02x %02x", buf[i * 8 + 0], buf[i * 8 + 1], buf[i * 8 + 2], buf[i * 8 + 3], buf[i * 8 + 4]); \
                                                                                                                                   \
      break;                                                                                                                       \
    case 6:                                                                                                                        \
      Debug(dump_tag, "%02x %02x %02x %02x %02x %02x", buf[i * 8 + 0], buf[i * 8 + 1], buf[i * 8 + 2], buf[i * 8 + 3],             \
            buf[i * 8 + 4], buf[i * 8 + 5]);                                                                                       \
                                                                                                                                   \
      break;                                                                                                                       \
    case 7:                                                                                                                        \
      Debug(dump_tag, "%02x %02x %02x %02x %02x %02x %02x", buf[i * 8 + 0], buf[i * 8 + 1], buf[i * 8 + 2], buf[i * 8 + 3],        \
            buf[i * 8 + 4], buf[i * 8 + 5], buf[i * 8 + 6]);                                                                       \
                                                                                                                                   \
      break;                                                                                                                       \
    default:                                                                                                                       \
      break;                                                                                                                       \
    }                                                                                                                              \
  }

static constexpr int UDP_MAXIMUM_PAYLOAD_SIZE = 65527;

QUICHandshake::QUICHandshake(QUICConnection *qc, QUICHandshakeProtocol *hsp) : QUICHandshake(qc, hsp, {}, false) {}

QUICHandshake::QUICHandshake(QUICConnection *qc, QUICHandshakeProtocol *hsp, QUICStatelessResetToken token, bool stateless_retry)
  : _qc(qc),
    _hs_protocol(hsp),
    _version_negotiator(new QUICVersionNegotiator()),
    _reset_token(token),
    _stateless_retry(stateless_retry)
{
  this->_hs_protocol->initialize_key_materials(this->_qc->original_connection_id());

  if (this->_qc->direction() == NET_VCONNECTION_OUT) {
    this->_client_initial = true;
  }
}

QUICHandshake::~QUICHandshake()
{
  delete this->_hs_protocol;
}

QUICConnectionErrorUPtr
QUICHandshake::start(const QUICTPConfig &tp_config, QUICPacketFactory *packet_factory, bool vn_exercise_enabled)
{
  QUICVersion initial_version = QUIC_SUPPORTED_VERSIONS[0];
  if (vn_exercise_enabled) {
    initial_version = QUIC_EXERCISE_VERSION;
  }

  this->_load_local_client_transport_parameters(tp_config);
  packet_factory->set_version(initial_version);

  return nullptr;
}

QUICConnectionErrorUPtr
QUICHandshake::start(const QUICTPConfig &tp_config, const QUICInitialPacketR &initial_packet, QUICPacketFactory *packet_factory,
                     const QUICPreferredAddress *pref_addr)
{
  // Negotiate version
  if (this->_version_negotiator->status() == QUICVersionNegotiationStatus::NOT_NEGOTIATED) {
    if (initial_packet.type() != QUICPacketType::INITIAL) {
      return std::make_unique<QUICConnectionError>(QUICTransErrorCode::PROTOCOL_VIOLATION);
    }
    if (initial_packet.version()) {
      if (this->_version_negotiator->negotiate(initial_packet) == QUICVersionNegotiationStatus::NEGOTIATED) {
        QUICHSDebug("Version negotiation succeeded: %x", initial_packet.version());
        this->_load_local_server_transport_parameters(tp_config, pref_addr);
        packet_factory->set_version(this->_version_negotiator->negotiated_version());
      } else {
        ink_assert(!"Unsupported version initial packet should be dropped QUICPacketHandler");
      }
    } else {
      return std::make_unique<QUICConnectionError>(QUICTransErrorCode::PROTOCOL_VIOLATION);
    }
  }
  return nullptr;
}

QUICConnectionErrorUPtr
QUICHandshake::negotiate_version(const QUICVersionNegotiationPacketR &vn, QUICPacketFactory *packet_factory)
{
  // Client side only
  ink_assert(this->_qc->direction() == NET_VCONNECTION_OUT);

  // If already negotiated, just ignore it
  if (this->_version_negotiator->status() == QUICVersionNegotiationStatus::NEGOTIATED ||
      this->_version_negotiator->status() == QUICVersionNegotiationStatus::VALIDATED) {
    QUICHSDebug("Ignore Version Negotiation packet");
    return nullptr;
  }

  if (vn.version() != 0x00) {
    QUICHSDebug("Version field must be 0x00000000");
    return std::make_unique<QUICConnectionError>(QUICTransErrorCode::PROTOCOL_VIOLATION);
  }

  if (this->_version_negotiator->negotiate(vn) == QUICVersionNegotiationStatus::NEGOTIATED) {
    QUICVersion version = this->_version_negotiator->negotiated_version();
    QUICHSDebug("Version negotiation succeeded: 0x%x", version);
    packet_factory->set_version(version);
  } else {
    QUICHSDebug("Version negotiation failed");
    return std::make_unique<QUICConnectionError>(QUICTransErrorCode::PROTOCOL_VIOLATION);
  }

  return nullptr;
}

bool
QUICHandshake::is_version_negotiated() const
{
  return (this->_version_negotiator->status() == QUICVersionNegotiationStatus::NEGOTIATED ||
          this->_version_negotiator->status() == QUICVersionNegotiationStatus::VALIDATED);
}

bool
QUICHandshake::is_completed() const
{
  return this->_hs_protocol->is_handshake_finished();
}

bool
QUICHandshake::is_confirmed() const
{
  if (this->_qc->direction() == NET_VCONNECTION_IN) {
    return this->is_completed();
  } else {
    return this->_is_handshake_done_received;
  }
}

bool
QUICHandshake::is_stateless_retry_enabled() const
{
  return this->_stateless_retry;
}

bool
QUICHandshake::has_remote_tp() const
{
  return this->_remote_transport_parameters != nullptr;
}

QUICVersion
QUICHandshake::negotiated_version() const
{
  return this->_version_negotiator->negotiated_version();
}

// Similar to SSLNetVConnection::getSSLCipherSuite()
const char *
QUICHandshake::negotiated_cipher_suite() const
{
  return this->_hs_protocol->negotiated_cipher_suite();
}

void
QUICHandshake::negotiated_application_name(const uint8_t **name, unsigned int *len) const
{
  this->_hs_protocol->negotiated_application_name(name, len);
}

bool
QUICHandshake::check_remote_transport_parameters()
{
  auto tp = this->_hs_protocol->remote_transport_parameters();

  if (tp == nullptr) {
    // nothing to check
    return true;
  }

  if (std::dynamic_pointer_cast<const QUICTransportParametersInClientHello>(tp)) {
    return this->_check_remote_transport_parameters(std::static_pointer_cast<const QUICTransportParametersInClientHello>(tp));
  } else {
    return this->_check_remote_transport_parameters(
      std::static_pointer_cast<const QUICTransportParametersInEncryptedExtensions>(tp));
  }
}

bool
QUICHandshake::_check_remote_transport_parameters(std::shared_ptr<const QUICTransportParametersInClientHello> tp)
{
  // An endpoint MUST treat receipt of duplicate transport parameters as a connection error of type TRANSPORT_PARAMETER_ERROR.
  if (!tp->is_valid()) {
    QUICHSDebug("Transport parameter is not valid");
    this->_abort_handshake(QUICTransErrorCode::TRANSPORT_PARAMETER_ERROR);
    return false;
  }

  this->_remote_transport_parameters = tp;

  return true;
}

bool
QUICHandshake::_check_remote_transport_parameters(std::shared_ptr<const QUICTransportParametersInEncryptedExtensions> tp)
{
  // An endpoint MUST treat receipt of duplicate transport parameters as a connection error of type TRANSPORT_PARAMETER_ERROR.
  if (!tp->is_valid()) {
    QUICHSDebug("Transport parameter is not valid");
    this->_abort_handshake(QUICTransErrorCode::TRANSPORT_PARAMETER_ERROR);
    return false;
  }

  this->_remote_transport_parameters = tp;

  return true;
}

std::shared_ptr<const QUICTransportParameters>
QUICHandshake::local_transport_parameters()
{
  return this->_local_transport_parameters;
}

std::shared_ptr<const QUICTransportParameters>
QUICHandshake::remote_transport_parameters()
{
  return this->_remote_transport_parameters;
}

/**
 * reset states for starting over
 */
void
QUICHandshake::reset()
{
  this->_client_initial = true;
  this->_hs_protocol->reset();

  for (auto level : QUIC_ENCRYPTION_LEVELS) {
    int index                = static_cast<int>(level);
    QUICCryptoStream *stream = &this->_crypto_streams[index];
    stream->reset_send_offset();
    stream->reset_recv_offset();
  }
}

std::vector<QUICFrameType>
QUICHandshake::interests()
{
  return {
    QUICFrameType::CRYPTO,
    QUICFrameType::HANDSHAKE_DONE,
  };
}

QUICConnectionErrorUPtr
QUICHandshake::handle_frame(QUICEncryptionLevel level, const QUICFrame &frame)
{
  QUICConnectionErrorUPtr error = nullptr;
  switch (frame.type()) {
  case QUICFrameType::CRYPTO:
    error = this->_crypto_streams[static_cast<int>(level)].recv(static_cast<const QUICCryptoFrame &>(frame));
    if (error == nullptr) {
      error = this->do_handshake();
    }
    break;
  case QUICFrameType::HANDSHAKE_DONE:
    if (this->_qc->direction() == NET_VCONNECTION_IN) {
      error = std::make_unique<QUICConnectionError>(QUICTransErrorCode::PROTOCOL_VIOLATION);
    } else {
      this->_is_handshake_done_received = true;
    }
    break;
  default:
    QUICHSDebug("Unexpected frame type: %02x", static_cast<unsigned int>(frame.type()));
    ink_assert(false);
    break;
  }

  return error;
}

bool
QUICHandshake::will_generate_frame(QUICEncryptionLevel level, size_t current_packet_size, bool ack_eliciting, uint32_t seq_num)
{
  if (!this->_is_level_matched(level)) {
    return false;
  }

  return (this->_qc->direction() == NET_VCONNECTION_IN && !this->_is_handshake_done_sent) ||
         this->_crypto_streams[static_cast<int>(level)].will_generate_frame(level, current_packet_size, ack_eliciting, seq_num);
}

QUICFrame *
QUICHandshake::generate_frame(uint8_t *buf, QUICEncryptionLevel level, uint64_t connection_credit, uint16_t maximum_frame_size,
                              size_t current_packet_size, uint32_t seq_num)
{
  QUICFrame *frame = nullptr;

  if (this->_is_level_matched(level)) {
    // CRYPTO
    frame = this->_crypto_streams[static_cast<int>(level)].generate_frame(buf, level, connection_credit, maximum_frame_size,
                                                                          current_packet_size, seq_num);
    if (frame) {
      return frame;
    }
  }

  if (level == QUICEncryptionLevel::ONE_RTT) {
    // HANDSHAKE_DONE
    if (!this->_is_handshake_done_sent && this->is_completed()) {
      frame = QUICFrameFactory::create_handshake_done_frame(buf, this->_issue_frame_id(), this);
    }
    if (frame) {
      this->_is_handshake_done_sent = true;
      return frame;
    }
  }

  return frame;
}

void
QUICHandshake::_load_local_server_transport_parameters(const QUICTPConfig &tp_config, const QUICPreferredAddress *pref_addr)
{
  QUICTransportParametersInEncryptedExtensions *tp = new QUICTransportParametersInEncryptedExtensions();

  // MUSTs
  tp->set(QUICTransportParameterId::MAX_IDLE_TIMEOUT, static_cast<uint16_t>(tp_config.no_activity_timeout()));
  if (this->_stateless_retry) {
    tp->set(QUICTransportParameterId::ORIGINAL_CONNECTION_ID, this->_qc->first_connection_id(),
            this->_qc->first_connection_id().length());
  }

  // MAYs
  if (tp_config.initial_max_data() != 0) {
    tp->set(QUICTransportParameterId::INITIAL_MAX_DATA, tp_config.initial_max_data());
  }
  if (tp_config.initial_max_streams_bidi() != 0) {
    tp->set(QUICTransportParameterId::INITIAL_MAX_STREAMS_BIDI, tp_config.initial_max_streams_bidi());
  }
  if (tp_config.initial_max_streams_uni() != 0) {
    tp->set(QUICTransportParameterId::INITIAL_MAX_STREAMS_UNI, tp_config.initial_max_streams_uni());
  }
  if (tp_config.initial_max_stream_data_bidi_local() != 0) {
    tp->set(QUICTransportParameterId::INITIAL_MAX_STREAM_DATA_BIDI_LOCAL, tp_config.initial_max_stream_data_bidi_local());
  }
  if (tp_config.initial_max_stream_data_bidi_remote() != 0) {
    tp->set(QUICTransportParameterId::INITIAL_MAX_STREAM_DATA_BIDI_REMOTE, tp_config.initial_max_stream_data_bidi_remote());
  }
  if (tp_config.initial_max_stream_data_uni() != 0) {
    tp->set(QUICTransportParameterId::INITIAL_MAX_STREAM_DATA_UNI, tp_config.initial_max_stream_data_uni());
  }
  if (tp_config.disable_active_migration()) {
    tp->set(QUICTransportParameterId::DISABLE_ACTIVE_MIGRATION, nullptr, 0);
  }
  if (pref_addr != nullptr) {
    uint8_t pref_addr_buf[QUICPreferredAddress::MAX_LEN];
    uint16_t len;
    pref_addr->store(pref_addr_buf, len);
    tp->set(QUICTransportParameterId::PREFERRED_ADDRESS, pref_addr_buf, len);
  }
  if (tp_config.active_cid_limit() != 0) {
    tp->set(QUICTransportParameterId::ACTIVE_CONNECTION_ID_LIMIT, tp_config.active_cid_limit());
  }

  // MAYs (server)
  tp->set(QUICTransportParameterId::STATELESS_RESET_TOKEN, this->_reset_token.buf(), QUICStatelessResetToken::LEN);
  tp->set(QUICTransportParameterId::ACK_DELAY_EXPONENT, tp_config.ack_delay_exponent());

  tp->add_version(QUIC_SUPPORTED_VERSIONS[0]);

  // Additional parameters
  for (auto &&param : tp_config.additional_tp()) {
    tp->set(param.first, param.second.first, param.second.second);
  }

  this->_local_transport_parameters = std::shared_ptr<QUICTransportParameters>(tp);
  this->_hs_protocol->set_local_transport_parameters(this->_local_transport_parameters);
}

void
QUICHandshake::_load_local_client_transport_parameters(const QUICTPConfig &tp_config)
{
  QUICTransportParametersInClientHello *tp = new QUICTransportParametersInClientHello();

  // MUSTs
  tp->set(QUICTransportParameterId::MAX_IDLE_TIMEOUT, static_cast<uint16_t>(tp_config.no_activity_timeout()));

  // MAYs
  if (tp_config.initial_max_data() != 0) {
    tp->set(QUICTransportParameterId::INITIAL_MAX_DATA, tp_config.initial_max_data());
  }
  if (tp_config.initial_max_streams_bidi() != 0) {
    tp->set(QUICTransportParameterId::INITIAL_MAX_STREAMS_BIDI, tp_config.initial_max_streams_bidi());
  }
  if (tp_config.initial_max_streams_uni() != 0) {
    tp->set(QUICTransportParameterId::INITIAL_MAX_STREAMS_UNI, tp_config.initial_max_streams_uni());
  }
  if (tp_config.initial_max_stream_data_bidi_local() != 0) {
    tp->set(QUICTransportParameterId::INITIAL_MAX_STREAM_DATA_BIDI_LOCAL, tp_config.initial_max_stream_data_bidi_local());
  }
  if (tp_config.initial_max_stream_data_bidi_remote() != 0) {
    tp->set(QUICTransportParameterId::INITIAL_MAX_STREAM_DATA_BIDI_REMOTE, tp_config.initial_max_stream_data_bidi_remote());
  }
  if (tp_config.initial_max_stream_data_uni() != 0) {
    tp->set(QUICTransportParameterId::INITIAL_MAX_STREAM_DATA_UNI, tp_config.initial_max_stream_data_uni());
  }
  tp->set(QUICTransportParameterId::ACK_DELAY_EXPONENT, tp_config.ack_delay_exponent());
  if (tp_config.active_cid_limit() != 0) {
    tp->set(QUICTransportParameterId::ACTIVE_CONNECTION_ID_LIMIT, tp_config.active_cid_limit());
  }

  // Additional parameters
  for (auto &&param : tp_config.additional_tp()) {
    tp->set(param.first, param.second.first, param.second.second);
  }

  this->_local_transport_parameters = std::shared_ptr<QUICTransportParameters>(tp);
  this->_hs_protocol->set_local_transport_parameters(std::unique_ptr<QUICTransportParameters>(tp));
}

QUICConnectionErrorUPtr
QUICHandshake::do_handshake()
{
  QUICConnectionErrorUPtr error = nullptr;

  QUICHandshakeMsgs in;
  uint8_t in_buf[UDP_MAXIMUM_PAYLOAD_SIZE] = {0};
  in.buf                                   = in_buf;
  in.max_buf_len                           = UDP_MAXIMUM_PAYLOAD_SIZE;

  if (this->_client_initial) {
    this->_client_initial = false;
  } else {
    for (auto level : QUIC_ENCRYPTION_LEVELS) {
      int index                = static_cast<int>(level);
      QUICCryptoStream *stream = &this->_crypto_streams[index];
      int64_t bytes_avail      = stream->read_avail();
      // TODO: check size
      if (bytes_avail > 0) {
        stream->read(in.buf + in.offsets[index], bytes_avail);
      }
      in.offsets[index + 1] = in.offsets[index] + bytes_avail;
    }
  }

  QUICHandshakeMsgs *out = nullptr;
  int result             = this->_hs_protocol->handshake(&out, &in);
  if (this->_remote_transport_parameters == nullptr) {
    if (!this->check_remote_transport_parameters()) {
      result = 0;
    }
  }

  if (result == 1) {
    if (out) {
      for (auto level : QUIC_ENCRYPTION_LEVELS) {
        int index                = static_cast<int>(level);
        QUICCryptoStream *stream = &this->_crypto_streams[index];
        size_t len               = out->offsets[index + 1] - out->offsets[index];
        // TODO: check size
        if (len > 0) {
          stream->write(out->buf + out->offsets[index], len);
        }
      }
    }
  } else {
    this->_hs_protocol->abort_handshake();
    if (this->_hs_protocol->has_crypto_error()) {
      error = std::make_unique<QUICConnectionError>(QUICErrorClass::TRANSPORT, this->_hs_protocol->crypto_error());
    } else {
      error = std::make_unique<QUICConnectionError>(QUICErrorClass::TRANSPORT,
                                                    static_cast<uint16_t>(QUICTransErrorCode::PROTOCOL_VIOLATION));
    }
  }

  return error;
}

void
QUICHandshake::_abort_handshake(QUICTransErrorCode code)
{
  QUICHSDebug("Abort Handshake");

  this->_hs_protocol->abort_handshake();

  this->_qc->close_quic_connection(QUICConnectionErrorUPtr(new QUICConnectionError(code)));
}

/*
   No limit of encryption level.
   ```
   std::array<QUICEncryptionLevel, 4> _encryption_level_filter = {
     QUICEncryptionLevel::INITIAL,
     QUICEncryptionLevel::ZERO_RTT,
     QUICEncryptionLevel::HANDSHAKE,
     QUICEncryptionLevel::ONE_RTT,
   };
   ```
*/
bool
QUICHandshake::_is_level_matched(QUICEncryptionLevel level)
{
  return true;
}

void
QUICHandshake::_on_frame_lost(QUICFrameInformationUPtr &info)
{
  ink_assert(info->type == QUICFrameType::HANDSHAKE_DONE);
  this->_is_handshake_done_sent = false;
}
