#pragma once
#include "common.hpp"
#include "config.hpp"
#include "chain.hpp"
#include "hooks.hpp"
#include <openssl/ssl.h>
#include <openssl/err.h>
#ifndef OPENSSL_NO_ENGINE
#include <openssl/engine.h>
#endif


typedef SSL_CTX ssl_ctx_t; // TODO: https://blog.fefe.de/?ts=a900fc5d
typedef struct {
    SSL* ssl;
    int fd;
    tristate_t init_finished; ///< TRI_NONE: handshake not yet started, TRI_FALSE: in progress, TRI_TRUE: as soon as SSL_is_init_finished() has been encountered, @see ssl_finish_handshake()
    buf_t* rbuf; ///< pre-read client helo data by sni peek
} ssl_t;

DH* ssl_dh_callback(SSL*, int, int);
RSA* ssl_rsa_callback(SSL*, int, int);

#define ssl_clear_err() ERR_clear_error()
#define ssl_log_err(lvl) _ssl_log_err(loglevels.lvl, src_basename(__FILE__), __LINE__)
#define ssl_log_err_code(lvl, e) _ssl_log_err(loglevels.lvl, e, src_basename(__FILE__), __LINE__)
void _ssl_log_err(loglevel_t, const char*, int);
void _ssl_log_err(loglevel_t, unsigned long, const char*, int);

bool validate_host(const char*, size_t); ///< validates given hostname/SNI/CN