#ifndef HEADER_ENGINE_INT_H
#define HEADER_ENGINE_INT_H

#include "cryptlib.h"
/* Take public definitions from engine.h */
#include "engine.h"

#ifdef __cplusplus
extern "C" {
#endif

#ifdef ENGINE_REF_COUNT_DEBUG

#define engine_ref_debug(e, isfunct, diff)                                     \
	fprintf(stderr, "engine: %08x %s from %d to %d (%s:%d)\n",             \
		(unsigned int)(e), (isfunct ? "funct" : "struct"),             \
		((isfunct) ? ((e)->funct_ref - (diff)) :                       \
			     ((e)->struct_ref - (diff))),                      \
		((isfunct) ? (e)->funct_ref : (e)->struct_ref), (__FILE__),    \
		(__LINE__));

#else

#define engine_ref_debug(e, isfunct, diff)

#endif

/* Any code that will need cleanup operations should use these functions to
 * register callbacks. ENGINE_cleanup() will call all registered callbacks in
 * order. NB: both the "add" functions assume CRYPTO_LOCK_ENGINE to already be
 * held (in "write" mode). */
typedef void(ENGINE_CLEANUP_CB)(void);
typedef struct st_engine_cleanup_item {
	ENGINE_CLEANUP_CB *cb;
} ENGINE_CLEANUP_ITEM;
DECLARE_STACK_OF(ENGINE_CLEANUP_ITEM)
void engine_cleanup_add_first(ENGINE_CLEANUP_CB *cb);
void engine_cleanup_add_last(ENGINE_CLEANUP_CB *cb);

/* We need stacks of ENGINEs for use in eng_table.c */
DECLARE_STACK_OF(ENGINE)

/* If this symbol is defined then engine_table_select(), the function that is
 * used by RSA, DSA (etc) code to select registered ENGINEs, cache defaults and
 * functional references (etc), will display debugging summaries to stderr. */
/* #define ENGINE_TABLE_DEBUG */

/* This represents an implementation table. Dependent code should instantiate it
 * as a (ENGINE_TABLE *) pointer value set initially to NULL. */
typedef struct st_engine_table ENGINE_TABLE;
int engine_table_register(ENGINE_TABLE **table, ENGINE_CLEANUP_CB *cleanup,
			  ENGINE *e, const int *nids, int num_nids,
			  int setdefault);
void engine_table_unregister(ENGINE_TABLE **table, ENGINE *e);
void engine_table_cleanup(ENGINE_TABLE **table);
#ifndef ENGINE_TABLE_DEBUG
ENGINE *engine_table_select(ENGINE_TABLE **table, int nid);
#else
ENGINE *engine_table_select_tmp(ENGINE_TABLE **table, int nid, const char *f,
				int l);
#define engine_table_select(t, n)                                              \
	engine_table_select_tmp(t, n, __FILE__, __LINE__)
#endif

/* Internal versions of API functions that have control over locking. These are
 * used between C files when functionality needs to be shared but the caller may
 * already be controlling of the CRYPTO_LOCK_ENGINE lock. */
int engine_unlocked_init(ENGINE *e);
int engine_unlocked_finish(ENGINE *e, int unlock_for_handlers);
int engine_free_util(ENGINE *e, int locked);

/* This function will reset all "set"able values in an ENGINE to NULL. This
 * won't touch reference counts or ex_data, but is equivalent to calling all the
 * ENGINE_set_***() functions with a NULL value. */
void engine_set_all_null(ENGINE *e);

/* NB: Bitwise OR-able values for the "flags" variable in ENGINE are now exposed
 * in engine.h. */

/* This is a structure for storing implementations of various crypto
 * algorithms and functions. */
struct engine_st {
	const char *id;
	const char *name;
	const RSA_METHOD *rsa_meth;
	const DSA_METHOD *dsa_meth;
	const DH_METHOD *dh_meth;
	const ECDH_METHOD *ecdh_meth;
	const ECDSA_METHOD *ecdsa_meth;
	const RAND_METHOD *rand_meth;
	const STORE_METHOD *store_meth;
	/* Cipher handling is via this callback */
	ENGINE_CIPHERS_PTR ciphers;
	/* Digest handling is via this callback */
	ENGINE_DIGESTS_PTR digests;

	ENGINE_GEN_INT_FUNC_PTR destroy;

	ENGINE_GEN_INT_FUNC_PTR init;
	ENGINE_GEN_INT_FUNC_PTR finish;
	ENGINE_CTRL_FUNC_PTR ctrl;
	ENGINE_LOAD_KEY_PTR load_privkey;
	ENGINE_LOAD_KEY_PTR load_pubkey;

	ENGINE_SSL_CLIENT_CERT_PTR load_ssl_client_cert;

	const ENGINE_CMD_DEFN *cmd_defns;
	int flags;
	/* reference count on the structure itself */
	int struct_ref;
	/* reference count on usability of the engine type. NB: This
	 * controls the loading and initialisation of any functionlity
	 * required by this engine, whereas the previous count is
	 * simply to cope with (de)allocation of this structure. Hence,
	 * running_ref <= struct_ref at all times. */
	int funct_ref;
	/* A place to store per-ENGINE data */
	CRYPTO_EX_DATA ex_data;
	/* Used to maintain the linked-list of engines. */
	struct engine_st *prev;
	struct engine_st *next;
};

#ifdef __cplusplus
}
#endif

#endif /* HEADER_ENGINE_INT_H */
