Asterisk - The Open Source Telephony Project GIT-master-f3e88d3
Data Structures | Macros | Functions | Variables
pbx.c File Reference

Core PBX routines. More...

#include "asterisk.h"
#include "asterisk/_private.h"
#include "asterisk/paths.h"
#include <ctype.h>
#include <time.h>
#include <sys/time.h>
#include <sys/sysinfo.h>
#include "asterisk/lock.h"
#include "asterisk/cli.h"
#include "asterisk/pbx.h"
#include "asterisk/channel.h"
#include "asterisk/file.h"
#include "asterisk/callerid.h"
#include "asterisk/cdr.h"
#include "asterisk/config.h"
#include "asterisk/term.h"
#include "asterisk/manager.h"
#include "asterisk/ast_expr.h"
#include "asterisk/linkedlists.h"
#include "asterisk/say.h"
#include "asterisk/utils.h"
#include "asterisk/causes.h"
#include "asterisk/musiconhold.h"
#include "asterisk/app.h"
#include "asterisk/devicestate.h"
#include "asterisk/presencestate.h"
#include "asterisk/hashtab.h"
#include "asterisk/module.h"
#include "asterisk/indications.h"
#include "asterisk/taskprocessor.h"
#include "asterisk/xmldoc.h"
#include "asterisk/astobj2.h"
#include "asterisk/stasis_channels.h"
#include "asterisk/dial.h"
#include "asterisk/vector.h"
#include "pbx_private.h"
Include dependency graph for pbx.c:

Go to the source code of this file.

Data Structures

struct  ast_autohint
 Structure for dial plan autohints. More...
 
struct  ast_context
 ast_context: An extension context More...
 
struct  ast_exten
 ast_exten: An extension The dialplan is saved as a linked list with each context having it's own linked list of extensions - one item per priority. More...
 
struct  ast_hint
 Structure for dial plan hints. More...
 
struct  ast_hintdevice
 Structure for dial plan hint devices. More...
 
struct  ast_state_cb
 ast_state_cb: An extension state notify register item More...
 
struct  cfextension_states
 
struct  dialplan_counters
 Counters for the show dialplan manager command. More...
 
struct  match_char
 match_char: forms a syntax tree for quick matching of extension patterns More...
 
struct  pattern_node
 
struct  pbx_exception
 
struct  pbx_outgoing
 Structure which contains information about an outgoing dial. More...
 
struct  scoreboard
 
struct  store_hint
 
struct  store_hints
 

Macros

#define ADVANCE(s)   candidate_exten_advance(s)
 
#define BITS_PER   8 /* Number of bits per unit (byte). */
 
#define EXT_DATA_SIZE   8192
 
#define HASH_EXTENHINT_SIZE   563
 
#define HINTDEVICE_DATA_LENGTH   16
 
#define INC_DST_OVERFLOW_CHECK
 
#define MAX_EXTENBUF_SIZE   512
 
#define MORE(s)   (*candidate_exten_advance(s))
 
#define NEW_MATCHER_CHK_MATCH
 
#define NEW_MATCHER_RECURSE
 
#define SAY_STUBS   /* generate declarations and stubs for say methods */
 
#define STATUS_NO_CONTEXT   1
 
#define STATUS_NO_EXTENSION   2
 
#define STATUS_NO_LABEL   4
 
#define STATUS_NO_PRIORITY   3
 
#define STATUS_SUCCESS   5
 
#define SWITCH_DATA_LENGTH   256
 
#define VAR_HARDTRAN   3
 
#define VAR_NORMAL   1
 
#define VAR_SOFTTRAN   2
 

Functions

void __ast_context_destroy (struct ast_context *list, struct ast_hashtab *contexttab, struct ast_context *con, const char *registrar)
 
static int __ast_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority, int async)
 
static void __ast_internal_context_destroy (struct ast_context *con)
 
static enum ast_pbx_result __ast_pbx_run (struct ast_channel *c, struct ast_pbx_args *args)
 
static void __init_extensionstate_buf (void)
 
static void __init_hintdevice_data (void)
 
static void __init_switch_data (void)
 
static int _extension_match_core (const char *pattern, const char *data, enum ext_match_t mode)
 
static int acf_exception_read (struct ast_channel *chan, const char *name, char *data, char *buf, size_t buflen)
 
static int action_extensionstatelist (struct mansession *s, const struct message *m)
 
static struct match_charadd_exten_to_pattern_tree (struct ast_context *con, struct ast_exten *e1, int findonly)
 
static int add_hintdevice (struct ast_hint *hint, const char *devicelist)
 add hintdevice structure and link it into the container. More...
 
static struct match_charadd_pattern_node (struct ast_context *con, struct match_char *current, const struct pattern_node *pattern, int is_pattern, int already, struct match_char **nextcharptr)
 
static int add_priority (struct ast_context *con, struct ast_exten *tmp, struct ast_exten *el, struct ast_exten *e, int replace)
 add the extension in the priority chain. More...
 
static struct ao2_containeralloc_device_state_info (void)
 
static struct match_charalready_in_tree (struct match_char *current, char *pat, int is_pattern)
 
int ast_active_calls (void)
 Retrieve the number of active calls. More...
 
int ast_add_extension (const char *context, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar)
 Add and extension to an extension context. More...
 
int ast_add_extension2 (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)
 Main interface to add extensions to the list for out context. More...
 
static int ast_add_extension2_lockopt (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, int lock_context)
 Same as ast_add_extension2() but controls the context locking. More...
 
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. More...
 
static int ast_add_extension_nolock (const char *context, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar)
 
static int ast_add_hint (struct ast_exten *e)
 Add hint to hint list, check initial extension state. More...
 
int ast_async_goto (struct ast_channel *chan, const char *context, const char *exten, int priority)
 Set the channel to next execute the specified dialplan location. More...
 
int ast_async_goto_by_name (const char *channame, const char *context, const char *exten, int priority)
 Set the channel to next execute the specified dialplan location. More...
 
int ast_async_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority)
 
int ast_async_parseable_goto (struct ast_channel *chan, const char *goto_string)
 
int ast_canmatch_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
 Looks for a valid matching extension. More...
 
static int ast_change_hint (struct ast_exten *oe, struct ast_exten *ne)
 Change hint for an extension. More...
 
int ast_context_add_ignorepat (const char *context, const char *value, const char *registrar)
 Add an ignorepat. More...
 
int ast_context_add_ignorepat2 (struct ast_context *con, const char *value, const char *registrar)
 
int ast_context_add_include (const char *context, const char *include, const char *registrar)
 Add a context include. More...
 
int ast_context_add_include2 (struct ast_context *con, const char *value, const char *registrar)
 Add a context include. More...
 
int ast_context_add_switch (const char *context, const char *sw, const char *data, int eval, const char *registrar)
 Add a switch. More...
 
int ast_context_add_switch2 (struct ast_context *con, const char *value, const char *data, int eval, const char *registrar)
 Adds a switch (first param is a ast_context) More...
 
void ast_context_destroy (struct ast_context *con, const char *registrar)
 Destroy a context (matches the specified context or ANY context if NULL) More...
 
int ast_context_destroy_by_name (const char *context, const char *registrar)
 Destroy a context by name. More...
 
struct ast_contextast_context_find (const char *name)
 Find a context. More...
 
struct ast_contextast_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. More...
 
int ast_context_ignorepats_count (const struct ast_context *con)
 
const struct ast_ignorepatast_context_ignorepats_get (const struct ast_context *con, int idx)
 
int ast_context_includes_count (const struct ast_context *con)
 
const struct ast_includeast_context_includes_get (const struct ast_context *con, int idx)
 
int ast_context_remove_extension (const char *context, const char *extension, int priority, const char *registrar)
 Simply remove extension from context. More...
 
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 extensions with given priority. If priority is set to 0, all peers are removed. After that, unlock context and return. More...
 
int ast_context_remove_extension_callerid (const char *context, const char *extension, int priority, const char *callerid, int matchcallerid, const char *registrar)
 
int ast_context_remove_extension_callerid2 (struct ast_context *con, const char *extension, int priority, const char *callerid, int matchcallerid, const char *registrar, int already_locked)
 
int ast_context_remove_ignorepat (const char *context, const char *ignorepat, const char *registrar)
 Remove an ignorepat. More...
 
int ast_context_remove_ignorepat2 (struct ast_context *con, const char *ignorepat, const char *registrar)
 
int ast_context_remove_include (const char *context, const char *include, const char *registrar)
 Remove included contexts. This function locks contexts list by &conlist, search for the right context structure, leave context list locked and call ast_context_remove_include2 which removes include, unlock contexts list and return ... More...
 
int ast_context_remove_include2 (struct ast_context *con, const char *include, const char *registrar)
 Locks context, remove included contexts, unlocks context. When we call this function, &conlock lock must be locked, because when we giving *con argument, some process can remove/change this context and after that there can be segfault. More...
 
int ast_context_remove_switch (const char *context, const char *sw, const char *data, const char *registrar)
 Remove a switch. More...
 
int ast_context_remove_switch2 (struct ast_context *con, const char *sw, const char *data, const char *registrar)
 This function locks given context, removes switch, unlock context and return. More...
 
void ast_context_set_autohints (struct ast_context *con, int enabled)
 Enable or disable autohints support on a context. More...
 
int ast_context_switches_count (const struct ast_context *con)
 
const struct ast_swast_context_switches_get (const struct ast_context *con, int idx)
 
int ast_context_verify_includes (struct ast_context *con)
 Verifies includes in an ast_contect structure. More...
 
enum ast_extension_states ast_devstate_to_extenstate (enum ast_device_state devstate)
 Map devstate to an extension state. More...
 
int ast_exists_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
 Determine whether an extension exists. More...
 
int ast_explicit_goto (struct ast_channel *chan, const char *context, const char *exten, int priority)
 
int ast_extension_close (const char *pattern, const char *data, int needmore)
 
int ast_extension_cmp (const char *a, const char *b)
 Determine if one extension should match before another. More...
 
int ast_extension_match (const char *pattern, const char *extension)
 Determine if a given extension matches a given pattern (in NXX format) More...
 
int ast_extension_state (struct ast_channel *c, const char *context, const char *exten)
 Check extension state for an extension by using hint. More...
 
static int ast_extension_state2 (struct ast_exten *e, struct ao2_container *device_state_info)
 Check state of extension by using hints. More...
 
const char * ast_extension_state2str (int extension_state)
 Return extension_state as string. More...
 
static int ast_extension_state3 (struct ast_str *hint_app, struct ao2_container *device_state_info)
 
int ast_extension_state_add (const char *context, const char *exten, ast_state_cb_type change_cb, void *data)
 Add watcher for extension states. More...
 
int ast_extension_state_add_destroy (const char *context, const char *exten, ast_state_cb_type change_cb, ast_state_cb_destroy_type destroy_cb, void *data)
 Add watcher for extension states with destructor. More...
 
int ast_extension_state_add_destroy_extended (const char *context, const char *exten, ast_state_cb_type change_cb, ast_state_cb_destroy_type destroy_cb, void *data)
 Add watcher for extended extension states with destructor. More...
 
int ast_extension_state_add_extended (const char *context, const char *exten, ast_state_cb_type change_cb, void *data)
 Add watcher for extended extension states. More...
 
int ast_extension_state_del (int id, ast_state_cb_type change_cb)
 Deletes a state change watcher by ID. More...
 
int ast_extension_state_extended (struct ast_channel *c, const char *context, const char *exten, struct ao2_container **device_state_info)
 Check extended extension state for an extension by using hint. More...
 
int ast_findlabel_extension (struct ast_channel *c, const char *context, const char *exten, const char *label, const char *callerid)
 Find the priority of an extension that has the specified label. More...
 
int ast_findlabel_extension2 (struct ast_channel *c, struct ast_context *con, const char *exten, const char *label, const char *callerid)
 Find the priority of an extension that has the specified label. More...
 
const char * ast_get_context_name (struct ast_context *con)
 
const char * ast_get_context_registrar (struct ast_context *c)
 
const char * ast_get_extension_app (struct ast_exten *e)
 
void * ast_get_extension_app_data (struct ast_exten *e)
 
const char * ast_get_extension_cidmatch (struct ast_exten *e)
 
struct ast_contextast_get_extension_context (struct ast_exten *exten)
 
int ast_get_extension_data (char *buf, int bufsize, struct ast_channel *c, const char *context, const char *exten, int priority)
 Fill a string buffer with the data at a dialplan extension. More...
 
const char * ast_get_extension_label (struct ast_exten *exten)
 
int ast_get_extension_matchcid (struct ast_exten *e)
 
const char * ast_get_extension_name (struct ast_exten *exten)
 
int ast_get_extension_priority (struct ast_exten *exten)
 
const char * ast_get_extension_registrar (struct ast_exten *e)
 
const char * ast_get_extension_registrar_file (struct ast_exten *e)
 Get name of configuration file used by registrar to register this extension. More...
 
int ast_get_extension_registrar_line (struct ast_exten *e)
 Get line number of configuration file used by registrar to register this extension. More...
 
int ast_get_hint (char *hint, int hintsize, char *name, int namesize, struct ast_channel *c, const char *context, const char *exten)
 Get hint for channel. More...
 
int ast_goto_if_exists (struct ast_channel *chan, const char *context, const char *exten, int priority)
 
int ast_hashtab_compare_contexts (const void *ah_a, const void *ah_b)
 hashtable functions for contexts More...
 
unsigned int ast_hashtab_hash_contexts (const void *obj)
 
static struct ast_extenast_hint_extension (struct ast_channel *c, const char *context, const char *exten)
 
static struct ast_extenast_hint_extension_nolock (struct ast_channel *c, const char *context, const char *exten)
 Find hint for given extension in context. More...
 
int ast_hint_presence_state (struct ast_channel *c, const char *context, const char *exten, char **subtype, char **message)
 Uses hint and presence state callback to get the presence state of an extension. More...
 
int ast_ignore_pattern (const char *context, const char *pattern)
 Checks to see if a number should be ignored. More...
 
int ast_matchmore_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
 Looks to see if adding anything to this extension might match something. (exists ^ canmatch) More...
 
void ast_merge_contexts_and_delete (struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *registrar)
 Merge the temporary contexts into a global contexts list and delete from the global list the ones that are being added. More...
 
int ast_parseable_goto (struct ast_channel *chan, const char *goto_string)
 
void ast_pbx_h_exten_run (struct ast_channel *chan, const char *context)
 Run the h exten from the given context. More...
 
int ast_pbx_init (void)
 
int ast_pbx_outgoing_app (const char *type, struct ast_format_cap *cap, const char *addr, int timeout, const char *app, const char *appdata, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel, const struct ast_assigned_ids *assignedids)
 Synchronously or asynchronously make an outbound call and execute an application on the channel. More...
 
int ast_pbx_outgoing_app_predial (const char *type, struct ast_format_cap *cap, const char *addr, int timeout, const char *app, const char *appdata, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel, const struct ast_assigned_ids *assignedids, const char *predial_callee)
 
int ast_pbx_outgoing_exten (const char *type, struct ast_format_cap *cap, const char *addr, int timeout, const char *context, const char *exten, int priority, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel, int early_media, const struct ast_assigned_ids *assignedids)
 Synchronously or asynchronously make an outbound call and send it to a particular extension. More...
 
int ast_pbx_outgoing_exten_predial (const char *type, struct ast_format_cap *cap, const char *addr, int timeout, const char *context, const char *exten, int priority, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel, int early_media, const struct ast_assigned_ids *assignedids, const char *predial_callee)
 
enum ast_pbx_result ast_pbx_run (struct ast_channel *c)
 Execute the PBX in the current thread. More...
 
enum ast_pbx_result ast_pbx_run_args (struct ast_channel *c, struct ast_pbx_args *args)
 Execute the PBX in the current thread. More...
 
enum ast_pbx_result ast_pbx_start (struct ast_channel *c)
 Create a new thread and start the PBX. More...
 
int ast_processed_calls (void)
 Retrieve the total number of calls processed through the PBX since last restart. More...
 
int ast_rdlock_context (struct ast_context *con)
 Read locks a given context. More...
 
int ast_rdlock_contexts (void)
 Read locks the context list. More...
 
static int ast_remove_hint (struct ast_exten *e)
 Remove hint from extension. More...
 
int ast_spawn_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid, int *found, int combined_find_spawn)
 Launch a new extension (i.e. new stack) More...
 
int ast_str_get_hint (struct ast_str **hint, ssize_t hintsize, struct ast_str **name, ssize_t namesize, struct ast_channel *c, const char *context, const char *exten)
 Get hint for channel. More...
 
int ast_unlock_context (struct ast_context *con)
 
int ast_unlock_contexts (void)
 Unlocks contexts. More...
 
struct ast_extenast_walk_context_extensions (struct ast_context *con, struct ast_exten *exten)
 
const struct ast_ignorepatast_walk_context_ignorepats (const struct ast_context *con, const struct ast_ignorepat *ip)
 
const struct ast_includeast_walk_context_includes (const struct ast_context *con, const struct ast_include *inc)
 
const struct ast_swast_walk_context_switches (const struct ast_context *con, const struct ast_sw *sw)
 
struct ast_contextast_walk_contexts (struct ast_context *con)
 
struct ast_extenast_walk_extension_priorities (struct ast_exten *exten, struct ast_exten *priority)
 
int ast_wrlock_context (struct ast_context *con)
 Write locks a given context. More...
 
int ast_wrlock_contexts (void)
 Write locks the context list. More...
 
static int autohint_cmp (void *obj, void *arg, int flags)
 
static int autohint_hash_cb (const void *obj, const int flags)
 
static const char * candidate_exten_advance (const char *str)
 
static void cli_match_char_tree (struct match_char *node, char *prefix, int fd)
 
static int collect_digits (struct ast_channel *c, int waittime, char *buf, int buflen, int pos)
 collect digits from the channel into the buffer. More...
 
static int compare_char (const void *a, const void *b)
 
static char * complete_core_show_hint (const char *line, const char *word, int pos, int state)
 autocomplete for CLI command 'core show hint' More...
 
static char * complete_show_dialplan_context (const char *line, const char *word, int pos, int state)
 
static void context_merge (struct ast_context **extcontexts, struct ast_hashtab *exttable, struct ast_context *context, const char *registrar)
 
static void context_merge_incls_swits_igps_other_registrars (struct ast_context *new, struct ast_context *old, const char *registrar)
 
static void context_table_create_autohints (struct ast_hashtab *table)
 
static void create_match_char_tree (struct ast_context *con)
 
static void decrease_call_count (void)
 
static void destroy_exten (struct ast_exten *e)
 
static void destroy_hint (void *obj)
 
static void destroy_pattern_tree (struct match_char *pattern_tree)
 
static void destroy_state_cb (void *doomed)
 
static void device_state_cb (void *unused, struct stasis_subscription *sub, struct stasis_message *msg)
 
static void device_state_info_dt (void *obj)
 
static void device_state_notify_callbacks (struct ast_hint *hint, struct ast_str **hint_app)
 
static void exception_store_free (void *data)
 
static int execute_state_callback (ast_state_cb_type cb, const char *context, const char *exten, void *data, enum ast_state_cb_update_reason reason, struct ast_hint *hint, struct ao2_container *device_state_info)
 
static int ext_cmp (const char *left, const char *right)
 
static int ext_cmp_exten (const char *left, const char *right)
 
static int ext_cmp_exten_partial (const char *left, const char *right)
 
static int ext_cmp_exten_strlen (const char *str)
 
static int ext_cmp_pattern (const char *left, const char *right)
 
static int ext_cmp_pattern_pos (const char **p, unsigned char *bitwise)
 helper functions to sort extension patterns in the desired way, so that more specific patterns appear first. More...
 
static int ext_fluff_count (const char *exten)
 
static unsigned int ext_strncpy (char *dst, const char *src, size_t dst_size, int nofluff)
 
static int extension_match_core (const char *pattern, const char *data, enum ext_match_t mode)
 
static int extension_presence_state_helper (struct ast_exten *e, char **subtype, char **message)
 
static int extension_state_add_destroy (const char *context, const char *exten, ast_state_cb_type change_cb, ast_state_cb_destroy_type destroy_cb, void *data, int extended)
 
static struct ast_contextfind_context (const char *context)
 lookup for a context with a given name, More...
 
static struct ast_contextfind_context_locked (const char *context)
 lookup for a context with a given name, More...
 
static int find_hint_by_cb_id (void *obj, void *arg, int flags)
 Find Hint by callback id. More...
 
static struct ast_extenget_canmatch_exten (struct match_char *node)
 
static void get_device_state_causing_channels (struct ao2_container *c)
 
static const char * get_pattern_node (struct pattern_node *node, const char *src, int pattern, const char *extenbuf)
 
static char * handle_debug_dialplan (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 Send ack once. More...
 
static int handle_hint_change_message_type (struct stasis_message *msg, enum ast_state_cb_update_reason reason)
 
static char * handle_set_extenpatternmatchnew (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_show_dialplan (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_show_hint (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 handle_show_hint: CLI support for listing registered dial plan hint More...
 
static char * handle_show_hints (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 handle_show_hints: CLI support for listing registered dial plan hints More...
 
static char * handle_unset_extenpatternmatchnew (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static int hashtab_compare_exten_labels (const void *ah_a, const void *ah_b)
 
static int hashtab_compare_exten_numbers (const void *ah_a, const void *ah_b)
 
static int hashtab_compare_extens (const void *ha_a, const void *ah_b)
 
static unsigned int hashtab_hash_extens (const void *obj)
 
static unsigned int hashtab_hash_labels (const void *obj)
 
static unsigned int hashtab_hash_priority (const void *obj)
 
static int hint_cmp (void *obj, void *arg, int flags)
 
static int hint_hash (const void *obj, const int flags)
 
static int hint_id_cmp (void *obj, void *arg, int flags)
 
static int hintdevice_cmp_multiple (void *obj, void *arg, int flags)
 
static void hintdevice_destroy (void *obj)
 
static int hintdevice_hash_cb (const void *obj, const int flags)
 
static int hintdevice_remove_cb (void *obj, void *arg, void *data, int flags)
 
static int increase_call_count (const struct ast_channel *c)
 Increase call count for channel. More...
 
static void insert_in_next_chars_alt_char_list (struct match_char **parent_ptr, struct match_char *node)
 
static int internal_extension_state_extended (struct ast_channel *c, const char *context, const char *exten, struct ao2_container *device_state_info)
 
int load_pbx (void)
 
static void manager_dpsendack (struct mansession *s, const struct message *m)
 Send ack once. More...
 
static int manager_show_dialplan (struct mansession *s, const struct message *m)
 Manager listing of dial plan. More...
 
static int manager_show_dialplan_helper (struct mansession *s, const struct message *m, const char *actionidtext, const char *context, const char *exten, struct dialplan_counters *dpc, const struct ast_include *rinclude, int includecount, const char *includes[])
 Show dialplan extensions XXX this function is similar but not exactly the same as the CLI's show dialplan. Must check whether the difference is intentional or not. More...
 
static int matchcid (const char *cidpattern, const char *callerid)
 
static void new_find_extension (const char *str, struct scoreboard *score, struct match_char *tree, int length, int spec, const char *callerid, const char *label, enum ext_match_t action)
 
static char * parse_hint_device (struct ast_str *hint_args)
 
static char * parse_hint_presence (struct ast_str *hint_args)
 
int pbx_checkcondition (const char *condition)
 Evaluate a condition. More...
 
static void pbx_destroy (struct ast_pbx *p)
 
static enum ast_control_frame_type pbx_dial_reason (enum ast_dial_result dial_result, int cause)
 Attempt to convert disconnect cause to old originate reason. More...
 
static int pbx_extension_helper (struct ast_channel *c, struct ast_context *con, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action, int *found, int combined_find_spawn)
 The return value depends on the action: More...
 
struct ast_extenpbx_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)
 
static int pbx_outgoing_attempt (const char *type, struct ast_format_cap *cap, const char *addr, int timeout, const char *context, const char *exten, int priority, const char *app, const char *appdata, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel, int early_media, const struct ast_assigned_ids *assignedids, const char *predial_callee)
 
static void pbx_outgoing_destroy (void *obj)
 Destructor for outgoing structure. More...
 
static void * pbx_outgoing_exec (void *data)
 Internal function which dials an outgoing leg and sends it to a provided extension or application. More...
 
static void pbx_outgoing_state_callback (struct ast_dial *dial)
 Internal dialing state callback which causes early media to trigger an answer. More...
 
int pbx_parse_location (struct ast_channel *chan, char **contextp, char **extenp, char **prip, int *ipri, int *mode, char *rest)
 Parses a dialplan location into context, extension, priority. More...
 
static int pbx_parseable_goto (struct ast_channel *chan, const char *goto_string, int async)
 
int pbx_set_autofallthrough (int newval)
 
int pbx_set_extenpatternmatchnew (int newval)
 
void pbx_set_overrideswitch (const char *newval)
 
static void pbx_shutdown (void)
 
static void * pbx_thread (void *data)
 
static void presence_state_cb (void *unused, struct stasis_subscription *sub, struct stasis_message *msg)
 
static void presence_state_notify_callbacks (struct ast_hint *hint, struct ast_str **hint_app, struct ast_presence_state_message *presence_state)
 
static void print_autohint_key (void *v_obj, void *where, ao2_prnt_fn *prnt)
 
static void print_ext (struct ast_exten *e, char *buf, int buflen)
 helper function to print an extension More...
 
static void print_hintdevices_key (void *v_obj, void *where, ao2_prnt_fn *prnt)
 
static void print_hints_key (void *v_obj, void *where, ao2_prnt_fn *prnt)
 
static void print_statecbs_key (void *v_obj, void *where, ao2_prnt_fn *prnt)
 
static int publish_hint_change (struct ast_hint *hint, struct ast_exten *ne)
 Publish a hint changed event
More...
 
static int publish_hint_remove (struct ast_hint *hint)
 Publish a hint removed event
More...
 
int raise_exception (struct ast_channel *chan, const char *reason, int priority)
 
static int remove_hintdevice (struct ast_hint *hint)
 
void set_ext_pri (struct ast_channel *c, const char *exten, int pri)
 
static int show_debug_helper (int fd, const char *context, const char *exten, struct dialplan_counters *dpc, struct ast_include *rinclude, int includecount, const char *includes[])
 
static int show_dialplan_helper (int fd, const char *context, const char *exten, struct dialplan_counters *dpc, const struct ast_include *rinclude, int includecount, const char *includes[])
 
static void show_dialplan_helper_extension_output (int fd, char *buf1, char *buf2, struct ast_exten *exten)
 Writes CLI output of a single extension for show dialplan. More...
 
 STASIS_MESSAGE_TYPE_DEFN_LOCAL (hint_change_message_type)
 
 STASIS_MESSAGE_TYPE_DEFN_LOCAL (hint_remove_message_type)
 
static int statecbs_cmp (void *obj, void *arg, int flags)
 
static int testtime_write (struct ast_channel *chan, const char *cmd, char *var, const char *value)
 
static struct ast_extentrie_find_next_match (struct match_char *node)
 
static void unload_pbx (void)
 
void unreference_cached_app (struct ast_app *app)
 
static void update_scoreboard (struct scoreboard *board, int length, int spec, struct ast_exten *exten, char last, const char *callerid, int deleted, struct match_char *node)
 
void wait_for_hangup (struct ast_channel *chan, const void *data)
 

Variables

static int autofallthrough = 1
 
static struct ao2_containerautohints
 Container for autohint contexts. More...
 
static ast_mutex_t conlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
 Lock for the ast_context list. More...
 
static ast_mutex_t context_merge_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
 Lock to hold off restructuring of hints by ast_merge_contexts_and_delete. More...
 
static struct ast_contextcontexts
 
static struct ast_hashtabcontexts_table = NULL
 
static int countcalls
 
static struct stasis_subscriptiondevice_state_sub
 Subscription for device state change events. More...
 
static struct ast_custom_function exception_function
 
static const struct ast_datastore_info exception_store_info
 
static int extenpatternmatchnew = 0
 
static const struct cfextension_states extension_states []
 
static struct ast_threadstorage extensionstate_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_extensionstate_buf , .custom_init = NULL , }
 
static struct ast_threadstorage hintdevice_data = { .once = PTHREAD_ONCE_INIT , .key_init = __init_hintdevice_data , .custom_init = NULL , }
 
static struct ao2_containerhintdevices
 Container for hint devices. More...
 
static struct ao2_containerhints
 
static ast_mutex_t maxcalllock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
 
static char * overrideswitch = NULL
 
static struct ast_cli_entry pbx_cli []
 
static struct stasis_subscriptionpresence_state_sub
 Subscription for presence state change events. More...
 
static struct ao2_containerstatecbs
 
static int stateid = 1
 
static struct ast_threadstorage switch_data = { .once = PTHREAD_ONCE_INIT , .key_init = __init_switch_data , .custom_init = NULL , }
 
static struct ast_custom_function testtime_function
 
static int totalcalls
 

Detailed Description

Core PBX routines.

Author
Mark Spencer marks.nosp@m.ter@.nosp@m.digiu.nosp@m.m.co.nosp@m.m

Definition in file pbx.c.

Macro Definition Documentation

◆ ADVANCE

#define ADVANCE (   s)    candidate_exten_advance(s)

Definition at line 1234 of file pbx.c.

◆ BITS_PER

#define BITS_PER   8 /* Number of bits per unit (byte). */

◆ EXT_DATA_SIZE

#define EXT_DATA_SIZE   8192
Note
I M P O R T A N T :
The speed of extension handling will likely be among the most important
aspects of this PBX. The switching scheme as it exists right now isn't terribly bad (it's O(N+M), where N is the # of extensions and M is the avg # of priorities, but a constant search time here would be great ;-)

A new algorithm to do searching based on a 'compiled' pattern tree is introduced here, and shows a fairly flat (constant) search time, even for over 10000 patterns.

Also, using a hash table for context/priority name lookup can help prevent the find_extension routines from absorbing exponential cpu cycles as the number of contexts/priorities grow. I've previously tested find_extension with red-black trees, which have O(log2(n)) speed. Right now, I'm using hash tables, which do searches (ideally) in O(1) time. While these techniques do not yield much speed in small dialplans, they are worth the trouble in large dialplans.

Definition at line 216 of file pbx.c.

◆ HASH_EXTENHINT_SIZE

#define HASH_EXTENHINT_SIZE   563

Definition at line 365 of file pbx.c.

◆ HINTDEVICE_DATA_LENGTH

#define HINTDEVICE_DATA_LENGTH   16

Definition at line 358 of file pbx.c.

◆ INC_DST_OVERFLOW_CHECK

#define INC_DST_OVERFLOW_CHECK

◆ MAX_EXTENBUF_SIZE

#define MAX_EXTENBUF_SIZE   512

Definition at line 1662 of file pbx.c.

◆ MORE

#define MORE (   s)    (*candidate_exten_advance(s))

Definition at line 1233 of file pbx.c.

◆ NEW_MATCHER_CHK_MATCH

#define NEW_MATCHER_CHK_MATCH

◆ NEW_MATCHER_RECURSE

#define NEW_MATCHER_RECURSE

◆ SAY_STUBS

#define SAY_STUBS   /* generate declarations and stubs for say methods */

Definition at line 57 of file pbx.c.

◆ STATUS_NO_CONTEXT

#define STATUS_NO_CONTEXT   1

Definition at line 2464 of file pbx.c.

◆ STATUS_NO_EXTENSION

#define STATUS_NO_EXTENSION   2

Definition at line 2465 of file pbx.c.

◆ STATUS_NO_LABEL

#define STATUS_NO_LABEL   4

Definition at line 2467 of file pbx.c.

◆ STATUS_NO_PRIORITY

#define STATUS_NO_PRIORITY   3

Definition at line 2466 of file pbx.c.

◆ STATUS_SUCCESS

#define STATUS_SUCCESS   5

Definition at line 2468 of file pbx.c.

◆ SWITCH_DATA_LENGTH

#define SWITCH_DATA_LENGTH   256

Definition at line 219 of file pbx.c.

◆ VAR_HARDTRAN

#define VAR_HARDTRAN   3

Definition at line 223 of file pbx.c.

◆ VAR_NORMAL

#define VAR_NORMAL   1

Definition at line 221 of file pbx.c.

◆ VAR_SOFTTRAN

#define VAR_SOFTTRAN   2

Definition at line 222 of file pbx.c.

Function Documentation

◆ __ast_context_destroy()

void __ast_context_destroy ( struct ast_context list,
struct ast_hashtab contexttab,
struct ast_context con,
const char *  registrar 
)

Definition at line 8056 of file pbx.c.

8057{
8058 struct ast_context *tmp, *tmpl=NULL;
8059 struct ast_exten *exten_item, *prio_item;
8060
8061 for (tmp = list; tmp; ) {
8062 struct ast_context *next = NULL; /* next starting point */
8063 /* The following code used to skip forward to the next
8064 context with matching registrar, but this didn't
8065 make sense; individual priorities registrar'd to
8066 the matching registrar could occur in any context! */
8067 ast_debug(1, "Investigate ctx %s %s\n", tmp->name, tmp->registrar);
8068 if (con) {
8069 for (; tmp; tmpl = tmp, tmp = tmp->next) { /* skip to the matching context */
8070 ast_debug(1, "check ctx %s %s\n", tmp->name, tmp->registrar);
8071 if ( !strcasecmp(tmp->name, con->name) ) {
8072 break; /* found it */
8073 }
8074 }
8075 }
8076
8077 if (!tmp) /* not found, we are done */
8078 break;
8080
8081 if (registrar) {
8082 /* then search thru and remove any extens that match registrar. */
8083 struct ast_hashtab_iter *exten_iter;
8084 struct ast_hashtab_iter *prio_iter;
8085 int idx;
8086
8087 /* remove any ignorepats whose registrar matches */
8088 for (idx = ast_context_ignorepats_count(tmp) - 1; idx >= 0; idx--) {
8089 struct ast_ignorepat *ip = AST_VECTOR_GET(&tmp->ignorepats, idx);
8090
8091 if (!strcmp(ast_get_ignorepat_registrar(ip), registrar)) {
8092 AST_VECTOR_REMOVE_ORDERED(&tmp->ignorepats, idx);
8093 ignorepat_free(ip);
8094 }
8095 }
8096 /* remove any includes whose registrar matches */
8097 for (idx = ast_context_includes_count(tmp) - 1; idx >= 0; idx--) {
8098 struct ast_include *i = AST_VECTOR_GET(&tmp->includes, idx);
8099
8100 if (!strcmp(ast_get_include_registrar(i), registrar)) {
8101 AST_VECTOR_REMOVE_ORDERED(&tmp->includes, idx);
8102 include_free(i);
8103 }
8104 }
8105 /* remove any switches whose registrar matches */
8106 for (idx = ast_context_switches_count(tmp) - 1; idx >= 0; idx--) {
8107 struct ast_sw *sw = AST_VECTOR_GET(&tmp->alts, idx);
8108
8109 if (!strcmp(ast_get_switch_registrar(sw), registrar)) {
8110 AST_VECTOR_REMOVE_ORDERED(&tmp->alts, idx);
8111 sw_free(sw);
8112 }
8113 }
8114
8115 if (tmp->root_table) { /* it is entirely possible that the context is EMPTY */
8116 exten_iter = ast_hashtab_start_traversal(tmp->root_table);
8117 while ((exten_item=ast_hashtab_next(exten_iter))) {
8118 int end_traversal = 1;
8119
8120 /*
8121 * If the extension could not be removed from the root_table due to
8122 * a loaded PBX app, it can exist here but have its peer_table be
8123 * destroyed due to a previous pass through this function.
8124 */
8125 if (!exten_item->peer_table) {
8126 continue;
8127 }
8128
8129 prio_iter = ast_hashtab_start_traversal(exten_item->peer_table);
8130 while ((prio_item=ast_hashtab_next(prio_iter))) {
8132 char cidmatch[AST_MAX_EXTENSION];
8133 if (!prio_item->registrar || strcmp(prio_item->registrar, registrar) != 0) {
8134 continue;
8135 }
8136 ast_verb(5, "Remove %s/%s/%d, registrar=%s; con=%s(%p); con->root=%p\n",
8137 tmp->name, prio_item->name, prio_item->priority, registrar, con? con->name : "<nil>", con, con? con->root_table: NULL);
8138 ast_copy_string(extension, prio_item->exten, sizeof(extension));
8139 if (prio_item->cidmatch) {
8140 ast_copy_string(cidmatch, prio_item->cidmatch, sizeof(cidmatch));
8141 }
8142 end_traversal &= ast_context_remove_extension_callerid2(tmp, extension, prio_item->priority, cidmatch, prio_item->matchcid, NULL, 1);
8143 }
8144 /* Explanation:
8145 * ast_context_remove_extension_callerid2 will destroy the extension that it comes across. This
8146 * destruction includes destroying the exten's peer_table, which we are currently traversing. If
8147 * ast_context_remove_extension_callerid2 ever should return '0' then this means we have destroyed
8148 * the hashtable which we are traversing, and thus calling ast_hashtab_end_traversal will result
8149 * in reading invalid memory. Thus, if we detect that we destroyed the hashtable, then we will simply
8150 * free the iterator
8151 */
8152 if (end_traversal) {
8153 ast_hashtab_end_traversal(prio_iter);
8154 } else {
8155 ast_free(prio_iter);
8156 }
8157 }
8158 ast_hashtab_end_traversal(exten_iter);
8159 }
8160
8161 /* delete the context if it's registrar matches, is empty, has refcount of 1, */
8162 /* it's not empty, if it has includes, ignorepats, or switches that are registered from
8163 another registrar. It's not empty if there are any extensions */
8164 if (strcmp(tmp->registrar, registrar) == 0 && tmp->refcount < 2 && !tmp->root && !ast_context_ignorepats_count(tmp) && !ast_context_includes_count(tmp) && !ast_context_switches_count(tmp)) {
8165 ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar);
8167
8168 next = tmp->next;
8169 if (tmpl)
8170 tmpl->next = next;
8171 else
8172 contexts = next;
8173 /* Okay, now we're safe to let it go -- in a sense, we were
8174 ready to let it go as soon as we locked it. */
8177 } else {
8178 ast_debug(1,"Couldn't delete ctx %s/%s; refc=%d; tmp.root=%p\n", tmp->name, tmp->registrar,
8179 tmp->refcount, tmp->root);
8181 next = tmp->next;
8182 tmpl = tmp;
8183 }
8184 } else if (con) {
8185 ast_verb(3, "Deleting context %s registrar=%s\n", tmp->name, tmp->registrar);
8186 ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar);
8188
8189 next = tmp->next;
8190 if (tmpl)
8191 tmpl->next = next;
8192 else
8193 contexts = next;
8194 /* Okay, now we're safe to let it go -- in a sense, we were
8195 ready to let it go as soon as we locked it. */
8198 }
8199
8200 /* if we have a specific match, we are done, otherwise continue */
8201 tmp = con ? NULL : next;
8202 }
8203}
#define ast_free(a)
Definition: astmm.h:180
static int tmp()
Definition: bt_open.c:389
#define AST_MAX_EXTENSION
Definition: channel.h:134
#define ast_hashtab_start_traversal(tab)
Definition: hashtab.h:356
void * ast_hashtab_remove_this_object(struct ast_hashtab *tab, void *obj)
Hash the object and then compare ptrs in bucket list instead of calling the compare routine,...
Definition: hashtab.c:789
void ast_hashtab_end_traversal(struct ast_hashtab_iter *it)
end the traversal, free the iterator, unlock if necc.
Definition: hashtab.c:674
void * ast_hashtab_next(struct ast_hashtab_iter *it)
Gets the next object in the list, advances iter one step returns null on end of traversal.
Definition: hashtab.c:683
#define ast_debug(level,...)
Log a DEBUG message.
#define ast_verb(level,...)
int ast_wrlock_context(struct ast_context *con)
Write locks a given context.
Definition: pbx.c:8481
int ast_unlock_context(struct ast_context *con)
Definition: pbx.c:8491
int ast_context_remove_extension_callerid2(struct ast_context *con, const char *extension, int priority, const char *callerid, int matchcallerid, const char *registrar, int already_locked)
Definition: pbx.c:4983
int ast_context_ignorepats_count(const struct ast_context *con)
Definition: pbx.c:8722
static struct ast_context * contexts
Definition: pbx.c:781
int ast_context_switches_count(const struct ast_context *con)
Definition: pbx.c:8634
int ast_context_includes_count(const struct ast_context *con)
Definition: pbx.c:8679
static void __ast_internal_context_destroy(struct ast_context *con)
Definition: pbx.c:8015
const char * ast_get_ignorepat_registrar(const struct ast_ignorepat *ip)
Definition: pbx_ignorepat.c:47
const char * ast_get_include_registrar(const struct ast_include *i)
Definition: pbx_include.c:60
const char * ast_get_switch_registrar(const struct ast_sw *sw)
Definition: pbx_sw.c:63
static char * registrar
Definition: pbx_ael.c:78
void ignorepat_free(struct ast_ignorepat *ip)
Definition: pbx_ignorepat.c:77
void include_free(struct ast_include *inc)
Definition: pbx_include.c:106
void sw_free(struct ast_sw *sw)
Definition: pbx_sw.c:101
#define NULL
Definition: resample.c:96
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
ast_context: An extension context
Definition: pbx.c:284
struct ast_context * next
Definition: pbx.c:292
struct ast_hashtab * root_table
Definition: pbx.c:290
const char * name
Definition: pbx.c:285
ast_exten: An extension The dialplan is saved as a linked list with each context having it's own link...
Definition: pbx.c:237
char * exten
Definition: pbx.c:238
struct ast_hashtab * peer_table
Definition: pbx.c:251
char * name
Definition: pbx.c:239
const char * registrar
Definition: pbx.c:253
const char * cidmatch
Definition: pbx.c:241
int priority
Definition: pbx.c:243
int matchcid
Definition: pbx.c:240
an iterator for traversing the buckets
Definition: hashtab.h:106
ast_ignorepat: Ignore patterns in dial plan
Definition: pbx_ignorepat.c:37
ast_include: include= support in extensions.conf
Definition: pbx_include.c:37
ast_sw: Switch statement in extensions.conf
Definition: pbx_sw.c:37
struct ast_sw * next
Definition: pbx_sw.c:44
structure to hold extensions
#define AST_VECTOR_REMOVE_ORDERED(vec, idx)
Remove an element from a vector by index while maintaining order.
Definition: vector.h:448
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:680

References __ast_internal_context_destroy(), ast_context_ignorepats_count(), ast_context_includes_count(), ast_context_remove_extension_callerid2(), ast_context_switches_count(), ast_copy_string(), ast_debug, ast_free, ast_get_ignorepat_registrar(), ast_get_include_registrar(), ast_get_switch_registrar(), ast_hashtab_end_traversal(), ast_hashtab_next(), ast_hashtab_remove_this_object(), ast_hashtab_start_traversal, AST_MAX_EXTENSION, ast_unlock_context(), AST_VECTOR_GET, AST_VECTOR_REMOVE_ORDERED, ast_verb, ast_wrlock_context(), ast_exten::cidmatch, contexts, ast_exten::exten, ignorepat_free(), include_free(), ast_exten::matchcid, ast_exten::name, ast_context::name, ast_context::next, ast_sw::next, NULL, ast_exten::peer_table, ast_exten::priority, ast_exten::registrar, registrar, ast_context::root_table, sw_free(), and tmp().

Referenced by ast_context_destroy().

◆ __ast_goto_if_exists()

static int __ast_goto_if_exists ( struct ast_channel chan,
const char *  context,
const char *  exten,
int  priority,
int  async 
)
static

Definition at line 8760 of file pbx.c.

8761{
8762 int (*goto_func)(struct ast_channel *chan, const char *context, const char *exten, int priority);
8763
8764 if (!chan)
8765 return -2;
8766
8767 if (context == NULL)
8769 if (exten == NULL)
8770 exten = ast_channel_exten(chan);
8771
8772 goto_func = (async) ? ast_async_goto : ast_explicit_goto;
8774 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL)))
8775 return goto_func(chan, context, exten, priority);
8776 else {
8777 return AST_PBX_GOTO_FAILED;
8778 }
8779}
static int priority
const char * ast_channel_context(const struct ast_channel *chan)
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
const char * ast_channel_exten(const struct ast_channel *chan)
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
Definition: pbx.c:4175
int ast_explicit_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
Definition: pbx.c:6945
int ast_async_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
Set the channel to next execute the specified dialplan location.
Definition: pbx.c:6969
#define AST_PBX_GOTO_FAILED
Definition: pbx.h:42
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition: strings.h:87
Main Channel structure associated with a channel.
char exten[AST_MAX_EXTENSION]
Number structure.
Definition: app_followme.c:154

References ast_async_goto(), ast_channel_caller(), ast_channel_context(), ast_channel_exten(), ast_exists_extension(), ast_explicit_goto(), AST_PBX_GOTO_FAILED, voicemailpwcheck::context, ast_channel::exten, NULL, priority, and S_COR.

Referenced by ast_async_goto_if_exists(), and ast_goto_if_exists().

◆ __ast_internal_context_destroy()

static void __ast_internal_context_destroy ( struct ast_context con)
static

Definition at line 8015 of file pbx.c.

8016{
8017 struct ast_exten *e, *el, *en;
8018 struct ast_context *tmp = con;
8019
8020 /* Free includes */
8022 AST_VECTOR_FREE(&tmp->includes);
8023
8024 /* Free ignorepats */
8026 AST_VECTOR_FREE(&tmp->ignorepats);
8027
8028 /* Free switches */
8030 AST_VECTOR_FREE(&tmp->alts);
8031
8032 /* destroy the hash tabs */
8033 if (tmp->root_table) {
8034 ast_hashtab_destroy(tmp->root_table, 0);
8035 }
8036 /* and destroy the pattern tree */
8037 if (tmp->pattern_tree)
8038 destroy_pattern_tree(tmp->pattern_tree);
8039
8040 for (e = tmp->root; e;) {
8041 for (en = e->peer; en;) {
8042 el = en;
8043 en = en->peer;
8045 }
8046 el = e;
8047 e = e->next;
8049 }
8050 tmp->root = NULL;
8051 ast_rwlock_destroy(&tmp->lock);
8052 ast_free(tmp);
8053}
static EditLine * el
Definition: asterisk.c:340
void ast_hashtab_destroy(struct ast_hashtab *tab, void(*objdestroyfunc)(void *obj))
This func will free the hash table and all its memory.
Definition: hashtab.c:363
#define ast_rwlock_destroy(rwlock)
Definition: lock.h:233
static void destroy_pattern_tree(struct match_char *pattern_tree)
Definition: pbx.c:1793
static void destroy_exten(struct ast_exten *e)
Definition: pbx.c:4674
struct ast_exten * peer
Definition: pbx.c:250
struct ast_exten * next
Definition: pbx.c:256
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
Definition: vector.h:174
#define AST_VECTOR_CALLBACK_VOID(vec, callback,...)
Execute a callback on every element in a vector disregarding callback return.
Definition: vector.h:862

References ast_free, ast_hashtab_destroy(), ast_rwlock_destroy, AST_VECTOR_CALLBACK_VOID, AST_VECTOR_FREE, destroy_exten(), destroy_pattern_tree(), el, ignorepat_free(), include_free(), ast_exten::next, NULL, ast_exten::peer, sw_free(), and tmp().

Referenced by __ast_context_destroy(), and ast_merge_contexts_and_delete().

◆ __ast_pbx_run()

static enum ast_pbx_result __ast_pbx_run ( struct ast_channel c,
struct ast_pbx_args args 
)
static
Note
We get here on a failure of some kind: non-existing extension or hangup. We have options, here. We can either catch the failure and continue, or we can drop out entirely.
If there is no match at priority 1, it is not a valid extension anymore. Try to continue at "i" (for invalid) or "e" (for exception) or exit if neither exist.

Definition at line 4306 of file pbx.c.

4308{
4309 int found = 0; /* set if we find at least one match */
4310 int res = 0;
4311 int autoloopflag;
4312 int error = 0; /* set an error conditions */
4313 struct ast_pbx *pbx;
4314 ast_callid callid;
4315
4316 /* A little initial setup here */
4317 if (ast_channel_pbx(c)) {
4318 ast_log(LOG_WARNING, "%s already has PBX structure??\n", ast_channel_name(c));
4319 /* XXX and now what ? */
4321 }
4322 if (!(pbx = ast_calloc(1, sizeof(*pbx)))) {
4323 return AST_PBX_FAILED;
4324 }
4325
4327 /* If the thread isn't already associated with a callid, we should create that association. */
4328 if (!callid) {
4329 /* Associate new PBX thread with the channel call id if it is availble.
4330 * If not, create a new one instead.
4331 */
4332 callid = ast_channel_callid(c);
4333 if (!callid) {
4334 callid = ast_create_callid();
4335 if (callid) {
4337 ast_channel_callid_set(c, callid);
4339 }
4340 }
4342 callid = 0;
4343 }
4344
4345 ast_channel_pbx_set(c, pbx);
4346 /* Set reasonable defaults */
4347 ast_channel_pbx(c)->rtimeoutms = 10000;
4348 ast_channel_pbx(c)->dtimeoutms = 5000;
4349
4351 autoloopflag = ast_test_flag(ast_channel_flags(c), AST_FLAG_IN_AUTOLOOP); /* save value to restore at the end */
4354
4356 /* If not successful fall back to 's' - but only if there is no given exten */
4357 ast_verb(2, "Starting %s at %s,%s,%d failed so falling back to exten 's'\n", ast_channel_name(c), ast_channel_context(c), ast_channel_exten(c), ast_channel_priority(c));
4358 /* XXX the original code used the existing priority in the call to
4359 * ast_exists_extension(), and reset it to 1 afterwards.
4360 * I believe the correct thing is to set it to 1 immediately.
4361 */
4362 set_ext_pri(c, "s", 1);
4363 }
4364
4365 for (;;) {
4366 char dst_exten[256]; /* buffer to accumulate digits */
4367 int pos = 0; /* XXX should check bounds */
4368 int digit = 0;
4369 int invalid = 0;
4370 int timeout = 0;
4371
4372 /* No digits pressed yet */
4373 dst_exten[pos] = '\0';
4374
4375 /* loop on priorities in this context/exten */
4378 &found, 1))) {
4379
4380 if (!ast_check_hangup(c)) {
4382 continue;
4383 }
4384
4385 /* Check softhangup flags. */
4388 continue;
4389 }
4392 S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4393 set_ext_pri(c, "T", 1);
4394 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
4397 continue;
4398 } else if (ast_exists_extension(c, ast_channel_context(c), "e", 1,
4399 S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4400 raise_exception(c, "ABSOLUTETIMEOUT", 1);
4401 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
4404 continue;
4405 }
4406
4407 /* Call timed out with no special extension to jump to. */
4408 error = 1;
4409 break;
4410 }
4411 ast_debug(1, "Extension %s, priority %d returned normally even though call was hung up\n",
4413 error = 1;
4414 break;
4415 } /* end while - from here on we can use 'break' to go out */
4416 if (found && res) {
4417 /* Something bad happened, or a hangup has been requested. */
4418 if (strchr("0123456789ABCDEF*#", res)) {
4419 ast_debug(1, "Oooh, got something to jump out with ('%c')!\n", res);
4420 pos = 0;
4421 dst_exten[pos++] = digit = res;
4422 dst_exten[pos] = '\0';
4423 } else if (res == AST_PBX_INCOMPLETE) {
4424 ast_debug(1, "Spawn extension (%s,%s,%d) exited INCOMPLETE on '%s'\n", ast_channel_context(c), ast_channel_exten(c), ast_channel_priority(c), ast_channel_name(c));
4425 ast_verb(2, "Spawn extension (%s, %s, %d) exited INCOMPLETE on '%s'\n", ast_channel_context(c), ast_channel_exten(c), ast_channel_priority(c), ast_channel_name(c));
4426
4427 /* Don't cycle on incomplete - this will happen if the only extension that matches is our "incomplete" extension */
4429 S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4430 invalid = 1;
4431 } else {
4432 ast_copy_string(dst_exten, ast_channel_exten(c), sizeof(dst_exten));
4433 digit = 1;
4434 pos = strlen(dst_exten);
4435 }
4436 } else {
4437 ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", ast_channel_context(c), ast_channel_exten(c), ast_channel_priority(c), ast_channel_name(c));
4438 ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", ast_channel_context(c), ast_channel_exten(c), ast_channel_priority(c), ast_channel_name(c));
4439
4440 if ((res == AST_PBX_ERROR)
4442 S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4443 /* if we are already on the 'e' exten, don't jump to it again */
4444 if (!strcmp(ast_channel_exten(c), "e")) {
4445 ast_verb(2, "Spawn extension (%s, %s, %d) exited ERROR while already on 'e' exten on '%s'\n", ast_channel_context(c), ast_channel_exten(c), ast_channel_priority(c), ast_channel_name(c));
4446 error = 1;
4447 } else {
4448 raise_exception(c, "ERROR", 1);
4449 continue;
4450 }
4451 }
4452
4455 continue;
4456 }
4459 S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4460 set_ext_pri(c, "T", 1);
4461 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
4464 continue;
4465 } else if (ast_exists_extension(c, ast_channel_context(c), "e", 1,
4466 S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4467 raise_exception(c, "ABSOLUTETIMEOUT", 1);
4468 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
4471 continue;
4472 }
4473 /* Call timed out with no special extension to jump to. */
4474 }
4475 error = 1;
4476 break;
4477 }
4478 }
4479 if (error)
4480 break;
4481
4482 /*!\note
4483 * We get here on a failure of some kind: non-existing extension or
4484 * hangup. We have options, here. We can either catch the failure
4485 * and continue, or we can drop out entirely. */
4486
4487 if (invalid
4488 || (ast_strlen_zero(dst_exten) &&
4490 S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL)))) {
4491 /*!\note
4492 * If there is no match at priority 1, it is not a valid extension anymore.
4493 * Try to continue at "i" (for invalid) or "e" (for exception) or exit if
4494 * neither exist.
4495 */
4497 S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4498 ast_verb(3, "Channel '%s' sent to invalid extension: context,exten,priority=%s,%s,%d\n",
4500 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", ast_channel_exten(c));
4501 set_ext_pri(c, "i", 1);
4502 } else if (ast_exists_extension(c, ast_channel_context(c), "e", 1,
4503 S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4504 raise_exception(c, "INVALID", 1);
4505 } else {
4506 ast_log(LOG_WARNING, "Channel '%s' sent to invalid extension but no invalid handler: context,exten,priority=%s,%s,%d\n",
4508 error = 1; /* we know what to do with it */
4509 break;
4510 }
4512 /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */
4514 } else { /* keypress received, get more digits for a full extension */
4515 int waittime = 0;
4516 if (digit)
4517 waittime = ast_channel_pbx(c)->dtimeoutms;
4518 else if (!autofallthrough)
4519 waittime = ast_channel_pbx(c)->rtimeoutms;
4520 if (!waittime) {
4521 const char *status = pbx_builtin_getvar_helper(c, "DIALSTATUS");
4522 if (!status)
4523 status = "UNKNOWN";
4524 ast_verb(3, "Auto fallthrough, channel '%s' status is '%s'\n", ast_channel_name(c), status);
4525 if (!strcasecmp(status, "CONGESTION"))
4526 res = indicate_congestion(c, "10");
4527 else if (!strcasecmp(status, "CHANUNAVAIL"))
4528 res = indicate_congestion(c, "10");
4529 else if (!strcasecmp(status, "BUSY"))
4530 res = indicate_busy(c, "10");
4531 error = 1; /* XXX disable message */
4532 break; /* exit from the 'for' loop */
4533 }
4534
4535 if (collect_digits(c, waittime, dst_exten, sizeof(dst_exten), pos))
4536 break;
4537 if (res == AST_PBX_INCOMPLETE && ast_strlen_zero(&dst_exten[pos]))
4538 timeout = 1;
4539 if (!timeout
4540 && ast_exists_extension(c, ast_channel_context(c), dst_exten, 1,
4541 S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) { /* Prepare the next cycle */
4542 set_ext_pri(c, dst_exten, 1);
4543 } else {
4544 /* No such extension */
4545 if (!timeout && !ast_strlen_zero(dst_exten)) {
4546 /* An invalid extension */
4548 S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4549 ast_verb(3, "Invalid extension '%s' in context '%s' on %s\n", dst_exten, ast_channel_context(c), ast_channel_name(c));
4550 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", dst_exten);
4551 set_ext_pri(c, "i", 1);
4552 } else if (ast_exists_extension(c, ast_channel_context(c), "e", 1,
4553 S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4554 raise_exception(c, "INVALID", 1);
4555 } else {
4557 "Invalid extension '%s', but no rule 'i' or 'e' in context '%s'\n",
4558 dst_exten, ast_channel_context(c));
4559 found = 1; /* XXX disable message */
4560 break;
4561 }
4562 } else {
4563 /* A simple timeout */
4565 S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4566 ast_verb(3, "Timeout on %s\n", ast_channel_name(c));
4567 set_ext_pri(c, "t", 1);
4568 } else if (ast_exists_extension(c, ast_channel_context(c), "e", 1,
4569 S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4570 raise_exception(c, "RESPONSETIMEOUT", 1);
4571 } else {
4573 "Timeout, but no rule 't' or 'e' in context '%s'\n",
4575 found = 1; /* XXX disable message */
4576 break;
4577 }
4578 }
4579 }
4580 }
4581 }
4582
4583 if (!found && !error) {
4584 ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", ast_channel_name(c));
4585 }
4586
4587 if (!args || !args->no_hangup_chan) {
4591 S_COR(ast_channel_caller(c)->id.number.valid,
4592 ast_channel_caller(c)->id.number.str, NULL))) {
4594 }
4596 }
4597
4600 ast_clear_flag(ast_channel_flags(c), AST_FLAG_BRIDGE_HANGUP_RUN); /* from one round to the next, make sure this gets cleared */
4604
4605 if (!args || !args->no_hangup_chan) {
4606 ast_hangup(c);
4607 }
4608
4609 return AST_PBX_SUCCESS;
4610}
char digit
jack_status_t status
Definition: app_jack.c:146
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define ast_log
Definition: astobj2.c:42
const char * ast_channel_name(const struct ast_channel *chan)
void ast_channel_clear_softhangup(struct ast_channel *chan, int flag)
Clear a set of softhangup flags from a channel.
Definition: channel.c:2432
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2541
#define ast_channel_lock(chan)
Definition: channel.h:2922
struct ast_flags * ast_channel_flags(struct ast_channel *chan)
int ast_channel_priority(const struct ast_channel *chan)
ast_callid ast_channel_callid(const struct ast_channel *chan)
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:445
int ast_softhangup(struct ast_channel *chan, int cause)
Softly hangup up a channel.
Definition: channel.c:2471
struct timeval * ast_channel_whentohangup(struct ast_channel *chan)
@ AST_SOFTHANGUP_ASYNCGOTO
Definition: channel.h:1126
@ AST_SOFTHANGUP_TIMEOUT
Definition: channel.h:1138
@ AST_SOFTHANGUP_APPUNLOAD
Definition: channel.h:1143
@ AST_FLAG_BRIDGE_HANGUP_RUN
Definition: channel.h:1018
@ AST_FLAG_IN_AUTOLOOP
Definition: channel.h:997
struct ast_pbx * ast_channel_pbx(const struct ast_channel *chan)
int ast_channel_softhangup_internal_flag(struct ast_channel *chan)
void ast_channel_callid_set(struct ast_channel *chan, ast_callid value)
void ast_channel_priority_set(struct ast_channel *chan, int value)
#define ast_channel_unlock(chan)
Definition: channel.h:2923
void ast_channel_pbx_set(struct ast_channel *chan, struct ast_pbx *value)
int indicate_busy(struct ast_channel *chan, const char *data)
Definition: pbx_builtins.c:757
int indicate_congestion(struct ast_channel *chan, const char *data)
Definition: pbx_builtins.c:775
ast_callid ast_read_threadstorage_callid(void)
extracts the callerid from the thread
Definition: logger.c:2298
int ast_callid_threadassoc_add(ast_callid callid)
Adds a known callid to thread storage of the calling thread.
Definition: logger.c:2320
ast_callid ast_create_callid(void)
factory function to create a new uniquely identifying callid.
Definition: logger.c:2293
unsigned int ast_callid
#define LOG_WARNING
static void pbx_destroy(struct ast_pbx *p)
Definition: pbx.c:990
static int autofallthrough
Definition: pbx.c:768
int raise_exception(struct ast_channel *chan, const char *reason, int priority)
Definition: pbx.c:2806
void ast_pbx_h_exten_run(struct ast_channel *chan, const char *context)
Run the h exten from the given context.
Definition: pbx.c:4205
int ast_spawn_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid, int *found, int combined_find_spawn)
Launch a new extension (i.e. new stack)
Definition: pbx.c:4200
int ast_matchmore_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Looks to see if adding anything to this extension might match something. (exists ^ canmatch)
Definition: pbx.c:4195
static int collect_digits(struct ast_channel *c, int waittime, char *buf, int buflen, int pos)
collect digits from the channel into the buffer.
Definition: pbx.c:4279
void set_ext_pri(struct ast_channel *c, const char *exten, int pri)
Definition: pbx.c:4264
@ AST_PBX_FAILED
Definition: pbx.h:372
@ AST_PBX_SUCCESS
Definition: pbx.h:371
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
#define AST_PBX_INCOMPLETE
Definition: pbx.h:51
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name.
#define AST_PBX_ERROR
Definition: pbx.h:50
int ast_pbx_hangup_handler_run(struct ast_channel *chan)
Run all hangup handlers on the channel.
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
Definition: pbx.h:214
int rtimeoutms
Definition: pbx.h:216
int dtimeoutms
Definition: pbx.h:215
const char * args
static struct test_val c
int error(const char *format,...)
Definition: utils/frame.c:999
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define ast_set2_flag(p, value, flag)
Definition: utils.h:94
#define ast_clear_flag(p, flag)
Definition: utils.h:77
#define ast_set_flag(p, flag)
Definition: utils.h:70

References args, ast_callid_threadassoc_add(), ast_calloc, ast_channel_caller(), ast_channel_callid(), ast_channel_callid_set(), ast_channel_clear_softhangup(), ast_channel_context(), ast_channel_exten(), ast_channel_flags(), ast_channel_lock, ast_channel_name(), ast_channel_pbx(), ast_channel_pbx_set(), ast_channel_priority(), ast_channel_priority_set(), ast_channel_softhangup_internal_flag(), ast_channel_unlock, ast_channel_whentohangup(), ast_check_hangup(), ast_clear_flag, ast_copy_string(), ast_create_callid(), ast_debug, ast_exists_extension(), AST_FLAG_BRIDGE_HANGUP_RUN, AST_FLAG_IN_AUTOLOOP, ast_free, ast_hangup(), ast_log, ast_matchmore_extension(), AST_PBX_ERROR, AST_PBX_FAILED, ast_pbx_h_exten_run(), ast_pbx_hangup_handler_run(), AST_PBX_INCOMPLETE, AST_PBX_SUCCESS, ast_read_threadstorage_callid(), ast_set2_flag, ast_set_flag, ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, AST_SOFTHANGUP_ASYNCGOTO, AST_SOFTHANGUP_TIMEOUT, ast_spawn_extension(), ast_strlen_zero(), ast_test_flag, ast_verb, autofallthrough, c, collect_digits(), digit, ast_pbx::dtimeoutms, error(), indicate_busy(), indicate_congestion(), LOG_WARNING, NULL, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), pbx_destroy(), raise_exception(), ast_pbx::rtimeoutms, S_COR, set_ext_pri(), and status.

Referenced by ast_pbx_run_args(), and pbx_thread().

◆ __init_extensionstate_buf()

static void __init_extensionstate_buf ( void  )
static

Definition at line 229 of file pbx.c.

237{

◆ __init_hintdevice_data()

static void __init_hintdevice_data ( void  )
static

Definition at line 359 of file pbx.c.

376{

◆ __init_switch_data()

static void __init_switch_data ( void  )
static

Definition at line 228 of file pbx.c.

237{

◆ _extension_match_core()

static int _extension_match_core ( const char *  pattern,
const char *  data,
enum ext_match_t  mode 
)
static

Definition at line 2223 of file pbx.c.

2224{
2225 mode &= E_MATCH_MASK; /* only consider the relevant bits */
2226
2227#ifdef NEED_DEBUG_HERE
2228 ast_log(LOG_NOTICE,"match core: pat: '%s', dat: '%s', mode=%d\n", pattern, data, (int)mode);
2229#endif
2230
2231 if (pattern[0] != '_') { /* not a pattern, try exact or partial match */
2232 int lp = ext_cmp_exten_strlen(pattern);
2233 int ld = ext_cmp_exten_strlen(data);
2234
2235 if (lp < ld) { /* pattern too short, cannot match */
2236#ifdef NEED_DEBUG_HERE
2237 ast_log(LOG_NOTICE,"return (0) - pattern too short, cannot match\n");
2238#endif
2239 return 0;
2240 }
2241 /* depending on the mode, accept full or partial match or both */
2242 if (mode == E_MATCH) {
2243#ifdef NEED_DEBUG_HERE
2244 ast_log(LOG_NOTICE,"return (!ext_cmp_exten(%s,%s) when mode== E_MATCH)\n", pattern, data);
2245#endif
2246 return !ext_cmp_exten(pattern, data); /* 1 on match, 0 on fail */
2247 }
2248 if (ld == 0 || !ext_cmp_exten_partial(pattern, data)) { /* partial or full match */
2249#ifdef NEED_DEBUG_HERE
2250 ast_log(LOG_NOTICE,"return (mode(%d) == E_MATCHMORE ? lp(%d) > ld(%d) : 1)\n", mode, lp, ld);
2251#endif
2252 return (mode == E_MATCHMORE) ? lp > ld : 1; /* XXX should consider '!' and '/' ? */
2253 } else {
2254#ifdef NEED_DEBUG_HERE
2255 ast_log(LOG_NOTICE,"return (0) when ld(%d) > 0 && pattern(%s) != data(%s)\n", ld, pattern, data);
2256#endif
2257 return 0;
2258 }
2259 }
2260 if (mode == E_MATCH && data[0] == '_') {
2261 /*
2262 * XXX It is bad design that we don't know if we should be
2263 * comparing data and pattern as patterns or comparing data if
2264 * it conforms to pattern when the function is called. First,
2265 * assume they are both patterns. If they don't match then try
2266 * to see if data conforms to the given pattern.
2267 *
2268 * note: if this test is left out, then _x. will not match _x. !!!
2269 */
2270#ifdef NEED_DEBUG_HERE
2271 ast_log(LOG_NOTICE, "Comparing as patterns first. pattern:%s data:%s\n", pattern, data);
2272#endif
2273 if (!ext_cmp_pattern(pattern + 1, data + 1)) {
2274#ifdef NEED_DEBUG_HERE
2275 ast_log(LOG_NOTICE,"return (1) - pattern matches pattern\n");
2276#endif
2277 return 1;
2278 }
2279 }
2280
2281 ++pattern; /* skip leading _ */
2282 /*
2283 * XXX below we stop at '/' which is a separator for the CID info. However we should
2284 * not store '/' in the pattern at all. When we insure it, we can remove the checks.
2285 */
2286 for (;;) {
2287 const char *end;
2288
2289 /* Ignore '-' chars as eye candy fluff. */
2290 while (*data == '-') {
2291 ++data;
2292 }
2293 while (*pattern == '-') {
2294 ++pattern;
2295 }
2296 if (!*data || !*pattern || *pattern == '/') {
2297 break;
2298 }
2299
2300 switch (*pattern) {
2301 case '[': /* a range */
2302 ++pattern;
2303 end = strchr(pattern, ']'); /* XXX should deal with escapes ? */
2304 if (!end) {
2305 ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n");
2306 return 0; /* unconditional failure */
2307 }
2308 if (pattern == end) {
2309 /* Ignore empty character sets. */
2310 ++pattern;
2311 continue;
2312 }
2313 for (; pattern < end; ++pattern) {
2314 if (pattern+2 < end && pattern[1] == '-') { /* this is a range */
2315 if (*data >= pattern[0] && *data <= pattern[2])
2316 break; /* match found */
2317 else {
2318 pattern += 2; /* skip a total of 3 chars */
2319 continue;
2320 }
2321 } else if (*data == pattern[0])
2322 break; /* match found */
2323 }
2324 if (pattern >= end) {
2325#ifdef NEED_DEBUG_HERE
2326 ast_log(LOG_NOTICE,"return (0) when pattern>=end\n");
2327#endif
2328 return 0;
2329 }
2330 pattern = end; /* skip and continue */
2331 break;
2332 case 'n':
2333 case 'N':
2334 if (*data < '2' || *data > '9') {
2335#ifdef NEED_DEBUG_HERE
2336 ast_log(LOG_NOTICE,"return (0) N is not matched\n");
2337#endif
2338 return 0;
2339 }
2340 break;
2341 case 'x':
2342 case 'X':
2343 if (*data < '0' || *data > '9') {
2344#ifdef NEED_DEBUG_HERE
2345 ast_log(LOG_NOTICE,"return (0) X is not matched\n");
2346#endif
2347 return 0;
2348 }
2349 break;
2350 case 'z':
2351 case 'Z':
2352 if (*data < '1' || *data > '9') {
2353#ifdef NEED_DEBUG_HERE
2354 ast_log(LOG_NOTICE,"return (0) Z is not matched\n");
2355#endif
2356 return 0;
2357 }
2358 break;
2359 case '.': /* Must match, even with more digits */
2360#ifdef NEED_DEBUG_HERE
2361 ast_log(LOG_NOTICE, "return (1) when '.' is matched\n");
2362#endif
2363 return 1;
2364 case '!': /* Early match */
2365#ifdef NEED_DEBUG_HERE
2366 ast_log(LOG_NOTICE, "return (2) when '!' is matched\n");
2367#endif
2368 return 2;
2369 default:
2370 if (*data != *pattern) {
2371#ifdef NEED_DEBUG_HERE
2372 ast_log(LOG_NOTICE, "return (0) when *data(%c) != *pattern(%c)\n", *data, *pattern);
2373#endif
2374 return 0;
2375 }
2376 break;
2377 }
2378 ++data;
2379 ++pattern;
2380 }
2381 if (*data) /* data longer than pattern, no match */ {
2382#ifdef NEED_DEBUG_HERE
2383 ast_log(LOG_NOTICE, "return (0) when data longer than pattern\n");
2384#endif
2385 return 0;
2386 }
2387
2388 /*
2389 * match so far, but ran off the end of data.
2390 * Depending on what is next, determine match or not.
2391 */
2392 if (*pattern == '\0' || *pattern == '/') { /* exact match */
2393#ifdef NEED_DEBUG_HERE
2394 ast_log(LOG_NOTICE, "at end, return (%d) in 'exact match'\n", (mode==E_MATCHMORE) ? 0 : 1);
2395#endif
2396 return (mode == E_MATCHMORE) ? 0 : 1; /* this is a failure for E_MATCHMORE */
2397 } else if (*pattern == '!') { /* early match */
2398#ifdef NEED_DEBUG_HERE
2399 ast_log(LOG_NOTICE, "at end, return (2) when '!' is matched\n");
2400#endif
2401 return 2;
2402 } else { /* partial match */
2403#ifdef NEED_DEBUG_HERE
2404 ast_log(LOG_NOTICE, "at end, return (%d) which deps on E_MATCH\n", (mode == E_MATCH) ? 0 : 1);
2405#endif
2406 return (mode == E_MATCH) ? 0 : 1; /* this is a failure for E_MATCH */
2407 }
2408}
char * end
Definition: eagi_proxy.c:73
@ E_MATCH_MASK
Definition: extconf.h:218
@ E_MATCH
Definition: extconf.h:217
@ E_MATCHMORE
Definition: extconf.h:215
#define LOG_NOTICE
static int ext_cmp_exten_strlen(const char *str)
Definition: pbx.c:1817
static int ext_cmp_exten(const char *left, const char *right)
Definition: pbx.c:1890
static int ext_cmp_pattern(const char *left, const char *right)
Definition: pbx.c:2092
static int ext_cmp_exten_partial(const char *left, const char *right)
Definition: pbx.c:1847

References ast_log, ast_exten::data, E_MATCH, E_MATCH_MASK, E_MATCHMORE, end, ext_cmp_exten(), ext_cmp_exten_partial(), ext_cmp_exten_strlen(), ext_cmp_pattern(), LOG_NOTICE, and LOG_WARNING.

Referenced by extension_match_core().

◆ acf_exception_read()

static int acf_exception_read ( struct ast_channel chan,
const char *  name,
char *  data,
char *  buf,
size_t  buflen 
)
static

Definition at line 2832 of file pbx.c.

2833{
2835 struct pbx_exception *exception = NULL;
2836 if (!ds || !ds->data)
2837 return -1;
2838 exception = ds->data;
2839 if (!strcasecmp(data, "REASON"))
2840 ast_copy_string(buf, exception->reason, buflen);
2841 else if (!strcasecmp(data, "CONTEXT"))
2842 ast_copy_string(buf, exception->context, buflen);
2843 else if (!strncasecmp(data, "EXTEN", 5))
2844 ast_copy_string(buf, exception->exten, buflen);
2845 else if (!strcasecmp(data, "PRIORITY"))
2846 snprintf(buf, buflen, "%d", exception->priority);
2847 else
2848 return -1;
2849 return 0;
2850}
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2399
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static const struct ast_datastore_info exception_store_info
Definition: pbx.c:2790
Structure for a data store object.
Definition: datastore.h:64
void * data
Definition: datastore.h:66
const ast_string_field context
Definition: pbx.c:630
const ast_string_field exten
Definition: pbx.c:630
int priority
Definition: pbx.c:632
const ast_string_field reason
Definition: pbx.c:630

References ast_channel_datastore_find(), ast_copy_string(), buf, pbx_exception::context, ast_datastore::data, exception_store_info, pbx_exception::exten, NULL, pbx_exception::priority, and pbx_exception::reason.

◆ action_extensionstatelist()

static int action_extensionstatelist ( struct mansession s,
const struct message m 
)
static

Definition at line 8344 of file pbx.c.

8345{
8346 const char *action_id = astman_get_header(m, "ActionID");
8347 struct ast_hint *hint;
8348 struct ao2_iterator it_hints;
8349 int hint_count = 0;
8350
8351 if (!hints) {
8352 astman_send_error(s, m, "No dialplan hints are available");
8353 return 0;
8354 }
8355
8356 astman_send_listack(s, m, "Extension Statuses will follow", "start");
8357
8358 ao2_lock(hints);
8359 it_hints = ao2_iterator_init(hints, 0);
8360 for (; (hint = ao2_iterator_next(&it_hints)); ao2_ref(hint, -1)) {
8361
8362 ao2_lock(hint);
8363
8364 /* Ignore pattern matching hints; they are stored in the
8365 * hints container but aren't real from the perspective of
8366 * an AMI user
8367 */
8368 if (hint->exten->exten[0] == '_') {
8369 ao2_unlock(hint);
8370 continue;
8371 }
8372
8373 ++hint_count;
8374
8375 astman_append(s, "Event: ExtensionStatus\r\n");
8376 if (!ast_strlen_zero(action_id)) {
8377 astman_append(s, "ActionID: %s\r\n", action_id);
8378 }
8379 astman_append(s,
8380 "Exten: %s\r\n"
8381 "Context: %s\r\n"
8382 "Hint: %s\r\n"
8383 "Status: %d\r\n"
8384 "StatusText: %s\r\n\r\n",
8385 hint->exten->exten,
8386 hint->exten->parent->name,
8387 hint->exten->app,
8388 hint->laststate,
8390 ao2_unlock(hint);
8391 }
8392
8393 ao2_iterator_destroy(&it_hints);
8395
8396 astman_send_list_complete_start(s, m, "ExtensionStateListComplete", hint_count);
8398
8399 return 0;
8400}
#define ao2_iterator_next(iter)
Definition: astobj2.h:1911
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
#define ao2_unlock(a)
Definition: astobj2.h:729
#define ao2_lock(a)
Definition: astobj2.h:717
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
void astman_send_listack(struct mansession *s, const struct message *m, char *msg, char *listflag)
Send ack in manager transaction to begin a list.
Definition: manager.c:3431
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:3389
void astman_send_list_complete_start(struct mansession *s, const struct message *m, const char *event_name, int count)
Start the list complete event.
Definition: manager.c:3467
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
Definition: manager.c:3050
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
Definition: manager.c:3475
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:3310
const char * ast_extension_state2str(int extension_state)
Return extension_state as string.
Definition: pbx.c:3126
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1821
const char * app
Definition: pbx.c:246
struct ast_context * parent
Definition: pbx.c:245
Structure for dial plan hints.
Definition: pbx.c:331
int laststate
Definition: pbx.c:342
struct ast_exten * exten
Hint extension.
Definition: pbx.c:338

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ast_exten::app, ast_extension_state2str(), ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), astman_send_list_complete_end(), astman_send_list_complete_start(), astman_send_listack(), ast_exten::exten, ast_hint::exten, ast_hint::laststate, ast_context::name, and ast_exten::parent.

Referenced by load_pbx().

◆ add_exten_to_pattern_tree()

static struct match_char * add_exten_to_pattern_tree ( struct ast_context con,
struct ast_exten e1,
int  findonly 
)
static

Definition at line 1663 of file pbx.c.

1664{
1665 struct match_char *m1 = NULL;
1666 struct match_char *m2 = NULL;
1667 struct match_char **m0;
1668 const char *pos;
1669 int already;
1670 int pattern = 0;
1671 int idx_cur;
1672 int idx_next;
1673 char extenbuf[MAX_EXTENBUF_SIZE];
1674 volatile size_t required_space = strlen(e1->exten) + 1;
1675 struct pattern_node pat_node[2];
1676
1677 if (e1->matchcid) {
1678 required_space += (strlen(e1->cidmatch) + 2 /* '/' + NULL */);
1679 if (required_space > MAX_EXTENBUF_SIZE) {
1681 "The pattern %s/%s is too big to deal with: it will be ignored! Disaster!\n",
1682 e1->exten, e1->cidmatch);
1683 return NULL;
1684 }
1685 sprintf(extenbuf, "%s/%s", e1->exten, e1->cidmatch);/* Safe. We just checked. */
1686 } else {
1687 if (required_space > MAX_EXTENBUF_SIZE) {
1689 "The pattern %s/%s is too big to deal with: it will be ignored! Disaster!\n",
1690 e1->exten, e1->cidmatch);
1691 return NULL;
1692 }
1693 ast_copy_string(extenbuf, e1->exten, required_space);
1694 }
1695
1696#ifdef NEED_DEBUG
1697 ast_debug(1, "Adding exten %s to tree\n", extenbuf);
1698#endif
1699 m1 = con->pattern_tree; /* each pattern starts over at the root of the pattern tree */
1700 m0 = &con->pattern_tree;
1701 already = 1;
1702
1703 pos = extenbuf;
1704 if (*pos == '_') {
1705 pattern = 1;
1706 ++pos;
1707 }
1708 idx_cur = 0;
1709 pos = get_pattern_node(&pat_node[idx_cur], pos, pattern, extenbuf);
1710 for (; pat_node[idx_cur].buf[0]; idx_cur = idx_next) {
1711 idx_next = (idx_cur + 1) % ARRAY_LEN(pat_node);
1712 pos = get_pattern_node(&pat_node[idx_next], pos, pattern, extenbuf);
1713
1714 /* See about adding node to tree. */
1715 m2 = NULL;
1716 if (already && (m2 = already_in_tree(m1, pat_node[idx_cur].buf, pattern))
1717 && m2->next_char) {
1718 if (!pat_node[idx_next].buf[0]) {
1719 /*
1720 * This is the end of the pattern, but not the end of the tree.
1721 * Mark this node with the exten... a shorter pattern might win
1722 * if the longer one doesn't match.
1723 */
1724 if (findonly) {
1725 return m2;
1726 }
1727 if (m2->exten) {
1728 ast_log(LOG_WARNING, "Found duplicate exten. Had %s found %s\n",
1729 m2->deleted ? "(deleted/invalid)" : m2->exten->name, e1->name);
1730 }
1731 m2->exten = e1;
1732 m2->deleted = 0;
1733 }
1734 m1 = m2->next_char; /* m1 points to the node to compare against */
1735 m0 = &m2->next_char; /* m0 points to the ptr that points to m1 */
1736 } else { /* not already OR not m2 OR nor m2->next_char */
1737 if (m2) {
1738 if (findonly) {
1739 return m2;
1740 }
1741 m1 = m2; /* while m0 stays the same */
1742 } else {
1743 if (findonly) {
1744 return m1;
1745 }
1746 m1 = add_pattern_node(con, m1, &pat_node[idx_cur], pattern, already, m0);
1747 if (!m1) { /* m1 is the node just added */
1748 return NULL;
1749 }
1750 m0 = &m1->next_char;
1751 }
1752 if (!pat_node[idx_next].buf[0]) {
1753 if (m2 && m2->exten) {
1754 ast_log(LOG_WARNING, "Found duplicate exten. Had %s found %s\n",
1755 m2->deleted ? "(deleted/invalid)" : m2->exten->name, e1->name);
1756 }
1757 m1->deleted = 0;
1758 m1->exten = e1;
1759 }
1760
1761 /* The 'already' variable is a mini-optimization designed to make it so that we
1762 * don't have to call already_in_tree when we know it will return false.
1763 */
1764 already = 0;
1765 }
1766 }
1767 return m1;
1768}
#define LOG_ERROR
static struct match_char * already_in_tree(struct match_char *current, char *pat, int is_pattern)
Definition: pbx.c:1402
static struct match_char * add_pattern_node(struct ast_context *con, struct match_char *current, const struct pattern_node *pattern, int is_pattern, int already, struct match_char **nextcharptr)
Definition: pbx.c:1464
#define MAX_EXTENBUF_SIZE
Definition: pbx.c:1662
static const char * get_pattern_node(struct pattern_node *node, const char *src, int pattern, const char *extenbuf)
Definition: pbx.c:1518
struct match_char * pattern_tree
Definition: pbx.c:291
match_char: forms a syntax tree for quick matching of extension patterns
Definition: pbx.c:262
int deleted
Definition: pbx.c:264
struct match_char * next_char
Definition: pbx.c:267
struct ast_exten * exten
Definition: pbx.c:268
#define ARRAY_LEN(a)
Definition: utils.h:666

References add_pattern_node(), already_in_tree(), ARRAY_LEN, ast_copy_string(), ast_debug, ast_log, pattern_node::buf, buf, ast_exten::cidmatch, match_char::deleted, ast_exten::exten, match_char::exten, get_pattern_node(), LOG_ERROR, LOG_WARNING, ast_exten::matchcid, MAX_EXTENBUF_SIZE, ast_exten::name, match_char::next_char, NULL, and ast_context::pattern_tree.

Referenced by add_priority(), ast_add_extension2_lockopt(), ast_context_remove_extension_callerid2(), and create_match_char_tree().

◆ add_hintdevice()

static int add_hintdevice ( struct ast_hint hint,
const char *  devicelist 
)
static

add hintdevice structure and link it into the container.

Definition at line 557 of file pbx.c.

558{
559 struct ast_str *str;
560 char *parse;
561 char *cur;
562 struct ast_hintdevice *device;
563 int devicelength;
564
565 if (!hint || !devicelist) {
566 /* Trying to add garbage? Don't bother. */
567 return 0;
568 }
569 if (!(str = ast_str_thread_get(&hintdevice_data, 16))) {
570 return -1;
571 }
572 ast_str_set(&str, 0, "%s", devicelist);
573 parse = ast_str_buffer(str);
574
575 /* Spit on '&' and ',' to handle presence hints as well */
576 while ((cur = strsep(&parse, "&,"))) {
577 char *device_name;
578
579 devicelength = strlen(cur);
580 if (!devicelength) {
581 continue;
582 }
583
584 device_name = ast_strdup(cur);
585 if (!device_name) {
586 return -1;
587 }
588
589 device = ao2_t_alloc(sizeof(*device) + devicelength, hintdevice_destroy,
590 "allocating a hintdevice structure");
591 if (!device) {
592 ast_free(device_name);
593 return -1;
594 }
595 strcpy(device->hintdevice, cur);
596 ao2_ref(hint, +1);
597 device->hint = hint;
598 if (AST_VECTOR_APPEND(&hint->devices, device_name)) {
599 ast_free(device_name);
600 ao2_ref(device, -1);
601 return -1;
602 }
603 ao2_t_link(hintdevices, device, "Linking device into hintdevice container.");
604 ao2_t_ref(device, -1, "hintdevice is linked so we can unref");
605 }
606
607 return 0;
608}
const char * str
Definition: app_jack.c:147
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
#define ao2_t_ref(o, delta, tag)
Definition: astobj2.h:460
#define ao2_t_link(container, obj, tag)
Definition: astobj2.h:1534
#define ao2_t_alloc(data_size, destructor_fn, debug_msg)
Definition: astobj2.h:407
char * strsep(char **str, const char *delims)
static void hintdevice_destroy(void *obj)
Definition: pbx.c:545
static struct ao2_container * hintdevices
Container for hint devices.
Definition: pbx.c:370
static struct ast_threadstorage hintdevice_data
Definition: pbx.c:359
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1113
struct ast_str * ast_str_thread_get(struct ast_threadstorage *ts, size_t init_len)
Retrieve a thread locally stored dynamic string.
Definition: strings.h:909
struct ast_hint::@376 devices
Structure for dial plan hint devices.
Definition: pbx.c:376
char hintdevice[1]
Definition: pbx.c:383
struct ast_hint * hint
Hint this hintdevice belongs to.
Definition: pbx.c:381
Support for dynamic strings.
Definition: strings.h:623
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition: vector.h:256

References ao2_ref, ao2_t_alloc, ao2_t_link, ao2_t_ref, ast_free, ast_str_buffer(), ast_str_set(), ast_str_thread_get(), ast_strdup, AST_VECTOR_APPEND, ast_hint::devices, ast_hintdevice::hint, ast_hintdevice::hintdevice, hintdevice_data, hintdevice_destroy(), hintdevices, str, and strsep().

Referenced by ast_add_hint(), and ast_change_hint().

◆ add_pattern_node()

static struct match_char * add_pattern_node ( struct ast_context con,
struct match_char current,
const struct pattern_node pattern,
int  is_pattern,
int  already,
struct match_char **  nextcharptr 
)
static

Definition at line 1464 of file pbx.c.

1465{
1466 struct match_char *m;
1467
1468 if (!(m = ast_calloc(1, sizeof(*m) + strlen(pattern->buf)))) {
1469 return NULL;
1470 }
1471
1472 /* strcpy is safe here since we know its size and have allocated
1473 * just enough space for when we allocated m
1474 */
1475 strcpy(m->x, pattern->buf);
1476
1477 /* the specificity scores are the same as used in the old
1478 pattern matcher. */
1480 if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'N') {
1481 m->specificity = 0x0832;
1482 } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'Z') {
1483 m->specificity = 0x0931;
1484 } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'X') {
1485 m->specificity = 0x0a30;
1486 } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == '.') {
1487 m->specificity = 0x18000;
1488 } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == '!') {
1489 m->specificity = 0x28000;
1490 } else {
1491 m->specificity = pattern->specif;
1492 }
1493
1494 if (!con->pattern_tree) {
1496 } else {
1497 if (already) { /* switch to the new regime (traversing vs appending)*/
1498 insert_in_next_chars_alt_char_list(nextcharptr, m);
1499 } else {
1501 }
1502 }
1503
1504 return m;
1505}
size_t current
Definition: main/cli.c:113
static void insert_in_next_chars_alt_char_list(struct match_char **parent_ptr, struct match_char *node)
Definition: pbx.c:1423
int is_pattern
Definition: pbx.c:263
int specificity
Definition: pbx.c:265
char x[1]
Definition: pbx.c:269
char buf[256]
Definition: pbx.c:1461
int specif
Definition: pbx.c:1459

References ast_calloc, pattern_node::buf, current, insert_in_next_chars_alt_char_list(), match_char::is_pattern, NULL, ast_context::pattern_tree, pattern_node::specif, match_char::specificity, and match_char::x.

Referenced by add_exten_to_pattern_tree().

◆ add_priority()

static int add_priority ( struct ast_context con,
struct ast_exten tmp,
struct ast_exten el,
struct ast_exten e,
int  replace 
)
static

add the extension in the priority chain.

Return values
0on success.
-1on failure.

Definition at line 7067 of file pbx.c.

7069{
7070 struct ast_exten *ep;
7071 struct ast_exten *eh=e;
7072 int repeated_label = 0; /* Track if this label is a repeat, assume no. */
7073
7074 for (ep = NULL; e ; ep = e, e = e->peer) {
7075 if (e->label && tmp->label && e->priority != tmp->priority && !strcmp(e->label, tmp->label)) {
7076 if (strcmp(e->name, tmp->name)) {
7078 "Extension '%s' priority %d in '%s', label '%s' already in use at aliased extension '%s' priority %d\n",
7079 tmp->name, tmp->priority, con->name, tmp->label, e->name, e->priority);
7080 } else {
7082 "Extension '%s' priority %d in '%s', label '%s' already in use at priority %d\n",
7083 tmp->name, tmp->priority, con->name, tmp->label, e->priority);
7084 }
7085 repeated_label = 1;
7086 }
7087 if (e->priority >= tmp->priority) {
7088 break;
7089 }
7090 }
7091
7092 if (repeated_label) { /* Discard the label since it's a repeat. */
7093 tmp->label = NULL;
7094 }
7095
7096 if (!e) { /* go at the end, and ep is surely set because the list is not empty */
7098
7099 if (tmp->label) {
7101 }
7102 ep->peer = tmp;
7103 return 0; /* success */
7104 }
7105 if (e->priority == tmp->priority) {
7106 /* Can't have something exactly the same. Is this a
7107 replacement? If so, replace, otherwise, bonk. */
7108 if (!replace) {
7109 if (strcmp(e->name, tmp->name)) {
7111 "Unable to register extension '%s' priority %d in '%s', already in use by aliased extension '%s'\n",
7112 tmp->name, tmp->priority, con->name, e->name);
7113 } else {
7115 "Unable to register extension '%s' priority %d in '%s', already in use\n",
7116 tmp->name, tmp->priority, con->name);
7117 }
7118
7119 return -1;
7120 }
7121 /* we are replacing e, so copy the link fields and then update
7122 * whoever pointed to e to point to us
7123 */
7124 tmp->next = e->next; /* not meaningful if we are not first in the peer list */
7125 tmp->peer = e->peer; /* always meaningful */
7126 if (ep) { /* We're in the peer list, just insert ourselves */
7128
7129 if (e->label) {
7131 }
7132
7134 if (tmp->label) {
7136 }
7137
7138 ep->peer = tmp;
7139 } else if (el) { /* We're the first extension. Take over e's functions */
7140 struct match_char *x = add_exten_to_pattern_tree(con, e, 1);
7141 tmp->peer_table = e->peer_table;
7142 tmp->peer_label_table = e->peer_label_table;
7144 ast_hashtab_insert_safe(tmp->peer_table,tmp);
7145 if (e->label) {
7146 ast_hashtab_remove_object_via_lookup(tmp->peer_label_table, e);
7147 }
7148 if (tmp->label) {
7149 ast_hashtab_insert_safe(tmp->peer_label_table, tmp);
7150 }
7151
7154 el->next = tmp;
7155 /* The pattern trie points to this exten; replace the pointer,
7156 and all will be well */
7157 if (x) { /* if the trie isn't formed yet, don't sweat this */
7158 if (x->exten) { /* this test for safety purposes */
7159 x->exten = tmp; /* replace what would become a bad pointer */
7160 } else {
7161 ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n");
7162 }
7163 }
7164 } else { /* We're the very first extension. */
7165 struct match_char *x = add_exten_to_pattern_tree(con, e, 1);
7168 tmp->peer_table = e->peer_table;
7169 tmp->peer_label_table = e->peer_label_table;
7171 ast_hashtab_insert_safe(tmp->peer_table, tmp);
7172 if (e->label) {
7173 ast_hashtab_remove_object_via_lookup(tmp->peer_label_table, e);
7174 }
7175 if (tmp->label) {
7176 ast_hashtab_insert_safe(tmp->peer_label_table, tmp);
7177 }
7178
7181 con->root = tmp;
7182 /* The pattern trie points to this exten; replace the pointer,
7183 and all will be well */
7184 if (x) { /* if the trie isn't formed yet; no problem */
7185 if (x->exten) { /* this test for safety purposes */
7186 x->exten = tmp; /* replace what would become a bad pointer */
7187 } else {
7188 ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n");
7189 }
7190 }
7191 }
7192 if (tmp->priority == PRIORITY_HINT)
7194 /* Destroy the old one */
7195 if (e->datad)
7196 e->datad(e->data);
7197 ast_free(e);
7198 } else { /* Slip ourselves in just before e */
7199 tmp->peer = e;
7200 tmp->next = e->next; /* extension chain, or NULL if e is not the first extension */
7201 if (ep) { /* Easy enough, we're just in the peer list */
7202 if (tmp->label) {
7204 }
7206 ep->peer = tmp;
7207 } else { /* we are the first in some peer list, so link in the ext list */
7208 tmp->peer_table = e->peer_table;
7209 tmp->peer_label_table = e->peer_label_table;
7210 e->peer_table = 0;
7211 e->peer_label_table = 0;
7212 ast_hashtab_insert_safe(tmp->peer_table, tmp);
7213 if (tmp->label) {
7214 ast_hashtab_insert_safe(tmp->peer_label_table, tmp);
7215 }
7218 if (el)
7219 el->next = tmp; /* in the middle... */
7220 else
7221 con->root = tmp; /* ... or at the head */
7222 e->next = NULL; /* e is no more at the head, so e->next must be reset */
7223 }
7224 /* And immediately return success. */
7225 if (tmp->priority == PRIORITY_HINT) {
7227 }
7228 }
7229 return 0;
7230}
static int replace(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)
Definition: func_strings.c:888
#define ast_hashtab_insert_safe(tab, obj)
Definition: hashtab.h:316
void * ast_hashtab_remove_object_via_lookup(struct ast_hashtab *tab, void *obj)
Looks up the object, removes the corresponding bucket.
Definition: hashtab.c:746
static struct match_char * add_exten_to_pattern_tree(struct ast_context *con, struct ast_exten *e1, int findonly)
Definition: pbx.c:1663
static int ast_change_hint(struct ast_exten *oe, struct ast_exten *ne)
Change hint for an extension.
Definition: pbx.c:4092
static int ast_add_hint(struct ast_exten *e)
Add hint to hint list, check initial extension state.
Definition: pbx.c:3978
#define PRIORITY_HINT
Definition: pbx.h:54
struct ast_exten * root
Definition: pbx.c:289
struct ast_hashtab * peer_label_table
Definition: pbx.c:252

References add_exten_to_pattern_tree(), ast_add_hint(), ast_change_hint(), ast_free, ast_hashtab_insert_safe, ast_hashtab_remove_object_via_lookup(), ast_log, ast_exten::data, ast_exten::datad, el, ast_exten::label, LOG_ERROR, LOG_WARNING, ast_exten::name, ast_context::name, ast_exten::next, NULL, ast_exten::peer, ast_exten::peer_label_table, ast_exten::peer_table, ast_exten::priority, PRIORITY_HINT, replace(), ast_context::root, ast_context::root_table, tmp(), and match_char::x.

Referenced by ast_add_extension2_lockopt().

◆ alloc_device_state_info()

static struct ao2_container * alloc_device_state_info ( void  )
static

Definition at line 3076 of file pbx.c.

3077{
3079}
@ AO2_ALLOC_OPT_LOCK_NOLOCK
Definition: astobj2.h:367
#define ao2_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn)
Allocate and initialize a list container.
Definition: astobj2.h:1327

References AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_container_alloc_list, and NULL.

Referenced by ast_extension_state_extended(), and device_state_notify_callbacks().

◆ already_in_tree()

static struct match_char * already_in_tree ( struct match_char current,
char *  pat,
int  is_pattern 
)
static

Definition at line 1402 of file pbx.c.

1403{
1404 struct match_char *t;
1405
1406 if (!current) {
1407 return 0;
1408 }
1409
1410 for (t = current; t; t = t->alt_char) {
1411 if (is_pattern == t->is_pattern && !strcmp(pat, t->x)) {/* uh, we may want to sort exploded [] contents to make matching easy */
1412 return t;
1413 }
1414 }
1415
1416 return 0;
1417}
struct match_char * alt_char
Definition: pbx.c:266

References match_char::alt_char, current, match_char::is_pattern, and match_char::x.

Referenced by add_exten_to_pattern_tree().

◆ ast_active_calls()

int ast_active_calls ( void  )

Retrieve the number of active calls.

Definition at line 4760 of file pbx.c.

4761{
4762 return countcalls;
4763}
static int countcalls
Definition: pbx.c:778

References countcalls.

Referenced by ast_var_Config(), get_current_call_count(), handle_chanlist(), handle_showcalls(), and sysinfo_helper().

◆ ast_add_extension()

int ast_add_extension ( const char *  context,
int  replace,
const char *  extension,
int  priority,
const char *  label,
const char *  callerid,
const char *  application,
void *  data,
void(*)(void *)  datad,
const char *  registrar 
)

Add and extension to an extension context.

Parameters
contextcontext to add the extension to
replace
extensionextension to add
prioritypriority level of extension addition
labelextension label
calleridpattern to match CallerID, or NULL to match any CallerID
applicationapplication to run on the extension with that priority level
datadata to pass to the application
datada pointer to a function that will deallocate data when needed or NULL if data does not need to be freed.
registrarwho registered the extension
Note
On any failure, the function pointed to by datap will be called and passed the data pointer.
Return values
0success
-1failure

Definition at line 6928 of file pbx.c.

6931{
6932 int ret = -1;
6933 struct ast_context *c;
6934
6936 if (c) {
6937 ret = ast_add_extension2(c, replace, extension, priority, label, callerid,
6938 application, data, datad, registrar, NULL, 0);
6940 }
6941
6942 return ret;
6943}
int ast_add_extension2(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)
Main interface to add extensions to the list for out context.
Definition: pbx.c:7257
static struct ast_context * find_context_locked(const char *context)
lookup for a context with a given name,
Definition: pbx.c:4814
int ast_unlock_contexts(void)
Unlocks contexts.
Definition: pbx.c:8473
char data[]
Definition: pbx.c:304

References ast_add_extension2(), ast_unlock_contexts(), c, voicemailpwcheck::context, ast_context::data, find_context_locked(), NULL, priority, registrar, and replace().

Referenced by add_to_regcontext(), app_create(), ast_hint_presence_state(), ast_sip_persistent_endpoint_update_state(), AST_TEST_DEFINE(), create_test_dialplan(), device_state_cb(), extension_state_add_destroy(), handle_cli_dialplan_add_extension(), internal_extension_state_extended(), join_conference_bridge(), load_module(), register_extension(), register_peer_exten(), sla_build_station(), and sla_build_trunk().

◆ ast_add_extension2()

int ast_add_extension2 ( struct ast_context con,
int  replace,
const char *  extension,
int  priority,
const char *  label,
const char *  callerid,
const char *  application,
void *  data,
void(*)(void *)  datad,
const char *  registrar,
const char *  registrar_file,
int  registrar_line 
)

Main interface to add extensions to the list for out context.

Add an extension to an extension context, this time with an ast_context *.

We sort extensions in order of matching preference, so that we can stop the search as soon as we find a suitable match. This ordering also takes care of wildcards such as '.' (meaning "one or more of any character") and '!' (which is 'earlymatch', meaning "zero or more of any character" but also impacts the return value from CANMATCH and EARLYMATCH.

The extension match rules defined in the devmeeting 2006.05.05 are quite simple: WE SELECT THE LONGEST MATCH. In detail, "longest" means the number of matched characters in the extension. In case of ties (e.g. _XXX and 333) in the length of a pattern, we give priority to entries with the smallest cardinality (e.g, [5-9] comes before [2-8] before the former has only 5 elements, while the latter has 7, etc. In case of same cardinality, the first element in the range counts. If we still have a tie, any final '!' will make this as a possibly less specific pattern.

EBUSY - can't lock EEXIST - extension with the same priority exist and no replace is set

Definition at line 7257 of file pbx.c.

7261{
7262 return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid,
7263 application, data, datad, registrar, registrar_file, registrar_line, 1);
7264}
static int ast_add_extension2_lockopt(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, int lock_context)
Same as ast_add_extension2() but controls the context locking.
Definition: pbx.c:7283

References ast_add_extension2_lockopt(), priority, registrar, and replace().

Referenced by add_extensions(), ast_add_extension(), context_merge(), lua_register_hints(), manager_dialplan_extension_add(), pbx_load_config(), and pbx_load_users().

◆ ast_add_extension2_lockopt()

static int ast_add_extension2_lockopt ( struct ast_context con,
int  replace,
const char *  extension,
int  priority,
const char *  label,
const char *  callerid,
const char *  application,
void *  data,
void(*)(void *)  datad,
const char *  registrar,
const char *  registrar_file,
int  registrar_line,
int  lock_context 
)
static

Same as ast_add_extension2() but controls the context locking.

Does all the work of ast_add_extension2, but adds an arg to determine if context locking should be done.

Definition at line 7283 of file pbx.c.

7287{
7288 /*
7289 * Sort extensions (or patterns) according to the rules indicated above.
7290 * These are implemented by the function ext_cmp()).
7291 * All priorities for the same ext/pattern/cid are kept in a list,
7292 * using the 'peer' field as a link field..
7293 */
7294 struct ast_exten *tmp, *tmp2, *e, *el = NULL;
7295 int res;
7296 int length;
7297 char *p;
7298 char expand_buf[VAR_BUF_SIZE];
7299 struct ast_exten dummy_exten = {0};
7300 char dummy_name[1024];
7301 int exten_fluff;
7302 int callerid_fluff;
7303
7305 ast_log(LOG_ERROR,"You have to be kidding-- add exten '' to context %s? Figure out a name and call me back. Action ignored.\n",
7306 con->name);
7307 /* We always need to deallocate 'data' on failure */
7308 if (datad) {
7309 datad(data);
7310 }
7311 return -1;
7312 }
7313
7314 /* If we are adding a hint evaluate in variables and global variables */
7315 if (priority == PRIORITY_HINT && strstr(application, "${") && extension[0] != '_') {
7316 int inhibited;
7318
7319 if (c) {
7322 }
7323
7324 /*
7325 * We can allow dangerous functions when adding a hint since
7326 * altering dialplan is itself a privileged activity. Otherwise,
7327 * we could never execute dangerous functions.
7328 */
7330 pbx_substitute_variables_helper(c, application, expand_buf, sizeof(expand_buf));
7331 if (0 < inhibited) {
7333 }
7334
7335 application = expand_buf;
7336 if (c) {
7338 }
7339 }
7340
7341 if (priority == PRIORITY_HINT) {
7342 /* Fluff in a hint is fine. This prevents the removal of dashes from dynamically
7343 * created hints during a reload. */
7344 exten_fluff = 0;
7345 } else {
7346 exten_fluff = ext_fluff_count(extension);
7347 }
7348
7349 callerid_fluff = callerid ? ext_fluff_count(callerid) : 0;
7350
7351 length = sizeof(struct ast_exten);
7352 length += strlen(extension) + 1;
7353 if (exten_fluff) {
7354 length += strlen(extension) + 1 - exten_fluff;
7355 }
7356 length += strlen(application) + 1;
7357 if (label) {
7358 length += strlen(label) + 1;
7359 }
7360 if (callerid) {
7361 length += strlen(callerid) + 1;
7362 if (callerid_fluff) {
7363 length += strlen(callerid) + 1 - callerid_fluff;
7364 }
7365 } else {
7366 length ++; /* just the '\0' */
7367 }
7368 if (registrar_file) {
7369 length += strlen(registrar_file) + 1;
7370 }
7371
7372 /* Be optimistic: Build the extension structure first */
7373 tmp = ast_calloc(1, length);
7374 if (!tmp) {
7375 /* We always need to deallocate 'data' on failure */
7376 if (datad) {
7377 datad(data);
7378 }
7379 return -1;
7380 }
7381
7382 if (ast_strlen_zero(label)) /* let's turn empty labels to a null ptr */
7383 label = 0;
7384
7385 /* use p as dst in assignments, as the fields are const char * */
7386 p = tmp->stuff;
7387 if (label) {
7388 tmp->label = p;
7389 strcpy(p, label);
7390 p += strlen(label) + 1;
7391 }
7392 tmp->name = p;
7393 p += ext_strncpy(p, extension, strlen(extension) + 1, 0);
7394 if (exten_fluff) {
7395 tmp->exten = p;
7396 p += ext_strncpy(p, extension, strlen(extension) + 1 - exten_fluff, 1);
7397 } else {
7398 /* no fluff, we don't need a copy. */
7399 tmp->exten = tmp->name;
7400 }
7401 tmp->priority = priority;
7402 tmp->cidmatch_display = tmp->cidmatch = p; /* but use p for assignments below */
7403
7404 /* Blank callerid and NULL callerid are two SEPARATE things. Do NOT confuse the two!!! */
7405 if (callerid) {
7406 p += ext_strncpy(p, callerid, strlen(callerid) + 1, 0);
7407 if (callerid_fluff) {
7408 tmp->cidmatch = p;
7409 p += ext_strncpy(p, callerid, strlen(callerid) + 1 - callerid_fluff, 1);
7410 }
7411 tmp->matchcid = AST_EXT_MATCHCID_ON;
7412 } else {
7413 *p++ = '\0';
7414 tmp->matchcid = AST_EXT_MATCHCID_OFF;
7415 }
7416
7417 if (registrar_file) {
7418 tmp->registrar_file = p;
7419 strcpy(p, registrar_file);
7420 p += strlen(registrar_file) + 1;
7421 } else {
7422 tmp->registrar_file = NULL;
7423 }
7424
7425 tmp->app = p;
7426 strcpy(p, application);
7427 tmp->parent = con;
7428 tmp->data = data;
7429 tmp->datad = datad;
7430 tmp->registrar = registrar;
7431 tmp->registrar_line = registrar_line;
7432
7433 if (lock_context) {
7434 ast_wrlock_context(con);
7435 }
7436
7437 if (con->pattern_tree) { /* usually, on initial load, the pattern_tree isn't formed until the first find_exten; so if we are adding
7438 an extension, and the trie exists, then we need to incrementally add this pattern to it. */
7439 ext_strncpy(dummy_name, tmp->exten, sizeof(dummy_name), 1);
7440 dummy_exten.exten = dummy_name;
7441 dummy_exten.matchcid = AST_EXT_MATCHCID_OFF;
7442 dummy_exten.cidmatch = 0;
7443 tmp2 = ast_hashtab_lookup(con->root_table, &dummy_exten);
7444 if (!tmp2) {
7445 /* hmmm, not in the trie; */
7447 ast_hashtab_insert_safe(con->root_table, tmp); /* for the sake of completeness */
7448 }
7449 }
7450 res = 0; /* some compilers will think it is uninitialized otherwise */
7451 for (e = con->root; e; el = e, e = e->next) { /* scan the extension list */
7452 res = ext_cmp(e->exten, tmp->exten);
7453 if (res == 0) { /* extension match, now look at cidmatch */
7454 if (e->matchcid == AST_EXT_MATCHCID_OFF && tmp->matchcid == AST_EXT_MATCHCID_OFF)
7455 res = 0;
7456 else if (tmp->matchcid == AST_EXT_MATCHCID_ON && e->matchcid == AST_EXT_MATCHCID_OFF)
7457 res = 1;
7458 else if (e->matchcid == AST_EXT_MATCHCID_ON && tmp->matchcid == AST_EXT_MATCHCID_OFF)
7459 res = -1;
7460 else
7461 res = ext_cmp(e->cidmatch, tmp->cidmatch);
7462 }
7463 if (res >= 0)
7464 break;
7465 }
7466 if (e && res == 0) { /* exact match, insert in the priority chain */
7467 res = add_priority(con, tmp, el, e, replace);
7468 if (res < 0) {
7469 if (con->pattern_tree) {
7470 struct match_char *x = add_exten_to_pattern_tree(con, tmp, 1);
7471
7472 if (x->exten) {
7473 x->deleted = 1;
7474 x->exten = 0;
7475 }
7476
7478 }
7479
7480 if (tmp->datad) {
7481 tmp->datad(tmp->data);
7482 /* if you free this, null it out */
7483 tmp->data = NULL;
7484 }
7485
7486 ast_free(tmp);
7487 }
7488 if (lock_context) {
7489 ast_unlock_context(con);
7490 }
7491 if (res < 0) {
7492 errno = EEXIST;
7493 return -1;
7494 }
7495 } else {
7496 /*
7497 * not an exact match, this is the first entry with this pattern,
7498 * so insert in the main list right before 'e' (if any)
7499 */
7500 tmp->next = e;
7501 tmp->peer_table = ast_hashtab_create(13,
7506 0);
7507 tmp->peer_label_table = ast_hashtab_create(7,
7512 0);
7513
7514 if (el) { /* there is another exten already in this context */
7515 el->next = tmp;
7516 } else { /* this is the first exten in this context */
7517 if (!con->root_table) {
7523 0);
7524 }
7525 con->root = tmp;
7526 }
7527 if (label) {
7528 ast_hashtab_insert_safe(tmp->peer_label_table, tmp);
7529 }
7530 ast_hashtab_insert_safe(tmp->peer_table, tmp);
7532
7533 if (lock_context) {
7534 ast_unlock_context(con);
7535 }
7536 if (tmp->priority == PRIORITY_HINT) {
7538 }
7539 }
7540 if (DEBUG_ATLEAST(1)) {
7541 if (tmp->matchcid == AST_EXT_MATCHCID_ON) {
7542 ast_log(LOG_DEBUG, "Added extension '%s' priority %d (CID match '%s') to %s (%p)\n",
7543 tmp->name, tmp->priority, tmp->cidmatch_display, con->name, con);
7544 } else {
7545 ast_log(LOG_DEBUG, "Added extension '%s' priority %d to %s (%p)\n",
7546 tmp->name, tmp->priority, con->name, con);
7547 }
7548 }
7549
7550 return 0;
7551}
void ast_channel_exten_set(struct ast_channel *chan, const char *value)
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2958
void ast_channel_context_set(struct ast_channel *chan, const char *value)
#define ast_dummy_channel_alloc()
Create a fake channel structure.
Definition: channel.h:1282
int ast_hashtab_newsize_java(struct ast_hashtab *tab)
Create a prime number roughly 2x the current table size.
Definition: hashtab.c:127
void * ast_hashtab_lookup(struct ast_hashtab *tab, const void *obj)
Lookup this object in the hash table.
Definition: hashtab.c:486
#define ast_hashtab_create(initial_buckets, compare, resize, newsize, hash, do_locking)
Create the hashtable list.
Definition: hashtab.h:254
int ast_hashtab_resize_java(struct ast_hashtab *tab)
Determines if a table resize should occur using the Java algorithm (if the table load factor is 75% o...
Definition: hashtab.c:84
#define DEBUG_ATLEAST(level)
#define LOG_DEBUG
int errno
static int hashtab_compare_extens(const void *ha_a, const void *ah_b)
Definition: pbx.c:698
static int hashtab_compare_exten_numbers(const void *ah_a, const void *ah_b)
Definition: pbx.c:726
static int ext_cmp(const char *left, const char *right)
Definition: pbx.c:2140
static int add_priority(struct ast_context *con, struct ast_exten *tmp, struct ast_exten *el, struct ast_exten *e, int replace)
add the extension in the priority chain.
Definition: pbx.c:7067
static int ext_fluff_count(const char *exten)
Definition: pbx.c:2162
static unsigned int hashtab_hash_extens(const void *obj)
Definition: pbx.c:746
static unsigned int hashtab_hash_priority(const void *obj)
Definition: pbx.c:756
static unsigned int ext_strncpy(char *dst, const char *src, size_t dst_size, int nofluff)
Definition: pbx.c:7026
static int hashtab_compare_exten_labels(const void *ah_a, const void *ah_b)
Definition: pbx.c:733
static unsigned int hashtab_hash_labels(const void *obj)
Definition: pbx.c:762
int ast_thread_inhibit_escalations_swap(int inhibit)
Swap the current thread escalation inhibit setting.
@ AST_EXT_MATCHCID_ON
Definition: pbx.h:79
@ AST_EXT_MATCHCID_OFF
Definition: pbx.h:78
int ast_thread_inhibit_escalations(void)
Inhibit (in the current thread) the execution of dialplan functions which cause privilege escalations...
void pbx_substitute_variables_helper(struct ast_channel *c, const char *cp1, char *cp2, int count)
Definition: ael_main.c:211
#define VAR_BUF_SIZE
Definition: pbx_private.h:68
const char * registrar_file
Definition: pbx.c:254
int registrar_line
Definition: pbx.c:255
void * data
Definition: pbx.c:248
void(* datad)(void *)
Definition: pbx.c:249
const char * label
Definition: pbx.c:244

References add_exten_to_pattern_tree(), add_priority(), ast_add_hint(), ast_calloc, ast_channel_context_set(), ast_channel_exten_set(), ast_channel_unref, ast_dummy_channel_alloc, AST_EXT_MATCHCID_OFF, AST_EXT_MATCHCID_ON, ast_free, ast_hashtab_create, ast_hashtab_insert_safe, ast_hashtab_lookup(), ast_hashtab_newsize_java(), ast_hashtab_remove_this_object(), ast_hashtab_resize_java(), ast_log, ast_strlen_zero(), ast_thread_inhibit_escalations(), ast_thread_inhibit_escalations_swap(), ast_unlock_context(), ast_wrlock_context(), c, ast_exten::cidmatch, ast_exten::data, ast_exten::datad, DEBUG_ATLEAST, el, errno, ext_cmp(), ext_fluff_count(), ext_strncpy(), ast_exten::exten, hashtab_compare_exten_labels(), hashtab_compare_exten_numbers(), hashtab_compare_extens(), hashtab_hash_extens(), hashtab_hash_labels(), hashtab_hash_priority(), ast_exten::label, LOG_DEBUG, LOG_ERROR, ast_exten::matchcid, ast_context::name, ast_exten::next, NULL, ast_context::pattern_tree, pbx_substitute_variables_helper(), priority, PRIORITY_HINT, registrar, ast_exten::registrar_file, ast_exten::registrar_line, replace(), ast_context::root, ast_context::root_table, tmp(), VAR_BUF_SIZE, and match_char::x.

Referenced by ast_add_extension2(), ast_add_extension2_nolock(), and ast_add_extension_nolock().

◆ ast_add_extension2_nolock()

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(*)(void *)  datad,
const char *  registrar,
const char *  registrar_file,
int  registrar_line 
)

Same as ast_add_extension2, but assumes you have already locked context.

Since
12.0.0
Note
con must be write locked prior to calling. For details about the arguments, check ast_add_extension()

Definition at line 7266 of file pbx.c.

7270{
7271 return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid,
7272 application, data, datad, registrar, registrar_file, registrar_line, 0);
7273}

References ast_add_extension2_lockopt(), priority, registrar, and replace().

Referenced by add_extension(), parking_add_extension(), and parking_duration_callback().

◆ ast_add_extension_nolock()

static int ast_add_extension_nolock ( const char *  context,
int  replace,
const char *  extension,
int  priority,
const char *  label,
const char *  callerid,
const char *  application,
void *  data,
void(*)(void *)  datad,
const char *  registrar 
)
static

Definition at line 6908 of file pbx.c.

6911{
6912 int ret = -1;
6913 struct ast_context *c;
6914
6916 if (c) {
6917 ret = ast_add_extension2_lockopt(c, replace, extension, priority, label, callerid,
6918 application, data, datad, registrar, NULL, 0, 1);
6919 }
6920
6921 return ret;
6922}
static struct ast_context * find_context(const char *context)
lookup for a context with a given name,
Definition: pbx.c:4800

References ast_add_extension2_lockopt(), c, voicemailpwcheck::context, ast_context::data, find_context(), NULL, priority, registrar, and replace().

Referenced by ast_merge_contexts_and_delete().

◆ ast_add_hint()

static int ast_add_hint ( struct ast_exten e)
static

Add hint to hint list, check initial extension state.

Definition at line 3978 of file pbx.c.

3979{
3980 struct ast_hint *hint_new;
3981 struct ast_hint *hint_found;
3982 char *message = NULL;
3983 char *subtype = NULL;
3984 int presence_state;
3985
3986 if (!e) {
3987 return -1;
3988 }
3989
3990 /*
3991 * We must create the hint we wish to add before determining if
3992 * it is already in the hints container to avoid possible
3993 * deadlock when getting the current extension state.
3994 */
3995 hint_new = ao2_alloc(sizeof(*hint_new), destroy_hint);
3996 if (!hint_new) {
3997 return -1;
3998 }
3999 AST_VECTOR_INIT(&hint_new->devices, 8);
4000
4001 /* Initialize new hint. */
4003 if (!hint_new->callbacks) {
4004 ao2_ref(hint_new, -1);
4005 return -1;
4006 }
4007 hint_new->exten = e;
4008 if (strstr(e->app, "${") && e->exten[0] == '_') {
4009 /* The hint is dynamic and hasn't been evaluated yet */
4010 hint_new->laststate = AST_DEVICE_INVALID;
4012 } else {
4013 hint_new->laststate = ast_extension_state2(e, NULL);
4014 if ((presence_state = extension_presence_state_helper(e, &subtype, &message)) > 0) {
4015 hint_new->last_presence_state = presence_state;
4016 hint_new->last_presence_subtype = subtype;
4017 hint_new->last_presence_message = message;
4018 }
4019 }
4020
4021 /* Prevent multiple add hints from adding the same hint at the same time. */
4022 ao2_lock(hints);
4023
4024 /* Search if hint exists, do nothing */
4025 hint_found = ao2_find(hints, e, 0);
4026 if (hint_found) {
4027 ao2_ref(hint_found, -1);
4029 ao2_ref(hint_new, -1);
4030 ast_debug(2, "HINTS: Not re-adding existing hint %s: %s\n",
4032 return -1;
4033 }
4034
4035 /* Add new hint to the hints container */
4036 ast_debug(2, "HINTS: Adding hint %s: %s\n",
4038 ao2_link(hints, hint_new);
4039 if (add_hintdevice(hint_new, ast_get_extension_app(e))) {
4040 ast_log(LOG_WARNING, "Could not add devices for hint: %s@%s.\n",
4043 }
4044
4045 /* if not dynamic */
4046 if (!(strstr(e->app, "${") && e->exten[0] == '_')) {
4047 struct ast_state_cb *state_cb;
4048 struct ao2_iterator cb_iter;
4049
4050 /* For general callbacks */
4051 cb_iter = ao2_iterator_init(statecbs, 0);
4052 for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_ref(state_cb, -1)) {
4056 state_cb->data,
4058 hint_new,
4059 NULL);
4060 }
4061 ao2_iterator_destroy(&cb_iter);
4062 }
4064 ao2_ref(hint_new, -1);
4065
4066 return 0;
4067}
#define ao2_link(container, obj)
Add an object to a container.
Definition: astobj2.h:1532
@ AO2_ALLOC_OPT_LOCK_MUTEX
Definition: astobj2.h:363
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1736
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:409
@ AST_DEVICE_INVALID
Definition: devicestate.h:57
static struct ao2_container * statecbs
Definition: pbx.c:808
const char * ast_get_extension_app(struct ast_exten *e)
Definition: pbx.c:8557
static int execute_state_callback(ast_state_cb_type cb, const char *context, const char *exten, void *data, enum ast_state_cb_update_reason reason, struct ast_hint *hint, struct ao2_container *device_state_info)
Definition: pbx.c:3250
static void destroy_hint(void *obj)
Definition: pbx.c:3903
struct ast_context * ast_get_extension_context(struct ast_exten *exten)
Definition: pbx.c:8504
static int ast_extension_state2(struct ast_exten *e, struct ao2_container *device_state_info)
Check state of extension by using hints.
Definition: pbx.c:3113
const char * ast_get_context_name(struct ast_context *con)
Definition: pbx.c:8499
static int extension_presence_state_helper(struct ast_exten *e, char **subtype, char **message)
Definition: pbx.c:3200
static int hint_id_cmp(void *obj, void *arg, int flags)
Definition: pbx.c:3889
static int add_hintdevice(struct ast_hint *hint, const char *devicelist)
add hintdevice structure and link it into the container.
Definition: pbx.c:557
const char * ast_get_extension_name(struct ast_exten *exten)
Definition: pbx.c:8509
@ AST_HINT_UPDATE_DEVICE
Definition: pbx.h:91
@ AST_PRESENCE_INVALID
Definition: presencestate.h:39
struct ao2_container * callbacks
Definition: pbx.c:339
int last_presence_state
Definition: pbx.c:345
char * last_presence_subtype
Definition: pbx.c:346
char * last_presence_message
Definition: pbx.c:347
ast_state_cb: An extension state notify register item
Definition: pbx.c:308
ast_state_cb_type change_cb
Definition: pbx.c:316
void * data
Definition: pbx.c:312
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition: vector.h:113

References add_hintdevice(), ao2_alloc, AO2_ALLOC_OPT_LOCK_MUTEX, ao2_container_alloc_list, ao2_find, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_link, ao2_lock, ao2_ref, ao2_unlock, ast_exten::app, ast_debug, AST_DEVICE_INVALID, ast_extension_state2(), ast_get_context_name(), ast_get_extension_app(), ast_get_extension_context(), ast_get_extension_name(), AST_HINT_UPDATE_DEVICE, ast_log, AST_PRESENCE_INVALID, AST_VECTOR_INIT, ast_hint::callbacks, ast_state_cb::change_cb, ast_state_cb::data, destroy_hint(), ast_hint::devices, execute_state_callback(), ast_exten::exten, ast_hint::exten, extension_presence_state_helper(), hint_id_cmp(), ast_hint::last_presence_message, ast_hint::last_presence_state, ast_hint::last_presence_subtype, ast_hint::laststate, LOG_WARNING, NULL, and statecbs.

Referenced by add_priority(), and ast_add_extension2_lockopt().

◆ ast_async_goto()

int ast_async_goto ( struct ast_channel chan,
const char *  context,
const char *  exten,
int  priority 
)

Set the channel to next execute the specified dialplan location.

See also
ast_async_parseable_goto, ast_async_goto_if_exists
Note
Do NOT hold any channel locks when calling this function.

Definition at line 6969 of file pbx.c.

6970{
6971 struct ast_channel *newchan;
6972
6973 ast_channel_lock(chan);
6974 /* Channels in a bridge or running a PBX can be sent directly to the specified destination */
6975 if (ast_channel_is_bridged(chan) || ast_channel_pbx(chan)) {
6977 priority += 1;
6978 }
6981 ast_channel_unlock(chan);
6982 return 0;
6983 }
6984 ast_channel_unlock(chan);
6985
6986 /* Otherwise, we need to gain control of the channel first */
6987 newchan = ast_channel_yank(chan);
6988 if (!newchan) {
6989 ast_log(LOG_WARNING, "Unable to gain control of channel %s\n", ast_channel_name(chan));
6990 return -1;
6991 }
6993 if (ast_pbx_start(newchan)) {
6994 ast_hangup(newchan);
6995 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(newchan));
6996 return -1;
6997 }
6998
6999 return 0;
7000}
struct ast_channel * ast_channel_yank(struct ast_channel *yankee)
Gain control of a channel in the system.
Definition: channel.c:10593
int ast_channel_is_bridged(const struct ast_channel *chan)
Determine if a channel is in a bridge.
Definition: channel.c:10545
int ast_softhangup_nolock(struct ast_channel *chan, int cause)
Softly hangup up a channel (no channel lock)
Definition: channel.c:2458
enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
Create a new thread and start the PBX.
Definition: pbx.c:4708

References ast_channel_flags(), ast_channel_is_bridged(), ast_channel_lock, ast_channel_name(), ast_channel_pbx(), ast_channel_unlock, ast_channel_yank(), ast_explicit_goto(), AST_FLAG_IN_AUTOLOOP, ast_hangup(), ast_log, ast_pbx_start(), AST_SOFTHANGUP_ASYNCGOTO, ast_softhangup_nolock(), ast_test_flag, voicemailpwcheck::context, ast_channel::exten, LOG_WARNING, and priority.

Referenced by __ast_goto_if_exists(), action_redirect(), ast_async_goto_by_name(), bridge_channel_blind_transfer(), chan_pjsip_cng_tone_detected(), comeback_goto(), dahdi_handle_dtmf(), fax_detect_framehook(), my_handle_dtmf(), onModeChanged(), ooh323_rtp_read(), and pbx_parseable_goto().

◆ ast_async_goto_by_name()

int ast_async_goto_by_name ( const char *  channame,
const char *  context,
const char *  exten,
int  priority 
)

Set the channel to next execute the specified dialplan location.

Definition at line 7002 of file pbx.c.

7003{
7004 struct ast_channel *chan;
7005 int res = -1;
7006
7007 if ((chan = ast_channel_get_by_name(channame))) {
7008 res = ast_async_goto(chan, context, exten, priority);
7009 chan = ast_channel_unref(chan);
7010 }
7011
7012 return res;
7013}
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1454

References ast_async_goto(), ast_channel_get_by_name(), ast_channel_unref, voicemailpwcheck::context, ast_channel::exten, and priority.

◆ ast_async_goto_if_exists()

int ast_async_goto_if_exists ( struct ast_channel chan,
const char *  context,
const char *  exten,
int  priority 
)
Note
This function will handle locking the channel as needed.

Definition at line 8786 of file pbx.c.

8787{
8788 return __ast_goto_if_exists(chan, context, exten, priority, 1);
8789}
static int __ast_goto_if_exists(struct ast_channel *chan, const char *context, const char *exten, int priority, int async)
Definition: pbx.c:8760

References __ast_goto_if_exists(), voicemailpwcheck::context, ast_channel::exten, and priority.

◆ ast_async_parseable_goto()

int ast_async_parseable_goto ( struct ast_channel chan,
const char *  goto_string 
)
Note
This function will handle locking the channel as needed.

Definition at line 8871 of file pbx.c.

8872{
8873 return pbx_parseable_goto(chan, goto_string, 1);
8874}
static int pbx_parseable_goto(struct ast_channel *chan, const char *goto_string, int async)
Definition: pbx.c:8832

References pbx_parseable_goto().

Referenced by asyncgoto_exec(), detect_callback(), handle_redirect(), and parking_duration_callback().

◆ ast_canmatch_extension()

int ast_canmatch_extension ( struct ast_channel c,
const char *  context,
const char *  exten,
int  priority,
const char *  callerid 
)

Looks for a valid matching extension.

Parameters
cnot really important
contextcontext to search within
extenextension to check
prioritypriority of extension path
calleridcallerid of extension being searched for
Note
It is possible for autoservice to be started and stopped on c during this function call, it is important that c is not locked prior to calling this. Otherwise a deadlock may occur
Returns
If "exten" could be a valid extension in this context with or without some more digits, return non-zero. Basically, when this returns 0, no matter what you add to exten, it's not going to be a valid extension anymore

Definition at line 4190 of file pbx.c.

4191{
4192 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH, 0, 0);
4193}
@ E_CANMATCH
Definition: extconf.h:216
static int pbx_extension_helper(struct ast_channel *c, struct ast_context *con, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action, int *found, int combined_find_spawn)
The return value depends on the action:
Definition: pbx.c:2875

References c, voicemailpwcheck::context, E_CANMATCH, ast_exten::exten, NULL, pbx_extension_helper(), and priority.

Referenced by __analog_ss_thread(), analog_ss_thread(), background_detect_exec(), dp_lookup(), dundi_lookup_local(), get_destination(), leave_voicemail(), loopback_canmatch(), pbx_builtin_background(), test_exten(), and valid_exit().

◆ ast_change_hint()

static int ast_change_hint ( struct ast_exten oe,
struct ast_exten ne 
)
static

Change hint for an extension.

Definition at line 4092 of file pbx.c.

4093{
4094 struct ast_hint *hint;
4095
4096 if (!oe || !ne) {
4097 return -1;
4098 }
4099
4100 ao2_lock(hints);/* Locked to hold off others while we move the hint around. */
4101
4102 /*
4103 * Unlink the hint from the hints container as the extension
4104 * name (which is the hash value) could change.
4105 */
4106 hint = ao2_find(hints, oe, OBJ_UNLINK);
4107 if (!hint) {
4110 return -1;
4111 }
4112
4113 remove_hintdevice(hint);
4114
4115 /* Update the hint and put it back in the hints container. */
4116 ao2_lock(hint);
4117 hint->exten = ne;
4118
4119 ao2_unlock(hint);
4120
4121 ao2_link(hints, hint);
4122 if (add_hintdevice(hint, ast_get_extension_app(ne))) {
4123 ast_log(LOG_WARNING, "Could not add devices for hint: %s@%s.\n",
4126 }
4128
4129 publish_hint_change(hint, ne);
4130
4131 ao2_ref(hint, -1);
4132
4133 return 0;
4134}
@ OBJ_UNLINK
Definition: astobj2.h:1039
#define ast_mutex_unlock(a)
Definition: lock.h:190
static int publish_hint_change(struct ast_hint *hint, struct ast_exten *ne)
Publish a hint changed event
Definition: pbx.c:4070
static int remove_hintdevice(struct ast_hint *hint)
Definition: pbx.c:524
static ast_mutex_t context_merge_lock
Lock to hold off restructuring of hints by ast_merge_contexts_and_delete.
Definition: pbx.c:795

References add_hintdevice(), ao2_find, ao2_link, ao2_lock, ao2_ref, ao2_unlock, ast_get_context_name(), ast_get_extension_app(), ast_get_extension_context(), ast_get_extension_name(), ast_log, ast_mutex_unlock, context_merge_lock, ast_hint::exten, LOG_WARNING, OBJ_UNLINK, publish_hint_change(), and remove_hintdevice().

Referenced by add_priority().

◆ ast_context_add_ignorepat()

int ast_context_add_ignorepat ( const char *  context,
const char *  ignorepat,
const char *  registrar 
)

Add an ignorepat.

Parameters
contextwhich context to add the ignorepattern to
ignorepatignorepattern to set up for the extension
registrarregistrar of the ignore pattern

Adds an ignore pattern to a particular context.

Return values
0on success
-1on failure

Definition at line 6835 of file pbx.c.

6836{
6837 int ret = -1;
6838 struct ast_context *c;
6839
6841 if (c) {
6844 }
6845 return ret;
6846}
int ast_context_add_ignorepat2(struct ast_context *con, const char *value, const char *registrar)
Definition: pbx.c:6848
int value
Definition: syslog.c:37

References ast_context_add_ignorepat2(), ast_unlock_contexts(), c, voicemailpwcheck::context, find_context_locked(), registrar, and value.

Referenced by handle_cli_dialplan_add_ignorepat().

◆ ast_context_add_ignorepat2()

int ast_context_add_ignorepat2 ( struct ast_context con,
const char *  value,
const char *  registrar 
)

Definition at line 6848 of file pbx.c.

6849{
6850 struct ast_ignorepat *ignorepat = ignorepat_alloc(value, registrar);
6851 int idx;
6852
6853 if (!ignorepat) {
6854 return -1;
6855 }
6856
6857 ast_wrlock_context(con);
6858 for (idx = 0; idx < ast_context_ignorepats_count(con); idx++) {
6859 const struct ast_ignorepat *i = ast_context_ignorepats_get(con, idx);
6860
6861 if (!strcasecmp(ast_get_ignorepat_name(i), value)) {
6862 /* Already there */
6863 ast_unlock_context(con);
6864 ignorepat_free(ignorepat);
6865 errno = EEXIST;
6866 return -1;
6867 }
6868 }
6869 if (AST_VECTOR_APPEND(&con->ignorepats, ignorepat)) {
6870 ignorepat_free(ignorepat);
6871 ast_unlock_context(con);
6872 return -1;
6873 }
6874 ast_unlock_context(con);
6875
6876 return 0;
6877}
const struct ast_ignorepat * ast_context_ignorepats_get(const struct ast_context *con, int idx)
Definition: pbx.c:8727
const char * ast_get_ignorepat_name(const struct ast_ignorepat *ip)
Definition: pbx_ignorepat.c:42
struct ast_ignorepat * ignorepat_alloc(const char *value, const char *registrar)
Definition: pbx_ignorepat.c:52
struct ast_ignorepats ignorepats
Definition: pbx.c:294

References ast_context_ignorepats_count(), ast_context_ignorepats_get(), ast_get_ignorepat_name(), ast_unlock_context(), AST_VECTOR_APPEND, ast_wrlock_context(), errno, ignorepat_alloc(), ignorepat_free(), ast_context::ignorepats, registrar, and value.

Referenced by ast_context_add_ignorepat(), and context_merge_incls_swits_igps_other_registrars().

◆ ast_context_add_include()

int ast_context_add_include ( const char *  context,
const char *  include,
const char *  registrar 
)

Add a context include.

Parameters
contextcontext to add include to
includenew include to add
registrarwho's registering it

Adds an include taking a char * string as the context parameter

Return values
0on success
-1on error

Definition at line 6664 of file pbx.c.

6665{
6666 int ret = -1;
6667 struct ast_context *c;
6668
6670 if (c) {
6671 ret = ast_context_add_include2(c, include, registrar);
6673 }
6674 return ret;
6675}
int ast_context_add_include2(struct ast_context *con, const char *value, const char *registrar)
Add a context include.
Definition: pbx.c:6684

References ast_context_add_include2(), ast_unlock_contexts(), c, voicemailpwcheck::context, find_context_locked(), and registrar.

Referenced by AST_TEST_DEFINE(), and handle_cli_dialplan_add_include().

◆ ast_context_add_include2()

int ast_context_add_include2 ( struct ast_context con,
const char *  value,
const char *  registrar 
)

Add a context include.

Adds an include taking a struct ast_context as the first parameter

Note
See ast_context_add_include for information on arguments

Definition at line 6684 of file pbx.c.

6686{
6687 struct ast_include *new_include;
6688 int idx;
6689
6690 /* allocate new include structure ... */
6691 new_include = include_alloc(value, registrar);
6692 if (!new_include) {
6693 return -1;
6694 }
6695
6696 ast_wrlock_context(con);
6697
6698 /* ... go to last include and check if context is already included too... */
6699 for (idx = 0; idx < ast_context_includes_count(con); idx++) {
6700 const struct ast_include *i = ast_context_includes_get(con, idx);
6701
6702 if (!strcasecmp(ast_get_include_name(i), ast_get_include_name(new_include))) {
6703 include_free(new_include);
6704 ast_unlock_context(con);
6705 errno = EEXIST;
6706 return -1;
6707 }
6708 }
6709
6710 /* ... include new context into context list, unlock, return */
6711 if (AST_VECTOR_APPEND(&con->includes, new_include)) {
6712 include_free(new_include);
6713 ast_unlock_context(con);
6714 return -1;
6715 }
6716 ast_debug(1, "Including context '%s' in context '%s'\n",
6717 ast_get_include_name(new_include), ast_get_context_name(con));
6718
6719 ast_unlock_context(con);
6720
6721 return 0;
6722}
const struct ast_include * ast_context_includes_get(const struct ast_context *con, int idx)
Definition: pbx.c:8684
const char * ast_get_include_name(const struct ast_include *include)
Definition: pbx_include.c:50
struct ast_include * include_alloc(const char *value, const char *registrar)
Definition: pbx_include.c:74
struct ast_includes includes
Definition: pbx.c:293

References ast_context_includes_count(), ast_context_includes_get(), ast_debug, ast_get_context_name(), ast_get_include_name(), ast_unlock_context(), AST_VECTOR_APPEND, ast_wrlock_context(), errno, include_alloc(), include_free(), ast_context::includes, registrar, and value.

Referenced by ast_context_add_include(), and context_merge_incls_swits_igps_other_registrars().

◆ ast_context_add_switch()

int ast_context_add_switch ( const char *  context,
const char *  sw,
const char *  data,
int  eval,
const char *  registrar 
)

Add a switch.

Parameters
contextcontext to which to add the switch
swswitch to add
datadata to pass to switch
evalwhether to evaluate variables when running switch
registrarwhoever registered the switch

This function registers a switch with the asterisk switch architecture

Return values
0on success
-1on failure

Definition at line 6729 of file pbx.c.

6730{
6731 int ret = -1;
6732 struct ast_context *c;
6733
6735 if (c) { /* found, add switch to this context */
6736 ret = ast_context_add_switch2(c, sw, data, eval, registrar);
6738 }
6739 return ret;
6740}
int ast_context_add_switch2(struct ast_context *con, const char *value, const char *data, int eval, const char *registrar)
Adds a switch (first param is a ast_context)
Definition: pbx.c:6749

References ast_context_add_switch2(), ast_unlock_contexts(), c, voicemailpwcheck::context, ast_context::data, find_context_locked(), and registrar.

◆ ast_context_add_switch2()

int ast_context_add_switch2 ( struct ast_context con,
const char *  value,
const char *  data,
int  eval,
const char *  registrar 
)

Adds a switch (first param is a ast_context)

Note
See ast_context_add_switch() for argument information, with the exception of the first argument. In this case, it's a pointer to an ast_context structure as opposed to the name.

Definition at line 6749 of file pbx.c.

6751{
6752 int idx;
6753 struct ast_sw *new_sw;
6754
6755 /* allocate new sw structure ... */
6756 if (!(new_sw = sw_alloc(value, data, eval, registrar))) {
6757 return -1;
6758 }
6759
6760 /* ... try to lock this context ... */
6761 ast_wrlock_context(con);
6762
6763 /* ... go to last sw and check if context is already swd too... */
6764 for (idx = 0; idx < ast_context_switches_count(con); idx++) {
6765 const struct ast_sw *i = ast_context_switches_get(con, idx);
6766
6767 if (!strcasecmp(ast_get_switch_name(i), ast_get_switch_name(new_sw)) &&
6768 !strcasecmp(ast_get_switch_data(i), ast_get_switch_data(new_sw))) {
6769 sw_free(new_sw);
6770 ast_unlock_context(con);
6771 errno = EEXIST;
6772 return -1;
6773 }
6774 }
6775
6776 /* ... sw new context into context list, unlock, return */
6777 if (AST_VECTOR_APPEND(&con->alts, new_sw)) {
6778 sw_free(new_sw);
6779 ast_unlock_context(con);
6780 return -1;
6781 }
6782
6783 ast_verb(3, "Including switch '%s/%s' in context '%s'\n",
6785
6786 ast_unlock_context(con);
6787
6788 return 0;
6789}
const struct ast_sw * ast_context_switches_get(const struct ast_context *con, int idx)
Definition: pbx.c:8639
const char * ast_get_switch_name(const struct ast_sw *sw)
Definition: pbx_sw.c:48
const char * ast_get_switch_data(const struct ast_sw *sw)
Definition: pbx_sw.c:53
struct ast_sw * sw_alloc(const char *value, const char *data, int eval, const char *registrar)
Definition: pbx_sw.c:68
struct ast_sws alts
Definition: pbx.c:295
int eval
Definition: pbx_sw.c:43
const char * data
Definition: pbx_sw.c:42

References ast_context::alts, ast_context_switches_count(), ast_context_switches_get(), ast_get_context_name(), ast_get_switch_data(), ast_get_switch_name(), ast_unlock_context(), AST_VECTOR_APPEND, ast_verb, ast_wrlock_context(), ast_sw::data, errno, ast_sw::eval, registrar, sw_alloc(), sw_free(), and value.

Referenced by ast_context_add_switch(), and context_merge_incls_swits_igps_other_registrars().

◆ ast_context_destroy()

void ast_context_destroy ( struct ast_context con,
const char *  registrar 
)

Destroy a context (matches the specified context or ANY context if NULL)

Parameters
concontext to destroy
registrarwho registered it

You can optionally leave out either parameter. It will find it based on either the ast_context or the registrar name.

Definition at line 8221 of file pbx.c.

8222{
8226}
void __ast_context_destroy(struct ast_context *list, struct ast_hashtab *contexttab, struct ast_context *con, const char *registrar)
Definition: pbx.c:8056
int ast_wrlock_contexts(void)
Write locks the context list.
Definition: pbx.c:8463
static struct ast_hashtab * contexts_table
Definition: pbx.c:782

References __ast_context_destroy(), ast_unlock_contexts(), ast_wrlock_contexts(), contexts, contexts_table, and registrar.

Referenced by ast_context_destroy_by_name(), AST_TEST_DEFINE(), parking_lot_cfg_remove_extensions(), remove_all_configured_parking_lot_extensions(), remove_pending_parking_lot_extensions(), sla_destroy(), and unload_module().

◆ ast_context_destroy_by_name()

int ast_context_destroy_by_name ( const char *  context,
const char *  registrar 
)

Destroy a context by name.

Parameters
contextName of the context to destroy
registrarwho registered it

You can optionally leave out the registrar parameter. It will find it based on the context name.

Return values
-1context not found
0Success

Definition at line 8205 of file pbx.c.

8206{
8207 struct ast_context *con;
8208 int ret = -1;
8209
8212 if (con) {
8214 ret = 0;
8215 }
8217
8218 return ret;
8219}
struct ast_context * ast_context_find(const char *name)
Find a context.
Definition: pbx.c:2439
void ast_context_destroy(struct ast_context *con, const char *registrar)
Destroy a context (matches the specified context or ANY context if NULL)
Definition: pbx.c:8221

References ast_context_destroy(), ast_context_find(), ast_unlock_contexts(), ast_wrlock_contexts(), voicemailpwcheck::context, and registrar.

Referenced by __unload_module(), app_dtor(), ast_sip_destroy_sorcery_global(), check_regcontext(), and handle_cli_dialplan_remove_context().

◆ ast_context_find()

struct ast_context * ast_context_find ( const char *  name)

Find a context.

Parameters
namename of the context to find

Will search for the context with the given name.

Returns
the ast_context on success, NULL on failure.

Definition at line 2439 of file pbx.c.

2440{
2441 struct ast_context *tmp;
2442 struct ast_context item = {
2443 .name = name,
2444 };
2445
2446 if (!name) {
2447 return NULL;
2448 }
2450 if (contexts_table) {
2452 } else {
2453 tmp = NULL;
2454 while ((tmp = ast_walk_contexts(tmp))) {
2455 if (!strcasecmp(name, tmp->name)) {
2456 break;
2457 }
2458 }
2459 }
2461 return tmp;
2462}
static const char name[]
Definition: format_mp3.c:68
struct ast_context * ast_walk_contexts(struct ast_context *con)
Definition: pbx.c:8591
int ast_rdlock_contexts(void)
Read locks the context list.
Definition: pbx.c:8468
const char * name
static struct aco_type item
Definition: test_config.c:1463

References ast_hashtab_lookup(), ast_rdlock_contexts(), ast_unlock_contexts(), ast_walk_contexts(), contexts_table, item, name, aco_type::name, NULL, and tmp().

Referenced by app_create(), ast_context_destroy_by_name(), ast_context_verify_includes(), ast_ignore_pattern(), context_included(), handle_cli_dialplan_add_extension(), handle_cli_dialplan_add_include(), and isexten_function_read().

◆ ast_context_find_or_create()

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.

Parameters
extcontextspointer to the ast_context structure pointer
exttablepointer to the hashtable that contains all the elements in extcontexts
namename of the new context
registrarregistrar of the context

This function allows you to play in two environments: the global contexts (active dialplan) or an external context set of your choosing. To act on the external set, make sure extcontexts and exttable are set; for the globals, make sure both extcontexts and exttable are NULL.

This will first search for a context with your name. If it exists already, it will not create a new one. If it does not exist, it will create a new one with the given name and registrar.

Returns
NULL on failure, and an ast_context structure on success

Definition at line 6149 of file pbx.c.

6150{
6151 struct ast_context *tmp, **local_contexts;
6152 struct ast_context search = {
6153 .name = name,
6154 };
6155 size_t name_bytes = strlen(name);
6156 size_t registrar_bytes = strlen(registrar);
6157 int length = sizeof(struct ast_context) + name_bytes + registrar_bytes + 2;
6158
6159 if (!contexts_table) {
6160 /* Protect creation of contexts_table from reentrancy. */
6162 if (!contexts_table) {
6168 0);
6169 }
6171 }
6172
6173 if (!extcontexts) {
6177 if (tmp) {
6178 tmp->refcount++;
6180 return tmp;
6181 }
6182 } else { /* local contexts just in a linked list; search there for the new context; slow, linear search, but not frequent */
6183 local_contexts = extcontexts;
6184 tmp = ast_hashtab_lookup(exttable, &search);
6185 if (tmp) {
6186 tmp->refcount++;
6187 return tmp;
6188 }
6189 }
6190
6191 if ((tmp = ast_calloc(1, length))) {
6192 ast_rwlock_init(&tmp->lock);
6193 tmp->name = memcpy(&tmp->data[0], name, name_bytes);
6194 tmp->registrar = memcpy(&tmp->data[name_bytes + 1], registrar, registrar_bytes);
6195 tmp->root = NULL;
6196 tmp->root_table = NULL;
6197 AST_VECTOR_INIT(&tmp->includes, 0);
6198 AST_VECTOR_INIT(&tmp->ignorepats, 0);
6199 AST_VECTOR_INIT(&tmp->alts, 0);
6200 tmp->refcount = 1;
6201
6202 /* The context 'name' must be stored at the beginning of 'data.' The
6203 * order of subsequent strings (currently only 'registrar') is not
6204 * relevant. */
6205 ast_assert(tmp->name == &tmp->data[0]);
6206 } else {
6207 ast_log(LOG_ERROR, "Danger! We failed to allocate a context for %s!\n", name);
6208 if (!extcontexts) {
6210 }
6211 return NULL;
6212 }
6213
6214 if (!extcontexts) {
6215 tmp->next = *local_contexts;
6217 ast_hashtab_insert_safe(contexts_table, tmp); /*put this context into the tree */
6219 } else {
6220 tmp->next = *local_contexts;
6221 if (exttable)
6222 ast_hashtab_insert_immediate(exttable, tmp); /*put this context into the tree */
6223
6225 }
6226 ast_debug(1, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar);
6227 return tmp;
6228}
#define ast_hashtab_insert_immediate(tab, obj)
Insert without checking.
Definition: hashtab.h:290
#define ast_rwlock_init(rwlock)
wrapper for rwlock with tracking enabled
Definition: lock.h:224
int ast_hashtab_compare_contexts(const void *ah_a, const void *ah_b)
hashtable functions for contexts
Definition: pbx.c:688
unsigned int ast_hashtab_hash_contexts(const void *obj)
Definition: pbx.c:740
static struct ast_context * local_contexts
Definition: pbx_config.c:113
#define ast_assert(a)
Definition: utils.h:739

References ast_assert, ast_calloc, ast_debug, ast_hashtab_compare_contexts(), ast_hashtab_create, ast_hashtab_hash_contexts(), ast_hashtab_insert_immediate, ast_hashtab_insert_safe, ast_hashtab_lookup(), ast_hashtab_newsize_java(), ast_hashtab_resize_java(), ast_log, ast_rdlock_contexts(), ast_rwlock_init, ast_unlock_contexts(), AST_VECTOR_INIT, ast_wrlock_contexts(), contexts, contexts_table, local_contexts, LOG_ERROR, name, ast_context::name, NULL, registrar, and tmp().

Referenced by add_hints(), app_create(), ast_compile_ael2(), ast_sip_persistent_endpoint_add_to_regcontext(), AST_TEST_DEFINE(), context_merge(), create_test_dialplan(), handle_cli_dialplan_add_extension(), handle_cli_dialplan_add_include(), load_module(), lua_register_hints(), lua_register_switches(), manager_dialplan_extension_add(), parking_duration_callback(), parking_lot_cfg_create_extensions(), pbx_load_config(), pbx_load_users(), set_config(), sla_build_station(), and sla_build_trunk().

◆ ast_context_ignorepats_count()

int ast_context_ignorepats_count ( const struct ast_context con)

◆ ast_context_ignorepats_get()

const struct ast_ignorepat * ast_context_ignorepats_get ( const struct ast_context con,
int  idx 
)

◆ ast_context_includes_count()

int ast_context_includes_count ( const struct ast_context con)

◆ ast_context_includes_get()

const struct ast_include * ast_context_includes_get ( const struct ast_context con,
int  idx 
)

◆ ast_context_remove_extension()

int ast_context_remove_extension ( const char *  context,
const char *  extension,
int  priority,
const char *  registrar 
)

Simply remove extension from context.

Note
This function will lock conlock.

Definition at line 4948 of file pbx.c.

4949{
4951}
int ast_context_remove_extension_callerid(const char *context, const char *extension, int priority, const char *callerid, int matchcallerid, const char *registrar)
Definition: pbx.c:4953
@ AST_EXT_MATCHCID_ANY
Definition: pbx.h:80

References ast_context_remove_extension_callerid(), AST_EXT_MATCHCID_ANY, voicemailpwcheck::context, NULL, priority, and registrar.

Referenced by ast_sip_persistent_endpoint_update_state(), AST_TEST_DEFINE(), conf_ended(), delete_extens(), register_peer_exten(), sla_station_destructor(), sla_trunk_destructor(), and unregister_extension().

◆ ast_context_remove_extension2()

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 extensions with given priority. If priority is set to 0, all peers are removed. After that, unlock context and return.

Note
When do you want to call this function, make sure that &conlock is locked, because some process can handle with your *con context before you lock it.

Definition at line 4978 of file pbx.c.

References ast_context_remove_extension_callerid2(), AST_EXT_MATCHCID_ANY, NULL, priority, and registrar.

Referenced by add_extension(), and add_hints().

◆ ast_context_remove_extension_callerid()

int ast_context_remove_extension_callerid ( const char *  context,
const char *  extension,
int  priority,
const char *  callerid,
int  matchcallerid,
const char *  registrar 
)

Definition at line 4953 of file pbx.c.

4954{
4955 int ret = -1; /* default error return */
4956 struct ast_context *c;
4957
4959 if (c) { /* ... remove extension ... */
4961 matchcallerid, registrar, 0);
4963 }
4964
4965 return ret;
4966}

References ast_context_remove_extension_callerid2(), ast_unlock_contexts(), c, voicemailpwcheck::context, find_context_locked(), priority, and registrar.

Referenced by ast_context_remove_extension(), handle_cli_dialplan_remove_extension(), and manager_dialplan_extension_remove().

◆ ast_context_remove_extension_callerid2()

int ast_context_remove_extension_callerid2 ( struct ast_context con,
const char *  extension,
int  priority,
const char *  callerid,
int  matchcallerid,
const char *  registrar,
int  already_locked 
)

Definition at line 4983 of file pbx.c.

4984{
4985 struct ast_exten *exten, *prev_exten = NULL;
4986 struct ast_exten *peer;
4987 struct ast_exten ex, *exten2, *exten3;
4988 char dummy_name[1024];
4989 char dummy_cid[1024];
4990 struct ast_exten *previous_peer = NULL;
4991 struct ast_exten *next_peer = NULL;
4992 int found = 0;
4993
4994 if (!already_locked)
4995 ast_wrlock_context(con);
4996
4997#ifdef NEED_DEBUG
4998 ast_verb(3,"Removing %s/%s/%d%s%s from trees, registrar=%s\n", con->name, extension, priority, matchcallerid ? "/" : "", matchcallerid ? callerid : "", registrar);
4999#endif
5000#ifdef CONTEXT_DEBUG
5001 check_contexts(__FILE__, __LINE__);
5002#endif
5003 /* find this particular extension */
5004 ex.exten = dummy_name;
5005 ext_strncpy(dummy_name, extension, sizeof(dummy_name), 1);
5006 ex.matchcid = matchcallerid;
5007 if (callerid) {
5008 ex.cidmatch = dummy_cid;
5009 ext_strncpy(dummy_cid, callerid, sizeof(dummy_cid), 1);
5010 } else {
5011 ex.cidmatch = NULL;
5012 }
5013 exten = ast_hashtab_lookup(con->root_table, &ex);
5014 if (exten) {
5015 if (priority == 0) {
5017 if (!exten2)
5018 ast_log(LOG_ERROR,"Trying to delete the exten %s from context %s, but could not remove from the root_table\n", extension, con->name);
5019 if (con->pattern_tree) {
5020 struct match_char *x = add_exten_to_pattern_tree(con, exten, 1);
5021
5022 if (x->exten) { /* this test for safety purposes */
5023 x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */
5024 x->exten = 0; /* get rid of what will become a bad pointer */
5025 } else {
5026 ast_log(LOG_WARNING,"Trying to delete an exten from a context, but the pattern tree node returned isn't a full extension\n");
5027 }
5028 }
5029 } else {
5030 ex.priority = priority;
5031 exten2 = ast_hashtab_lookup(exten->peer_table, &ex);
5032 if (exten2) {
5033 if (exten2->label) { /* if this exten has a label, remove that, too */
5035 if (!exten3) {
5036 ast_log(LOG_ERROR, "Did not remove this priority label (%d/%s) "
5037 "from the peer_label_table of context %s, extension %s!\n",
5038 priority, exten2->label, con->name, exten2->name);
5039 }
5040 }
5041
5043 if (!exten3) {
5044 ast_log(LOG_ERROR, "Did not remove this priority (%d) from the "
5045 "peer_table of context %s, extension %s!\n",
5046 priority, con->name, exten2->name);
5047 }
5048 if (exten2 == exten && exten2->peer) {
5051 }
5052 if (ast_hashtab_size(exten->peer_table) == 0) {
5053 /* well, if the last priority of an exten is to be removed,
5054 then, the extension is removed, too! */
5056 if (!exten3) {
5057 ast_log(LOG_ERROR, "Did not remove this exten (%s) from the "
5058 "context root_table (%s) (priority %d)\n",
5059 exten->name, con->name, priority);
5060 }
5061 if (con->pattern_tree) {
5062 struct match_char *x = add_exten_to_pattern_tree(con, exten, 1);
5063 if (x->exten) { /* this test for safety purposes */
5064 x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */
5065 x->exten = 0; /* get rid of what will become a bad pointer */
5066 }
5067 }
5068 }
5069 } else {
5070 ast_debug(3,"Could not find priority %d of exten %s in context %s!\n",
5071 priority, exten->name, con->name);
5072 }
5073 }
5074 } else {
5075 /* hmmm? this exten is not in this pattern tree? */
5076 ast_log(LOG_WARNING,"Cannot find extension %s in root_table in context %s\n",
5077 extension, con->name);
5078 }
5079#ifdef NEED_DEBUG
5080 if (con->pattern_tree) {
5081 ast_log(LOG_NOTICE,"match char tree after exten removal:\n");
5082 log_match_char_tree(con->pattern_tree, " ");
5083 }
5084#endif
5085
5086 /* scan the extension list to find first matching extension-registrar */
5087 for (exten = con->root; exten; prev_exten = exten, exten = exten->next) {
5088 if (!strcmp(exten->exten, ex.exten) &&
5089 (!matchcallerid ||
5090 (!ast_strlen_zero(ex.cidmatch) && !ast_strlen_zero(exten->cidmatch) && !strcmp(exten->cidmatch, ex.cidmatch)) ||
5091 (ast_strlen_zero(ex.cidmatch) && ast_strlen_zero(exten->cidmatch)))) {
5092 break;
5093 }
5094 }
5095 if (!exten) {
5096 /* we can't find right extension */
5097 if (!already_locked)
5098 ast_unlock_context(con);
5099 return -1;
5100 }
5101
5102 /* scan the priority list to remove extension with exten->priority == priority */
5103 for (peer = exten, next_peer = exten->peer ? exten->peer : exten->next;
5104 peer && !strcmp(peer->exten, ex.exten) &&
5105 (!callerid || (!matchcallerid && !peer->matchcid) || (matchcallerid && peer->matchcid && !strcmp(peer->cidmatch, ex.cidmatch))) ;
5106 peer = next_peer, next_peer = next_peer ? (next_peer->peer ? next_peer->peer : next_peer->next) : NULL) {
5107
5108 if ((priority == 0 || peer->priority == priority) &&
5109 (!registrar || !strcmp(peer->registrar, registrar) )) {
5110 found = 1;
5111
5112 /* we are first priority extension? */
5113 if (!previous_peer) {
5114 /*
5115 * We are first in the priority chain, so must update the extension chain.
5116 * The next node is either the next priority or the next extension
5117 */
5118 struct ast_exten *next_node = peer->peer ? peer->peer : peer->next;
5119 if (peer->peer) {
5120 /* move the peer_table and peer_label_table down to the next peer, if
5121 it is there */
5124 peer->peer_table = NULL;
5126 }
5127 if (!prev_exten) { /* change the root... */
5128 con->root = next_node;
5129 } else {
5130 prev_exten->next = next_node; /* unlink */
5131 }
5132 if (peer->peer) { /* update the new head of the pri list */
5133 peer->peer->next = peer->next;
5134 }
5135 } else { /* easy, we are not first priority in extension */
5136 previous_peer->peer = peer->peer;
5137 }
5138
5139
5140 /* now, free whole priority extension */
5142 } else {
5143 previous_peer = peer;
5144 }
5145 }
5146 if (!already_locked)
5147 ast_unlock_context(con);
5148 return found ? 0 : -1;
5149}
int ast_hashtab_size(struct ast_hashtab *tab)
Returns the number of elements stored in the hashtab.
Definition: hashtab.c:577

References add_exten_to_pattern_tree(), ast_debug, ast_hashtab_insert_immediate, ast_hashtab_lookup(), ast_hashtab_remove_this_object(), ast_hashtab_size(), ast_log, ast_strlen_zero(), ast_unlock_context(), ast_verb, ast_wrlock_context(), ast_exten::cidmatch, destroy_exten(), ext_strncpy(), ast_exten::exten, match_char::exten, ast_exten::label, LOG_ERROR, LOG_NOTICE, LOG_WARNING, ast_exten::matchcid, ast_exten::name, ast_context::name, ast_exten::next, NULL, ast_context::pattern_tree, ast_exten::peer, ast_exten::peer_label_table, ast_exten::peer_table, priority, ast_exten::priority, ast_exten::registrar, registrar, ast_context::root, ast_context::root_table, and match_char::x.

Referenced by __ast_context_destroy(), ast_context_remove_extension2(), and ast_context_remove_extension_callerid().

◆ ast_context_remove_ignorepat()

int ast_context_remove_ignorepat ( const char *  context,
const char *  ignorepat,
const char *  registrar 
)

Remove an ignorepat.

Parameters
contextcontext from which to remove the pattern
ignorepatthe pattern to remove
registrarthe registrar of the ignore pattern

This removes the given ignorepattern

Return values
0on success
-1on failure

Definition at line 6795 of file pbx.c.

6796{
6797 int ret = -1;
6798 struct ast_context *c;
6799
6801 if (c) {
6802 ret = ast_context_remove_ignorepat2(c, ignorepat, registrar);
6804 }
6805 return ret;
6806}
int ast_context_remove_ignorepat2(struct ast_context *con, const char *ignorepat, const char *registrar)
Definition: pbx.c:6808

References ast_context_remove_ignorepat2(), ast_unlock_contexts(), c, voicemailpwcheck::context, find_context_locked(), and registrar.

Referenced by handle_cli_dialplan_remove_ignorepat().

◆ ast_context_remove_ignorepat2()

int ast_context_remove_ignorepat2 ( struct ast_context con,
const char *  ignorepat,
const char *  registrar 
)

Definition at line 6808 of file pbx.c.

6809{
6810 int idx;
6811
6812 ast_wrlock_context(con);
6813
6814 for (idx = 0; idx < ast_context_ignorepats_count(con); idx++) {
6815 struct ast_ignorepat *ip = AST_VECTOR_GET(&con->ignorepats, idx);
6816
6817 if (!strcmp(ast_get_ignorepat_name(ip), ignorepat) &&
6820 ignorepat_free(ip);
6821 ast_unlock_context(con);
6822 return 0;
6823 }
6824 }
6825
6826 ast_unlock_context(con);
6827 errno = EINVAL;
6828 return -1;
6829}

References ast_context_ignorepats_count(), ast_get_ignorepat_name(), ast_get_ignorepat_registrar(), ast_unlock_context(), AST_VECTOR_GET, AST_VECTOR_REMOVE_ORDERED, ast_wrlock_context(), errno, ignorepat_free(), ast_context::ignorepats, and registrar.

Referenced by ast_context_remove_ignorepat().

◆ ast_context_remove_include()

int ast_context_remove_include ( const char *  context,
const char *  include,
const char *  registrar 
)

Remove included contexts. This function locks contexts list by &conlist, search for the right context structure, leave context list locked and call ast_context_remove_include2 which removes include, unlock contexts list and return ...

Remove a context include.

Definition at line 4836 of file pbx.c.

4837{
4838 int ret = -1;
4839 struct ast_context *c;
4840
4842 if (c) {
4843 /* found, remove include from this context ... */
4844 ret = ast_context_remove_include2(c, include, registrar);
4846 }
4847 return ret;
4848}
int ast_context_remove_include2(struct ast_context *con, const char *include, const char *registrar)
Locks context, remove included contexts, unlocks context. When we call this function,...
Definition: pbx.c:4859

References ast_context_remove_include2(), ast_unlock_contexts(), c, voicemailpwcheck::context, find_context_locked(), and registrar.

Referenced by handle_cli_dialplan_remove_include().

◆ ast_context_remove_include2()

int ast_context_remove_include2 ( struct ast_context con,
const char *  include,
const char *  registrar 
)

Locks context, remove included contexts, unlocks context. When we call this function, &conlock lock must be locked, because when we giving *con argument, some process can remove/change this context and after that there can be segfault.

Removes an include by an ast_context structure.

Return values
0on success.
-1on failure.

Definition at line 4859 of file pbx.c.

4860{
4861 int ret = -1;
4862 int idx;
4863
4864 ast_wrlock_context(con);
4865
4866 /* find our include */
4867 for (idx = 0; idx < ast_context_includes_count(con); idx++) {
4868 struct ast_include *i = AST_VECTOR_GET(&con->includes, idx);
4869
4870 if (!strcmp(ast_get_include_name(i), include) &&
4871 (!registrar || !strcmp(ast_get_include_registrar(i), registrar))) {
4872
4873 /* remove from list */
4874 ast_verb(3, "Removing inclusion of context '%s' in context '%s; registrar=%s'\n", include, ast_get_context_name(con), registrar);
4876
4877 /* free include and return */
4878 include_free(i);
4879 ret = 0;
4880 break;
4881 }
4882 }
4883
4884 ast_unlock_context(con);
4885
4886 return ret;
4887}

References ast_context_includes_count(), ast_get_context_name(), ast_get_include_name(), ast_get_include_registrar(), ast_unlock_context(), AST_VECTOR_GET, AST_VECTOR_REMOVE_ORDERED, ast_verb, ast_wrlock_context(), include_free(), ast_context::includes, and registrar.

Referenced by ast_context_remove_include().

◆ ast_context_remove_switch()

int ast_context_remove_switch ( const char *  context,
const char *  sw,
const char *  data,
const char *  registrar 
)

Remove a switch.

Note
This function locks contexts list by &conlist, search for the right context structure, leave context list locked and call ast_context_remove_switch2 which removes switch, unlock contexts list and return ...

Definition at line 4894 of file pbx.c.

4895{
4896 int ret = -1; /* default error return */
4897 struct ast_context *c;
4898
4900 if (c) {
4901 /* remove switch from this context ... */
4904 }
4905 return ret;
4906}
int ast_context_remove_switch2(struct ast_context *con, const char *sw, const char *data, const char *registrar)
This function locks given context, removes switch, unlock context and return.
Definition: pbx.c:4916

References ast_context_remove_switch2(), ast_unlock_contexts(), c, voicemailpwcheck::context, ast_context::data, find_context_locked(), and registrar.

◆ ast_context_remove_switch2()

int ast_context_remove_switch2 ( struct ast_context con,
const char *  sw,
const char *  data,
const char *  registrar 
)

This function locks given context, removes switch, unlock context and return.

Note
When we call this function, &conlock lock must be locked, because when we giving *con argument, some process can remove/change this context and after that there can be segfault.

Definition at line 4916 of file pbx.c.

4917{
4918 int idx;
4919 int ret = -1;
4920
4921 ast_wrlock_context(con);
4922
4923 /* walk switches */
4924 for (idx = 0; idx < ast_context_switches_count(con); idx++) {
4925 struct ast_sw *i = AST_VECTOR_GET(&con->alts, idx);
4926
4927 if (!strcmp(ast_get_switch_name(i), sw) &&
4928 !strcmp(ast_get_switch_data(i), data) &&
4929 (!registrar || !strcmp(ast_get_switch_registrar(i), registrar))) {
4930
4931 /* found, remove from list */
4932 ast_verb(3, "Removing switch '%s' from context '%s; registrar=%s'\n", sw, ast_get_context_name(con), registrar);
4933 AST_VECTOR_REMOVE_ORDERED(&con->alts, idx);
4934
4935 /* free switch and return */
4936 sw_free(i);
4937 ret = 0;
4938 break;
4939 }
4940 }
4941
4942 ast_unlock_context(con);
4943
4944 return ret;
4945}

References ast_context::alts, ast_context_switches_count(), ast_get_context_name(), ast_get_switch_data(), ast_get_switch_name(), ast_get_switch_registrar(), ast_unlock_context(), AST_VECTOR_GET, AST_VECTOR_REMOVE_ORDERED, ast_verb, ast_wrlock_context(), ast_sw::data, registrar, and sw_free().

Referenced by ast_context_remove_switch().

◆ ast_context_set_autohints()

void ast_context_set_autohints ( struct ast_context con,
int  enabled 
)

Enable or disable autohints support on a context.

Parameters
conpointer to the context
enabledwhether autohints are enabled

Definition at line 6230 of file pbx.c.

6231{
6232 con->autohints = enabled;
6233}
static int enabled
Definition: dnsmgr.c:91
int autohints
Definition: pbx.c:297

References ast_context::autohints, and enabled.

Referenced by pbx_load_config().

◆ ast_context_switches_count()

int ast_context_switches_count ( const struct ast_context con)

◆ ast_context_switches_get()

const struct ast_sw * ast_context_switches_get ( const struct ast_context con,
int  idx 
)

◆ ast_context_verify_includes()

int ast_context_verify_includes ( struct ast_context con)

Verifies includes in an ast_contect structure.

Parameters
concontext in which to verify the includes
Return values
0if no problems found
-1if there were any missing context

Definition at line 8732 of file pbx.c.

8733{
8734 int idx;
8735 int res = 0;
8736 int includecount = ast_context_includes_count(con);
8737
8738 if (includecount >= AST_PBX_MAX_STACK) {
8739 ast_log(LOG_WARNING, "Context %s contains too many includes (%d). Maximum is %d.\n",
8740 ast_get_context_name(con), includecount, AST_PBX_MAX_STACK);
8741 }
8742
8743 for (idx = 0; idx < includecount; idx++) {
8744 const struct ast_include *inc = ast_context_includes_get(con, idx);
8745
8746 if (ast_context_find(include_rname(inc))) {
8747 continue;
8748 }
8749
8750 res = -1;
8751 ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n",
8753 break;
8754 }
8755
8756 return res;
8757}
#define AST_PBX_MAX_STACK
Definition: extconf.h:225
const char * include_rname(const struct ast_include *inc)
Definition: pbx_include.c:55

References ast_context_find(), ast_context_includes_count(), ast_context_includes_get(), ast_get_context_name(), ast_log, AST_PBX_MAX_STACK, include_rname(), and LOG_WARNING.

Referenced by pbx_load_module().

◆ ast_devstate_to_extenstate()

enum ast_extension_states ast_devstate_to_extenstate ( enum ast_device_state  devstate)

Map devstate to an extension state.

Parameters
[in]devstatedevice state
Returns
the extension state mapping.

Definition at line 3006 of file pbx.c.

3007{
3008 switch (devstate) {
3009 case AST_DEVICE_ONHOLD:
3010 return AST_EXTENSION_ONHOLD;
3011 case AST_DEVICE_BUSY:
3012 return AST_EXTENSION_BUSY;
3013 case AST_DEVICE_UNKNOWN:
3016 case AST_DEVICE_INVALID:
3020 case AST_DEVICE_RINGING:
3021 return AST_EXTENSION_RINGING;
3022 case AST_DEVICE_INUSE:
3023 return AST_EXTENSION_INUSE;
3026 case AST_DEVICE_TOTAL: /* not a device state, included for completeness */
3027 break;
3028 }
3029
3031}
@ AST_DEVICE_RINGINUSE
Definition: devicestate.h:60
@ AST_DEVICE_INUSE
Definition: devicestate.h:55
@ AST_DEVICE_UNKNOWN
Definition: devicestate.h:53
@ AST_DEVICE_ONHOLD
Definition: devicestate.h:61
@ AST_DEVICE_RINGING
Definition: devicestate.h:59
@ AST_DEVICE_BUSY
Definition: devicestate.h:56
@ AST_DEVICE_NOT_INUSE
Definition: devicestate.h:54
@ AST_DEVICE_TOTAL
Definition: devicestate.h:62
@ AST_DEVICE_UNAVAILABLE
Definition: devicestate.h:58
@ AST_EXTENSION_RINGING
Definition: pbx.h:68
@ AST_EXTENSION_NOT_INUSE
Definition: pbx.h:64
@ AST_EXTENSION_INUSE
Definition: pbx.h:65
@ AST_EXTENSION_UNAVAILABLE
Definition: pbx.h:67
@ AST_EXTENSION_ONHOLD
Definition: pbx.h:69
@ AST_EXTENSION_BUSY
Definition: pbx.h:66

References AST_DEVICE_BUSY, AST_DEVICE_INUSE, AST_DEVICE_INVALID, AST_DEVICE_NOT_INUSE, AST_DEVICE_ONHOLD, AST_DEVICE_RINGING, AST_DEVICE_RINGINUSE, AST_DEVICE_TOTAL, AST_DEVICE_UNAVAILABLE, AST_DEVICE_UNKNOWN, AST_EXTENSION_BUSY, AST_EXTENSION_INUSE, AST_EXTENSION_NOT_INUSE, AST_EXTENSION_ONHOLD, AST_EXTENSION_RINGING, and AST_EXTENSION_UNAVAILABLE.

Referenced by ast_extension_state3(), and AST_TEST_DEFINE().

◆ ast_exists_extension()

int ast_exists_extension ( struct ast_channel c,
const char *  context,
const char *  exten,
int  priority,
const char *  callerid 
)

Determine whether an extension exists.

Parameters
cthis is not important
contextwhich context to look in
extenwhich extension to search for
prioritypriority of the action within the extension
calleridcallerid to search for
Note
It is possible for autoservice to be started and stopped on c during this function call, it is important that c is not locked prior to calling this. Otherwise a deadlock may occur
Returns
If an extension within the given context(or callerid) with the given priority is found a non zero value will be returned. Otherwise, 0 is returned.

Definition at line 4175 of file pbx.c.

4176{
4177 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH, 0, 0);
4178}

References c, voicemailpwcheck::context, E_MATCH, ast_exten::exten, NULL, pbx_extension_helper(), and priority.

Referenced by __analog_ss_thread(), __ast_goto_if_exists(), __ast_pbx_run(), acf_isexten_exec(), action_originate(), add_to_regcontext(), analog_ss_thread(), ast_app_dtget(), ast_bridge_setup_after_goto(), ast_pbx_outgoing_exten_predial(), ast_sip_persistent_endpoint_update_state(), chan_pjsip_cng_tone_detected(), cli_console_dial(), comeback_goto(), conf_run(), dahdi_handle_dtmf(), dial_exec_full(), dialplan_has_destination_cb(), disa_exec(), dp_lookup(), dundi_lookup_local(), fax_detect_framehook(), findmeexec(), get_destination(), gosub_exec(), grab_transfer(), handle_gosub(), isexten_function_read(), jingle_new(),