Asterisk - The Open Source Telephony Project GIT-master-70eff7f
Loading...
Searching...
No Matches
Data Structures | Macros | Functions | Variables
res_pjsip_config_wizard.c File Reference

PJSIP Configuration Wizard. More...

#include "asterisk.h"
#include <regex.h>
#include <pjsip.h>
#include "asterisk/astobj2.h"
#include "asterisk/cli.h"
#include "asterisk/res_pjsip.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/sorcery.h"
#include "asterisk/vector.h"
#include "asterisk/stasis.h"
#include "asterisk/acl.h"
#include "asterisk/security_events.h"
#include "asterisk/lock.h"
Include dependency graph for res_pjsip_config_wizard.c:

Go to the source code of this file.

Data Structures

struct  object_type_wizard
 Keeps track of the sorcery wizard and last config for each object type. More...
 
struct  string_vector
 A generic char * vector definition. More...
 

Macros

#define BASE_REGISTRAR   "res_pjsip_config_wizard"
 
#define IS_ACL_RELOAD_ACTIVE()   (ast_atomic_fetchadd_int(&named_acl_reload_count, 0) > 0)
 
#define MAX_ID_SUFFIX   20
 Defines the maximum number of characters that can be added to a wizard id.
 
#define NOT_EQUALS(a, b)   (a != b)
 
#define OTW_DELETE_CB(otw)
 
#define variable_list_append_return(existing, name, value)
 Appends a variable to the end of an existing list. On failure, cause the calling function to return -1.
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
static void acl_change_stasis_cb (void *data, struct stasis_subscription *sub, struct stasis_message *message)
 Callback for Named ACL changed.
 
static int add_extension (struct ast_context *context, const char *exten, int priority, const char *application)
 
static int add_hints (const char *context, const char *exten, const char *application, const char *id)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static AST_VECTOR_RW (object_type_wizards, struct object_type_wizard *)
 
static void * create_object (const struct ast_sorcery *sorcery, const char *id, const char *type, struct ast_variable *vars)
 Creates a sorcery object and applies a variable list.
 
static int delete_existing_cb (void *obj, void *arg, int flags)
 
static int delete_extens (const char *context, const char *exten)
 
static struct object_type_wizardfind_wizard (const char *object_type)
 Finds the otw for the object type.
 
static struct ast_variableget_object_variables (struct ast_variable *vars, char *prefix)
 We need to strip off the prefix from the name of each variable so they're suitable for objectset_apply. I.E. will transform outbound_auth/username to username.
 
static int handle_aor (const struct ast_sorcery *sorcery, struct object_type_wizard *otw, struct ast_category *wiz, struct string_vector *remote_hosts_vector)
 
static int handle_auth (const struct ast_sorcery *sorcery, struct object_type_wizard *otw, struct ast_category *wiz, char *direction)
 
static int handle_auths (const struct ast_sorcery *sorcery, struct object_type_wizard *otw, struct ast_category *wiz)
 
static int handle_endpoint (const struct ast_sorcery *sorcery, struct object_type_wizard *otw, struct ast_category *wiz)
 
static char * handle_export_primitives (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static int handle_identify (const struct ast_sorcery *sorcery, struct object_type_wizard *otw, struct ast_category *wiz, struct string_vector *remote_hosts_vector)
 
static int handle_phoneprov (const struct ast_sorcery *sorcery, struct object_type_wizard *otw, struct ast_category *wiz)
 
static int handle_registrations (const struct ast_sorcery *sorcery, struct object_type_wizard *otw, struct ast_category *wiz, struct string_vector *remote_hosts_vector)
 
static void instance_created_observer (const char *name, struct ast_sorcery *sorcery)
 When the res_pjsip instance is created, add an observer to it and initialize the wizard vector. Also, bump the module's ref count so it can't be unloaded before the sorcery instance is destroyed.
 
static void instance_destroying_observer (const char *name, struct ast_sorcery *sorcery)
 When the res_pjsip instance is destroyed, remove the observer and unref the module. This should then allow this module to unload cleanly.
 
static int is_one_of (const char *needle, const char *haystack[])
 
static int is_variable_true (struct ast_variable *vars, const char *name)
 Finds the last variable in a list and tests it.
 
static int load_module (void)
 
static void object_type_loaded_observer (const char *name, const struct ast_sorcery *sorcery, const char *object_type, int reloaded)
 Called after an object type is loaded/reloaded.
 
static void object_type_registered_observer (const char *name, struct ast_sorcery *sorcery, const char *object_type)
 When each object type is registered, map a memory wizard to it.
 
static int reload_configuration_task (void *obj)
 
static int reload_module (void)
 
static int unload_module (void)
 
static int variable_list_append (struct ast_variable **existing, const char *name, const char *value)
 Appends a variable to the end of an existing list.
 
static int wizard_apply_handler (const struct ast_sorcery *sorcery, struct object_type_wizard *otw, struct ast_category *wiz)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "PJSIP Config Wizard" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .reload = reload_module, .unload = unload_module, .load_pri = AST_MODPRI_REALTIME_DRIVER, }
 
static struct stasis_subscriptionacl_change_sub
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static struct ast_cli_entry config_wizard_cli []
 
static ast_mutex_t config_wizard_observer_lock = AST_MUTEX_INIT_VALUE
 
static const struct ast_sorcery_global_observer global_observer
 
static int named_acl_reload_count = 0
 
struct ast_sorcery_instance_observer observer
 

Detailed Description

PJSIP Configuration Wizard.

Author
George Joseph georg.nosp@m.e.jo.nosp@m.seph@.nosp@m.fair.nosp@m.view5.nosp@m..com

Definition in file res_pjsip_config_wizard.c.

Macro Definition Documentation

◆ BASE_REGISTRAR

#define BASE_REGISTRAR   "res_pjsip_config_wizard"

Definition at line 280 of file res_pjsip_config_wizard.c.

◆ IS_ACL_RELOAD_ACTIVE

#define IS_ACL_RELOAD_ACTIVE ( )    (ast_atomic_fetchadd_int(&named_acl_reload_count, 0) > 0)

Definition at line 312 of file res_pjsip_config_wizard.c.

◆ MAX_ID_SUFFIX

#define MAX_ID_SUFFIX   20

Defines the maximum number of characters that can be added to a wizard id.

Definition at line 278 of file res_pjsip_config_wizard.c.

◆ NOT_EQUALS

#define NOT_EQUALS (   a,
  b 
)    (a != b)

◆ OTW_DELETE_CB

#define OTW_DELETE_CB (   otw)
Value:
({ \
ast_config_destroy(otw->last_config); \
ast_free(otw); \
})

◆ variable_list_append_return

#define variable_list_append_return (   existing,
  name,
  value 
)

Appends a variable to the end of an existing list. On failure, cause the calling function to return -1.

Definition at line 402 of file res_pjsip_config_wizard.c.

402 { \
403 struct ast_variable *new = ast_variable_new(name, value, ""); \
404 if (!new) { \
405 ast_log(LOG_ERROR, "Unable to allocate memory for new variable '%s'.\n", name); \
406 return -1; \
407 } \
408 ast_variable_list_append(existing, new); \
409})
static const char name[]
Definition format_mp3.c:68
#define ast_variable_new(name, value, filename)
#define LOG_ERROR
Structure for variables, used for configurations and for channel variables.
int value
Definition syslog.c:37

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 1427 of file res_pjsip_config_wizard.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 1427 of file res_pjsip_config_wizard.c.

◆ acl_change_stasis_cb()

static void acl_change_stasis_cb ( void *  data,
struct stasis_subscription sub,
struct stasis_message message 
)
static

Callback for Named ACL changed.

Definition at line 317 of file res_pjsip_config_wizard.c.

318{
320 return;
321 }
322
323 ast_debug(3, "PJSIP Wizard: Named ACL change detected via Stasis. Triggering reload.\n");
327}
struct stasis_message_type * ast_named_acl_change_type(void)
a stasis_message_type for changes against a named ACL or the set of all named ACLs
#define ast_debug(level,...)
Log a DEBUG message.
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Definition lock.h:764
static int reload_module(void)
static int named_acl_reload_count

References ast_atomic_fetchadd_int(), ast_debug, ast_named_acl_change_type(), named_acl_reload_count, and reload_module().

Referenced by load_module().

◆ add_extension()

static int add_extension ( struct ast_context context,
const char *  exten,
int  priority,
const char *  application 
)
static

Definition at line 449 of file res_pjsip_config_wizard.c.

451{
452 struct pbx_find_info find_info = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */
453 struct ast_exten *existing_exten;
454 char *data = NULL;
455 char *app = NULL;
456 void *free_ptr = NULL;
457 const char *paren;
458 const char *context_name;
459
460 if (!context || ast_strlen_zero(exten) || ast_strlen_zero(application)) {
461 return -1;
462 }
463
464 /* The incoming application has to be split into the app name and the
465 * arguments (data). The app name can be any storage type as add_extension
466 * copies it into its own buffer. Data however, needs to be dynamically
467 * allocated and a free function provided.
468 */
469
470 paren = strchr(application, '(');
471 if (!paren) {
472 app = (char *)application;
473 } else {
474 app = ast_strdupa(application);
475 app[paren - application] = '\0';
476 data = ast_strdup(paren + 1);
477 if (!data) {
478 return -1;
479 }
480 data[strlen(data) - 1] = '\0';
481 free_ptr = ast_free_ptr;
483 ast_free(data);
484 return -1;
485 }
486 }
487
488 /* Don't disturb existing, exact-match, entries. */
490 if ((existing_exten = pbx_find_extension(NULL, NULL, &find_info, context_name, exten,
491 priority, NULL, NULL, E_MATCH))) {
492 const char *existing_app = ast_get_extension_app(existing_exten);
493 const char *existing_data = ast_get_extension_app_data(existing_exten);
494 if (!strcmp(existing_app, app)
495 && !strcmp(existing_data ? existing_data : "", data ? data : "")) {
496 ast_free(data);
497 return 0;
498 }
499
501 }
502
504 app, data, free_ptr, BASE_REGISTRAR, NULL, 0)) {
505 return -1;
506 }
507
508 return 0;
509}
#define paren
Definition ael_lex.c:962
static const char app[]
#define ast_free(a)
Definition astmm.h:180
#define ast_strdup(str)
A wrapper for strdup()
Definition astmm.h:241
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition astmm.h:298
void ast_free_ptr(void *ptr)
free() wrapper
Definition astmm.c:1739
static int priority
@ E_MATCH
Definition extconf.h:217
static const char context_name[]
void * ast_get_extension_app_data(struct ast_exten *e)
Definition pbx.c:6720
int ast_context_remove_extension2(struct ast_context *con, const char *extension, int priority, const char *registrar, int already_locked)
This functionc locks given context, search for the right extension and fires out all peer in this ext...
Definition pbx.c:3538
const char * ast_get_extension_app(struct ast_exten *e)
Definition pbx.c:6715
const char * ast_get_context_name(struct ast_context *con)
Definition ael_main.c:421
int ast_add_extension2_nolock(struct ast_context *con, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar, const char *registrar_file, int registrar_line)
Same as ast_add_extension2, but assumes you have already locked context.
Definition pbx.c:5548
struct ast_exten * pbx_find_extension(struct ast_channel *chan, struct ast_context *bypass, struct pbx_find_info *q, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action)
Definition ael_main.c:152
#define BASE_REGISTRAR
#define NULL
Definition resample.c:96
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition strings.h:65
ast_exten: An extension The dialplan is saved as a linked list with each context having it's own link...
Definition pbx.c:207
char * exten
Definition pbx.c:208
void * data
Definition pbx.c:218

References app, ast_add_extension2_nolock(), ast_context_remove_extension2(), ast_free, ast_free_ptr(), ast_get_context_name(), ast_get_extension_app(), ast_get_extension_app_data(), ast_strdup, ast_strdupa, ast_strlen_zero(), BASE_REGISTRAR, context_name, ast_exten::data, E_MATCH, ast_exten::exten, NULL, paren, pbx_find_extension(), priority, and pbx_find_info::stacklen.

Referenced by add_hints().

◆ add_hints()

static int add_hints ( const char *  context,
const char *  exten,
const char *  application,
const char *  id 
)
static

Definition at line 511 of file res_pjsip_config_wizard.c.

512{
513 struct ast_context *hint_context;
514 char *hint_device;
515
516 hint_device = ast_alloca(strlen("PJSIP/") + strlen(id) + 1);
517 sprintf(hint_device, "PJSIP/%s", id);
518
519 /* We need the contexts list locked to safely be able to both read and lock the specific context within */
520 if (ast_wrlock_contexts()) {
521 ast_log(LOG_ERROR, "Failed to lock the contexts list.\n");
522 return -1;
523 }
524
525 if (!(hint_context = ast_context_find_or_create(NULL, NULL, context, BASE_REGISTRAR))) {
526 ast_log(LOG_ERROR, "Unable to find or create hint context '%s'\n", context);
527 if (ast_unlock_contexts()) {
528 ast_assert(0);
529 }
530 return -1;
531 }
532
533 /* Transfer the all-contexts lock to the specific context */
534 if (ast_wrlock_context(hint_context)) {
536 ast_log(LOG_ERROR, "failed to obtain write lock on context\n");
537 return -1;
538 }
540
541 if (add_extension(hint_context, exten, PRIORITY_HINT, hint_device)) {
542 ast_log(LOG_ERROR, "Failed to add hint '%s@%s' to the PBX.\n",
543 exten, context);
544 }
545
546 if (!ast_strlen_zero(application)) {
547 if (add_extension(hint_context, exten, 1, application)) {
548 ast_log(LOG_ERROR, "Failed to add hint '%s@%s' to the PBX.\n",
549 exten, context);
550 }
551 } else {
552 ast_context_remove_extension2(hint_context, exten, 1, BASE_REGISTRAR, 1);
553 }
554
555 ast_unlock_context(hint_context);
556
557 return 0;
558}
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition astmm.h:288
#define ast_log
Definition astobj2.c:42
int ast_wrlock_contexts(void)
Write locks the context list.
Definition pbx.c:6621
int ast_wrlock_context(struct ast_context *con)
Write locks a given context.
Definition pbx.c:6639
struct ast_context * ast_context_find_or_create(struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *name, const char *registrar)
Register a new context or find an existing one.
Definition pbx.c:4542
int ast_unlock_context(struct ast_context *con)
Definition pbx.c:6649
#define PRIORITY_HINT
Definition pbx.h:54
int ast_unlock_contexts(void)
Unlocks contexts.
Definition pbx.c:6631
static int add_extension(struct ast_context *context, const char *exten, int priority, const char *application)
ast_context: An extension context
Definition pbx.c:254
#define ast_assert(a)
Definition utils.h:779

References add_extension(), ast_alloca, ast_assert, ast_context_find_or_create(), ast_context_remove_extension2(), ast_log, ast_strlen_zero(), ast_unlock_context(), ast_unlock_contexts(), ast_wrlock_context(), ast_wrlock_contexts(), BASE_REGISTRAR, LOG_ERROR, NULL, and PRIORITY_HINT.

Referenced by handle_endpoint().

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 1427 of file res_pjsip_config_wizard.c.

◆ AST_VECTOR_RW()

static AST_VECTOR_RW (   object_type_wizards,
struct object_type_wizard  
)
static

Definition at line 293 of file res_pjsip_config_wizard.c.

297 { \
298 ast_config_destroy(otw->last_config); \
299 ast_free(otw); \
300})
301
302const static char *object_types[] = {"phoneprov", "registration", "identify", "endpoint", "aor", "auth", NULL};

References NULL.

◆ create_object()

static void * create_object ( const struct ast_sorcery sorcery,
const char *  id,
const char *  type,
struct ast_variable vars 
)
static

Creates a sorcery object and applies a variable list.

Definition at line 360 of file res_pjsip_config_wizard.c.

362{
364
365 if (!obj) {
366 ast_log(LOG_ERROR, "Unable to allocate an object of type '%s' with id '%s'.\n", type, id);
367 return NULL;
368 }
369
370 if (ast_sorcery_objectset_apply(sorcery, obj, vars)) {
371 ast_log(LOG_ERROR, "Unable to apply object type '%s' with id '%s'. Check preceeding errors.\n", type, id);
372 ao2_ref(obj, -1);
373 return NULL;
374 }
375
376 return obj;
377}
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition astobj2.h:459
static const char type[]
static struct ast_sorcery * sorcery
void * ast_sorcery_alloc(const struct ast_sorcery *sorcery, const char *type, const char *id)
Allocate an object.
Definition sorcery.c:1808
int ast_sorcery_objectset_apply(const struct ast_sorcery *sorcery, void *object, struct ast_variable *objectset)
Apply an object set (KVP list) to an object.
Definition sorcery.c:1696
Structure for internal sorcery object information.
Definition sorcery.c:128

References ao2_ref, ast_log, ast_sorcery_alloc(), ast_sorcery_objectset_apply(), LOG_ERROR, NULL, sorcery, and type.

Referenced by handle_aor(), handle_auth(), handle_endpoint(), handle_identify(), handle_phoneprov(), and handle_registrations().

◆ delete_existing_cb()

static int delete_existing_cb ( void *  obj,
void *  arg,
int  flags 
)
static

Definition at line 854 of file res_pjsip_config_wizard.c.

855{
856 struct object_type_wizard *otw = arg;
857
858 if (!strcmp(otw->object_type, "endpoint")) {
859 const char *context = ast_sorcery_object_get_extended(obj, "hint_context");
860 const char *exten = ast_sorcery_object_get_extended(obj, "hint_exten");
861 if (!ast_strlen_zero(context) && !ast_strlen_zero(exten)) {
862 delete_extens(context, exten);
863 }
864 }
865
866 otw->wizard->delete(otw->sorcery, otw->wizard_data, obj);
867
868 return CMP_MATCH;
869}
@ CMP_MATCH
Definition astobj2.h:1027
static int delete_extens(const char *context, const char *exten)
const char * ast_sorcery_object_get_extended(const void *object, const char *name)
Get an extended field value from a sorcery object.
Definition sorcery.c:2399
int(* delete)(const struct ast_sorcery *sorcery, void *data, void *object)
Callback for deleting an object.
Definition sorcery.h:319
Keeps track of the sorcery wizard and last config for each object type.
struct ast_sorcery * sorcery
struct ast_sorcery_wizard * wizard

References ast_sorcery_object_get_extended(), ast_strlen_zero(), CMP_MATCH, ast_sorcery_wizard::delete, delete_extens(), object_type_wizard::object_type, object_type_wizard::sorcery, object_type_wizard::wizard, and object_type_wizard::wizard_data.

Referenced by handle_registrations(), and object_type_loaded_observer().

◆ delete_extens()

static int delete_extens ( const char *  context,
const char *  exten 
)
static

Definition at line 434 of file res_pjsip_config_wizard.c.

435{
436 struct pbx_find_info find_info = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */
437
438 if (pbx_find_extension(NULL, NULL, &find_info, context, exten, PRIORITY_HINT, NULL, NULL, E_MATCH)) {
440 }
441
442 if (pbx_find_extension(NULL, NULL, &find_info, context, exten, 1, NULL, NULL, E_MATCH)) {
444 }
445
446 return 0;
447}
int ast_context_remove_extension(const char *context, const char *extension, int priority, const char *registrar)
Simply remove extension from context.
Definition pbx.c:3508

References ast_context_remove_extension(), BASE_REGISTRAR, E_MATCH, NULL, pbx_find_extension(), PRIORITY_HINT, and pbx_find_info::stacklen.

Referenced by delete_existing_cb(), and handle_endpoint().

◆ find_wizard()

static struct object_type_wizard * find_wizard ( const char *  object_type)
static

Finds the otw for the object type.

Definition at line 342 of file res_pjsip_config_wizard.c.

343{
344 int idx;
345
346 AST_VECTOR_RW_RDLOCK(&object_type_wizards);
347 for(idx = 0; idx < AST_VECTOR_SIZE(&object_type_wizards); idx++) {
348 struct object_type_wizard *otw = AST_VECTOR_GET(&object_type_wizards, idx);
349 if (!strcmp(otw->object_type, object_type)) {
350 AST_VECTOR_RW_UNLOCK(&object_type_wizards);
351 return otw;
352 }
353 }
354 AST_VECTOR_RW_UNLOCK(&object_type_wizards);
355
356 return NULL;
357}
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition vector.h:637
#define AST_VECTOR_RW_UNLOCK(vec)
Unlock vector.
Definition vector.h:925
#define AST_VECTOR_RW_RDLOCK(vec)
Obtain read lock on vector.
Definition vector.h:905
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition vector.h:708

References AST_VECTOR_GET, AST_VECTOR_RW_RDLOCK, AST_VECTOR_RW_UNLOCK, AST_VECTOR_SIZE, NULL, and object_type_wizard::object_type.

Referenced by object_type_loaded_observer().

◆ get_object_variables()

static struct ast_variable * get_object_variables ( struct ast_variable vars,
char *  prefix 
)
static

We need to strip off the prefix from the name of each variable so they're suitable for objectset_apply. I.E. will transform outbound_auth/username to username.

Definition at line 415 of file res_pjsip_config_wizard.c.

416{
417 struct ast_variable *return_vars = NULL;
418 struct ast_variable *v = vars;
419 int plen = strlen(prefix);
420
421 for(; v; v = v->next) {
422 if (ast_begins_with(v->name, prefix) && strlen(v->name) > plen) {
423 if (variable_list_append(&return_vars, v->name + plen, v->value)) {
424 ast_variables_destroy(return_vars);
425 return NULL;
426 }
427 }
428 }
429
430 return return_vars;
431}
static char prefix[MAX_PREFIX]
Definition http.c:145
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition extconf.c:1260
static int variable_list_append(struct ast_variable **existing, const char *name, const char *value)
Appends a variable to the end of an existing list.
static int force_inline attribute_pure ast_begins_with(const char *str, const char *prefix)
Checks whether a string begins with another.
Definition strings.h:97
struct ast_variable * next

References ast_begins_with(), ast_variables_destroy(), ast_variable::name, ast_variable::next, NULL, prefix, ast_variable::value, and variable_list_append().

Referenced by handle_aor(), handle_auth(), handle_endpoint(), handle_identify(), handle_phoneprov(), and handle_registrations().

◆ handle_aor()

static int handle_aor ( const struct ast_sorcery sorcery,
struct object_type_wizard otw,
struct ast_category wiz,
struct string_vector remote_hosts_vector 
)
static

Definition at line 630 of file res_pjsip_config_wizard.c.

632{
633 struct ast_variable *wizvars = ast_category_first(wiz);
634 struct ast_sorcery_object *obj = NULL;
635 const char *id = ast_category_get_name(wiz);
636 const char *contact_pattern;
637 const char *outbound_proxy = ast_variable_find_last_in_list(wizvars, "outbound_proxy");
638 int host_count = AST_VECTOR_SIZE(remote_hosts_vector);
639 RAII_VAR(struct ast_variable *, vars, get_object_variables(wizvars, "aor/"), ast_variables_destroy);
640
641 variable_list_append(&vars, "@pjsip_wizard", id);
642
643 if (!ast_strlen_zero(outbound_proxy)) {
644 variable_list_append_return(&vars, "outbound_proxy", outbound_proxy);
645 }
646
647 /* If the user explicitly specified an aor/contact, don't use remote hosts. */
648 if (!ast_variable_find_last_in_list(vars, "contact")) {
649 if (!(contact_pattern = ast_variable_find_last_in_list(wizvars, "contact_pattern"))) {
650 contact_pattern = "sip:${REMOTE_HOST}";
651 }
652
653 if (host_count > 0 && !ast_strlen_zero(contact_pattern)) {
654 int host_counter;
655
656 /* ast_str_substitute_variables operate on a varshead list so we have
657 * to create one to hold the REPORT_HOST substitution, do the substitution,
658 * then append the result to the ast_variable list.
659 */
660 for (host_counter = 0; host_counter < host_count; host_counter++) {
661 RAII_VAR(struct ast_str *, new_str, ast_str_create(64), ast_free);
663 struct ast_var_t *var = ast_var_assign("REMOTE_HOST",
664 AST_VECTOR_GET(remote_hosts_vector, host_counter));
665
666 AST_VAR_LIST_INSERT_TAIL(subst_vars, var);
667 ast_str_substitute_variables_varshead(&new_str, 0, subst_vars,
668 contact_pattern);
669
670 variable_list_append_return(&vars, "contact", ast_str_buffer(new_str));
671 }
672 }
673 }
674
675 obj = create_object(sorcery, id, "aor", vars);
676 if (!obj) {
677 return -1;
678 }
679
680 if (otw->wizard->update(sorcery, otw->wizard_data, obj)) {
681 otw->wizard->create(sorcery, otw->wizard_data, obj);
682 }
683 ao2_ref(obj, -1);
684
685 return 0;
686}
#define var
Definition ast_expr2f.c:605
void ast_var_list_destroy(struct varshead *head)
Definition chanvars.c:109
static void AST_VAR_LIST_INSERT_TAIL(struct varshead *head, struct ast_var_t *var)
Definition chanvars.h:51
#define ast_var_assign(name, value)
Definition chanvars.h:40
struct varshead * ast_var_list_create(void)
Definition chanvars.c:97
const char * ast_category_get_name(const struct ast_category *category)
Return the name of the category.
const char * ast_variable_find_last_in_list(const struct ast_variable *list, const char *variable)
Gets the value of the LAST occurrence of a variable from a variable list.
struct ast_variable * ast_category_first(struct ast_category *cat)
given a pointer to a category, return the root variable.
void ast_str_substitute_variables_varshead(struct ast_str **buf, ssize_t maxlen, struct varshead *headp, const char *templ)
#define variable_list_append_return(existing, name, value)
Appends a variable to the end of an existing list. On failure, cause the calling function to return -...
static void * create_object(const struct ast_sorcery *sorcery, const char *id, const char *type, struct ast_variable *vars)
Creates a sorcery object and applies a variable list.
static struct ast_variable * get_object_variables(struct ast_variable *vars, char *prefix)
We need to strip off the prefix from the name of each variable so they're suitable for objectset_appl...
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition strings.h:659
char *attribute_pure ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition strings.h:761
int(* create)(const struct ast_sorcery *sorcery, void *data, void *object)
Callback for creating an object.
Definition sorcery.h:293
int(* update)(const struct ast_sorcery *sorcery, void *data, void *object)
Callback for updating an object.
Definition sorcery.h:316
Support for dynamic strings.
Definition strings.h:623
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition utils.h:981

References ao2_ref, ast_category_first(), ast_category_get_name(), ast_free, ast_str_buffer(), ast_str_create, ast_str_substitute_variables_varshead(), ast_strlen_zero(), ast_var_assign, ast_var_list_create(), ast_var_list_destroy(), AST_VAR_LIST_INSERT_TAIL(), ast_variable_find_last_in_list(), ast_variables_destroy(), AST_VECTOR_GET, AST_VECTOR_SIZE, ast_sorcery_wizard::create, create_object(), get_object_variables(), NULL, RAII_VAR, sorcery, ast_sorcery_wizard::update, var, variable_list_append(), variable_list_append_return, object_type_wizard::wizard, and object_type_wizard::wizard_data.

Referenced by wizard_apply_handler().

◆ handle_auth()

static int handle_auth ( const struct ast_sorcery sorcery,
struct object_type_wizard otw,
struct ast_category wiz,
char *  direction 
)
static

Definition at line 560 of file res_pjsip_config_wizard.c.

562{
563 struct ast_variable *wizvars = ast_category_first(wiz);
564 struct ast_sorcery_object *obj = NULL;
565 const char *id = ast_category_get_name(wiz);
566 char new_id[strlen(id) + MAX_ID_SUFFIX];
567 char prefix[strlen(direction) + strlen("_auth/") + 1];
568 char *test_variable = NULL;
570
571 snprintf(prefix, sizeof(prefix), "%s_auth/", direction);
572 vars = get_object_variables(wizvars, prefix);
573
574 if (!strcmp(direction, "outbound")) {
575 snprintf(new_id, sizeof(new_id), "%s-oauth", id);
576 test_variable = "sends_auth";
577 } else {
578 snprintf(new_id, sizeof(new_id), "%s-iauth", id);
579 test_variable = "accepts_auth";
580 }
581
582 if (is_variable_true(wizvars, test_variable)) {
583 if (!ast_variable_find_last_in_list(vars, "username")) {
585 "Wizard '%s' must have '%s_auth/username' if it %s.\n", id, direction, test_variable);
586 return -1;
587 }
588 } else {
589 /* Delete auth if sends or accepts is now false. */
590 obj = otw->wizard->retrieve_id(sorcery, otw->wizard_data, "auth", new_id);
591 if (obj) {
592 otw->wizard->delete(sorcery, otw->wizard_data, obj);
593 ao2_ref(obj, -1);
594 }
595 return 0;
596 }
597
598 variable_list_append_return(&vars, "@pjsip_wizard", id);
599
600 /* If the user set auth_type, don't override it. */
601 if (!ast_variable_find_last_in_list(vars, "auth_type")) {
602 variable_list_append_return(&vars, "auth_type", "userpass");
603 }
604
605 obj = create_object(sorcery, new_id, "auth", vars);
606 if (!obj) {
607 return -1;
608 }
609
610 if (otw->wizard->update(sorcery, otw->wizard_data, obj)) {
611 otw->wizard->create(sorcery, otw->wizard_data, obj);
612 }
613 ao2_ref(obj, -1);
614
615 return 0;
616}
direction
static int is_variable_true(struct ast_variable *vars, const char *name)
Finds the last variable in a list and tests it.
#define MAX_ID_SUFFIX
Defines the maximum number of characters that can be added to a wizard id.
void *(* retrieve_id)(const struct ast_sorcery *sorcery, void *data, const char *type, const char *id)
Callback for retrieving an object using an id.
Definition sorcery.h:296

References ao2_ref, ast_category_first(), ast_category_get_name(), ast_log, ast_variable_find_last_in_list(), ast_variables_destroy(), ast_sorcery_wizard::create, create_object(), ast_sorcery_wizard::delete, get_object_variables(), is_variable_true(), LOG_ERROR, MAX_ID_SUFFIX, NULL, prefix, RAII_VAR, ast_sorcery_wizard::retrieve_id, sorcery, ast_sorcery_wizard::update, variable_list_append_return, object_type_wizard::wizard, and object_type_wizard::wizard_data.

Referenced by handle_auths().

◆ handle_auths()

static int handle_auths ( const struct ast_sorcery sorcery,
struct object_type_wizard otw,
struct ast_category wiz 
)
static

Definition at line 618 of file res_pjsip_config_wizard.c.

620{
621 int rc;
622
623 if ((rc = handle_auth(sorcery, otw, wiz, "outbound"))) {
624 return rc;
625 }
626
627 return handle_auth(sorcery, otw, wiz, "inbound");
628}
static int handle_auth(const struct ast_sorcery *sorcery, struct object_type_wizard *otw, struct ast_category *wiz, char *direction)

References handle_auth(), and sorcery.

Referenced by wizard_apply_handler().

◆ handle_endpoint()

static int handle_endpoint ( const struct ast_sorcery sorcery,
struct object_type_wizard otw,
struct ast_category wiz 
)
static

Definition at line 688 of file res_pjsip_config_wizard.c.

690{
691 struct ast_variable *wizvars = ast_category_first(wiz);
692 struct ast_sorcery_object *obj = NULL;
693 const char *id = ast_category_get_name(wiz);
694 const char *outbound_proxy = ast_variable_find_last_in_list(wizvars, "outbound_proxy");
695 const char *transport = ast_variable_find_last_in_list(wizvars, "transport");
696 const char *hint_context = hint_context = ast_variable_find_last_in_list(wizvars, "hint_context");
697 const char *hint_exten = ast_variable_find_last_in_list(wizvars, "hint_exten");
698 const char *hint_application= ast_variable_find_last_in_list(wizvars, "hint_application");
699 char new_id[strlen(id) + MAX_ID_SUFFIX];
700 RAII_VAR(struct ast_variable *, vars, get_object_variables(wizvars, "endpoint/"), ast_variables_destroy);
701
702 variable_list_append_return(&vars, "@pjsip_wizard", id);
703 variable_list_append_return(&vars, "aors", id);
704
705 if (!ast_strlen_zero(outbound_proxy)) {
706 variable_list_append_return(&vars, "outbound_proxy", outbound_proxy);
707 }
708
709 if (ast_strlen_zero(hint_context)) {
710 hint_context = ast_variable_find_last_in_list(vars, "context");
711 }
712
713 if (ast_strlen_zero(hint_context)) {
714 hint_context = "default";
715 }
716
717 if (!ast_strlen_zero(hint_exten)) {
718 /* These are added so we can find and delete the hints when the endpoint gets deleted */
719 variable_list_append_return(&vars, "@hint_context", hint_context);
720 variable_list_append_return(&vars, "@hint_exten", hint_exten);
721 }
722
723 if (!ast_strlen_zero(transport)) {
724 variable_list_append_return(&vars, "transport", transport);
725 }
726
727 if (is_variable_true(wizvars, "sends_auth")) {
728 snprintf(new_id, sizeof(new_id), "%s-oauth", id);
729 variable_list_append_return(&vars, "outbound_auth", new_id);
730 }
731
732 if (is_variable_true(wizvars, "accepts_auth")) {
733 snprintf(new_id, sizeof(new_id), "%s-iauth", id);
734 variable_list_append_return(&vars, "auth", new_id);
735 }
736
737 obj = create_object(sorcery, id, "endpoint", vars);
738 if (!obj) {
739 return -1;
740 }
741
742 if (otw->wizard->update(sorcery, otw->wizard_data, obj)) {
743 otw->wizard->create(sorcery, otw->wizard_data, obj);
744 }
745 ao2_ref(obj, -1);
746
747 if (!ast_strlen_zero(hint_exten)) {
748 if (is_variable_true(wizvars, "has_hint")) {
749 add_hints(hint_context, hint_exten, hint_application, id);
750 } else {
751 delete_extens(hint_context, hint_exten);
752 }
753 }
754
755 return 0;
756}
static int add_hints(const char *context, const char *exten, const char *application, const char *id)

References add_hints(), ao2_ref, ast_category_first(), ast_category_get_name(), ast_strlen_zero(), ast_variable_find_last_in_list(), ast_variables_destroy(), ast_sorcery_wizard::create, create_object(), delete_extens(), get_object_variables(), is_variable_true(), MAX_ID_SUFFIX, NULL, RAII_VAR, sorcery, ast_sorcery_wizard::update, variable_list_append_return, object_type_wizard::wizard, and object_type_wizard::wizard_data.

Referenced by wizard_apply_handler().

◆ handle_export_primitives()

static char * handle_export_primitives ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 1248 of file res_pjsip_config_wizard.c.

1249{
1250 struct ast_sorcery *sorcery;
1251 int idx;
1252 FILE *f = NULL;
1253 const char *fn = NULL;
1254
1255 switch (cmd) {
1256 case CLI_INIT:
1257 e->command = "pjsip export config_wizard primitives [to]";
1258 e->usage =
1259 "Usage: pjsip export config_wizard primitives [ to <filename> ]\n"
1260 " Export the config_wizard objects as pjsip primitives to\n"
1261 " the console or to <filename>\n";
1262 return NULL;
1263 case CLI_GENERATE:
1264 return NULL;
1265 }
1266
1267 if (a->argc > 5) {
1268 char date[256]="";
1269 time_t t;
1270 fn = a->argv[5];
1271
1272 time(&t);
1273 ast_copy_string(date, ctime(&t), sizeof(date));
1274 f = fopen(fn, "w");
1275 if (!f) {
1276 ast_log(LOG_ERROR, "Unable to write %s (%s)\n", fn, strerror(errno));
1277 return CLI_FAILURE;
1278 }
1279
1280 fprintf(f, ";!\n");
1281 fprintf(f, ";! Automatically generated configuration file\n");
1282 fprintf(f, ";! Filename: %s\n", fn);
1283 fprintf(f, ";! Generator: %s\n", "'pjsip export config_wizard primitives'");
1284 fprintf(f, ";! Creation Date: %s", date);
1285 fprintf(f, ";!\n");
1286 }
1287
1289
1290 AST_VECTOR_RW_RDLOCK(&object_type_wizards);
1291 for(idx = 0; idx < AST_VECTOR_SIZE(&object_type_wizards); idx++) {
1292 struct object_type_wizard *otw = AST_VECTOR_GET(&object_type_wizards, idx);
1293 struct ao2_container *container;
1294 struct ao2_iterator i;
1295 void *o;
1296
1298 if (!container) {
1299 continue;
1300 }
1301
1303 while ((o = ao2_iterator_next(&i))) {
1304 struct ast_variable *vars;
1305 struct ast_variable *v;
1306
1308 if (vars && ast_variable_find_in_list(vars, "@pjsip_wizard")) {
1309 if (f) {
1310 fprintf(f, "\n[%s]\ntype = %s\n", ast_sorcery_object_get_id(o), otw->object_type);
1311 } else {
1312 ast_cli(a->fd, "\n[%s]\ntype = %s\n", ast_sorcery_object_get_id(o), otw->object_type);
1313 }
1314 for (v = vars; v; v = v->next) {
1315 if (!ast_strlen_zero(v->value)) {
1316 if (f) {
1317 fprintf(f, "%s = %s\n", v->name, v->value);
1318 } else {
1319 ast_cli(a->fd, "%s = %s\n", v->name, v->value);
1320 }
1321 }
1322 }
1323 }
1325 ao2_ref(o, -1);
1326 }
1329 }
1330 AST_VECTOR_RW_UNLOCK(&object_type_wizards);
1331
1332 if (f) {
1333 fclose(f);
1334 ast_cli(a->fd, "Wrote configuration to %s\n", fn);
1335 }
1336
1337
1338 return CLI_SUCCESS;
1339}
#define ao2_iterator_next(iter)
Definition astobj2.h:1911
#define ao2_cleanup(obj)
Definition astobj2.h:1934
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
#define CLI_SUCCESS
Definition cli.h:44
void ast_cli(int fd, const char *fmt,...)
Definition clicompat.c:6
@ CLI_INIT
Definition cli.h:152
@ CLI_GENERATE
Definition cli.h:153
#define CLI_FAILURE
Definition cli.h:46
const char * ast_variable_find_in_list(const struct ast_variable *list, const char *variable)
Gets the value of a variable from a variable list by name.
int errno
struct ao2_container * container
Definition res_fax.c:603
struct ast_sorcery * ast_sip_get_sorcery(void)
Get a pointer to the SIP sorcery structure.
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition sorcery.c:2381
#define ast_sorcery_objectset_create(sorcery, object)
Create an object set (KVP list) for an object.
Definition sorcery.h:1137
@ AST_RETRIEVE_FLAG_MULTIPLE
Return all matching objects.
Definition sorcery.h:120
void * ast_sorcery_retrieve_by_fields(const struct ast_sorcery *sorcery, const char *type, unsigned int flags, struct ast_variable *fields)
Retrieve an object or multiple objects using specific fields.
Definition sorcery.c:1961
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition strings.h:425
Generic container type.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition astobj2.h:1821
char * command
Definition cli.h:186
const char * usage
Definition cli.h:177
Full structure for sorcery.
Definition sorcery.c:231
static struct test_val a

References a, ao2_cleanup, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_cli(), ast_copy_string(), ast_log, AST_RETRIEVE_FLAG_MULTIPLE, ast_sip_get_sorcery(), ast_sorcery_object_get_id(), ast_sorcery_objectset_create, ast_sorcery_retrieve_by_fields(), ast_strlen_zero(), ast_variable_find_in_list(), ast_variables_destroy(), AST_VECTOR_GET, AST_VECTOR_RW_RDLOCK, AST_VECTOR_RW_UNLOCK, AST_VECTOR_SIZE, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, container, errno, LOG_ERROR, ast_variable::name, ast_variable::next, NULL, object_type_wizard::object_type, sorcery, ast_cli_entry::usage, and ast_variable::value.

◆ handle_identify()

static int handle_identify ( const struct ast_sorcery sorcery,
struct object_type_wizard otw,
struct ast_category wiz,
struct string_vector remote_hosts_vector 
)
static

Definition at line 758 of file res_pjsip_config_wizard.c.

760{
761 struct ast_variable *wizvars = ast_category_first(wiz);
762 struct ast_sorcery_object *obj = NULL;
763 const char *id = ast_category_get_name(wiz);
764 char new_id[strlen(id) + MAX_ID_SUFFIX];
765 int host_count = AST_VECTOR_SIZE(remote_hosts_vector);
766 int host_counter;
767 RAII_VAR(struct ast_variable *, vars, get_object_variables(wizvars, "identify/"), ast_variables_destroy);
768
769 snprintf(new_id, sizeof(new_id), "%s-identify", id);
770
771 /* If accepting registrations or we're sending line, we don't need an identify. */
772 if (is_variable_true(wizvars, "accepts_registrations")
773 || is_variable_true(wizvars, "sends_line_with_registrations")) {
774 /* If one exists, delete it. */
775 obj = otw->wizard->retrieve_id(sorcery, otw->wizard_data, "identify", new_id);
776 if (obj) {
777 otw->wizard->delete(sorcery, otw->wizard_data, obj);
778 ao2_ref(obj, -1);
779 }
780 return 0;
781 }
782
783 if (!host_count) {
785 "Wizard '%s' must have 'remote_hosts' if it doesn't accept registrations.\n", id);
786 return -1;
787 }
788
789 variable_list_append_return(&vars, "endpoint", id);
790 variable_list_append_return(&vars, "@pjsip_wizard", id);
791
792 if (!ast_variable_find_last_in_list(vars, "match")) {
793 for (host_counter = 0; host_counter < host_count; host_counter++) {
794 variable_list_append_return(&vars, "match",
795 AST_VECTOR_GET(remote_hosts_vector, host_counter));
796 }
797 }
798
799 obj = create_object(sorcery, new_id, "identify", vars);
800 if (!obj) {
801 return -1;
802 }
803
804 if (otw->wizard->update(sorcery, otw->wizard_data, obj)) {
805 otw->wizard->create(sorcery, otw->wizard_data, obj);
806 }
807 ao2_ref(obj, -1);
808
809 return 0;
810}

References ao2_ref, ast_category_first(), ast_category_get_name(), ast_log, ast_variable_find_last_in_list(), ast_variables_destroy(), AST_VECTOR_GET, AST_VECTOR_SIZE, ast_sorcery_wizard::create, create_object(), ast_sorcery_wizard::delete, get_object_variables(), is_variable_true(), LOG_ERROR, MAX_ID_SUFFIX, NULL, RAII_VAR, ast_sorcery_wizard::retrieve_id, sorcery, ast_sorcery_wizard::update, variable_list_append_return, object_type_wizard::wizard, and object_type_wizard::wizard_data.

Referenced by wizard_apply_handler().

◆ handle_phoneprov()

static int handle_phoneprov ( const struct ast_sorcery sorcery,
struct object_type_wizard otw,
struct ast_category wiz 
)
static

Definition at line 812 of file res_pjsip_config_wizard.c.

814{
815 struct ast_variable *wizvars = ast_category_first(wiz);
816 struct ast_sorcery_object *obj = NULL;
817 const char *id = ast_category_get_name(wiz);
818 char new_id[strlen(id) + MAX_ID_SUFFIX];
819 RAII_VAR(struct ast_variable *, vars, get_object_variables(wizvars, "phoneprov/"), ast_variables_destroy);
820
821 snprintf(new_id, sizeof(new_id), "%s-phoneprov", id);
822
823 if (!is_variable_true(wizvars, "has_phoneprov")) {
824 obj = otw->wizard->retrieve_id(sorcery, otw->wizard_data, "phoneprov", new_id);
825 if (obj) {
826 otw->wizard->delete(sorcery, otw->wizard_data, obj);
827 ao2_ref(obj, -1);
828 }
829 return 0;
830 }
831
832 if (!ast_variable_find_last_in_list(wizvars, "phoneprov/MAC")) {
834 "Wizard '%s' must have 'phoneprov/MAC' if it has_phoneprov.\n", id);
835 return -1;
836 }
837
838 variable_list_append_return(&vars, "endpoint", id);
839 variable_list_append_return(&vars, "@pjsip_wizard", id);
840
841 obj = create_object(sorcery, new_id, "phoneprov", vars);
842 if (!obj) {
843 return -1;
844 }
845
846 if (otw->wizard->update(sorcery, otw->wizard_data, obj)) {
847 otw->wizard->create(sorcery, otw->wizard_data, obj);
848 }
849 ao2_ref(obj, -1);
850
851 return 0;
852}

References ao2_ref, ast_category_first(), ast_category_get_name(), ast_log, ast_variable_find_last_in_list(), ast_variables_destroy(), ast_sorcery_wizard::create, create_object(), ast_sorcery_wizard::delete, get_object_variables(), is_variable_true(), LOG_ERROR, MAX_ID_SUFFIX, NULL, RAII_VAR, ast_sorcery_wizard::retrieve_id, sorcery, ast_sorcery_wizard::update, variable_list_append_return, object_type_wizard::wizard, and object_type_wizard::wizard_data.

Referenced by wizard_apply_handler().

◆ handle_registrations()

static int handle_registrations ( const struct ast_sorcery sorcery,
struct object_type_wizard otw,
struct ast_category wiz,
struct string_vector remote_hosts_vector 
)
static

Definition at line 871 of file res_pjsip_config_wizard.c.

873{
874 struct ast_variable *search;
875 struct ast_variable *wizvars = ast_category_first(wiz);
876 const char *id = ast_category_get_name(wiz);
877 const char *server_uri_pattern;
878 const char *client_uri_pattern;
879 const char *outbound_proxy = ast_variable_find_last_in_list(wizvars, "outbound_proxy");
880 const char *transport = ast_variable_find_last_in_list(wizvars, "transport");
881 const char *username;
882 char new_id[strlen(id) + MAX_ID_SUFFIX];
883 int host_count = AST_VECTOR_SIZE(remote_hosts_vector);
884 int host_counter;
885 RAII_VAR(struct ast_variable *, vars, get_object_variables(wizvars, "registration/"), ast_variables_destroy);
886 RAII_VAR(struct ao2_container *, existing,
888
889 if (!existing) {
890 return -1;
891 }
892
893 /* Find any existing registrations. */
894 search = ast_variable_new("@pjsip_wizard", id, "");
895 if (!search) {
896 return -1;
897 }
898
899 if (!ast_strlen_zero(outbound_proxy)) {
900 variable_list_append_return(&vars, "outbound_proxy", outbound_proxy);
901 }
902
903 otw->wizard->retrieve_multiple(sorcery, otw->wizard_data, "registration", existing, search);
904 ast_variables_destroy(search);
905
906 /* If not sending registrations, delete ALL existing registrations for this wizard. */
907 if (!is_variable_true(wizvars, "sends_registrations")) {
908 if (ao2_container_count(existing) > 0) {
910 }
911 return 0;
912 }
913
914 if (!host_count) {
915 ast_log(LOG_ERROR, "Wizard '%s' must have 'remote_hosts' if it sends registrations.\n", id);
916 return -1;
917 }
918
919 variable_list_append_return(&vars, "@pjsip_wizard", id);
920
921 if (!(server_uri_pattern = ast_variable_find_last_in_list(wizvars, "server_uri_pattern"))) {
922 server_uri_pattern = "sip:${REMOTE_HOST}";
923 }
924
925 if (!(client_uri_pattern = ast_variable_find_last_in_list(wizvars, "client_uri_pattern"))) {
926 client_uri_pattern = "sip:${USERNAME}@${REMOTE_HOST}";
927 }
928
929 if (is_variable_true(wizvars, "sends_auth")) {
930 if (!(username = ast_variable_find_last_in_list(wizvars, "outbound_auth/username"))) {
931 ast_log(LOG_ERROR, "Wizard '%s' must have 'outbound_auth/username' if it sends"
932 " authentication.\n", id);
933 return -1;
934 }
935 } else {
936 username = id;
937 }
938
939
940 /* Unlike aor and identify, we need to create a separate registration object
941 * for each remote host.
942 */
943 for (host_counter = 0; host_counter < host_count; host_counter++) {
944 struct ast_var_t *rh = ast_var_assign("REMOTE_HOST",
945 AST_VECTOR_GET(remote_hosts_vector, host_counter));
946 struct ast_var_t *un = ast_var_assign("USERNAME", username);
947 struct ast_sorcery_object *obj;
948 RAII_VAR(struct ast_str *, uri, ast_str_create(64), ast_free);
950 RAII_VAR(struct ast_variable *, registration_vars, vars ? ast_variables_dup(vars) : NULL, ast_variables_destroy);
951
952 AST_VAR_LIST_INSERT_TAIL(subst_vars, rh);
953 AST_VAR_LIST_INSERT_TAIL(subst_vars, un);
954
955 if (!ast_strlen_zero(server_uri_pattern)) {
956 ast_str_substitute_variables_varshead(&uri, 0, subst_vars,
957 server_uri_pattern);
958 variable_list_append_return(&registration_vars, "server_uri", ast_str_buffer(uri));
959 }
960
961 if (!ast_strlen_zero(client_uri_pattern)) {
962 ast_str_reset(uri);
963 ast_str_substitute_variables_varshead(&uri, 0, subst_vars,
964 client_uri_pattern);
965 variable_list_append_return(&registration_vars, "client_uri", ast_str_buffer(uri));
966 }
967
968 if (is_variable_true(wizvars, "sends_auth")) {
969 snprintf(new_id, sizeof(new_id), "%s-oauth", id);
970 variable_list_append_return(&registration_vars, "outbound_auth", new_id);
971 }
972
973 if (!ast_strlen_zero(transport)) {
974 variable_list_append_return(&registration_vars, "transport", transport);
975 }
976
977 if (is_variable_true(wizvars, "sends_line_with_registrations")) {
978 variable_list_append_return(&registration_vars, "line", "yes");
979 variable_list_append_return(&registration_vars, "endpoint", id);
980 }
981
982 snprintf(new_id, sizeof(new_id), "%s-reg-%d", id, host_counter);
983
984 obj = create_object(sorcery, new_id, "registration", registration_vars);
985 if (!obj) {
986 return -1;
987 }
988
989 if (otw->wizard->update(sorcery, otw->wizard_data, obj)) {
990 otw->wizard->create(sorcery, otw->wizard_data, obj);
991 }
992 ao2_ref(obj, -1);
993
994 /* Unlink it from the 'existing' container. Any left will be deleted from
995 * sorcery. If it wasn't in the existing container, no harm.
996 */
998 }
999
1000 /* If there are any excess registrations, delete them. */
1001 if (ao2_container_count(existing) > 0) {
1003 }
1004
1005 return 0;
1006}
enum queue_result id
Definition app_queue.c:1790
@ AO2_ALLOC_OPT_LOCK_NOLOCK
Definition astobj2.h:367
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container,...
Definition astobj2.h:1693
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
@ OBJ_NODATA
Definition astobj2.h:1044
@ OBJ_MULTIPLE
Definition astobj2.h:1049
@ OBJ_UNLINK
Definition astobj2.h:1039
@ OBJ_SEARCH_KEY
The arg parameter is a search key, but is not an object.
Definition astobj2.h:1101
#define ao2_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn)
Allocate and initialize a list container.
Definition astobj2.h:1327
static rc_handle * rh
Definition cdr_radius.c:96
struct ast_variable * ast_variables_dup(struct ast_variable *var)
Duplicate variable list.
static int delete_existing_cb(void *obj, void *arg, int flags)
int ast_sorcery_object_id_compare(void *obj, void *arg, int flags)
ao2 object comparator based on sorcery id.
Definition sorcery.c:2528
void ast_str_reset(struct ast_str *buf)
Reset the content of a dynamic string. Useful before a series of ast_str_append.
Definition strings.h:693
void(* retrieve_multiple)(const struct ast_sorcery *sorcery, void *data, const char *type, struct ao2_container *objects, const struct ast_variable *fields)
Optional callback for retrieving multiple objects using some optional field criteria.
Definition sorcery.h:313

References AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_callback, ao2_cleanup, ao2_container_alloc_list, ao2_container_count(), ao2_ref, ast_category_first(), ast_category_get_name(), ast_free, ast_log, ast_sorcery_object_id_compare(), ast_str_buffer(), ast_str_create, ast_str_reset(), ast_str_substitute_variables_varshead(), ast_strlen_zero(), ast_var_assign, ast_var_list_create(), ast_var_list_destroy(), AST_VAR_LIST_INSERT_TAIL(), ast_variable_find_last_in_list(), ast_variable_new, ast_variables_destroy(), ast_variables_dup(), AST_VECTOR_GET, AST_VECTOR_SIZE, ast_sorcery_wizard::create, create_object(), delete_existing_cb(), get_object_variables(), id, is_variable_true(), LOG_ERROR, MAX_ID_SUFFIX, NULL, OBJ_MULTIPLE, OBJ_NODATA, OBJ_SEARCH_KEY, OBJ_UNLINK, RAII_VAR, ast_sorcery_wizard::retrieve_multiple, rh, sorcery, ast_sorcery_wizard::update, variable_list_append_return, object_type_wizard::wizard, and object_type_wizard::wizard_data.

Referenced by wizard_apply_handler().

◆ instance_created_observer()

static void instance_created_observer ( const char *  name,
struct ast_sorcery sorcery 
)
static

When the res_pjsip instance is created, add an observer to it and initialize the wizard vector. Also, bump the module's ref count so it can't be unloaded before the sorcery instance is destroyed.

Definition at line 1226 of file res_pjsip_config_wizard.c.

1227{
1228 if (strcmp(name, "res_pjsip")) {
1229 return;
1230 }
1233}
#define ast_module_ref(mod)
Hold a reference to the module.
Definition module.h:457
struct ast_sorcery_instance_observer observer
int ast_sorcery_instance_observer_add(struct ast_sorcery *sorcery, const struct ast_sorcery_instance_observer *callbacks)
Add an observer to a sorcery instance.
Definition sorcery.c:584
struct ast_module * self
Definition module.h:356

References ast_module_ref, ast_sorcery_instance_observer_add(), name, observer, ast_module_info::self, and sorcery.

◆ instance_destroying_observer()

static void instance_destroying_observer ( const char *  name,
struct ast_sorcery sorcery 
)
static

When the res_pjsip instance is destroyed, remove the observer and unref the module. This should then allow this module to unload cleanly.

Definition at line 1238 of file res_pjsip_config_wizard.c.

1239{
1240 if (strcmp(name, "res_pjsip")) {
1241 return;
1242 }
1243
1246}
#define ast_module_unref(mod)
Release a reference to the module.
Definition module.h:483
void ast_sorcery_instance_observer_remove(struct ast_sorcery *sorcery, const struct ast_sorcery_instance_observer *callbacks)
Remove an observer from a sorcery instance.
Definition sorcery.c:601

References ast_module_unref, ast_sorcery_instance_observer_remove(), name, observer, ast_module_info::self, and sorcery.

◆ is_one_of()

static int is_one_of ( const char *  needle,
const char *  haystack[] 
)
static

Definition at line 329 of file res_pjsip_config_wizard.c.

330{
331 int i;
332 for (i = 0; haystack[i]; i++) {
333 if (!strcmp(needle, haystack[i])) {
334 return 1;
335 }
336 }
337
338 return 0;
339}

Referenced by object_type_registered_observer().

◆ is_variable_true()

static int is_variable_true ( struct ast_variable vars,
const char *  name 
)
static

Finds the last variable in a list and tests it.

Definition at line 380 of file res_pjsip_config_wizard.c.

381{
383}
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
Definition utils.c:2233

References ast_true(), ast_variable_find_last_in_list(), and name.

Referenced by handle_auth(), handle_endpoint(), handle_identify(), handle_phoneprov(), and handle_registrations().

◆ load_module()

static int load_module ( void  )
static

Definition at line 1368 of file res_pjsip_config_wizard.c.

1369{
1370 AST_VECTOR_RW_INIT(&object_type_wizards, 12);
1373
1375
1376 /* If the PJSIP sorcery instance exists it means that we have been explicitly
1377 * loaded and things are potentially already set up. Since we won't receive any
1378 * observer callbacks informing us of this we add ourselves to the instance
1379 * as an observer in case it goes away, and determine which object types have
1380 * been registered and synthesize the observer callbacks for them. Once done
1381 * we force a reload so we are aware of the state of things.
1382 */
1383 if (ast_sip_get_sorcery()) {
1384 int i;
1385
1388
1389 /* See which object types already exist */
1390 for (i = 0; i < ARRAY_LEN(object_types); ++i) {
1391 if (!object_types[i]) {
1392 break;
1393 } else if (!ast_sorcery_get_object_type(ast_sip_get_sorcery(), object_types[i])) {
1394 continue;
1395 }
1396
1398 object_types[i]);
1399 }
1400
1402 }
1403
1405}
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition cli.h:265
@ AST_MODULE_LOAD_SUCCESS
Definition module.h:70
static struct stasis_subscription * acl_change_sub
static const struct ast_sorcery_global_observer global_observer
static void object_type_registered_observer(const char *name, struct ast_sorcery *sorcery, const char *object_type)
When each object type is registered, map a memory wizard to it.
static struct ast_cli_entry config_wizard_cli[]
static void acl_change_stasis_cb(void *data, struct stasis_subscription *sub, struct stasis_message *message)
Callback for Named ACL changed.
struct stasis_topic * ast_security_topic(void)
A stasis_topic which publishes messages for security related issues.
struct ast_sorcery_object_type * ast_sorcery_get_object_type(const struct ast_sorcery *sorcery, const char *type)
Get the sorcery object type given a type name.
Definition sorcery.c:2558
void ast_sorcery_reload(const struct ast_sorcery *sorcery)
Inform any wizards to reload persistent objects.
Definition sorcery.c:1472
int ast_sorcery_global_observer_add(const struct ast_sorcery_global_observer *callbacks)
Add a global observer to sorcery.
Definition sorcery.c:562
#define stasis_subscribe(topic, callback, data)
Definition stasis.h:649
#define ARRAY_LEN(a)
Definition utils.h:706
#define AST_VECTOR_RW_INIT(vec, size)
Initialize a vector with a read/write lock.
Definition vector.h:169

References acl_change_stasis_cb(), acl_change_sub, ARRAY_LEN, ast_cli_register_multiple, AST_MODULE_LOAD_SUCCESS, ast_module_ref, ast_security_topic(), ast_sip_get_sorcery(), ast_sorcery_get_object_type(), ast_sorcery_global_observer_add(), ast_sorcery_instance_observer_add(), ast_sorcery_reload(), AST_VECTOR_RW_INIT, config_wizard_cli, global_observer, NULL, object_type_registered_observer(), observer, ast_module_info::self, and stasis_subscribe.

◆ object_type_loaded_observer()

static void object_type_loaded_observer ( const char *  name,
const struct ast_sorcery sorcery,
const char *  object_type,
int  reloaded 
)
static

Called after an object type is loaded/reloaded.

Definition at line 1076 of file res_pjsip_config_wizard.c.

1078{
1079 struct ast_category *category = NULL;
1080 struct object_type_wizard *otw = NULL;
1081 char *filename = "pjsip_wizard.conf";
1082 struct ast_flags flags = { 0 };
1083 struct ast_config *cfg;
1085
1086 if (!strstr("auth aor endpoint identify registration phoneprov", object_type)) {
1087 /* Not interested. */
1088 return;
1089 }
1090
1091 otw = find_wizard(object_type);
1092 if (!otw) {
1093 ast_log(LOG_ERROR, "There was no wizard for object type '%s'\n", object_type);
1094 return;
1095 }
1096
1097 /* Only use the FILEUNCHANGED optimization if the ACLs haven't changed.
1098 * If ACLs changed, we force a reload of the config file to re-evaluate rules. */
1099 if (reloaded && otw->last_config && !IS_ACL_RELOAD_ACTIVE()) {
1101 }
1102
1103 cfg = ast_config_load2(filename, object_type, flags);
1104
1105 if (!cfg) {
1106 ast_log(LOG_ERROR, "Unable to load config file '%s'\n", filename);
1107 return;
1108 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
1109 ast_debug(2, "Config file '%s' was unchanged for '%s'.\n", filename, object_type);
1110 return;
1111 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
1112 ast_log(LOG_ERROR, "Contents of config file '%s' are invalid and cannot be parsed\n", filename);
1113 return;
1114 }
1115
1116 while ((category = ast_category_browse_filtered(cfg, NULL, category, "type=^wizard$"))) {
1117 const char *id = ast_category_get_name(category);
1118 struct ast_category *last_cat = NULL;
1119 int changes = 0;
1120
1121 if (otw->last_config) {
1122 last_cat = ast_category_get(otw->last_config, id, "type=^wizard$");
1123 changes = !ast_variable_lists_match(ast_category_first(category), ast_category_first(last_cat), 1);
1124
1125 /* If the ACL has changed, we assume EVERYTHING might have changed.
1126 * We force an update for all wizard objects. */
1127 if (!changes && reloaded && IS_ACL_RELOAD_ACTIVE()) {
1128 ast_debug(3, "Forcing update of wizard '%s' due to global ACL change.\n", id);
1129 changes = 1;
1130 }
1131
1132 if (last_cat) {
1133 ast_category_delete(otw->last_config, last_cat);
1134 }
1135 }
1136
1137 if (!last_cat || changes) {
1138 ast_debug(3, "%s: %s(s) for wizard '%s'\n", reloaded ? "Reload" : "Load", object_type, id);
1139 if (wizard_apply_handler(sorcery, otw, category)) {
1140 ast_log(LOG_ERROR, "Unable to create objects for wizard '%s'\n", id);
1141 }
1142 }
1143 }
1144
1145 if (!otw->last_config) {
1146 otw->last_config = cfg;
1147 return;
1148 }
1149
1150 /* Only wizards that weren't in the new config are left in last_config now so we need to delete
1151 * all objects belonging to them.
1152 */
1153 category = NULL;
1154 while ((category = ast_category_browse_filtered(otw->last_config, NULL, category, "type=^wizard$"))) {
1155 const char *id = ast_category_get_name(category);
1156 struct ast_variable *search;
1157 RAII_VAR(struct ao2_container *, existing,
1159
1160 if (!existing) {
1161 ast_log(LOG_ERROR, "Unable to allocate temporary container.\n");
1162 break;
1163 }
1164
1165 search = ast_variable_new("@pjsip_wizard", id, "");
1166 if (!search) {
1167 ast_log(LOG_ERROR, "Unable to allocate memory for vaiable '@pjsip_wizard'.\n");
1168 break;
1169 }
1170 otw->wizard->retrieve_multiple(sorcery, otw->wizard_data, object_type, existing, search);
1171 ast_variables_destroy(search);
1172
1173 if (ao2_container_count(existing) > 0) {
1174 ast_debug(3, "Delete on %s: %d %s(s) for wizard: %s\n",
1175 reloaded ? "Reload" : "Load", ao2_container_count(existing), object_type, id);
1177 delete_existing_cb, otw);
1178 }
1179 }
1180
1182 otw->last_config = cfg;
1183}
ast_mutex_t lock
Definition app_sla.c:337
@ CONFIG_FLAG_FILEUNCHANGED
struct ast_config * ast_config_load2(const char *filename, const char *who_asked, struct ast_flags flags)
Load a config file.
struct ast_category * ast_category_delete(struct ast_config *cfg, struct ast_category *cat)
Delete a category.
#define CONFIG_STATUS_FILEUNCHANGED
#define CONFIG_STATUS_FILEINVALID
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
Definition extconf.c:1287
int ast_variable_lists_match(const struct ast_variable *left, const struct ast_variable *right, int exact_match)
Tests 2 variable lists to see if they match.
struct ast_category * ast_category_get(const struct ast_config *config, const char *category_name, const char *filter)
Retrieve a category if it exists.
struct ast_category * ast_category_browse_filtered(struct ast_config *config, const char *category_name, struct ast_category *prev, const char *filter)
Browse categories with filters.
#define SCOPED_MUTEX(varname, lock)
scoped lock specialization for mutexes
Definition lock.h:596
static ast_mutex_t config_wizard_observer_lock
static struct object_type_wizard * find_wizard(const char *object_type)
Finds the otw for the object type.
#define IS_ACL_RELOAD_ACTIVE()
static int wizard_apply_handler(const struct ast_sorcery *sorcery, struct object_type_wizard *otw, struct ast_category *wiz)
Structure used to handle boolean flags.
Definition utils.h:220
unsigned int flags
Definition utils.h:221
struct ast_config * last_config

References AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_callback, ao2_cleanup, ao2_container_alloc_list, ao2_container_count(), ast_category_browse_filtered(), ast_category_delete(), ast_category_first(), ast_category_get(), ast_category_get_name(), ast_config_destroy(), ast_config_load2(), ast_debug, ast_log, ast_variable_lists_match(), ast_variable_new, ast_variables_destroy(), CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, config_wizard_observer_lock, delete_existing_cb(), find_wizard(), ast_flags::flags, id, IS_ACL_RELOAD_ACTIVE, object_type_wizard::last_config, lock, LOG_ERROR, NULL, OBJ_MULTIPLE, OBJ_NODATA, OBJ_UNLINK, RAII_VAR, ast_sorcery_wizard::retrieve_multiple, SCOPED_MUTEX, sorcery, object_type_wizard::wizard, wizard_apply_handler(), and object_type_wizard::wizard_data.

◆ object_type_registered_observer()

static void object_type_registered_observer ( const char *  name,
struct ast_sorcery sorcery,
const char *  object_type 
)
static

When each object type is registered, map a memory wizard to it.

Definition at line 1186 of file res_pjsip_config_wizard.c.

1188{
1189 struct ast_sorcery_wizard *wizard;
1190 void *wizard_data;
1191 struct object_type_wizard *otw;
1192
1193 if (is_one_of(object_type, object_types)) {
1197 ast_log(LOG_ERROR, "Unable to apply pjsip_wizard to object type '%s'\n", object_type);
1198 return;
1199 }
1200
1201 otw = ast_malloc(sizeof(*otw) + strlen(object_type) + 1);
1202 if (!otw) {
1203 return;
1204 }
1205
1206 otw->sorcery = sorcery;
1207 otw->wizard = wizard;
1208 otw->wizard_data = wizard_data;
1209 otw->last_config = NULL;
1210 strcpy(otw->object_type, object_type); /* Safe */
1211 AST_VECTOR_RW_WRLOCK(&object_type_wizards);
1212 if (AST_VECTOR_APPEND(&object_type_wizards, otw)) {
1213 ast_free(otw);
1214 } else {
1215 ast_debug(1, "Wizard mapped for object_type '%s'\n", object_type);
1216 }
1217 AST_VECTOR_RW_UNLOCK(&object_type_wizards);
1218
1219 }
1220}
#define ast_malloc(len)
A wrapper for malloc()
Definition astmm.h:191
static int is_one_of(const char *needle, const char *haystack[])
@ AST_SORCERY_WIZARD_APPLY_ALLOW_DUPLICATE
Definition sorcery.h:583
@ AST_SORCERY_WIZARD_APPLY_READONLY
Definition sorcery.h:581
@ AST_SORCERY_APPLY_SUCCESS
Definition sorcery.h:427
#define ast_sorcery_object_type_apply_wizard(sorcery, object_type_name, wizard_type_name, wizard_args, flags, wizard, wizard_data)
Apply additional object wizard mappings returning wizard information.
Definition sorcery.h:678
Interface for a sorcery wizard.
Definition sorcery.h:276
#define AST_VECTOR_RW_WRLOCK(vec)
Obtain write lock on vector.
Definition vector.h:915
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition vector.h:267

References ast_debug, ast_free, ast_log, ast_malloc, AST_SORCERY_APPLY_SUCCESS, ast_sorcery_object_type_apply_wizard, AST_SORCERY_WIZARD_APPLY_ALLOW_DUPLICATE, AST_SORCERY_WIZARD_APPLY_READONLY, AST_VECTOR_APPEND, AST_VECTOR_RW_UNLOCK, AST_VECTOR_RW_WRLOCK, is_one_of(), object_type_wizard::last_config, LOG_ERROR, NULL, object_type_wizard::object_type, sorcery, object_type_wizard::sorcery, object_type_wizard::wizard, and object_type_wizard::wizard_data.

Referenced by load_module().

◆ reload_configuration_task()

static int reload_configuration_task ( void *  obj)
static

Definition at line 1349 of file res_pjsip_config_wizard.c.

1350{
1352 if (sip_sorcery) {
1354 }
1355 return 0;
1356}
static struct ast_sorcery * sip_sorcery

References ast_sip_get_sorcery(), ast_sorcery_reload(), and sip_sorcery.

Referenced by reload_module().

◆ reload_module()

static int reload_module ( void  )
static

Definition at line 1358 of file res_pjsip_config_wizard.c.

1359{
1361 ast_log(LOG_WARNING, "Failed to reload PJSIP\n");
1362 return -1;
1363 }
1364
1365 return 0;
1366}
#define ast_sip_push_task_wait_servant(serializer, sip_task, task_data)
Definition res_pjsip.h:2165
#define LOG_WARNING
static int reload_configuration_task(void *obj)

References ast_log, ast_sip_push_task_wait_servant, LOG_WARNING, NULL, and reload_configuration_task().

Referenced by acl_change_stasis_cb().

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 1407 of file res_pjsip_config_wizard.c.

1408{
1409 if (acl_change_sub) {
1411 }
1412
1416 AST_VECTOR_RW_FREE(&object_type_wizards);
1417
1418 return 0;
1419}
void ast_cli_unregister_multiple(void)
Definition ael_main.c:408
#define NOT_EQUALS(a, b)
#define OTW_DELETE_CB(otw)
void ast_sorcery_global_observer_remove(const struct ast_sorcery_global_observer *callbacks)
Remove a global observer from sorcery.
Definition sorcery.c:578
struct stasis_subscription * stasis_unsubscribe_and_join(struct stasis_subscription *subscription)
Cancel a subscription, blocking until the last message is processed.
Definition stasis.c:1212
#define AST_VECTOR_REMOVE_ALL_CMP_UNORDERED(vec, value, cmp, cleanup)
Remove all elements from a vector that matches the given comparison.
Definition vector.h:489
#define AST_VECTOR_RW_FREE(vec)
Deallocates this locked vector.
Definition vector.h:213

References acl_change_sub, ARRAY_LEN, ast_cli_unregister_multiple(), ast_sorcery_global_observer_remove(), AST_VECTOR_REMOVE_ALL_CMP_UNORDERED, AST_VECTOR_RW_FREE, config_wizard_cli, global_observer, NOT_EQUALS, NULL, OTW_DELETE_CB, and stasis_unsubscribe_and_join().

◆ variable_list_append()

static int variable_list_append ( struct ast_variable **  existing,
const char *  name,
const char *  value 
)
static

Appends a variable to the end of an existing list.

Definition at line 386 of file res_pjsip_config_wizard.c.

387{
388 struct ast_variable *new = ast_variable_new(name, value, "");
389
390 if (!new) {
391 ast_log(LOG_ERROR, "Unable to allocate memory for new variable '%s'.\n", name);
392 return -1;
393 }
394
395 ast_variable_list_append(existing, new);
396
397 return 0;
398}
#define ast_variable_list_append(head, new_var)

References ast_log, ast_variable_list_append, ast_variable_new, LOG_ERROR, name, and value.

Referenced by get_object_variables(), and handle_aor().

◆ wizard_apply_handler()

static int wizard_apply_handler ( const struct ast_sorcery sorcery,
struct object_type_wizard otw,
struct ast_category wiz 
)
static

Definition at line 1008 of file res_pjsip_config_wizard.c.

1010{
1011 struct ast_variable *wizvars = ast_category_first(wiz);
1012 struct string_vector remote_hosts_vector;
1013 const char *remote_hosts;
1014 int rc = -1;
1015
1016 AST_VECTOR_INIT(&remote_hosts_vector, 16);
1017 remote_hosts = ast_variable_find_last_in_list(wizvars, "remote_hosts");
1018
1019 if (!ast_strlen_zero(remote_hosts)) {
1020 char *host;
1021 char *hosts = ast_strdupa(remote_hosts);
1022
1023 while ((host = ast_strsep(&hosts, ',', AST_STRSEP_TRIM))) {
1024 host = ast_strdup(host);
1025 if (host && AST_VECTOR_APPEND(&remote_hosts_vector, host)) {
1026 ast_free(host);
1027 }
1028 }
1029 }
1030
1031 ast_debug(4, "%s handler starting.\n", otw->object_type);
1032
1033 if (!strcmp(otw->object_type, "auth")) {
1034 rc = handle_auths(sorcery, otw, wiz);
1035 } else if (!strcmp(otw->object_type, "aor")) {
1036 rc = handle_aor(sorcery, otw, wiz, &remote_hosts_vector);
1037 } else if (!strcmp(otw->object_type, "endpoint")) {
1038 rc = handle_endpoint(sorcery, otw, wiz);
1039 } else if (!strcmp(otw->object_type, "identify")) {
1040 rc = handle_identify(sorcery, otw, wiz, &remote_hosts_vector);
1041 } else if (!strcmp(otw->object_type, "phoneprov")) {
1042 rc = handle_phoneprov(sorcery, otw, wiz);
1043 } else if (!strcmp(otw->object_type, "registration")) {
1044 rc = handle_registrations(sorcery, otw, wiz, &remote_hosts_vector);
1045 }
1046
1048 AST_VECTOR_FREE(&remote_hosts_vector);
1049
1050 ast_debug(4, "%s handler complete. rc: %d\n", otw->object_type, rc);
1051
1052 return rc;
1053}
static int handle_aor(const struct ast_sorcery *sorcery, struct object_type_wizard *otw, struct ast_category *wiz, struct string_vector *remote_hosts_vector)
static int handle_endpoint(const struct ast_sorcery *sorcery, struct object_type_wizard *otw, struct ast_category *wiz)
static int handle_registrations(const struct ast_sorcery *sorcery, struct object_type_wizard *otw, struct ast_category *wiz, struct string_vector *remote_hosts_vector)
static int handle_identify(const struct ast_sorcery *sorcery, struct object_type_wizard *otw, struct ast_category *wiz, struct string_vector *remote_hosts_vector)
static int handle_auths(const struct ast_sorcery *sorcery, struct object_type_wizard *otw, struct ast_category *wiz)
static int handle_phoneprov(const struct ast_sorcery *sorcery, struct object_type_wizard *otw, struct ast_category *wiz)
@ AST_STRSEP_TRIM
Definition strings.h:256
char * ast_strsep(char **s, const char sep, uint32_t flags)
Act like strsep but ignore separators inside quotes.
Definition utils.c:1869
A generic char * vector definition.
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
Definition vector.h:185
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition vector.h:124

References ast_category_first(), ast_debug, ast_free, ast_strdup, ast_strdupa, ast_strlen_zero(), ast_strsep(), AST_STRSEP_TRIM, ast_variable_find_last_in_list(), AST_VECTOR_APPEND, AST_VECTOR_FREE, AST_VECTOR_INIT, AST_VECTOR_REMOVE_ALL_CMP_UNORDERED, handle_aor(), handle_auths(), handle_endpoint(), handle_identify(), handle_phoneprov(), handle_registrations(), NOT_EQUALS, NULL, object_type_wizard::object_type, and sorcery.

Referenced by object_type_loaded_observer().

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "PJSIP Config Wizard" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .reload = reload_module, .unload = unload_module, .load_pri = AST_MODPRI_REALTIME_DRIVER, }
static

Definition at line 1427 of file res_pjsip_config_wizard.c.

◆ acl_change_sub

struct stasis_subscription* acl_change_sub
static

Definition at line 309 of file res_pjsip_config_wizard.c.

Referenced by load_module(), and unload_module().

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 1427 of file res_pjsip_config_wizard.c.

◆ config_wizard_cli

struct ast_cli_entry config_wizard_cli[]
static
Initial value:
= {
{ .handler = handle_export_primitives , .summary = "Export config wizard primitives" ,},
}
static char * handle_export_primitives(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)

Definition at line 1341 of file res_pjsip_config_wizard.c.

1341 {
1342 AST_CLI_DEFINE(handle_export_primitives, "Export config wizard primitives"),
1343};
#define AST_CLI_DEFINE(fn, txt,...)
Definition cli.h:197

Referenced by load_module(), and unload_module().

◆ config_wizard_observer_lock

ast_mutex_t config_wizard_observer_lock = AST_MUTEX_INIT_VALUE
static

Definition at line 310 of file res_pjsip_config_wizard.c.

Referenced by object_type_loaded_observer().

◆ global_observer

const struct ast_sorcery_global_observer global_observer
static
Initial value:
= {
.instance_created = instance_created_observer,
.instance_destroying = instance_destroying_observer,
}
static void instance_destroying_observer(const char *name, struct ast_sorcery *sorcery)
When the res_pjsip instance is destroyed, remove the observer and unref the module....
static void instance_created_observer(const char *name, struct ast_sorcery *sorcery)
When the res_pjsip instance is created, add an observer to it and initialize the wizard vector....

Definition at line 1065 of file res_pjsip_config_wizard.c.

1065 {
1066 .instance_created = instance_created_observer,
1067 .instance_destroying = instance_destroying_observer,
1068};

Referenced by load_module(), and unload_module().

◆ named_acl_reload_count

int named_acl_reload_count = 0
static

Definition at line 308 of file res_pjsip_config_wizard.c.

Referenced by acl_change_stasis_cb().

◆ observer

Initial value:
= {
.object_type_registered = object_type_registered_observer,
.object_type_loaded = object_type_loaded_observer,
}
static void object_type_loaded_observer(const char *name, const struct ast_sorcery *sorcery, const char *object_type, int reloaded)
Called after an object type is loaded/reloaded.

Definition at line 1070 of file res_pjsip_config_wizard.c.

1070 {
1071 .object_type_registered = object_type_registered_observer,
1072 .object_type_loaded = object_type_loaded_observer,
1073};

Referenced by ast_mwi_add_observer(), ast_mwi_remove_observer(), ast_sorcery_observer_add(), instance_created_observer(), instance_destroying_observer(), load_module(), sorcery_generic_observer_remove(), sorcery_observer_notify_create(), sorcery_observer_notify_delete(), sorcery_observer_notify_loaded(), sorcery_observer_notify_update(), sorcery_observer_remove(), stasis_state_add_observer(), and stasis_state_remove_observer().