=pod

=head1 NAME

ossl_lib_ctx_get_data, ossl_lib_ctx_run_once, ossl_lib_ctx_onfree,
ossl_lib_ctx_is_child
- internal OSSL_LIB_CTX routines

=head1 SYNOPSIS

 #include <openssl/types.h>
 #include "internal/cryptlib.h"

 typedef struct ossl_lib_ctx_method {
     int priority;
     void *(*new_func)(OSSL_LIB_CTX *ctx);
     void (*free_func)(void *);
 } OSSL_LIB_CTX_METHOD;

 void *ossl_lib_ctx_get_data(OSSL_LIB_CTX *ctx, int index,
                             const OSSL_LIB_CTX_METHOD *meth);

 int ossl_lib_ctx_run_once(OSSL_LIB_CTX *ctx, unsigned int idx,
                           ossl_lib_ctx_run_once_fn run_once_fn);
 int ossl_lib_ctx_onfree(OSSL_LIB_CTX *ctx, ossl_lib_ctx_onfree_fn onfreefn);

 int ossl_lib_ctx_is_child(OSSL_LIB_CTX *ctx);

=head1 DESCRIPTION

Internally, the OpenSSL library context B<OSSL_LIB_CTX> is implemented
as a B<CRYPTO_EX_DATA>, which allows data from diverse parts of the
library to be added and removed dynamically.
Each such data item must have a corresponding CRYPTO_EX_DATA index
associated with it. Unlike normal CRYPTO_EX_DATA objects we use static indexes
to identify data items. These are mapped transparently to CRYPTO_EX_DATA dynamic
indexes internally to the implementation.
See the example further down to see how that's done.

ossl_lib_ctx_get_data() is used to retrieve a pointer to the data in
the library context I<ctx> associated with the given I<index>. An
OSSL_LIB_CTX_METHOD must be defined and given in the I<meth> parameter. The index
for it should be defined in cryptlib.h. The functions through the method are
used to create or free items that are stored at that index whenever a library
context is created or freed, meaning that the code that use a data item of that
index doesn't have to worry about that, just use the data available.

Deallocation of an index happens automatically when the library
context is freed.

ossl_lib_ctx_run_once is used to run some initialisation routine I<run_once_fn>
exactly once per library context I<ctx> object. Each initialisation routine
should be allocate a unique run once index in cryptlib.h.

Any resources allocated via a run once initialisation routine can be cleaned up
using ossl_lib_ctx_onfree. This associates an "on free" routine I<onfreefn> with
the library context I<ctx>. When I<ctx> is freed all associated "on free"
routines are called.

ossl_lib_ctx_is_child() returns 1 if this library context is a child and 0
otherwise.

=head1 RETURN VALUES

ossl_lib_ctx_get_data() returns a pointer on success, or NULL on
failure.

=head1 EXAMPLES

=head2 Initialization

For a type C<FOO> that should end up in the OpenSSL library context, a
small bit of initialization is needed, i.e. to associate a constructor
and a destructor to an index.

 typedef struct foo_st {
     int i;
     void *data;
 } FOO;

 static void *foo_new(OSSL_LIB_CTX *ctx)
 {
     FOO *ptr = OPENSSL_zalloc(sizeof(*foo));
     if (ptr != NULL)
         ptr->i = 42;
     return ptr;
 }
 static void foo_free(void *ptr)
 {
     OPENSSL_free(ptr);
 }

 /*
  * Include a reference to this in the methods table in context.c
  * OSSL_LIB_CTX_FOO_INDEX should be added to internal/cryptlib.h
  * Priorities can be OSSL_LIB_CTX_METHOD_DEFAULT_PRIORITY,
  * OSSL_LIB_CTX_METHOD_PRIORITY_1, OSSL_LIB_CTX_METHOD_PRIORITY_2, etc.
  * Default priority is low (0). The higher the priority the earlier the
  * method's destructor will be called when the library context is cleaned up.
  */
 const OSSL_LIB_CTX_METHOD foo_method = {
     OSSL_LIB_CTX_METHOD_DEFAULT_PRIORITY,
     foo_new,
     foo_free
 };

=head2 Usage

To get and use the data stored in the library context, simply do this:

 /*
  * ctx is received from a caller,
  */
 FOO *data = ossl_lib_ctx_get_data(ctx, OSSL_LIB_CTX_FOO_INDEX, &foo_method);

=head2 Run Once

 void foo_cleanup(OSSL_LIB_CTX *ctx)
 {
     /* Free foo resources associated with ctx */
 }

 static ossl_lib_ctx_run_once_fn do_foo_init;
 static int do_foo_init(OSSL_LIB_CTX *ctx)
 {
     /* Allocate and initialise some foo resources and associated with ctx */
     return ossl_lib_ctx_onfree(ctx, &foo_cleanup)
 }

 int foo_some_function(OSSL_LIB_CTX *ctx)
 {
    if (!ossl_lib_ctx_run_once(ctx,
                               OSSL_LIB_CTX_FOO_RUN_ONCE_INDEX,
                               do_foo_init))
        return 0;

    /* Do some work using foo resources in ctx */
 }


=head1 SEE ALSO

L<OSSL_LIB_CTX(3)>

=head1 COPYRIGHT

Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.

Licensed under the Apache License 2.0 (the "License").  You may not use
this file except in compliance with the License.  You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.

=cut
