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

#include <cstdint>
#include <stdexcept>

#include <ace/Guard_T.h>

namespace apache {
namespace geode {
namespace client {

ACE_Recursive_Thread_Mutex SSLImpl::s_mutex;
volatile bool SSLImpl::s_initialized = false;

void *gf_create_SslImpl(ACE_HANDLE sock, const char *pubkeyfile,
                        const char *privkeyfile, const char *pemPassword) {
  return reinterpret_cast<void *>(
      new SSLImpl(sock, pubkeyfile, privkeyfile, pemPassword));
}

void gf_destroy_SslImpl(void *impl) {
  SSLImpl *theLib = reinterpret_cast<SSLImpl *>(impl);
  delete theLib;
}

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

SSLImpl::SSLImpl(ACE_HANDLE sock, const char *pubkeyfile,
                 const char *privkeyfile, const char *password) {
  ACE_Guard<ACE_Recursive_Thread_Mutex> guard(SSLImpl::s_mutex);

  if (SSLImpl::s_initialized == false) {
    ACE_SSL_Context *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(pubkeyfile) != 0) {
      throw std::invalid_argument("Failed to read SSL trust store.");
    }

    if (strlen(password) > 0) {
      SSL_CTX_set_default_passwd_cb(sslContext->context(), pem_passwd_cb);
      SSL_CTX_set_default_passwd_cb_userdata(sslContext->context(),
                                             const_cast<char *>(password));
    }

    if (privkeyfile && *privkeyfile) {
      if (sslContext->certificate(privkeyfile) != 0) {
        throw std::invalid_argument("Failed to read SSL certificate.");
      }
      if (sslContext->private_key(privkeyfile) != 0) {
        throw std::invalid_argument("Invalid SSL keystore password.");
      }
      if (::SSL_CTX_use_certificate_chain_file(sslContext->context(),
                                               privkeyfile) <= 0) {
        throw std::invalid_argument("Failed to read SSL certificate chain.");
      }
    }
    SSLImpl::s_initialized = true;
  }
  m_io = new ACE_SSL_SOCK_Stream();
  m_io->set_handle(sock);
}

SSLImpl::~SSLImpl() {
  ACE_Guard<ACE_Recursive_Thread_Mutex> guard(SSLImpl::s_mutex);

  if (m_io) {
    delete m_io;
  }
}

void SSLImpl::close() {
  ACE_Guard<ACE_Recursive_Thread_Mutex> guard(SSLImpl::s_mutex);

  if (m_io) {
    m_io->close();
  }
}

int SSLImpl::setOption(int level, int option, void *optval, int optlen) {
  return m_io->set_option(level, option, optval, optlen);
}

int SSLImpl::listen(ACE_INET_Addr addr, std::chrono::microseconds waitSeconds) {
  ACE_SSL_SOCK_Acceptor listener(addr, 1);
  if (waitSeconds > std::chrono::microseconds::zero()) {
    ACE_Time_Value wtime(waitSeconds);
    return listener.accept(*m_io, nullptr, &wtime);
  } else {
    return listener.accept(*m_io, nullptr);
  }
}

int SSLImpl::connect(ACE_INET_Addr ipaddr,
                     std::chrono::microseconds waitSeconds) {
  ACE_SSL_SOCK_Connector conn;
  if (waitSeconds > std::chrono::microseconds::zero()) {
    ACE_Time_Value wtime(waitSeconds);
    return conn.connect(*m_io, ipaddr, &wtime);
  } else {
    return conn.connect(*m_io, ipaddr);
  }
}

ssize_t SSLImpl::recv(void *buf, size_t len, const ACE_Time_Value *timeout,
                      size_t *bytes_transferred) {
  return m_io->recv_n(buf, len, 0, timeout, bytes_transferred);
}

ssize_t SSLImpl::send(const void *buf, size_t len,
                      const ACE_Time_Value *timeout,
                      size_t *bytes_transferred) {
  return m_io->send_n(buf, len, 0, timeout, bytes_transferred);
}

int SSLImpl::getLocalAddr(ACE_Addr &addr) { return m_io->get_local_addr(addr); }

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