/*
 * 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 "TcpSslConn.hpp"

#include <memory>

#include <ace/SSL/SSL_SOCK_Connector.h>

#include <geode/ExceptionTypes.hpp>
#include <geode/SystemProperties.hpp>

#include "util/Log.hpp"

namespace apache {
namespace geode {
namespace client {
std::atomic_flag TcpSslConn::initialized_ = ATOMIC_FLAG_INIT;

void TcpSslConn::createSocket(ACE_HANDLE sock) {
  LOGDEBUG("Creating SSL socket stream");
  stream_ = std::unique_ptr<ACE_SSL_SOCK_Stream>(new ACE_SSL_SOCK_Stream());
  stream_->set_handle(sock);
}

void TcpSslConn::connect() {
  using apache::geode::internal::chrono::duration::to_string;

  ACE_OS::signal(SIGPIPE, SIG_IGN);  // Ignore broken pipe

  LOGFINER(std::string("Connecting SSL socket stream to ") +
           inetAddress_.get_host_name() + ":" +
           std::to_string(inetAddress_.get_port_number()) + " waiting " +
           to_string(timeout_));

  if (!sniHostname_.empty()) {
    SSL_set_tlsext_host_name(stream_->ssl(), sniHostname_.c_str());
  }

  ACE_SSL_SOCK_Connector conn;
  ACE_Time_Value actTimeout(timeout_);
  if (conn.connect(*stream_, inetAddress_,
                   timeout_ > std::chrono::microseconds::zero()
                       ? &actTimeout
                       : nullptr) == -1) {
    const auto lastError = ACE_OS::last_error();
    if (lastError == ETIME || lastError == ETIMEDOUT) {
      throw TimeoutException(
          "TcpSslConn::connect Attempt to connect timed out after " +
          to_string(timeout_) + ".");
    }
    close();
    throw GeodeIOException("TcpSslConn::connect failed with errno: " +
                           ACE_errno_to_string(lastError));
  }
}

void TcpSslConn::close() {
  if (stream_) {
    stream_->close();
    stream_ = nullptr;
  }
}

uint16_t TcpSslConn::getPort() {
  ACE_INET_Addr localAddr;
  stream_->get_local_addr(localAddr);
  return localAddr.get_port_number();
}

static int pem_passwd_cb(char* buf, int size, int /*rwflag*/, void* passwd) {
  strncpy(buf, reinterpret_cast<char*>(passwd), size);
  buf[size - 1] = '\0';
  return static_cast<int>(strlen(buf));
}

void TcpSslConn::initSsl() {
  if (!TcpSslConn::initialized_.test_and_set()) {
    auto sslContext = ACE_SSL_Context::instance();

    SSL_CTX_set_cipher_list(sslContext->context(), "DEFAULT");
    sslContext->set_mode(ACE_SSL_Context::SSLv23_client);
    sslContext->set_verify_peer();
    if (sslContext->load_trusted_ca(trustStoreFile_.c_str()) != 0) {
      throw SslException("Failed to read SSL trust store.");
    }

    if (!password_.empty()) {
      SSL_CTX_set_default_passwd_cb(sslContext->context(), pem_passwd_cb);
      SSL_CTX_set_default_passwd_cb_userdata(
          sslContext->context(), const_cast<char*>(password_.c_str()));
    }

    if (!privateKeyFile_.empty()) {
      if (sslContext->certificate(privateKeyFile_.c_str()) != 0) {
        throw SslException("Failed to read SSL certificate.");
      }
      if (sslContext->private_key(privateKeyFile_.c_str()) != 0) {
        throw SslException("Invalid SSL keystore password.");
      }
      if (SSL_CTX_use_certificate_chain_file(sslContext->context(),
                                             privateKeyFile_.c_str()) <= 0) {
        throw SslException("Failed to read SSL certificate chain.");
      }
    }
  }
}

ssize_t TcpSslConn::doOperation(const TcpConn::SockOp& op, void* buff,
                                size_t sendlen, ACE_Time_Value& waitTime,
                                size_t& readLen) const {
  if (op == SOCK_READ) {
    return stream_->recv_n(buff, sendlen, &waitTime, &readLen);
  } else {
    return stream_->send_n(buff, sendlen, &waitTime, &readLen);
  }
}

}  // namespace client
}  // namespace geode
}  // namespace apache
