Asterisk - The Open Source Telephony Project  21.4.1
Data Structures | Macros | Functions | Variables
optional_api.c File Reference
#include "asterisk.h"
#include "asterisk/optional_api.h"
#include "asterisk/utils.h"
#include "asterisk/vector.h"

Go to the source code of this file.

Data Structures

struct  optional_api
 An optional API. More...
 
struct  optional_api_user
 A user of an optional API. More...
 

Macros

#define OPTIONAL_API_SYMNAME_CMP(ele, value)   (!strcmp(ele->symname, value))
 
#define USER_OPTIONAL_REF_CMP(ele, value)   (ele->optional_ref == value)
 

Functions

void ast_optional_api_provide (const char *symname, ast_optional_fn impl)
 
void ast_optional_api_unprovide (const char *symname, ast_optional_fn impl)
 
void ast_optional_api_unuse (const char *symname, ast_optional_fn *optional_ref, const char *module)
 
void ast_optional_api_use (const char *symname, ast_optional_fn *optional_ref, ast_optional_fn stub, const char *module)
 
static struct optional_apiget_api (const char *symname)
 Gets (or creates) the optional_api for the given function. More...
 
static struct optional_apioptional_api_create (const char *symname)
 Create and link an optional_api. More...
 
static void optional_api_destroy (struct optional_api *api)
 Free an optional_api. More...
 
static void optional_api_set_impl (struct optional_api *api, ast_optional_fn impl)
 Sets the implementation function pointer for an api. More...
 
static struct optional_api_useroptional_api_user_create (ast_optional_fn *optional_ref, ast_optional_fn stub, const char *module)
 Create an optional_api_user. More...
 
static void optional_api_user_destroy (struct optional_api_user *user)
 Free an optional_api_user. More...
 
static void optional_api_user_relink (struct optional_api_user *user, struct optional_api *api)
 Re-links a given user against its associated api. More...
 

Variables

struct {
   size_t   current
 
   struct optional_api **   elems
 
   size_t   max
 
apis
 

Detailed Description

The calls to ast_optional_api_*() happen implicitly from constructor calls which are defined in header files. This means that some number of them happen before main() is called. This makes calling most Asterisk APIs dangerous, since we could be called before they are initialized. This includes things like AO2, malloc debug, and static mutexes.

Another limitation is that most functions are called from the midst of dlopen() or dlclose(), and there is no opportunity to return a failure code. The best we can do is log an error, and call ast_do_crash().

Fortunately, there are some constraints that help us out. The ast_optional_api_*() are called during module loads, which happens either before main(), or during dlopen() calls. These are already serialized, so we don't have to lock ourselves.

Definition in file optional_api.c.

Function Documentation

static struct optional_api* get_api ( const char *  symname)
static

Gets (or creates) the optional_api for the given function.

Parameters
symnameName of the function to look up.
Returns
Corresponding optional_api.
Return values
NULLon error.

Definition at line 158 of file optional_api.c.

References AST_VECTOR_GET_CMP, and optional_api_create().

159 {
160  struct optional_api **api;
161 
162  /* Find one, if we already have it */
163  api = AST_VECTOR_GET_CMP(&apis, symname, OPTIONAL_API_SYMNAME_CMP);
164  if (api) {
165  return *api;
166  }
167 
168  /* API not found. Build one */
170 }
char symname[]
Definition: optional_api.c:63
An optional API.
Definition: optional_api.c:57
static struct optional_api * optional_api_create(const char *symname)
Create and link an optional_api.
Definition: optional_api.c:134
struct @379 apis
#define AST_VECTOR_GET_CMP(vec, value, cmp)
Get an element from a vector that matches the given comparison.
Definition: vector.h:731
static struct optional_api* optional_api_create ( const char *  symname)
static

Create and link an optional_api.

Parameters
symnameName of the optional function.
Returns
New optional_api.
Return values
NULLon error.

Definition at line 134 of file optional_api.c.

References ast_calloc, ast_do_crash(), AST_VECTOR_APPEND, and optional_api::symname.

Referenced by get_api().

135 {
136  struct optional_api *api;
137 
138  api = ast_calloc(1, sizeof(*api) + strlen(symname) + 1);
139  if (!api || AST_VECTOR_APPEND(&apis, api)) {
140  ast_free(api);
141  ast_do_crash();
142 
143  return NULL;
144  }
145 
146  strcpy(api->symname, symname); /* SAFE */
147 
148  return api;
149 }
char symname[]
Definition: optional_api.c:63
An optional API.
Definition: optional_api.c:57
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition: vector.h:256
struct @379 apis
void DO_CRASH_NORETURN ast_do_crash(void)
Force a crash if DO_CRASH is defined.
Definition: utils.c:2804
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
static void optional_api_destroy ( struct optional_api api)
static

Free an optional_api.

Parameters
apiAPI struct to free.

Definition at line 118 of file optional_api.c.

References AST_VECTOR_CALLBACK_VOID, AST_VECTOR_ELEM_CLEANUP_NOOP, AST_VECTOR_ELEM_DEFAULT_CMP, AST_VECTOR_FREE, AST_VECTOR_REMOVE_CMP_UNORDERED, optional_api_user_destroy(), and optional_api::users.

Referenced by optional_api_set_impl().

119 {
123  AST_VECTOR_FREE(&api->users);
124  ast_free(api);
125 }
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
Definition: vector.h:174
#define AST_VECTOR_REMOVE_CMP_UNORDERED(vec, value, cmp, cleanup)
Remove an element from a vector that matches the given comparison.
Definition: vector.h:488
#define AST_VECTOR_ELEM_DEFAULT_CMP(elem, value)
Default comparator for AST_VECTOR_REMOVE_ELEM_UNORDERED()
Definition: vector.h:564
struct @379 apis
#define AST_VECTOR_ELEM_CLEANUP_NOOP(elem)
Vector element cleanup that does nothing.
Definition: vector.h:571
static void optional_api_user_destroy(struct optional_api_user *user)
Free an optional_api_user.
Definition: optional_api.c:77
struct optional_api::@380 users
#define AST_VECTOR_CALLBACK_VOID(vec, callback,...)
Execute a callback on every element in a vector disregarding callback return.
Definition: vector.h:862
static void optional_api_set_impl ( struct optional_api api,
ast_optional_fn  impl 
)
static

Sets the implementation function pointer for an api.

Parameters
apiAPI to implement/stub out.
implPointer to implementation function. Can be 0 to remove implementation.

Definition at line 198 of file optional_api.c.

References AST_VECTOR_CALLBACK_VOID, AST_VECTOR_SIZE, optional_api::impl, optional_api_destroy(), optional_api_user_relink(), and optional_api::users.

200 {
201  api->impl = impl;
202 
203  /* re-link all users */
204  if (AST_VECTOR_SIZE(&api->users)) {
206  } else if (!impl) {
207  /* No users or impl means we should delete this api. */
209  }
210 }
static void optional_api_destroy(struct optional_api *api)
Free an optional_api.
Definition: optional_api.c:118
ast_optional_fn impl
Definition: optional_api.c:59
struct optional_api::@380 users
static void optional_api_user_relink(struct optional_api_user *user, struct optional_api *api)
Re-links a given user against its associated api.
Definition: optional_api.c:181
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:609
#define AST_VECTOR_CALLBACK_VOID(vec, callback,...)
Execute a callback on every element in a vector disregarding callback return.
Definition: vector.h:862
static struct optional_api_user* optional_api_user_create ( ast_optional_fn *  optional_ref,
ast_optional_fn  stub,
const char *  module 
)
static

Create an optional_api_user.

Parameters
optional_refPointer-to-function-pointer to link to impl/stub.
stubStub function to link to when impl is not available.
moduleName of the module requesting the API.
Returns
New optional_api_user.
Return values
NULLon error.

Definition at line 93 of file optional_api.c.

References ast_calloc, ast_do_crash(), optional_api_user::module, optional_api_user::optional_ref, and optional_api_user::stub.

95 {
96  struct optional_api_user *user;
97  size_t size = sizeof(*user) + strlen(module) + 1;
98 
99  user = ast_calloc(1, size);
100  if (!user) {
101  ast_do_crash();
102 
103  return NULL;
104  }
105 
106  user->optional_ref = optional_ref;
107  user->stub = stub;
108  strcpy(user->module, module); /* SAFE */
109 
110  return user;
111 }
A user of an optional API.
Definition: optional_api.c:47
void DO_CRASH_NORETURN ast_do_crash(void)
Force a crash if DO_CRASH is defined.
Definition: utils.c:2804
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
structure to hold users read from users.conf
ast_optional_fn * optional_ref
Definition: optional_api.c:49
ast_optional_fn stub
Definition: optional_api.c:51
static void optional_api_user_destroy ( struct optional_api_user user)
static

Free an optional_api_user.

Parameters
userUser struct to free.

Definition at line 77 of file optional_api.c.

References optional_api_user::optional_ref, and optional_api_user::stub.

Referenced by optional_api_destroy().

78 {
79  *user->optional_ref = user->stub;
80  ast_free(user);
81 }
ast_optional_fn * optional_ref
Definition: optional_api.c:49
ast_optional_fn stub
Definition: optional_api.c:51
static void optional_api_user_relink ( struct optional_api_user user,
struct optional_api api 
)
static

Re-links a given user against its associated api.

If the api has an implementation, the user is linked to that implementation. Otherwise, the user is linked to its stub.

Parameters
useroptional_api_user to link.
apioptional_api to link.

Definition at line 181 of file optional_api.c.

References optional_api::impl, optional_api_user::optional_ref, and optional_api_user::stub.

Referenced by optional_api_set_impl().

183 {
184  if (api->impl && *user->optional_ref != api->impl) {
185  *user->optional_ref = api->impl;
186  } else if (!api->impl && *user->optional_ref != user->stub) {
187  *user->optional_ref = user->stub;
188  }
189 }
ast_optional_fn impl
Definition: optional_api.c:59
ast_optional_fn * optional_ref
Definition: optional_api.c:49
ast_optional_fn stub
Definition: optional_api.c:51

Variable Documentation

struct { ... } apis

Vector of optional_api functions