#ifndef SSLUTIL_HPP
#define SSLUTIL_HPP

#include <openssl/ssl.h>
#include <openssl/rsa.h>
#include <openssl/x509.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include <openssl/bio.h>
#include <openssl/pem.h>
#include <openssl/conf.h>

#include <memory>

namespace sslutil {

struct SSL_Deleter {
    void operator()(SSL *ssl) { SSL_free(ssl); }
};

struct CTX_Deleter {
    void operator()(SSL_CTX *ctx) { SSL_CTX_free(ctx); }
};

struct BIO_Deleter {
    void operator()(BIO *bio) { BIO_free(bio); }
};

struct X509_Deleter {
    void operator()(X509 *x) { X509_free(x); }
};

struct PKEY_Deleter {
    void operator()(EVP_PKEY *p) { EVP_PKEY_free(p); }
};

using UniqueSSL = std::unique_ptr<SSL, SSL_Deleter>;
using UniqueCTX = std::unique_ptr<SSL_CTX, CTX_Deleter>;
using UniqueBIO = std::unique_ptr<BIO, BIO_Deleter>;
using UniqueX509 = std::unique_ptr<X509, X509_Deleter>;
using UniquePKEY = std::unique_ptr<EVP_PKEY, PKEY_Deleter>;

struct ErrClearErrorOnExit {
    ~ErrClearErrorOnExit() {
        ERR_clear_error();
    }
};

// Return the OpenSSL error as a string.
std::string error_string();
void clear_all_errors();
SSL_CTX *new_context(int verify);
void ctx_load_dummy_cert(SSL_CTX *ctx);
void ctx_load_cert_from_directory(SSL_CTX *ctx, const std::string &dir);

} // namespace sslutil

#endif // SSLUTIL_HPP

