//
//
// Copyright 2018 gRPC authors.
//
// Licensed 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.
//
//

// Generated by tools/codegen/core/gen_grpc_tls_credentials_options.py

#ifndef GRPC_SRC_CORE_CREDENTIALS_TRANSPORT_TLS_GRPC_TLS_CREDENTIALS_OPTIONS_H
#define GRPC_SRC_CORE_CREDENTIALS_TRANSPORT_TLS_GRPC_TLS_CREDENTIALS_OPTIONS_H

#include <grpc/support/port_platform.h>

#include <vector>

#include "absl/container/inlined_vector.h"

#include <grpc/credentials.h>
#include <grpc/grpc_security.h>

#include "src/core/util/ref_counted.h"
#include "src/core/credentials/transport/tls/grpc_tls_certificate_distributor.h"
#include "src/core/credentials/transport/tls/grpc_tls_certificate_provider.h"
#include "src/core/credentials/transport/tls/grpc_tls_certificate_verifier.h"
#include "src/core/credentials/transport/tls/ssl_utils.h"

// Contains configurable options specified by callers to configure their certain
// security features supported in TLS.
// TODO(ZhenLian): consider making this not ref-counted.
struct grpc_tls_credentials_options
    : public grpc_core::RefCounted<grpc_tls_credentials_options> {
 public:
  grpc_tls_credentials_options() = default;
  ~grpc_tls_credentials_options() override = default;

  // Getters for member fields.
  grpc_ssl_client_certificate_request_type cert_request_type() const { return cert_request_type_; }
  bool verify_server_cert() const { return verify_server_cert_; }
  grpc_tls_version min_tls_version() const { return min_tls_version_; }
  grpc_tls_version max_tls_version() const { return max_tls_version_; }
  grpc_tls_certificate_verifier* certificate_verifier() {
    return certificate_verifier_.get();
  }
  bool check_call_host() const { return check_call_host_; }
  const std::string& root_cert_name() const { return root_cert_name_; }
  const std::string& identity_cert_name() const { return identity_cert_name_; }
  const std::string& tls_session_key_log_file_path() const { return tls_session_key_log_file_path_; }
  const std::string& crl_directory() const { return crl_directory_; }
  // Returns the CRL Provider
  std::shared_ptr<grpc_core::experimental::CrlProvider> crl_provider() const { return crl_provider_; }
  bool send_client_ca_list() const { return send_client_ca_list_; }
  // Returns the distributor from identity_certificate_provider_ if it is set, nullptr otherwise.
  grpc_tls_certificate_distributor* identity_certificate_distributor() {
    if (identity_certificate_provider_ != nullptr) { return identity_certificate_provider_->distributor().get(); }
    return nullptr;
  }
  // Returns the distributor from root_certificate_provider_ if it is set, nullptr otherwise.
  grpc_tls_certificate_distributor* root_certificate_distributor() {
    if (root_certificate_provider_ != nullptr) { return root_certificate_provider_->distributor().get(); }
    return nullptr;
  }
  const std::optional<std::string>& sni_override() const { return sni_override_; }
  std::vector<grpc_tls_key_exchange_group> key_exchange_groups() const { return key_exchange_groups_; }

  // Setters for member fields.
  void set_cert_request_type(grpc_ssl_client_certificate_request_type cert_request_type) { cert_request_type_ = cert_request_type; }
  void set_verify_server_cert(bool verify_server_cert) { verify_server_cert_ = verify_server_cert; }
  void set_min_tls_version(grpc_tls_version min_tls_version) { min_tls_version_ = min_tls_version; }
  void set_max_tls_version(grpc_tls_version max_tls_version) { max_tls_version_ = max_tls_version; }
  void set_certificate_verifier(grpc_core::RefCountedPtr<grpc_tls_certificate_verifier> certificate_verifier) { certificate_verifier_ = std::move(certificate_verifier); }
  void set_check_call_host(bool check_call_host) { check_call_host_ = check_call_host; }
  // Sets the name of root certificates being watched, if |set_watch_root_cert| is called. If not set, an empty string will be used as the name.
  void set_root_cert_name(std::string root_cert_name) { root_cert_name_ = std::move(root_cert_name); }
  // Sets the name of identity key-cert pairs being watched, if |set_watch_identity_pair| is called. If not set, an empty string will be used as the name.
  void set_identity_cert_name(std::string identity_cert_name) { identity_cert_name_ = std::move(identity_cert_name); }
  void set_tls_session_key_log_file_path(std::string tls_session_key_log_file_path) { tls_session_key_log_file_path_ = std::move(tls_session_key_log_file_path); }
  //  gRPC will enforce CRLs on all handshakes from all hashed CRL files inside of the crl_directory. If not set, an empty string will be used, which will not enable CRL checking. Only supported for OpenSSL version > 1.1.
  void set_crl_directory(std::string crl_directory) { crl_directory_ = std::move(crl_directory); }
  void set_crl_provider(std::shared_ptr<grpc_core::experimental::CrlProvider> crl_provider) { crl_provider_ = std::move(crl_provider); }
  void set_send_client_ca_list(bool send_client_ca_list) { send_client_ca_list_ = send_client_ca_list; }
  void set_identity_certificate_provider(grpc_core::RefCountedPtr<grpc_tls_certificate_provider> identity_certificate_provider) { identity_certificate_provider_ = std::move(identity_certificate_provider); }
  void set_root_certificate_provider(grpc_core::RefCountedPtr<grpc_tls_certificate_provider> root_certificate_provider) { root_certificate_provider_ = std::move(root_certificate_provider); }
  // If set to nullopt, do not override. If set to empty string, disable sending SNI. Otherwise, override SNI
  void set_sni_override(std::optional<std::string> sni_override) { sni_override_ = std::move(sni_override); }
  void set_key_exchange_groups(std::vector<grpc_tls_key_exchange_group> key_exchange_groups) { key_exchange_groups_ = std::move(key_exchange_groups); }

  bool operator==(const grpc_tls_credentials_options& other) const {
    return cert_request_type_ == other.cert_request_type_ &&
      verify_server_cert_ == other.verify_server_cert_ &&
      min_tls_version_ == other.min_tls_version_ &&
      max_tls_version_ == other.max_tls_version_ &&
      (certificate_verifier_ == other.certificate_verifier_ || (certificate_verifier_ != nullptr && other.certificate_verifier_ != nullptr && certificate_verifier_->Compare(other.certificate_verifier_.get()) == 0)) &&
      check_call_host_ == other.check_call_host_ &&
      root_cert_name_ == other.root_cert_name_ &&
      identity_cert_name_ == other.identity_cert_name_ &&
      tls_session_key_log_file_path_ == other.tls_session_key_log_file_path_ &&
      crl_directory_ == other.crl_directory_ &&
      (crl_provider_ == other.crl_provider_) &&
      send_client_ca_list_ == other.send_client_ca_list_ &&
      (identity_certificate_provider_ == other.identity_certificate_provider_ || (identity_certificate_provider_ != nullptr && other.identity_certificate_provider_ != nullptr && identity_certificate_provider_->Compare(other.identity_certificate_provider_.get()) == 0)) &&
      (root_certificate_provider_ == other.root_certificate_provider_ || (root_certificate_provider_ != nullptr && other.root_certificate_provider_ != nullptr && root_certificate_provider_->Compare(other.root_certificate_provider_.get()) == 0)) &&
      sni_override_ == other.sni_override_ &&
      key_exchange_groups_ == other.key_exchange_groups_;
  }

  grpc_tls_credentials_options(grpc_tls_credentials_options& other) :
      cert_request_type_(other.cert_request_type_),
      verify_server_cert_(other.verify_server_cert_),
      min_tls_version_(other.min_tls_version_),
      max_tls_version_(other.max_tls_version_),
      certificate_verifier_(other.certificate_verifier_),
      check_call_host_(other.check_call_host_),
      root_cert_name_(other.root_cert_name_),
      identity_cert_name_(other.identity_cert_name_),
      tls_session_key_log_file_path_(other.tls_session_key_log_file_path_),
      crl_directory_(other.crl_directory_),
      crl_provider_(other.crl_provider_),
      send_client_ca_list_(other.send_client_ca_list_),
      identity_certificate_provider_(other.identity_certificate_provider_),
      root_certificate_provider_(other.root_certificate_provider_),
      sni_override_(other.sni_override_),
      key_exchange_groups_(other.key_exchange_groups_)  {}

 private:
  grpc_ssl_client_certificate_request_type cert_request_type_ = GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE;
  bool verify_server_cert_ = true;
  grpc_tls_version min_tls_version_ = grpc_tls_version::TLS1_2;
  grpc_tls_version max_tls_version_ = grpc_tls_version::TLS1_3;
  grpc_core::RefCountedPtr<grpc_tls_certificate_verifier> certificate_verifier_;
  bool check_call_host_ = true;
  std::string root_cert_name_;
  std::string identity_cert_name_;
  std::string tls_session_key_log_file_path_;
  std::string crl_directory_;
  std::shared_ptr<grpc_core::experimental::CrlProvider> crl_provider_;
  bool send_client_ca_list_ = false;
  grpc_core::RefCountedPtr<grpc_tls_certificate_provider> identity_certificate_provider_;
  grpc_core::RefCountedPtr<grpc_tls_certificate_provider> root_certificate_provider_;
  std::optional<std::string> sni_override_;
  std::vector<grpc_tls_key_exchange_group> key_exchange_groups_;
};

#endif  // GRPC_SRC_CORE_CREDENTIALS_TRANSPORT_TLS_GRPC_TLS_CREDENTIALS_OPTIONS_H
