Asterisk - The Open Source Telephony Project GIT-master-77d630f
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 1249 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 231 of file pbx.c.

◆ HASH_EXTENHINT_SIZE

#define HASH_EXTENHINT_SIZE   563

Definition at line 380 of file pbx.c.

◆ HINTDEVICE_DATA_LENGTH

#define HINTDEVICE_DATA_LENGTH   16

Definition at line 373 of file pbx.c.

◆ INC_DST_OVERFLOW_CHECK

#define INC_DST_OVERFLOW_CHECK

◆ MAX_EXTENBUF_SIZE

#define MAX_EXTENBUF_SIZE   512

Definition at line 1677 of file pbx.c.

◆ MORE

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

Definition at line 1248 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 2479 of file pbx.c.

◆ STATUS_NO_EXTENSION

#define STATUS_NO_EXTENSION   2

Definition at line 2480 of file pbx.c.

◆ STATUS_NO_LABEL

#define STATUS_NO_LABEL   4

Definition at line 2482 of file pbx.c.

◆ STATUS_NO_PRIORITY

#define STATUS_NO_PRIORITY   3

Definition at line 2481 of file pbx.c.

◆ STATUS_SUCCESS

#define STATUS_SUCCESS   5

Definition at line 2483 of file pbx.c.

◆ SWITCH_DATA_LENGTH

#define SWITCH_DATA_LENGTH   256

Definition at line 234 of file pbx.c.

◆ VAR_HARDTRAN

#define VAR_HARDTRAN   3

Definition at line 238 of file pbx.c.

◆ VAR_NORMAL

#define VAR_NORMAL   1

Definition at line 236 of file pbx.c.

◆ VAR_SOFTTRAN

#define VAR_SOFTTRAN   2

Definition at line 237 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 8081 of file pbx.c.

8082{
8083 struct ast_context *tmp, *tmpl=NULL;
8084 struct ast_exten *exten_item, *prio_item;
8085
8086 for (tmp = list; tmp; ) {
8087 struct ast_context *next = NULL; /* next starting point */
8088 /* The following code used to skip forward to the next
8089 context with matching registrar, but this didn't
8090 make sense; individual priorities registrar'd to
8091 the matching registrar could occur in any context! */
8092 ast_debug(1, "Investigate ctx %s %s\n", tmp->name, tmp->registrar);
8093 if (con) {
8094 for (; tmp; tmpl = tmp, tmp = tmp->next) { /* skip to the matching context */
8095 ast_debug(1, "check ctx %s %s\n", tmp->name, tmp->registrar);
8096 if ( !strcasecmp(tmp->name, con->name) ) {
8097 break; /* found it */
8098 }
8099 }
8100 }
8101
8102 if (!tmp) /* not found, we are done */
8103 break;
8104 ast_wrlock_context(tmp);
8105
8106 if (registrar) {
8107 /* then search thru and remove any extens that match registrar. */
8108 struct ast_hashtab_iter *exten_iter;
8109 struct ast_hashtab_iter *prio_iter;
8110 int idx;
8111
8112 /* remove any ignorepats whose registrar matches */
8113 for (idx = ast_context_ignorepats_count(tmp) - 1; idx >= 0; idx--) {
8114 struct ast_ignorepat *ip = AST_VECTOR_GET(&tmp->ignorepats, idx);
8115
8116 if (!strcmp(ast_get_ignorepat_registrar(ip), registrar)) {
8117 AST_VECTOR_REMOVE_ORDERED(&tmp->ignorepats, idx);
8118 ignorepat_free(ip);
8119 }
8120 }
8121 /* remove any includes whose registrar matches */
8122 for (idx = ast_context_includes_count(tmp) - 1; idx >= 0; idx--) {
8123 struct ast_include *i = AST_VECTOR_GET(&tmp->includes, idx);
8124
8125 if (!strcmp(ast_get_include_registrar(i), registrar)) {
8126 AST_VECTOR_REMOVE_ORDERED(&tmp->includes, idx);
8127 include_free(i);
8128 }
8129 }
8130 /* remove any switches whose registrar matches */
8131 for (idx = ast_context_switches_count(tmp) - 1; idx >= 0; idx--) {
8132 struct ast_sw *sw = AST_VECTOR_GET(&tmp->alts, idx);
8133
8134 if (!strcmp(ast_get_switch_registrar(sw), registrar)) {
8135 AST_VECTOR_REMOVE_ORDERED(&tmp->alts, idx);
8136 sw_free(sw);
8137 }
8138 }
8139
8140 if (tmp->root_table) { /* it is entirely possible that the context is EMPTY */
8141 exten_iter = ast_hashtab_start_traversal(tmp->root_table);
8142 while ((exten_item=ast_hashtab_next(exten_iter))) {
8143 int end_traversal = 1;
8144
8145 /*
8146 * If the extension could not be removed from the root_table due to
8147 * a loaded PBX app, it can exist here but have its peer_table be
8148 * destroyed due to a previous pass through this function.
8149 */
8150 if (!exten_item->peer_table) {
8151 continue;
8152 }
8153
8154 prio_iter = ast_hashtab_start_traversal(exten_item->peer_table);
8155 while ((prio_item=ast_hashtab_next(prio_iter))) {
8157 char cidmatch[AST_MAX_EXTENSION];
8158 if (!prio_item->registrar || strcmp(prio_item->registrar, registrar) != 0) {
8159 continue;
8160 }
8161 ast_verb(5, "Remove %s/%s/%d, registrar=%s; con=%s(%p); con->root=%p\n",
8162 tmp->name, prio_item->name, prio_item->priority, registrar, con? con->name : "<nil>", con, con? con->root_table: NULL);
8163 ast_copy_string(extension, prio_item->exten, sizeof(extension));
8164 if (prio_item->cidmatch) {
8165 ast_copy_string(cidmatch, prio_item->cidmatch, sizeof(cidmatch));
8166 }
8167 end_traversal &= ast_context_remove_extension_callerid2(tmp, extension, prio_item->priority, cidmatch, prio_item->matchcid, NULL, 1);
8168 }
8169 /* Explanation:
8170 * ast_context_remove_extension_callerid2 will destroy the extension that it comes across. This
8171 * destruction includes destroying the exten's peer_table, which we are currently traversing. If
8172 * ast_context_remove_extension_callerid2 ever should return '0' then this means we have destroyed
8173 * the hashtable which we are traversing, and thus calling ast_hashtab_end_traversal will result
8174 * in reading invalid memory. Thus, if we detect that we destroyed the hashtable, then we will simply
8175 * free the iterator
8176 */
8177 if (end_traversal) {
8178 ast_hashtab_end_traversal(prio_iter);
8179 } else {
8180 ast_free(prio_iter);
8181 }
8182 }
8183 ast_hashtab_end_traversal(exten_iter);
8184 }
8185
8186 /* delete the context if it's registrar matches, is empty, has refcount of 1, */
8187 /* it's not empty, if it has includes, ignorepats, or switches that are registered from
8188 another registrar. It's not empty if there are any extensions */
8189 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)) {
8190 ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar);
8191 ast_hashtab_remove_this_object(contexttab, tmp);
8192
8193 next = tmp->next;
8194 if (tmpl)
8195 tmpl->next = next;
8196 else
8197 contexts = next;
8198 /* Okay, now we're safe to let it go -- in a sense, we were
8199 ready to let it go as soon as we locked it. */
8200 ast_unlock_context(tmp);
8202 } else {
8203 ast_debug(1,"Couldn't delete ctx %s/%s; refc=%d; tmp.root=%p\n", tmp->name, tmp->registrar,
8204 tmp->refcount, tmp->root);
8205 ast_unlock_context(tmp);
8206 next = tmp->next;
8207 tmpl = tmp;
8208 }
8209 } else if (con) {
8210 ast_verb(3, "Deleting context %s registrar=%s\n", tmp->name, tmp->registrar);
8211 ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar);
8212 ast_hashtab_remove_this_object(contexttab, tmp);
8213
8214 next = tmp->next;
8215 if (tmpl)
8216 tmpl->next = next;
8217 else
8218 contexts = next;
8219 /* Okay, now we're safe to let it go -- in a sense, we were
8220 ready to let it go as soon as we locked it. */
8221 ast_unlock_context(tmp);
8223 }
8224
8225 /* if we have a specific match, we are done, otherwise continue */
8226 tmp = con ? NULL : next;
8227 }
8228}
#define ast_free(a)
Definition: astmm.h:180
#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:8506
int ast_unlock_context(struct ast_context *con)
Definition: pbx.c:8516
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:5004
int ast_context_ignorepats_count(const struct ast_context *con)
Definition: pbx.c:8747
static struct ast_context * contexts
Definition: pbx.c:796
int ast_context_switches_count(const struct ast_context *con)
Definition: pbx.c:8659
int ast_context_includes_count(const struct ast_context *con)
Definition: pbx.c:8704
static void __ast_internal_context_destroy(struct ast_context *con)
Definition: pbx.c:8040
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:81
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:299
const char * registrar
Definition: pbx.c:301
struct ast_context * next
Definition: pbx.c:307
struct ast_hashtab * root_table
Definition: pbx.c:305
const char * name
Definition: pbx.c:300
ast_exten: An extension The dialplan is saved as a linked list with each context having it's own link...
Definition: pbx.c:252
char * exten
Definition: pbx.c:253
struct ast_hashtab * peer_table
Definition: pbx.c:266
char * name
Definition: pbx.c:254
const char * registrar
Definition: pbx.c:268
const char * cidmatch
Definition: pbx.c:256
int priority
Definition: pbx.c:258
int matchcid
Definition: pbx.c:255
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:459
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:691

References __ast_internal_context_destroy(), ast_context::alts, 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(), ast_context::ignorepats, include_free(), ast_context::includes, ast_exten::matchcid, ast_exten::name, ast_context::name, ast_context::next, ast_sw::next, NULL, ast_exten::peer_table, ast_exten::priority, ast_context::refcount, ast_exten::registrar, ast_context::registrar, registrar, ast_context::root, ast_context::root_table, and sw_free().

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 8785 of file pbx.c.

8786{
8787 int (*goto_func)(struct ast_channel *chan, const char *context, const char *exten, int priority);
8788
8789 if (!chan)
8790 return -2;
8791
8792 if (context == NULL)
8794 if (exten == NULL)
8795 exten = ast_channel_exten(chan);
8796
8797 goto_func = (async) ? ast_async_goto : ast_explicit_goto;
8799 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL)))
8800 return goto_func(chan, context, exten, priority);
8801 else {
8802 return AST_PBX_GOTO_FAILED;
8803 }
8804}
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:4196
int ast_explicit_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
Definition: pbx.c:6966
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:6994
#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:157

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 8040 of file pbx.c.

8041{
8042 struct ast_exten *e, *el, *en;
8043 struct ast_context *tmp = con;
8044
8045 /* Free includes */
8048
8049 /* Free ignorepats */
8052
8053 /* Free switches */
8055 AST_VECTOR_FREE(&tmp->alts);
8056
8057 /* destroy the hash tabs */
8058 if (tmp->root_table) {
8060 }
8061 /* and destroy the pattern tree */
8062 if (tmp->pattern_tree)
8064
8065 for (e = tmp->root; e;) {
8066 for (en = e->peer; en;) {
8067 el = en;
8068 en = en->peer;
8070 }
8071 el = e;
8072 e = e->next;
8074 }
8075 tmp->root = NULL;
8076 ast_rwlock_destroy(&tmp->lock);
8077 ast_free(tmp);
8078}
static EditLine * el
Definition: asterisk.c:347
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:240
static void destroy_pattern_tree(struct match_char *pattern_tree)
Definition: pbx.c:1808
static void destroy_exten(struct ast_exten *e)
Definition: pbx.c:4695
struct ast_sws alts
Definition: pbx.c:310
struct ast_exten * root
Definition: pbx.c:304
struct match_char * pattern_tree
Definition: pbx.c:306
struct ast_ignorepats ignorepats
Definition: pbx.c:309
struct ast_includes includes
Definition: pbx.c:308
ast_rwlock_t lock
Definition: pbx.c:303
struct ast_exten * peer
Definition: pbx.c:265
struct ast_exten * next
Definition: pbx.c:271
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
Definition: vector.h:185
#define AST_VECTOR_CALLBACK_VOID(vec, callback,...)
Execute a callback on every element in a vector disregarding callback return.
Definition: vector.h:873

References ast_context::alts, ast_free, ast_hashtab_destroy(), ast_rwlock_destroy, AST_VECTOR_CALLBACK_VOID, AST_VECTOR_FREE, destroy_exten(), destroy_pattern_tree(), el, ignorepat_free(), ast_context::ignorepats, include_free(), ast_context::includes, ast_context::lock, ast_exten::next, NULL, ast_context::pattern_tree, ast_exten::peer, ast_context::root, ast_context::root_table, and sw_free().

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 4327 of file pbx.c.

4329{
4330 int found = 0; /* set if we find at least one match */
4331 int res = 0;
4332 int autoloopflag;
4333 int error = 0; /* set an error conditions */
4334 struct ast_pbx *pbx;
4335 ast_callid callid;
4336
4337 /* A little initial setup here */
4338 if (ast_channel_pbx(c)) {
4339 ast_log(LOG_WARNING, "%s already has PBX structure??\n", ast_channel_name(c));
4340 /* XXX and now what ? */
4342 }
4343 if (!(pbx = ast_calloc(1, sizeof(*pbx)))) {
4344 return AST_PBX_FAILED;
4345 }
4346
4348 /* If the thread isn't already associated with a callid, we should create that association. */
4349 if (!callid) {
4350 /* Associate new PBX thread with the channel call id if it is available.
4351 * If not, create a new one instead.
4352 */
4353 callid = ast_channel_callid(c);
4354 if (!callid) {
4355 callid = ast_create_callid();
4356 if (callid) {
4358 ast_channel_callid_set(c, callid);
4360 }
4361 }
4363 callid = 0;
4364 }
4365
4366 ast_channel_pbx_set(c, pbx);
4367 /* Set reasonable defaults */
4368 ast_channel_pbx(c)->rtimeoutms = 10000;
4369 ast_channel_pbx(c)->dtimeoutms = 5000;
4370
4372 autoloopflag = ast_test_flag(ast_channel_flags(c), AST_FLAG_IN_AUTOLOOP); /* save value to restore at the end */
4375
4377 /* If not successful fall back to 's' - but only if there is no given exten */
4378 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));
4379 /* XXX the original code used the existing priority in the call to
4380 * ast_exists_extension(), and reset it to 1 afterwards.
4381 * I believe the correct thing is to set it to 1 immediately.
4382 */
4383 set_ext_pri(c, "s", 1);
4384 }
4385
4386 for (;;) {
4387 char dst_exten[256]; /* buffer to accumulate digits */
4388 int pos = 0; /* XXX should check bounds */
4389 int digit = 0;
4390 int invalid = 0;
4391 int timeout = 0;
4392
4393 /* No digits pressed yet */
4394 dst_exten[pos] = '\0';
4395
4396 /* loop on priorities in this context/exten */
4399 &found, 1))) {
4400
4401 if (!ast_check_hangup(c)) {
4403 continue;
4404 }
4405
4406 /* Check softhangup flags. */
4409 continue;
4410 }
4413 S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4414 set_ext_pri(c, "T", 1);
4415 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
4418 continue;
4419 } else if (ast_exists_extension(c, ast_channel_context(c), "e", 1,
4420 S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4421 raise_exception(c, "ABSOLUTETIMEOUT", 1);
4422 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
4425 continue;
4426 }
4427
4428 /* Call timed out with no special extension to jump to. */
4429 error = 1;
4430 break;
4431 }
4432 ast_debug(1, "Extension %s, priority %d returned normally even though call was hung up\n",
4434 error = 1;
4435 break;
4436 } /* end while - from here on we can use 'break' to go out */
4437 if (found && res) {
4438 /* Something bad happened, or a hangup has been requested. */
4439 if (strchr("0123456789ABCDEF*#", res)) {
4440 ast_debug(1, "Oooh, got something to jump out with ('%c')!\n", res);
4441 pos = 0;
4442 dst_exten[pos++] = digit = res;
4443 dst_exten[pos] = '\0';
4444 } else if (res == AST_PBX_INCOMPLETE) {
4445 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));
4446 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));
4447
4448 /* Don't cycle on incomplete - this will happen if the only extension that matches is our "incomplete" extension */
4450 S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4451 invalid = 1;
4452 } else {
4453 ast_copy_string(dst_exten, ast_channel_exten(c), sizeof(dst_exten));
4454 digit = 1;
4455 pos = strlen(dst_exten);
4456 }
4457 } else {
4458 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));
4459 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));
4460
4461 if ((res == AST_PBX_ERROR)
4463 S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4464 /* if we are already on the 'e' exten, don't jump to it again */
4465 if (!strcmp(ast_channel_exten(c), "e")) {
4466 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));
4467 error = 1;
4468 } else {
4469 raise_exception(c, "ERROR", 1);
4470 continue;
4471 }
4472 }
4473
4476 continue;
4477 }
4480 S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4481 set_ext_pri(c, "T", 1);
4482 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
4485 continue;
4486 } else if (ast_exists_extension(c, ast_channel_context(c), "e", 1,
4487 S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4488 raise_exception(c, "ABSOLUTETIMEOUT", 1);
4489 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
4492 continue;
4493 }
4494 /* Call timed out with no special extension to jump to. */
4495 }
4496 error = 1;
4497 break;
4498 }
4499 }
4500 if (error)
4501 break;
4502
4503 /*!\note
4504 * We get here on a failure of some kind: non-existing extension or
4505 * hangup. We have options, here. We can either catch the failure
4506 * and continue, or we can drop out entirely. */
4507
4508 if (invalid
4509 || (ast_strlen_zero(dst_exten) &&
4511 S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL)))) {
4512 /*!\note
4513 * If there is no match at priority 1, it is not a valid extension anymore.
4514 * Try to continue at "i" (for invalid) or "e" (for exception) or exit if
4515 * neither exist.
4516 */
4518 S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4519 ast_verb(3, "Channel '%s' sent to invalid extension: context,exten,priority=%s,%s,%d\n",
4521 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", ast_channel_exten(c));
4522 set_ext_pri(c, "i", 1);
4523 } else if (ast_exists_extension(c, ast_channel_context(c), "e", 1,
4524 S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4525 raise_exception(c, "INVALID", 1);
4526 } else {
4527 ast_log(LOG_WARNING, "Channel '%s' sent to invalid extension but no invalid handler: context,exten,priority=%s,%s,%d\n",
4529 error = 1; /* we know what to do with it */
4530 break;
4531 }
4533 /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */
4535 } else { /* keypress received, get more digits for a full extension */
4536 int waittime = 0;
4537 if (digit)
4538 waittime = ast_channel_pbx(c)->dtimeoutms;
4539 else if (!autofallthrough)
4540 waittime = ast_channel_pbx(c)->rtimeoutms;
4541 if (!waittime) {
4542 const char *status = pbx_builtin_getvar_helper(c, "DIALSTATUS");
4543 if (!status)
4544 status = "UNKNOWN";
4545 ast_verb(3, "Auto fallthrough, channel '%s' status is '%s'\n", ast_channel_name(c), status);
4546 if (!strcasecmp(status, "CONGESTION"))
4547 res = indicate_congestion(c, "10");
4548 else if (!strcasecmp(status, "CHANUNAVAIL"))
4549 res = indicate_congestion(c, "10");
4550 else if (!strcasecmp(status, "BUSY"))
4551 res = indicate_busy(c, "10");
4552 error = 1; /* XXX disable message */
4553 break; /* exit from the 'for' loop */
4554 }
4555
4556 if (collect_digits(c, waittime, dst_exten, sizeof(dst_exten), pos))
4557 break;
4558 if (res == AST_PBX_INCOMPLETE && ast_strlen_zero(&dst_exten[pos]))
4559 timeout = 1;
4560 if (!timeout
4561 && ast_exists_extension(c, ast_channel_context(c), dst_exten, 1,
4562 S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) { /* Prepare the next cycle */
4563 set_ext_pri(c, dst_exten, 1);
4564 } else {
4565 /* No such extension */
4566 if (!timeout && !ast_strlen_zero(dst_exten)) {
4567 /* An invalid extension */
4569 S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4570 ast_verb(3, "Invalid extension '%s' in context '%s' on %s\n", dst_exten, ast_channel_context(c), ast_channel_name(c));
4571 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", dst_exten);
4572 set_ext_pri(c, "i", 1);
4573 } else if (ast_exists_extension(c, ast_channel_context(c), "e", 1,
4574 S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4575 raise_exception(c, "INVALID", 1);
4576 } else {
4578 "Invalid extension '%s', but no rule 'i' or 'e' in context '%s'\n",
4579 dst_exten, ast_channel_context(c));
4580 found = 1; /* XXX disable message */
4581 break;
4582 }
4583 } else {
4584 /* A simple timeout */
4586 S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4587 ast_verb(3, "Timeout on %s\n", ast_channel_name(c));
4588 set_ext_pri(c, "t", 1);
4589 } else if (ast_exists_extension(c, ast_channel_context(c), "e", 1,
4590 S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4591 raise_exception(c, "RESPONSETIMEOUT", 1);
4592 } else {
4594 "Timeout, but no rule 't' or 'e' in context '%s'\n",
4596 found = 1; /* XXX disable message */
4597 break;
4598 }
4599 }
4600 }
4601 }
4602 }
4603
4604 if (!found && !error) {
4605 ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", ast_channel_name(c));
4606 }
4607
4608 if (!args || !args->no_hangup_chan) {
4612 S_COR(ast_channel_caller(c)->id.number.valid,
4613 ast_channel_caller(c)->id.number.str, NULL))) {
4615 }
4617 }
4618
4621 ast_clear_flag(ast_channel_flags(c), AST_FLAG_BRIDGE_HANGUP_RUN); /* from one round to the next, make sure this gets cleared */
4625
4626 if (!args || !args->no_hangup_chan) {
4627 ast_hangup(c);
4628 }
4629
4630 return AST_PBX_SUCCESS;
4631}
char digit
jack_status_t status
Definition: app_jack.c:149
#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:2402
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2511
#define ast_channel_lock(chan)
Definition: channel.h:2972
struct ast_flags * ast_channel_flags(struct ast_channel *chan)
int ast_channel_priority(const struct ast_channel *chan)
@ AST_FLAG_BRIDGE_HANGUP_RUN
Definition: channel.h:1038
@ AST_FLAG_IN_AUTOLOOP
Definition: channel.h:1017
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
@ AST_SOFTHANGUP_ASYNCGOTO
Definition: channel.h:1146
@ AST_SOFTHANGUP_TIMEOUT
Definition: channel.h:1158
@ AST_SOFTHANGUP_APPUNLOAD
Definition: channel.h:1163
int ast_softhangup(struct ast_channel *chan, int cause)
Softly hangup up a channel.
Definition: channel.c:2441
struct timeval * ast_channel_whentohangup(struct ast_channel *chan)
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:2973
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:846
int indicate_congestion(struct ast_channel *chan, const char *data)
Definition: pbx_builtins.c:864
ast_callid ast_read_threadstorage_callid(void)
extracts the callerid from the thread
Definition: logger.c:2268
int ast_callid_threadassoc_add(ast_callid callid)
Adds a known callid to thread storage of the calling thread.
Definition: logger.c:2290
ast_callid ast_create_callid(void)
factory function to create a new uniquely identifying callid.
Definition: logger.c:2263
unsigned int ast_callid
#define LOG_WARNING
static void pbx_destroy(struct ast_pbx *p)
Definition: pbx.c:1005
static int autofallthrough
Definition: pbx.c:783
int raise_exception(struct ast_channel *chan, const char *reason, int priority)
Definition: pbx.c:2821
void ast_pbx_h_exten_run(struct ast_channel *chan, const char *context)
Run the h exten from the given context.
Definition: pbx.c:4226
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:4221
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:4216
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:4300
void set_ext_pri(struct ast_channel *c, const char *exten, int pri)
Definition: pbx.c:4285
@ AST_PBX_FAILED
Definition: pbx.h:373
@ AST_PBX_SUCCESS
Definition: pbx.h:372
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:215
int rtimeoutms
Definition: pbx.h:217
int dtimeoutms
Definition: pbx.h:216
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 244 of file pbx.c.

252{

◆ __init_hintdevice_data()

static void __init_hintdevice_data ( void  )
static

Definition at line 374 of file pbx.c.

391{

◆ __init_switch_data()

static void __init_switch_data ( void  )
static

Definition at line 243 of file pbx.c.

252{

◆ _extension_match_core()

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

Definition at line 2238 of file pbx.c.

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

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 2847 of file pbx.c.

2848{
2850 struct pbx_exception *exception = NULL;
2851 if (!ds || !ds->data)
2852 return -1;
2853 exception = ds->data;
2854 if (!strcasecmp(data, "REASON"))
2855 ast_copy_string(buf, exception->reason, buflen);
2856 else if (!strcasecmp(data, "CONTEXT"))
2857 ast_copy_string(buf, exception->context, buflen);
2858 else if (!strncasecmp(data, "EXTEN", 5))
2859 ast_copy_string(buf, exception->exten, buflen);
2860 else if (!strcasecmp(data, "PRIORITY"))
2861 snprintf(buf, buflen, "%d", exception->priority);
2862 else
2863 return -1;
2864 return 0;
2865}
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:2369
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static const struct ast_datastore_info exception_store_info
Definition: pbx.c:2805
Structure for a data store object.
Definition: datastore.h:64
void * data
Definition: datastore.h:66
const ast_string_field context
Definition: pbx.c:645
const ast_string_field exten
Definition: pbx.c:645
int priority
Definition: pbx.c:647
const ast_string_field reason
Definition: pbx.c:645

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 8369 of file pbx.c.

8370{
8371 const char *action_id = astman_get_header(m, "ActionID");
8372 struct ast_hint *hint;
8373 struct ao2_iterator it_hints;
8374 int hint_count = 0;
8375
8376 if (!hints) {
8377 astman_send_error(s, m, "No dialplan hints are available");
8378 return 0;
8379 }
8380
8381 astman_send_listack(s, m, "Extension Statuses will follow", "start");
8382
8383 ao2_lock(hints);
8384 it_hints = ao2_iterator_init(hints, 0);
8385 for (; (hint = ao2_iterator_next(&it_hints)); ao2_ref(hint, -1)) {
8386
8387 ao2_lock(hint);
8388
8389 /* Ignore pattern matching hints; they are stored in the
8390 * hints container but aren't real from the perspective of
8391 * an AMI user
8392 */
8393 if (hint->exten->exten[0] == '_') {
8394 ao2_unlock(hint);
8395 continue;
8396 }
8397
8398 ++hint_count;
8399
8400 astman_append(s, "Event: ExtensionStatus\r\n");
8401 if (!ast_strlen_zero(action_id)) {
8402 astman_append(s, "ActionID: %s\r\n", action_id);
8403 }
8404 astman_append(s,
8405 "Exten: %s\r\n"
8406 "Context: %s\r\n"
8407 "Hint: %s\r\n"
8408 "Status: %d\r\n"
8409 "StatusText: %s\r\n\r\n",
8410 hint->exten->exten,
8411 hint->exten->parent->name,
8412 hint->exten->app,
8413 hint->laststate,
8415 ao2_unlock(hint);
8416 }
8417
8418 ao2_iterator_destroy(&it_hints);
8420
8421 astman_send_list_complete_start(s, m, "ExtensionStateListComplete", hint_count);
8423
8424 return 0;
8425}
#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:2024
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:1982
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:2060
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
Definition: manager.c:1643
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
Definition: manager.c:2068
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:1903
const char * ast_extension_state2str(int extension_state)
Return extension_state as string.
Definition: pbx.c:3147
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:261
struct ast_context * parent
Definition: pbx.c:260
Structure for dial plan hints.
Definition: pbx.c:346
int laststate
Definition: pbx.c:357
struct ast_exten * exten
Hint extension.
Definition: pbx.c:353

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 1678 of file pbx.c.

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

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 572 of file pbx.c.

573{
574 struct ast_str *str;
575 char *parse;
576 char *cur;
577 struct ast_hintdevice *device;
578 int devicelength;
579
580 if (!hint || !devicelist) {
581 /* Trying to add garbage? Don't bother. */
582 return 0;
583 }
584 if (!(str = ast_str_thread_get(&hintdevice_data, 16))) {
585 return -1;
586 }
587 ast_str_set(&str, 0, "%s", devicelist);
588 parse = ast_str_buffer(str);
589
590 /* Spit on '&' and ',' to handle presence hints as well */
591 while ((cur = strsep(&parse, "&,"))) {
592 char *device_name;
593
594 devicelength = strlen(cur);
595 if (!devicelength) {
596 continue;
597 }
598
599 device_name = ast_strdup(cur);
600 if (!device_name) {
601 return -1;
602 }
603
604 device = ao2_t_alloc(sizeof(*device) + devicelength, hintdevice_destroy,
605 "allocating a hintdevice structure");
606 if (!device) {
607 ast_free(device_name);
608 return -1;
609 }
610 strcpy(device->hintdevice, cur);
611 ao2_ref(hint, +1);
612 device->hint = hint;
613 if (AST_VECTOR_APPEND(&hint->devices, device_name)) {
614 ast_free(device_name);
615 ao2_ref(device, -1);
616 return -1;
617 }
618 ao2_t_link(hintdevices, device, "Linking device into hintdevice container.");
619 ao2_t_ref(device, -1, "hintdevice is linked so we can unref");
620 }
621
622 return 0;
623}
const char * str
Definition: app_jack.c:150
char * strsep(char **str, const char *delims)
#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
static void hintdevice_destroy(void *obj)
Definition: pbx.c:560
static struct ao2_container * hintdevices
Container for hint devices.
Definition: pbx.c:385
static struct ast_threadstorage hintdevice_data
Definition: pbx.c:374
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::@382 devices
Structure for dial plan hint devices.
Definition: pbx.c:391
char hintdevice[1]
Definition: pbx.c:398
struct ast_hint * hint
Hint this hintdevice belongs to.
Definition: pbx.c:396
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:267

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 1479 of file pbx.c.

1480{
1481 struct match_char *m;
1482
1483 if (!(m = ast_calloc(1, sizeof(*m) + strlen(pattern->buf)))) {
1484 return NULL;
1485 }
1486
1487 /* strcpy is safe here since we know its size and have allocated
1488 * just enough space for when we allocated m
1489 */
1490 strcpy(m->x, pattern->buf);
1491
1492 /* the specificity scores are the same as used in the old
1493 pattern matcher. */
1495 if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'N') {
1496 m->specificity = 0x0832;
1497 } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'Z') {
1498 m->specificity = 0x0931;
1499 } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'X') {
1500 m->specificity = 0x0a30;
1501 } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == '.') {
1502 m->specificity = 0x18000;
1503 } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == '!') {
1504 m->specificity = 0x28000;
1505 } else {
1506 m->specificity = pattern->specif;
1507 }
1508
1509 if (!con->pattern_tree) {
1511 } else {
1512 if (already) { /* switch to the new regime (traversing vs appending)*/
1513 insert_in_next_chars_alt_char_list(nextcharptr, m);
1514 } else {
1516 }
1517 }
1518
1519 return m;
1520}
size_t current
static void insert_in_next_chars_alt_char_list(struct match_char **parent_ptr, struct match_char *node)
Definition: pbx.c:1438
int is_pattern
Definition: pbx.c:278
int specificity
Definition: pbx.c:280
char x[1]
Definition: pbx.c:284
char buf[256]
Definition: pbx.c:1476
int specif
Definition: pbx.c:1474

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 7092 of file pbx.c.

7094{
7095 struct ast_exten *ep;
7096 struct ast_exten *eh=e;
7097 int repeated_label = 0; /* Track if this label is a repeat, assume no. */
7098
7099 for (ep = NULL; e ; ep = e, e = e->peer) {
7100 if (e->label && tmp->label && e->priority != tmp->priority && !strcmp(e->label, tmp->label)) {
7101 if (strcmp(e->name, tmp->name)) {
7103 "Extension '%s' priority %d in '%s', label '%s' already in use at aliased extension '%s' priority %d\n",
7104 tmp->name, tmp->priority, con->name, tmp->label, e->name, e->priority);
7105 } else {
7107 "Extension '%s' priority %d in '%s', label '%s' already in use at priority %d\n",
7108 tmp->name, tmp->priority, con->name, tmp->label, e->priority);
7109 }
7110 repeated_label = 1;
7111 }
7112 if (e->priority >= tmp->priority) {
7113 break;
7114 }
7115 }
7116
7117 if (repeated_label) { /* Discard the label since it's a repeat. */
7118 tmp->label = NULL;
7119 }
7120
7121 if (!e) { /* go at the end, and ep is surely set because the list is not empty */
7123
7124 if (tmp->label) {
7126 }
7127 ep->peer = tmp;
7128 return 0; /* success */
7129 }
7130 if (e->priority == tmp->priority) {
7131 /* Can't have something exactly the same. Is this a
7132 replacement? If so, replace, otherwise, bonk. */
7133 if (!replace) {
7134 if (strcmp(e->name, tmp->name)) {
7136 "Unable to register extension '%s' priority %d in '%s', already in use by aliased extension '%s'\n",
7137 tmp->name, tmp->priority, con->name, e->name);
7138 } else {
7140 "Unable to register extension '%s' priority %d in '%s', already in use\n",
7141 tmp->name, tmp->priority, con->name);
7142 }
7143
7144 return -1;
7145 }
7146 /* we are replacing e, so copy the link fields and then update
7147 * whoever pointed to e to point to us
7148 */
7149 tmp->next = e->next; /* not meaningful if we are not first in the peer list */
7150 tmp->peer = e->peer; /* always meaningful */
7151 if (ep) { /* We're in the peer list, just insert ourselves */
7153
7154 if (e->label) {
7156 }
7157
7159 if (tmp->label) {
7161 }
7162
7163 ep->peer = tmp;
7164 } else if (el) { /* We're the first extension. Take over e's functions */
7165 struct match_char *x = add_exten_to_pattern_tree(con, e, 1);
7166 tmp->peer_table = e->peer_table;
7167 tmp->peer_label_table = e->peer_label_table;
7170 if (e->label) {
7172 }
7173 if (tmp->label) {
7175 }
7176
7179 el->next = tmp;
7180 /* The pattern trie points to this exten; replace the pointer,
7181 and all will be well */
7182 if (x) { /* if the trie isn't formed yet, don't sweat this */
7183 if (x->exten) { /* this test for safety purposes */
7184 x->exten = tmp; /* replace what would become a bad pointer */
7185 } else {
7186 ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n");
7187 }
7188 }
7189 } else { /* We're the very first extension. */
7190 struct match_char *x = add_exten_to_pattern_tree(con, e, 1);
7193 tmp->peer_table = e->peer_table;
7194 tmp->peer_label_table = e->peer_label_table;
7197 if (e->label) {
7199 }
7200 if (tmp->label) {
7202 }
7203
7206 con->root = tmp;
7207 /* The pattern trie points to this exten; replace the pointer,
7208 and all will be well */
7209 if (x) { /* if the trie isn't formed yet; no problem */
7210 if (x->exten) { /* this test for safety purposes */
7211 x->exten = tmp; /* replace what would become a bad pointer */
7212 } else {
7213 ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n");
7214 }
7215 }
7216 }
7217 if (tmp->priority == PRIORITY_HINT)
7218 ast_change_hint(e,tmp);
7219 /* Destroy the old one */
7220 if (e->datad)
7221 e->datad(e->data);
7222 ast_free(e);
7223 } else { /* Slip ourselves in just before e */
7224 tmp->peer = e;
7225 tmp->next = e->next; /* extension chain, or NULL if e is not the first extension */
7226 if (ep) { /* Easy enough, we're just in the peer list */
7227 if (tmp->label) {
7229 }
7231 ep->peer = tmp;
7232 } else { /* we are the first in some peer list, so link in the ext list */
7233 tmp->peer_table = e->peer_table;
7234 tmp->peer_label_table = e->peer_label_table;
7235 e->peer_table = 0;
7236 e->peer_label_table = 0;
7238 if (tmp->label) {
7240 }
7243 if (el)
7244 el->next = tmp; /* in the middle... */
7245 else
7246 con->root = tmp; /* ... or at the head */
7247 e->next = NULL; /* e is no more at the head, so e->next must be reset */
7248 }
7249 /* And immediately return success. */
7250 if (tmp->priority == PRIORITY_HINT) {
7251 ast_add_hint(tmp);
7252 }
7253 }
7254 return 0;
7255}
static int replace(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)
Definition: func_strings.c:980
#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:1678
static int ast_change_hint(struct ast_exten *oe, struct ast_exten *ne)
Change hint for an extension.
Definition: pbx.c:4113
static int ast_add_hint(struct ast_exten *e)
Add hint to hint list, check initial extension state.
Definition: pbx.c:3999
#define PRIORITY_HINT
Definition: pbx.h:54
struct ast_hashtab * peer_label_table
Definition: pbx.c:267
const char * label
Definition: pbx.c:259

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, 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 3097 of file pbx.c.

3098{
3100}
@ 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 1417 of file pbx.c.

1418{
1419 struct match_char *t;
1420
1421 if (!current) {
1422 return 0;
1423 }
1424
1425 for (t = current; t; t = t->alt_char) {
1426 if (is_pattern == t->is_pattern && !strcmp(pat, t->x)) {/* uh, we may want to sort exploded [] contents to make matching easy */
1427 return t;
1428 }
1429 }
1430
1431 return 0;
1432}
struct match_char * alt_char
Definition: pbx.c:281

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 4781 of file pbx.c.

4782{
4783 return countcalls;
4784}
static int countcalls
Definition: pbx.c:793

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 6949 of file pbx.c.

6952{
6953 int ret = -1;
6954 struct ast_context *c;
6955
6957 if (c) {
6958 ret = ast_add_extension2(c, replace, extension, priority, label, callerid,
6959 application, data, datad, registrar, NULL, 0);
6961 }
6962
6963 return ret;
6964}
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:7282
static struct ast_context * find_context_locked(const char *context)
lookup for a context with a given name,
Definition: pbx.c:4835
int ast_unlock_contexts(void)
Unlocks contexts.
Definition: pbx.c:8498
char data[]
Definition: pbx.c:319

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(), session_register_apps(), 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 7282 of file pbx.c.

7286{
7287 return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid,
7288 application, data, datad, registrar, registrar_file, registrar_line, 1);
7289}
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:7308

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(), and pbx_load_config().

◆ 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 7308 of file pbx.c.

7312{
7313 /*
7314 * Sort extensions (or patterns) according to the rules indicated above.
7315 * These are implemented by the function ext_cmp()).
7316 * All priorities for the same ext/pattern/cid are kept in a list,
7317 * using the 'peer' field as a link field..
7318 */
7319 struct ast_exten *tmp, *tmp2, *e, *el = NULL;
7320 int res;
7321 int length;
7322 char *p;
7323 char expand_buf[VAR_BUF_SIZE];
7324 struct ast_exten dummy_exten = {0};
7325 char dummy_name[1024];
7326 int exten_fluff;
7327 int callerid_fluff;
7328
7330 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",
7331 con->name);
7332 /* We always need to deallocate 'data' on failure */
7333 if (datad) {
7334 datad(data);
7335 }
7336 return -1;
7337 }
7338
7339 /* If we are adding a hint evaluate in variables and global variables */
7340 if (priority == PRIORITY_HINT && strstr(application, "${") && extension[0] != '_') {
7341 int inhibited;
7343
7344 if (c) {
7347 }
7348
7349 /*
7350 * We can allow dangerous functions when adding a hint since
7351 * altering dialplan is itself a privileged activity. Otherwise,
7352 * we could never execute dangerous functions.
7353 */
7355 pbx_substitute_variables_helper(c, application, expand_buf, sizeof(expand_buf));
7356 if (0 < inhibited) {
7358 }
7359
7360 application = expand_buf;
7361 if (c) {
7363 }
7364 }
7365
7366 if (priority == PRIORITY_HINT) {
7367 /* Fluff in a hint is fine. This prevents the removal of dashes from dynamically
7368 * created hints during a reload. */
7369 exten_fluff = 0;
7370 } else {
7371 exten_fluff = ext_fluff_count(extension);
7372 }
7373
7374 callerid_fluff = callerid ? ext_fluff_count(callerid) : 0;
7375
7376 length = sizeof(struct ast_exten);
7377 length += strlen(extension) + 1;
7378 if (exten_fluff) {
7379 length += strlen(extension) + 1 - exten_fluff;
7380 }
7381 length += strlen(application) + 1;
7382 if (label) {
7383 length += strlen(label) + 1;
7384 }
7385 if (callerid) {
7386 length += strlen(callerid) + 1;
7387 if (callerid_fluff) {
7388 length += strlen(callerid) + 1 - callerid_fluff;
7389 }
7390 } else {
7391 length ++; /* just the '\0' */
7392 }
7393 if (registrar_file) {
7394 length += strlen(registrar_file) + 1;
7395 }
7396
7397 /* Be optimistic: Build the extension structure first */
7398 tmp = ast_calloc(1, length);
7399 if (!tmp) {
7400 /* We always need to deallocate 'data' on failure */
7401 if (datad) {
7402 datad(data);
7403 }
7404 return -1;
7405 }
7406
7407 if (ast_strlen_zero(label)) /* let's turn empty labels to a null ptr */
7408 label = 0;
7409
7410 /* use p as dst in assignments, as the fields are const char * */
7411 p = tmp->stuff;
7412 if (label) {
7413 tmp->label = p;
7414 strcpy(p, label);
7415 p += strlen(label) + 1;
7416 }
7417 tmp->name = p;
7418 p += ext_strncpy(p, extension, strlen(extension) + 1, 0);
7419 if (exten_fluff) {
7420 tmp->exten = p;
7421 p += ext_strncpy(p, extension, strlen(extension) + 1 - exten_fluff, 1);
7422 } else {
7423 /* no fluff, we don't need a copy. */
7424 tmp->exten = tmp->name;
7425 }
7426 tmp->priority = priority;
7427 tmp->cidmatch_display = tmp->cidmatch = p; /* but use p for assignments below */
7428
7429 /* Blank callerid and NULL callerid are two SEPARATE things. Do NOT confuse the two!!! */
7430 if (callerid) {
7431 p += ext_strncpy(p, callerid, strlen(callerid) + 1, 0);
7432 if (callerid_fluff) {
7433 tmp->cidmatch = p;
7434 p += ext_strncpy(p, callerid, strlen(callerid) + 1 - callerid_fluff, 1);
7435 }
7437 } else {
7438 *p++ = '\0';
7440 }
7441
7442 if (registrar_file) {
7443 tmp->registrar_file = p;
7444 strcpy(p, registrar_file);
7445 p += strlen(registrar_file) + 1;
7446 } else {
7447 tmp->registrar_file = NULL;
7448 }
7449
7450 tmp->app = p;
7451 strcpy(p, application);
7452 tmp->parent = con;
7453 tmp->data = data;
7454 tmp->datad = datad;
7455 tmp->registrar = registrar;
7457
7458 if (lock_context) {
7459 ast_wrlock_context(con);
7460 }
7461
7462 if (con->pattern_tree) { /* usually, on initial load, the pattern_tree isn't formed until the first find_exten; so if we are adding
7463 an extension, and the trie exists, then we need to incrementally add this pattern to it. */
7464 ext_strncpy(dummy_name, tmp->exten, sizeof(dummy_name), 1);
7465 dummy_exten.exten = dummy_name;
7466 dummy_exten.matchcid = AST_EXT_MATCHCID_OFF;
7467 dummy_exten.cidmatch = 0;
7468 tmp2 = ast_hashtab_lookup(con->root_table, &dummy_exten);
7469 if (!tmp2) {
7470 /* hmmm, not in the trie; */
7471 add_exten_to_pattern_tree(con, tmp, 0);
7472 ast_hashtab_insert_safe(con->root_table, tmp); /* for the sake of completeness */
7473 }
7474 }
7475 res = 0; /* some compilers will think it is uninitialized otherwise */
7476 for (e = con->root; e; el = e, e = e->next) { /* scan the extension list */
7477 res = ext_cmp(e->exten, tmp->exten);
7478 if (res == 0) { /* extension match, now look at cidmatch */
7480 res = 0;
7482 res = 1;
7484 res = -1;
7485 else
7486 res = ext_cmp(e->cidmatch, tmp->cidmatch);
7487 }
7488 if (res >= 0)
7489 break;
7490 }
7491 if (e && res == 0) { /* exact match, insert in the priority chain */
7492 res = add_priority(con, tmp, el, e, replace);
7493 if (res < 0) {
7494 if (con->pattern_tree) {
7495 struct match_char *x = add_exten_to_pattern_tree(con, tmp, 1);
7496
7497 if (x->exten) {
7498 x->deleted = 1;
7499 x->exten = 0;
7500 }
7501
7503 }
7504
7505 if (tmp->datad) {
7506 tmp->datad(tmp->data);
7507 /* if you free this, null it out */
7508 tmp->data = NULL;
7509 }
7510
7511 ast_free(tmp);
7512 }
7513 if (lock_context) {
7514 ast_unlock_context(con);
7515 }
7516 if (res < 0) {
7517 errno = EEXIST;
7518 return -1;
7519 }
7520 } else {
7521 /*
7522 * not an exact match, this is the first entry with this pattern,
7523 * so insert in the main list right before 'e' (if any)
7524 */
7525 tmp->next = e;
7531 0);
7537 0);
7538
7539 if (el) { /* there is another exten already in this context */
7540 el->next = tmp;
7541 } else { /* this is the first exten in this context */
7542 if (!con->root_table) {
7548 0);
7549 }
7550 con->root = tmp;
7551 }
7552 if (label) {
7554 }
7557
7558 if (lock_context) {
7559 ast_unlock_context(con);
7560 }
7561 if (tmp->priority == PRIORITY_HINT) {
7562 ast_add_hint(tmp);
7563 }
7564 }
7565 if (DEBUG_ATLEAST(1)) {
7566 if (tmp->matchcid == AST_EXT_MATCHCID_ON) {
7567 ast_log(LOG_DEBUG, "Added extension '%s' priority %d (CID match '%s') to %s (%p)\n",
7568 tmp->name, tmp->priority, tmp->cidmatch_display, con->name, con);
7569 } else {
7570 ast_log(LOG_DEBUG, "Added extension '%s' priority %d to %s (%p)\n",
7571 tmp->name, tmp->priority, con->name, con);
7572 }
7573 }
7574
7575 return 0;
7576}
void ast_channel_exten_set(struct ast_channel *chan, const char *value)
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:3008
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:1328
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:713
static int hashtab_compare_exten_numbers(const void *ah_a, const void *ah_b)
Definition: pbx.c:741
static int ext_cmp(const char *left, const char *right)
Definition: pbx.c:2155
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:7092
static int ext_fluff_count(const char *exten)
Definition: pbx.c:2177
static unsigned int hashtab_hash_extens(const void *obj)
Definition: pbx.c:761
static unsigned int hashtab_hash_priority(const void *obj)
Definition: pbx.c:771
static unsigned int ext_strncpy(char *dst, const char *src, size_t dst_size, int nofluff)
Definition: pbx.c:7051
static int hashtab_compare_exten_labels(const void *ah_a, const void *ah_b)
Definition: pbx.c:748
static unsigned int hashtab_hash_labels(const void *obj)
Definition: pbx.c:777
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 * cidmatch_display
Definition: pbx.c:257
char stuff[0]
Definition: pbx.c:272
const char * registrar_file
Definition: pbx.c:269
int registrar_line
Definition: pbx.c:270
void * data
Definition: pbx.c:263
void(* datad)(void *)
Definition: pbx.c:264

References add_exten_to_pattern_tree(), add_priority(), ast_exten::app, 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::cidmatch_display, 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_exten::name, ast_context::name, ast_exten::next, NULL, ast_exten::parent, ast_context::pattern_tree, pbx_substitute_variables_helper(), ast_exten::peer_label_table, ast_exten::peer_table, priority, ast_exten::priority, PRIORITY_HINT, ast_exten::registrar, registrar, ast_exten::registrar_file, ast_exten::registrar_line, replace(), ast_context::root, ast_context::root_table, ast_exten::stuff, 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 7291 of file pbx.c.

7295{
7296 return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid,
7297 application, data, datad, registrar, registrar_file, registrar_line, 0);
7298}

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 6929 of file pbx.c.

6932{
6933 int ret = -1;
6934 struct ast_context *c;
6935
6937 if (c) {
6938 ret = ast_add_extension2_lockopt(c, replace, extension, priority, label, callerid,
6939 application, data, datad, registrar, NULL, 0, 1);
6940 }
6941
6942 return ret;
6943}
static struct ast_context * find_context(const char *context)
lookup for a context with a given name,
Definition: pbx.c:4821

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 3999 of file pbx.c.

4000{
4001 struct ast_hint *hint_new;
4002 struct ast_hint *hint_found;
4003 char *message = NULL;
4004 char *subtype = NULL;
4005 int presence_state;
4006
4007 if (!e) {
4008 return -1;
4009 }
4010
4011 /*
4012 * We must create the hint we wish to add before determining if
4013 * it is already in the hints container to avoid possible
4014 * deadlock when getting the current extension state.
4015 */
4016 hint_new = ao2_alloc(sizeof(*hint_new), destroy_hint);
4017 if (!hint_new) {
4018 return -1;
4019 }
4020 AST_VECTOR_INIT(&hint_new->devices, 8);
4021
4022 /* Initialize new hint. */
4024 if (!hint_new->callbacks) {
4025 ao2_ref(hint_new, -1);
4026 return -1;
4027 }
4028 hint_new->exten = e;
4029 if (strstr(e->app, "${") && e->exten[0] == '_') {
4030 /* The hint is dynamic and hasn't been evaluated yet */
4031 hint_new->laststate = AST_DEVICE_INVALID;
4033 } else {
4034 hint_new->laststate = ast_extension_state2(e, NULL);
4035 if ((presence_state = extension_presence_state_helper(e, &subtype, &message)) > 0) {
4036 hint_new->last_presence_state = presence_state;
4037 hint_new->last_presence_subtype = subtype;
4038 hint_new->last_presence_message = message;
4039 }
4040 }
4041
4042 /* Prevent multiple add hints from adding the same hint at the same time. */
4043 ao2_lock(hints);
4044
4045 /* Search if hint exists, do nothing */
4046 hint_found = ao2_find(hints, e, 0);
4047 if (hint_found) {
4048 ao2_ref(hint_found, -1);
4050 ao2_ref(hint_new, -1);
4051 ast_debug(2, "HINTS: Not re-adding existing hint %s: %s\n",
4053 return -1;
4054 }
4055
4056 /* Add new hint to the hints container */
4057 ast_debug(2, "HINTS: Adding hint %s: %s\n",
4059 ao2_link(hints, hint_new);
4060 if (add_hintdevice(hint_new, ast_get_extension_app(e))) {
4061 ast_log(LOG_WARNING, "Could not add devices for hint: %s@%s.\n",
4064 }
4065
4066 /* if not dynamic */
4067 if (!(strstr(e->app, "${") && e->exten[0] == '_')) {
4068 struct ast_state_cb *state_cb;
4069 struct ao2_iterator cb_iter;
4070
4071 /* For general callbacks */
4072 cb_iter = ao2_iterator_init(statecbs, 0);
4073 for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_ref(state_cb, -1)) {
4077 state_cb->data,
4079 hint_new,
4080 NULL);
4081 }
4082 ao2_iterator_destroy(&cb_iter);
4083 }
4085 ao2_ref(hint_new, -1);
4086
4087 return 0;
4088}
#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:823
const char * ast_get_extension_app(struct ast_exten *e)
Definition: pbx.c:8582
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:3271
static void destroy_hint(void *obj)
Definition: pbx.c:3924
struct ast_context * ast_get_extension_context(struct ast_exten *exten)
Definition: pbx.c:8529
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:3134
const char * ast_get_context_name(struct ast_context *con)
Definition: pbx.c:8524
static int extension_presence_state_helper(struct ast_exten *e, char **subtype, char **message)
Definition: pbx.c:3221
static int hint_id_cmp(void *obj, void *arg, int flags)
Definition: pbx.c:3910
static int add_hintdevice(struct ast_hint *hint, const char *devicelist)
add hintdevice structure and link it into the container.
Definition: pbx.c:572
const char * ast_get_extension_name(struct ast_exten *exten)
Definition: pbx.c:8534
@ AST_HINT_UPDATE_DEVICE
Definition: pbx.h:91
@ AST_PRESENCE_INVALID
Definition: presencestate.h:39
struct ao2_container * callbacks
Definition: pbx.c:354
int last_presence_state
Definition: pbx.c:360
char * last_presence_subtype
Definition: pbx.c:361
char * last_presence_message
Definition: pbx.c:362
ast_state_cb: An extension state notify register item
Definition: pbx.c:323
ast_state_cb_type change_cb
Definition: pbx.c:331
void * data
Definition: pbx.c:327
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition: vector.h:124

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
If the AST_SOFTHANGUP_ASYNCGOTO flag is set, it can prevent the dialplan location from being overwritten by ast_explicit_goto.
Do NOT hold any channel locks when calling this function.

Definition at line 6994 of file pbx.c.

6995{
6996 struct ast_channel *newchan;
6997
6998 ast_channel_lock(chan);
6999 /* Channels in a bridge or running a PBX can be sent directly to the specified destination */
7000 if (ast_channel_is_bridged(chan) || ast_channel_pbx(chan)) {
7002 priority += 1;
7003 }
7006 ast_channel_unlock(chan);
7007 return 0;
7008 }
7009 ast_channel_unlock(chan);
7010
7011 /* Otherwise, we need to gain control of the channel first */
7012 newchan = ast_channel_yank(chan);
7013 if (!newchan) {
7014 ast_log(LOG_WARNING, "Unable to gain control of channel %s\n", ast_channel_name(chan));
7015 return -1;
7016 }
7018 if (ast_pbx_start(newchan)) {
7019 ast_hangup(newchan);
7020 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(newchan));
7021 return -1;
7022 }
7023
7024 return 0;
7025}
struct ast_channel * ast_channel_yank(struct ast_channel *yankee)
Gain control of a channel in the system.
Definition: channel.c:10607
int ast_channel_is_bridged(const struct ast_channel *chan)
Determine if a channel is in a bridge.
Definition: channel.c:10559
int ast_softhangup_nolock(struct ast_channel *chan, int cause)
Softly hangup up a channel (no channel lock)
Definition: channel.c:2428
enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
Create a new thread and start the PBX.
Definition: pbx.c:4729

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(), ast_async_goto_by_name(), async_goto_with_discard_bridge_after(), 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 7027 of file pbx.c.

7028{
7029 struct ast_channel *chan;
7030 int res = -1;
7031
7032 if ((chan = ast_channel_get_by_name(channame))) {
7033 res = ast_async_goto(chan, context, exten, priority);
7034 chan = ast_channel_unref(chan);
7035 }
7036
7037 return res;
7038}
struct ast_channel * ast_channel_get_by_name(const char *search)
Find a channel by name or uniqueid.
Definition: channel.c:1398

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 8811 of file pbx.c.

8812{
8813 return __ast_goto_if_exists(chan, context, exten, priority, 1);
8814}
static int __ast_goto_if_exists(struct ast_channel *chan, const char *context, const char *exten, int priority, int async)
Definition: pbx.c:8785

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 8896 of file pbx.c.

8897{
8898 return pbx_parseable_goto(chan, goto_string, 1);
8899}
static int pbx_parseable_goto(struct ast_channel *chan, const char *goto_string, int async)
Definition: pbx.c:8857

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 4211 of file pbx.c.

4212{
4213 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH, 0, 0);
4214}
@ 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:2890

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 4113 of file pbx.c.

4114{
4115 struct ast_hint *hint;
4116
4117 if (!oe || !ne) {
4118 return -1;
4119 }
4120
4121 ao2_lock(hints);/* Locked to hold off others while we move the hint around. */
4122
4123 /*
4124 * Unlink the hint from the hints container as the extension
4125 * name (which is the hash value) could change.
4126 */
4127 hint = ao2_find(hints, oe, OBJ_UNLINK);
4128 if (!hint) {
4131 return -1;
4132 }
4133
4134 remove_hintdevice(hint);
4135
4136 /* Update the hint and put it back in the hints container. */
4137 ao2_lock(hint);
4138 hint->exten = ne;
4139
4140 ao2_unlock(hint);
4141
4142 ao2_link(hints, hint);
4143 if (add_hintdevice(hint, ast_get_extension_app(ne))) {
4144 ast_log(LOG_WARNING, "Could not add devices for hint: %s@%s.\n",
4147 }
4149
4150 publish_hint_change(hint, ne);
4151
4152 ao2_ref(hint, -1);
4153
4154 return 0;
4155}
@ OBJ_UNLINK
Definition: astobj2.h:1039
#define ast_mutex_unlock(a)
Definition: lock.h:197
static int publish_hint_change(struct ast_hint *hint, struct ast_exten *ne)
Publish a hint changed event
Definition: pbx.c:4091
static int remove_hintdevice(struct ast_hint *hint)
Definition: pbx.c:539
static ast_mutex_t context_merge_lock
Lock to hold off restructuring of hints by ast_merge_contexts_and_delete.
Definition: pbx.c:810

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 6856 of file pbx.c.

6857{
6858 int ret = -1;
6859 struct ast_context *c;
6860
6862 if (c) {
6865 }
6866 return ret;
6867}
int ast_context_add_ignorepat2(struct ast_context *con, const char *value, const char *registrar)
Definition: pbx.c:6869
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 6869 of file pbx.c.

6870{
6871 struct ast_ignorepat *ignorepat = ignorepat_alloc(value, registrar);
6872 int idx;
6873
6874 if (!ignorepat) {
6875 return -1;
6876 }
6877
6878 ast_wrlock_context(con);
6879 for (idx = 0; idx < ast_context_ignorepats_count(con); idx++) {
6880 const struct ast_ignorepat *i = ast_context_ignorepats_get(con, idx);
6881
6882 if (!strcasecmp(ast_get_ignorepat_name(i), value)) {
6883 /* Already there */
6884 ast_unlock_context(con);
6885 ignorepat_free(ignorepat);
6886 errno = EEXIST;
6887 return -1;
6888 }
6889 }
6890 if (AST_VECTOR_APPEND(&con->ignorepats, ignorepat)) {
6891 ignorepat_free(ignorepat);
6892 ast_unlock_context(con);
6893 return -1;
6894 }
6895 ast_unlock_context(con);
6896
6897 return 0;
6898}
const struct ast_ignorepat * ast_context_ignorepats_get(const struct ast_context *con, int idx)
Definition: pbx.c:8752
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

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 6685 of file pbx.c.

6686{
6687 int ret = -1;
6688 struct ast_context *c;
6689
6691 if (c) {
6692 ret = ast_context_add_include2(c, include, registrar);
6694 }
6695 return ret;
6696}
int ast_context_add_include2(struct ast_context *con, const char *value, const char *registrar)
Add a context include.
Definition: pbx.c:6705

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 6705 of file pbx.c.

6707{
6708 struct ast_include *new_include;
6709 int idx;
6710
6711 /* allocate new include structure ... */
6712 new_include = include_alloc(value, registrar);
6713 if (!new_include) {
6714 return -1;
6715 }
6716
6717 ast_wrlock_context(con);
6718
6719 /* ... go to last include and check if context is already included too... */
6720 for (idx = 0; idx < ast_context_includes_count(con); idx++) {
6721 const struct ast_include *i = ast_context_includes_get(con, idx);
6722
6723 if (!strcasecmp(ast_get_include_name(i), ast_get_include_name(new_include))) {
6724 include_free(new_include);
6725 ast_unlock_context(con);
6726 errno = EEXIST;
6727 return -1;
6728 }
6729 }
6730
6731 /* ... include new context into context list, unlock, return */
6732 if (AST_VECTOR_APPEND(&con->includes, new_include)) {
6733 include_free(new_include);
6734 ast_unlock_context(con);
6735 return -1;
6736 }
6737 ast_debug(1, "Including context '%s' in context '%s'\n",
6738 ast_get_include_name(new_include), ast_get_context_name(con));
6739
6740 ast_unlock_context(con);
6741
6742 return 0;
6743}
const struct ast_include * ast_context_includes_get(const struct ast_context *con, int idx)
Definition: pbx.c:8709
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

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 6750 of file pbx.c.

6751{
6752 int ret = -1;
6753 struct ast_context *c;
6754
6756 if (c) { /* found, add switch to this context */
6757 ret = ast_context_add_switch2(c, sw, data, eval, registrar);
6759 }
6760 return ret;
6761}
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:6770

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 6770 of file pbx.c.

6772{
6773 int idx;
6774 struct ast_sw *new_sw;
6775
6776 /* allocate new sw structure ... */
6777 if (!(new_sw = sw_alloc(value, data, eval, registrar))) {
6778 return -1;
6779 }
6780
6781 /* ... try to lock this context ... */
6782 ast_wrlock_context(con);
6783
6784 /* ... go to last sw and check if context is already swd too... */
6785 for (idx = 0; idx < ast_context_switches_count(con); idx++) {
6786 const struct ast_sw *i = ast_context_switches_get(con, idx);
6787
6788 if (!strcasecmp(ast_get_switch_name(i), ast_get_switch_name(new_sw)) &&
6789 !strcasecmp(ast_get_switch_data(i), ast_get_switch_data(new_sw))) {
6790 sw_free(new_sw);
6791 ast_unlock_context(con);
6792 errno = EEXIST;
6793 return -1;
6794 }
6795 }
6796
6797 /* ... sw new context into context list, unlock, return */
6798 if (AST_VECTOR_APPEND(&con->alts, new_sw)) {
6799 sw_free(new_sw);
6800 ast_unlock_context(con);
6801 return -1;
6802 }
6803
6804 ast_verb(3, "Including switch '%s/%s' in context '%s'\n",
6806
6807 ast_unlock_context(con);
6808
6809 return 0;
6810}
const struct ast_sw * ast_context_switches_get(const struct ast_context *con, int idx)
Definition: pbx.c:8664
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
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 8246 of file pbx.c.

8247{
8251}
void __ast_context_destroy(struct ast_context *list, struct ast_hashtab *contexttab, struct ast_context *con, const char *registrar)
Definition: pbx.c:8081
int ast_wrlock_contexts(void)
Write locks the context list.
Definition: pbx.c:8488
static struct ast_hashtab * contexts_table
Definition: pbx.c:797

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 8230 of file pbx.c.

8231{
8232 struct ast_context *con;
8233 int ret = -1;
8234
8237 if (con) {
8239 ret = 0;
8240 }
8242
8243 return ret;
8244}
struct ast_context * ast_context_find(const char *name)
Find a context.
Definition: pbx.c:2454
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:8246

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(), handle_cli_dialplan_remove_context(), and session_unregister_app_cb().

◆ 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 2454 of file pbx.c.

2455{
2456 struct ast_context *tmp;
2457 struct ast_context item = {
2458 .name = name,
2459 };
2460
2461 if (!name) {
2462 return NULL;
2463 }
2465 if (contexts_table) {
2467 } else {
2468 tmp = NULL;
2469 while ((tmp = ast_walk_contexts(tmp))) {
2470 if (!strcasecmp(name, tmp->name)) {
2471 break;
2472 }
2473 }
2474 }
2476 return tmp;
2477}
static const char name[]
Definition: format_mp3.c:68
struct ast_context * ast_walk_contexts(struct ast_context *con)
Definition: pbx.c:8616
int ast_rdlock_contexts(void)
Read locks the context list.
Definition: pbx.c:8493
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, ast_context::name, and NULL.

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(), isexten_function_read(), and session_register_apps().

◆ 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 6170 of file pbx.c.

6171{
6172 struct ast_context *tmp, **local_contexts;
6173 struct ast_context search = {
6174 .name = name,
6175 };
6176 size_t name_bytes = strlen(name);
6177 size_t registrar_bytes = strlen(registrar);
6178 int length = sizeof(struct ast_context) + name_bytes + registrar_bytes + 2;
6179
6180 if (!contexts_table) {
6181 /* Protect creation of contexts_table from reentrancy. */
6183 if (!contexts_table) {
6189 0);
6190 }
6192 }
6193
6194 if (!extcontexts) {
6197 tmp = ast_hashtab_lookup(contexts_table, &search);
6198 if (tmp) {
6199 tmp->refcount++;
6201 return tmp;
6202 }
6203 } else { /* local contexts just in a linked list; search there for the new context; slow, linear search, but not frequent */
6204 local_contexts = extcontexts;
6205 tmp = ast_hashtab_lookup(exttable, &search);
6206 if (tmp) {
6207 tmp->refcount++;
6208 return tmp;
6209 }
6210 }
6211
6212 if ((tmp = ast_calloc(1, length))) {
6213 ast_rwlock_init(&tmp->lock);
6214 tmp->name = memcpy(&tmp->data[0], name, name_bytes);
6215 tmp->registrar = memcpy(&tmp->data[name_bytes + 1], registrar, registrar_bytes);
6216 tmp->root = NULL;
6217 tmp->root_table = NULL;
6218 AST_VECTOR_INIT(&tmp->includes, 0);
6219 AST_VECTOR_INIT(&tmp->ignorepats, 0);
6220 AST_VECTOR_INIT(&tmp->alts, 0);
6221 tmp->refcount = 1;
6222
6223 /* The context 'name' must be stored at the beginning of 'data.' The
6224 * order of subsequent strings (currently only 'registrar') is not
6225 * relevant. */
6226 ast_assert(tmp->name == &tmp->data[0]);
6227 } else {
6228 ast_log(LOG_ERROR, "Danger! We failed to allocate a context for %s!\n", name);
6229 if (!extcontexts) {
6231 }
6232 return NULL;
6233 }
6234
6235 if (!extcontexts) {
6236 tmp->next = *local_contexts;
6237 *local_contexts = tmp;
6238 ast_hashtab_insert_safe(contexts_table, tmp); /*put this context into the tree */
6240 } else {
6241 tmp->next = *local_contexts;
6242 if (exttable)
6243 ast_hashtab_insert_immediate(exttable, tmp); /*put this context into the tree */
6244
6245 *local_contexts = tmp;
6246 }
6247 ast_debug(1, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar);
6248 return tmp;
6249}
#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:231
int ast_hashtab_compare_contexts(const void *ah_a, const void *ah_b)
hashtable functions for contexts
Definition: pbx.c:703
unsigned int ast_hashtab_hash_contexts(const void *obj)
Definition: pbx.c:755
static struct ast_context * local_contexts
Definition: pbx_config.c:117
int refcount
Definition: pbx.c:311
#define ast_assert(a)
Definition: utils.h:776

References ast_context::alts, 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, ast_context::data, ast_context::ignorepats, ast_context::includes, local_contexts, ast_context::lock, LOG_ERROR, name, ast_context::name, ast_context::next, NULL, ast_context::refcount, ast_context::registrar, registrar, ast_context::root, and ast_context::root_table.

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(), session_register_apps(), 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 4969 of file pbx.c.

4970{
4972}
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:4974
@ 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 4999 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 4974 of file pbx.c.

4975{
4976 int ret = -1; /* default error return */
4977 struct ast_context *c;
4978
4980 if (c) { /* ... remove extension ... */
4982 matchcallerid, registrar, 0);
4984 }
4985
4986 return ret;
4987}

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 5004 of file pbx.c.

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

6817{
6818 int ret = -1;
6819 struct ast_context *c;
6820
6822 if (c) {
6823 ret = ast_context_remove_ignorepat2(c, ignorepat, registrar);
6825 }
6826 return ret;
6827}
int ast_context_remove_ignorepat2(struct ast_context *con, const char *ignorepat, const char *registrar)
Definition: pbx.c:6829

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 6829 of file pbx.c.

6830{
6831 int idx;
6832
6833 ast_wrlock_context(con);
6834
6835 for (idx = 0; idx < ast_context_ignorepats_count(con); idx++) {
6836 struct ast_ignorepat *ip = AST_VECTOR_GET(&con->ignorepats, idx);
6837
6838 if (!strcmp(ast_get_ignorepat_name(ip), ignorepat) &&
6841 ignorepat_free(ip);
6842 ast_unlock_context(con);
6843 return 0;
6844 }
6845 }
6846
6847 ast_unlock_context(con);
6848 errno = EINVAL;
6849 return -1;
6850}

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 4857 of file pbx.c.

4858{
4859 int ret = -1;
4860 struct ast_context *c;
4861
4863 if (c) {
4864 /* found, remove include from this context ... */
4865 ret = ast_context_remove_include2(c, include, registrar);
4867 }
4868 return ret;
4869}
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:4880

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 4880 of file pbx.c.

4881{
4882 int ret = -1;
4883 int idx;
4884
4885 ast_wrlock_context(con);
4886
4887 /* find our include */
4888 for (idx = 0; idx < ast_context_includes_count(con); idx++) {
4889 struct ast_include *i = AST_VECTOR_GET(&con->includes, idx);
4890
4891 if (!strcmp(ast_get_include_name(i), include) &&
4892 (!registrar || !strcmp(ast_get_include_registrar(i), registrar))) {
4893
4894 /* remove from list */
4895 ast_verb(3, "Removing inclusion of context '%s' in context '%s; registrar=%s'\n", include, ast_get_context_name(con), registrar);
4897
4898 /* free include and return */
4899 include_free(i);
4900 ret = 0;
4901 break;
4902 }
4903 }
4904
4905 ast_unlock_context(con);
4906
4907 return ret;
4908}

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 4915 of file pbx.c.

4916{
4917 int ret = -1; /* default error return */
4918 struct ast_context *c;
4919
4921 if (c) {
4922 /* remove switch from this context ... */
4925 }
4926 return ret;
4927}
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:4937

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 4937 of file pbx.c.

4938{
4939 int idx;
4940 int ret = -1;
4941
4942 ast_wrlock_context(con);
4943
4944 /* walk switches */
4945 for (idx = 0; idx < ast_context_switches_count(con); idx++) {
4946 struct ast_sw *i = AST_VECTOR_GET(&con->alts, idx);
4947
4948 if (!strcmp(ast_get_switch_name(i), sw) &&
4949 !strcmp(ast_get_switch_data(i), data) &&
4950 (!registrar || !strcmp(ast_get_switch_registrar(i), registrar))) {
4951
4952 /* found, remove from list */
4953 ast_verb(3, "Removing switch '%s' from context '%s; registrar=%s'\n", sw, ast_get_context_name(con), registrar);
4954 AST_VECTOR_REMOVE_ORDERED(&con->alts, idx);
4955
4956 /* free switch and return */
4957 sw_free(i);
4958 ret = 0;
4959 break;
4960 }
4961 }
4962
4963 ast_unlock_context(con);
4964
4965 return ret;
4966}

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 6251 of file pbx.c.

6252{
6253 con->autohints = enabled;
6254}
static int enabled
Definition: dnsmgr.c:91
int autohints
Definition: pbx.c:312

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 8757 of file pbx.c.

8758{
8759 int idx;
8760 int res = 0;
8761 int includecount = ast_context_includes_count(con);
8762
8763 if (includecount >= AST_PBX_MAX_STACK) {
8764 ast_log(LOG_WARNING, "Context %s contains too many includes (%d). Maximum is %d.\n",
8765 ast_get_context_name(con), includecount, AST_PBX_MAX_STACK);
8766 }
8767
8768 for (idx = 0; idx < includecount; idx++) {
8769 const struct ast_include *inc = ast_context_includes_get(con, idx);
8770
8771 if (ast_context_find(include_rname(inc))) {
8772 continue;
8773 }
8774
8775 res = -1;
8776 ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n",
8778 break;
8779 }
8780
8781 return res;
8782}
#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 3027 of file pbx.c.

3028{
3029 switch (devstate) {
3030 case AST_DEVICE_ONHOLD:
3031 return AST_EXTENSION_ONHOLD;
3032 case AST_DEVICE_BUSY:
3033 return AST_EXTENSION_BUSY;
3034 case AST_DEVICE_UNKNOWN:
3037 case AST_DEVICE_INVALID:
3041 case AST_DEVICE_RINGING:
3042 return AST_EXTENSION_RINGING;
3043 case AST_DEVICE_INUSE:
3044 return AST_EXTENSION_INUSE;
3047 case AST_DEVICE_TOTAL: /* not a device state, included for completeness */
3048 break;
3049 }
3050
3052}
@ 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 4196 of file pbx.c.

4197{
4198 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH, 0, 0);
4199}

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(), 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(), join_conference_bridge(), key_dial_page(), leave_voicemail(), local_call(), local_devicestate(), loopback_exists(), minivm_greet_exec(), my_handle_dtmf(), new_subscribe(), onModeChanged(), ooh323_rtp_read(), options_on_rx_request(), pbx_builtin_waitexten(), privacy_exec(), readexten_exec(), refer_incoming_attended_request(), refer_incoming_blind_request(), register_peer_exten(), show_debug_helper(), socket_process_helper(), try_calling(), vm_authenticate(), and waitstream_core().

◆ ast_explicit_goto()

int ast_explicit_goto ( struct ast_channel chan,
const char *  context,
const char *  exten,
int  priority 
)
Note
This function will handle locking the channel as needed.
If the AST_SOFTHANGUP_ASYNCGOTO flag is set on the channel, this function will fail and return -1.

Definition at line 6966 of file pbx.c.

6967{
6968 if (!chan)
6969 return -1;
6970
6971 ast_channel_lock(chan);
6972
6974 ast_channel_unlock(chan);
6975 return -1;
6976 }
6979 if (!ast_strlen_zero(exten))
6980 ast_channel_exten_set(chan, exten);
6981 if (priority > -1) {
6982 /* see flag description in channel.h for explanation */
6984 --priority;
6985 }
6987 }
6988
6989 ast_channel_unlock(chan);
6990
6991 return 0;
6992}

References ast_channel_context_set(), ast_channel_exten_set(), ast_channel_flags(), ast_channel_lock, ast_channel_priority_set(), ast_channel_softhangup_internal_flag(), ast_channel_unlock, AST_FLAG_IN_AUTOLOOP, AST_SOFTHANGUP_ASYNCGOTO, ast_strlen_zero(), ast_test_flag, voicemailpwcheck::context, and priority.

Referenced by __ast_goto_if_exists(), app_control_continue(), ast_async_goto(), ast_bridge_setup_after_goto(), disa_exec(), handle_setpriority(), msg_route(), and pbx_parseable_goto().

◆ ast_extension_close()

int ast_extension_close ( const char *  pattern,
const char *  data,
int  needmore 
)

Definition at line 2447 of file pbx.c.

2448{
2449 if (needmore != E_MATCHMORE && needmore != E_CANMATCH)
2450 ast_log(LOG_WARNING, "invalid argument %d\n", needmore);
2451 return extension_match_core(pattern, data, needmore);
2452}
static int extension_match_core(const char *pattern, const char *data, enum ext_match_t mode)
Definition: pbx.c:2429

References ast_log, ast_exten::data, E_CANMATCH, E_MATCHMORE, extension_match_core(), and LOG_WARNING.

Referenced by lua_find_extension(), and realtime_switch_common().

◆ ast_extension_cmp()

int ast_extension_cmp ( const char *  a,
const char *  b 
)

Determine if one extension should match before another.

Parameters
aextension to compare with b
bextension to compare with a

Checks whether or extension a should match before extension b

Return values
0if the two extensions have equal matching priority
1on a > b
-1on a < b

Definition at line 2212 of file pbx.c.

2213{
2214 int cmp;
2215
2216 cmp = ext_cmp(a, b);
2217 if (cmp < 0) {
2218 return -1;
2219 }
2220 if (cmp > 0) {
2221 return 1;
2222 }
2223 return 0;
2224}
static struct test_val b
static struct test_val a

References a, b, and ext_cmp().

Referenced by lua_extension_cmp().

◆ ast_extension_match()

int ast_extension_match ( const char *  pattern,
const char *  extension 
)

Determine if a given extension matches a given pattern (in NXX format)

Parameters
patternpattern to match
extensionextension to check against the pattern.

Checks whether or not the given extension matches the given pattern.

Return values
1on match
0on failure

Definition at line 2442 of file pbx.c.

2443{
2444 return extension_match_core(pattern, extension, E_MATCH);
2445}

References ast_context::data, E_MATCH, and extension_match_core().

Referenced by ast_ignore_pattern(), do_say(), find_matching_priority(), load_module(), loopback_canmatch(), loopback_exists(), loopback_matchmore(), lua_find_extension(), manager_show_dialplan_helper(), matchcid(), realtime_switch_common(), reload(), and show_dialplan_helper().

◆ ast_extension_state()

int ast_extension_state ( struct ast_channel c,
const char *  context,
const char *  exten 
)

Check extension state for an extension by using hint.

Uses hint and devicestate callback to get the state of an extension.

Definition at line 3191 of file pbx.c.

3192{
3194}
static int internal_extension_state_extended(struct ast_channel *c, const char *context, const char *exten, struct ao2_container *device_state_info)
Definition: pbx.c:3162

References c, voicemailpwcheck::context, ast_exten::exten, internal_extension_state_extended(), and NULL.

Referenced by action_extensionstate(), extstate_read(), and get_queue_member_status().

◆ ast_extension_state2()

static int ast_extension_state2 ( struct ast_exten e,
struct ao2_container device_state_info 
)
static

Check state of extension by using hints.

Definition at line 3134 of file pbx.c.

3135{
3136 struct ast_str *hint_app = ast_str_thread_get(&extensionstate_buf, 32);
3137
3138 if (!e || !hint_app) {
3139 return -1;
3140 }
3141
3142 ast_str_set(&hint_app, 0, "%s", ast_get_extension_app(e));
3143 return ast_extension_state3(hint_app, device_state_info);
3144}
static int ast_extension_state3(struct ast_str *hint_app, struct ao2_container *device_state_info)
Definition: pbx.c:3102
static struct ast_threadstorage extensionstate_buf
Definition: pbx.c:244

References ast_extension_state3(), ast_get_extension_app(), ast_str_set(), ast_str_thread_get(), and extensionstate_buf.

Referenced by ast_add_hint(), and internal_extension_state_extended().

◆ ast_extension_state2str()

const char * ast_extension_state2str ( int  extension_state)

Return extension_state as string.

Return string representation of the state of an extension.

Definition at line 3147 of file pbx.c.

3148{
3149 int i;
3150
3151 for (i = 0; (i < ARRAY_LEN(extension_states)); i++) {
3152 if (extension_states[i].extension_state == extension_state)
3153 return extension_states[i].text;
3154 }
3155 return "Unknown";
3156}
static const struct cfextension_states extension_states[]
const char *const text
Definition: pbx.c:628

References ARRAY_LEN, extension_states, and cfextension_states::text.

Referenced by action_extensionstate(), action_extensionstatelist(), AST_TEST_DEFINE(), exten_state_publisher_state_cb(), handle_show_hint(), handle_show_hints(), manager_state_cb(), and to_ami().

◆ ast_extension_state3()

static int ast_extension_state3 ( struct ast_str hint_app,
struct ao2_container device_state_info 
)
static

Definition at line 3102 of file pbx.c.

3103{
3104 char *cur;
3105 char *rest;
3106 struct ast_devstate_aggregate agg;
3107
3108 /* One or more devices separated with a & character */
3109 rest = parse_hint_device(hint_app);
3110
3112 while ((cur = strsep(&rest, "&"))) {
3114
3116 if (device_state_info) {
3117 struct ast_device_state_info *obj;
3118
3119 obj = ao2_alloc_options(sizeof(*obj) + strlen(cur), device_state_info_dt, AO2_ALLOC_OPT_LOCK_NOLOCK);
3120 /* if failed we cannot add this device */
3121 if (obj) {
3122 obj->device_state = state;
3123 strcpy(obj->device_name, cur);
3124 ao2_link(device_state_info, obj);
3125 ao2_ref(obj, -1);
3126 }
3127 }
3128 }
3129
3131}
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:404
enum cc_state state
Definition: ccss.c:399
void ast_devstate_aggregate_add(struct ast_devstate_aggregate *agg, enum ast_device_state state)
Add a device state to the aggregate device state.
Definition: devicestate.c:639
void ast_devstate_aggregate_init(struct ast_devstate_aggregate *agg)
Initialize aggregate device state.
Definition: devicestate.c:633
enum ast_device_state ast_devstate_aggregate_result(struct ast_devstate_aggregate *agg)
Get the aggregate device state result.
Definition: devicestate.c:666
ast_device_state
Device States.
Definition: devicestate.h:52
enum ast_extension_states ast_devstate_to_extenstate(enum ast_device_state devstate)
Map devstate to an extension state.
Definition: pbx.c:3027
static char * parse_hint_device(struct ast_str *hint_args)
Definition: pbx.c:3077
static void device_state_info_dt(void *obj)
Definition: pbx.c:3090
char device_name[1]
Definition: pbx.h:99
enum ast_device_state device_state
Definition: pbx.h:97
You shouldn't care about the contents of this struct.
Definition: devicestate.h:228

References AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_alloc_options, ao2_link, ao2_ref, ast_devstate_aggregate_add(), ast_devstate_aggregate_init(), ast_devstate_aggregate_result(), ast_devstate_to_extenstate(), ast_device_state_info::device_name, ast_device_state_info::device_state, device_state_info_dt(), parse_hint_device(), state, and strsep().

Referenced by ast_extension_state2(), and device_state_notify_callbacks().

◆ ast_extension_state_add()

int ast_extension_state_add ( const char *  context,
const char *  exten,
ast_state_cb_type  change_cb,
void *  data 
)

Add watcher for extension states.

Parameters
contextwhich context to look in
extenwhich extension to get state
change_cbcallback to call if state changed
datato pass to callback
Note
If context and exten are NULL then the added watcher is global. The change_cb is called for every extension's state change.
The change_cb is called if the state of an extension is changed.
Return values
-1on failure
0Global watcher added successfully
IDon success

Definition at line 3844 of file pbx.c.

3846{
3847 return extension_state_add_destroy(context, exten, change_cb, NULL, data, 0);
3848}
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)
Definition: pbx.c:3748

References voicemailpwcheck::context, ast_exten::data, ast_exten::exten, extension_state_add_destroy(), and NULL.

Referenced by __init_manager(), create_queue_member(), and publisher_start().

◆ ast_extension_state_add_destroy()

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.

Since
1.8.9
10.1.0
Parameters
contextwhich context to look in
extenwhich extension to get state
change_cbcallback to call if state changed
destroy_cbcallback to call when the watcher is destroyed.
datato pass to callbacks
Note
If context and exten are NULL then the added watcher is global. The change_cb is called for every extension's state change.
The change_cb is called if the state of an extension is changed.
The destroy_cb is called when the watcher is deleted so the watcher can release any associated resources.
Return values
-1on failure
0Global watcher added successfully
IDon success

Definition at line 3838 of file pbx.c.

3840{
3841 return extension_state_add_destroy(context, exten, change_cb, destroy_cb, data, 0);
3842}

References voicemailpwcheck::context, ast_exten::data, ast_exten::exten, and extension_state_add_destroy().

◆ ast_extension_state_add_destroy_extended()

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.

Since
11
Parameters
contextwhich context to look in
extenwhich extension to get state
change_cbcallback to call if state changed
destroy_cbcallback to call when the watcher is destroyed.
datato pass to callbacks
Note
If context and exten are NULL then the added watcher is global. The change_cb is called for every extension's state change.
The change_cb is called if the state of an extension is changed. The extended state is passed to the callback in the device_state_info member of ast_state_cb_info.
The destroy_cb is called when the watcher is deleted so the watcher can release any associated resources.
Return values
-1on failure
0Global watcher added successfully
IDon success

Definition at line 3850 of file pbx.c.

3852{
3853 return extension_state_add_destroy(context, exten, change_cb, destroy_cb, data, 1);
3854}

References voicemailpwcheck::context, ast_exten::data, ast_exten::exten, and extension_state_add_destroy().

Referenced by subscription_established().

◆ ast_extension_state_add_extended()

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.

Since
11
Parameters
contextwhich context to look in
extenwhich extension to get state
change_cbcallback to call if state changed
datato pass to callback
Note
If context and exten are NULL then the added watcher is global. The change_cb is called for every extension's state change.
The change_cb is called if the state of an extension is changed. The extended state is passed to the callback in the device_state_info member of ast_state_cb_info.
Return values
-1on failure
0Global watcher added successfully
IDon success

Definition at line 3856 of file pbx.c.

3858{
3859 return extension_state_add_destroy(context, exten, change_cb, NULL, data, 1);
3860}

References voicemailpwcheck::context, ast_exten::data, ast_exten::exten, extension_state_add_destroy(), and NULL.

◆ ast_extension_state_del()

int ast_extension_state_del ( int  id,
ast_state_cb_type  change_cb 
)

Deletes a state change watcher by ID.

Parameters
idof the state watcher to delete (0 for global watcher)
change_cbcallback to call if state changed (Used if id == 0 (global))
Return values
0success
-1failure

Definition at line 3877 of file pbx.c.

3878{
3879 struct ast_state_cb *p_cur;
3880 int ret = -1;
3881
3882 if (!id) { /* id == 0 is a callback without extension */
3883 if (!change_cb) {
3884 return ret;
3885 }
3887 if (p_cur) {
3888 ret = 0;
3889 ao2_ref(p_cur, -1);
3890 }
3891 } else { /* callback with extension, find the callback based on ID */
3892 struct ast_hint *hint;
3893
3894 ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */
3895 hint = ao2_callback(hints, 0, find_hint_by_cb_id, &id);
3896 if (hint) {
3897 p_cur = ao2_find(hint->callbacks, &id, OBJ_UNLINK);
3898 if (p_cur) {
3899 ret = 0;
3900 ao2_ref(p_cur, -1);
3901 }
3902 ao2_ref(hint, -1);
3903 }
3905 }
3906
3907 return ret;
3908}
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container,...
Definition: astobj2.h:1693
static int find_hint_by_cb_id(void *obj, void *arg, int flags)
Find Hint by callback id.
Definition: pbx.c:3863

References ao2_callback, ao2_find, ao2_lock, ao2_ref, ao2_unlock, ast_hint::callbacks, ast_state_cb::change_cb, find_hint_by_cb_id(), OBJ_UNLINK, and statecbs.

Referenced by destroy_queue_member_cb(), subscription_shutdown(), and unload_module().

◆ ast_extension_state_extended()

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.

Uses hint and devicestate callback to get the extended state of an extension.

Definition at line 3197 of file pbx.c.

3199{
3200 struct ao2_container *container = NULL;
3201 int ret;
3202
3203 if (device_state_info) {
3205 }
3206
3208 if (ret < 0 && container) {
3209 ao2_ref(container, -1);
3210 container = NULL;
3211 }
3212
3213 if (device_state_info) {
3215 *device_state_info = container;
3216 }
3217
3218 return ret;
3219}
static struct ao2_container * alloc_device_state_info(void)
Definition: pbx.c:3097
static void get_device_state_causing_channels(struct ao2_container *c)
Definition: pbx.c:3317
struct ao2_container * container
Definition: res_fax.c:531
Generic container type.

References alloc_device_state_info(), ao2_ref, c, container, voicemailpwcheck::context, get_device_state_causing_channels(), internal_extension_state_extended(), and NULL.

Referenced by exten_state_data_alloc().

◆ ast_findlabel_extension()

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.

Parameters
cthis is not important
contextwhich context to look in
extenwhich extension to search for
labellabel of the action within the extension to match to priority
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
Return values
thepriority which matches the given label in the extension
-1if not found.

Definition at line 4201 of file pbx.c.

4202{
4203 return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
4204}
@ E_FINDLABEL
Definition: extconf.h:220

References c, voicemailpwcheck::context, E_FINDLABEL, ast_exten::exten, ast_exten::label, NULL, and pbx_extension_helper().

Referenced by action_originate(), action_redirect(), ari_channels_handle_originate_with_id(), ast_ari_channels_continue_in_dialplan(), handle_gosub(), handle_setpriority(), isexten_function_read(), and pbx_parse_location().

◆ ast_findlabel_extension2()

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.

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
This function is the same as ast_findlabel_extension, except that it accepts a pointer to an ast_context structure to specify the context instead of the name of the context. Otherwise, the functions behave the same.

Definition at line 4206 of file pbx.c.

4207{
4208 return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
4209}

References c, E_FINDLABEL, ast_exten::exten, ast_exten::label, NULL, and pbx_extension_helper().

Referenced by pbx_load_config().

◆ ast_get_context_name()

const char * ast_get_context_name ( struct ast_context con)

◆ ast_get_context_registrar()

const char * ast_get_context_registrar ( struct ast_context c)

Definition at line 8552 of file pbx.c.

8553{
8554 return c ? c->registrar : NULL;
8555}

References c, and NULL.

Referenced by handle_cli_dialplan_save(), show_debug_helper(), and show_dialplan_helper().

◆ ast_get_extension_app()

const char * ast_get_extension_app ( struct ast_exten e)

◆ ast_get_extension_app_data()

void * ast_get_extension_app_data ( struct ast_exten e)

◆ ast_get_extension_cidmatch()

const char * ast_get_extension_cidmatch ( struct ast_exten e)

Definition at line 8577 of file pbx.c.

8578{
8579 return e ? e->cidmatch_display : NULL;
8580}

References ast_exten::cidmatch_display, and NULL.

Referenced by complete_dialplan_remove_extension(), find_matching_priority(), handle_cli_dialplan_save(), and test_exten().

◆ ast_get_extension_context()

struct ast_context * ast_get_extension_context ( struct ast_exten exten)

◆ ast_get_extension_data()

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.

Parameters
bufString buffer
bufsizeSize of buf
cChannel
contextDialplan context
extenDialplan extension
priorityDialplan priority
Return values
-1Failed to obtain extension data
0Successfully obtained extension data

Definition at line 8592 of file pbx.c.

8594{
8595 struct ast_exten *e;
8596 struct pbx_find_info q = { .stacklen = 0 }; /* the rest is set in pbx_find_context */
8598 e = pbx_find_extension(c, NULL, &q, context, exten, priority, NULL, "", E_MATCH);
8599 if (e) {
8600 if (buf) {
8601 const char *tmp = ast_get_extension_app_data(e);
8602 if (tmp) {
8603 ast_copy_string(buf, tmp, bufsize);
8604 }
8605 }
8607 return 0;
8608 }
8610 return -1;
8611}
void * ast_get_extension_app_data(struct ast_exten *e)
Definition: pbx.c:8587
struct ast_exten * pbx_find_extension(struct ast_channel *chan, struct ast_context *bypass, struct pbx_find_info *q, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action)
Definition: pbx.c:2497
int stacklen
Definition: extconf.h:237

References ast_copy_string(), ast_get_extension_app_data(), ast_rdlock_contexts(), ast_unlock_contexts(), buf, c, voicemailpwcheck::context, E_MATCH, NULL, pbx_find_extension(), priority, and pbx_find_info::stacklen.

Referenced by eval_exten_read().

◆ ast_get_extension_label()

const char * ast_get_extension_label ( struct ast_exten exten)

Definition at line 8539 of file pbx.c.

8540{
8541 return exten ? exten->label : NULL;
8542}

References ast_exten::label, and NULL.

Referenced by handle_cli_dialplan_save(), manager_show_dialplan_helper(), and show_dialplan_helper().

◆ ast_get_extension_matchcid()

int ast_get_extension_matchcid ( struct ast_exten e)

Definition at line 8572 of file pbx.c.

8573{
8574 return e ? e->matchcid : 0;
8575}

References ast_exten::matchcid.

Referenced by complete_dialplan_remove_extension(), find_matching_priority(), and handle_cli_dialplan_save().

◆ ast_get_extension_name()

const char * ast_get_extension_name ( struct ast_exten exten)

◆ ast_get_extension_priority()

int ast_get_extension_priority ( struct ast_exten exten)

Definition at line 8544 of file pbx.c.

8545{
8546 return exten ? exten->priority : -1;
8547}

References ast_exten::priority.

Referenced by complete_dialplan_remove_extension(), find_matching_priority(), handle_cli_dialplan_save(), manager_show_dialplan_helper(), and print_ext().

◆ ast_get_extension_registrar()

const char * ast_get_extension_registrar ( struct ast_exten e)

◆ ast_get_extension_registrar_file()

const char * ast_get_extension_registrar_file ( struct ast_exten e)

Get name of configuration file used by registrar to register this extension.

Return values
NULLif registrar did not indicate config file when registering the extension
nameof the file used to register the extension

Definition at line 8562 of file pbx.c.

8563{
8564 return e ? e->registrar_file : NULL;
8565}

References NULL, and ast_exten::registrar_file.

Referenced by show_dialplan_helper_extension_output().

◆ ast_get_extension_registrar_line()

int ast_get_extension_registrar_line ( struct ast_exten e)

Get line number of configuration file used by registrar to register this extension.

Return values
0if the line wasn't indicated when the extension was registered
positiveinteger indicating what line in the config file was responsible for registering the extension.

Definition at line 8567 of file pbx.c.

8568{
8569 return e ? e->registrar_line : 0;
8570}

References ast_exten::registrar_line.

Referenced by show_dialplan_helper_extension_output().

◆ ast_get_hint()

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.

If an extension hint exists, return non-zero.

Definition at line 4158 of file pbx.c.

4159{
4161
4162 if (e) {
4163 if (hint)
4164 ast_copy_string(hint, ast_get_extension_app(e), hintsize);
4165 if (name) {
4166 const char *tmp = ast_get_extension_app_data(e);
4167 if (tmp)
4168 ast_copy_string(name, tmp, namesize);
4169 }
4170 return -1;
4171 }
4172 return 0;
4173}
static struct ast_exten * ast_hint_extension(struct ast_channel *c, const char *context, const char *exten)
Definition: pbx.c:3018

References ast_copy_string(), ast_get_extension_app(), ast_get_extension_app_data(), ast_hint_extension(), c, voicemailpwcheck::context, ast_exten::exten, and name.

Referenced by action_extensionstate(), device_state_cb(), get_cid_name(), get_resource_display_name(), hint_read(), and manager_state_cb().

◆ ast_goto_if_exists()

int ast_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 8806 of file pbx.c.

8807{
8808 return __ast_goto_if_exists(chan, context, exten, priority, 0);
8809}

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

Referenced by ast_bridge_setup_after_goto(), background_detect_exec(), channel_spy(), common_exec(), conf_run(), goto_exten(), onedigit_goto(), select_entry(), valid_exit(), vm_execmain(), and vmauthenticate().

◆ ast_hashtab_compare_contexts()

int ast_hashtab_compare_contexts ( const void *  ah_a,
const void *  ah_b 
)

hashtable functions for contexts

Definition at line 703 of file pbx.c.

704{
705 const struct ast_context *ac = ah_a;
706 const struct ast_context *bc = ah_b;
707 if (!ac || !bc) /* safety valve, but it might prevent a crash you'd rather have happen */
708 return 1;
709 /* assume context names are registered in a string table! */
710 return strcmp(ac->name, bc->name);
711}
#define bc

References bc, and ast_context::name.

Referenced by ast_context_find_or_create().

◆ ast_hashtab_hash_contexts()

unsigned int ast_hashtab_hash_contexts ( const void *  obj)

Definition at line 755 of file pbx.c.

756{
757 const struct ast_context *ac = obj;
758 return ast_hashtab_hash_string(ac->name);
759}
unsigned int ast_hashtab_hash_string(const void *obj)
Hashes a string to a number.
Definition: hashtab.c:153

References ast_hashtab_hash_string(), and ast_context::name.

Referenced by ast_context_find_or_create().

◆ ast_hint_extension()

static struct ast_exten * ast_hint_extension ( struct ast_channel c,
const char *  context,
const char *  exten 
)
static

Definition at line 3018 of file pbx.c.

3019{
3020 struct ast_exten *e;
3024 return e;
3025}
static struct ast_exten * ast_hint_extension_nolock(struct ast_channel *c, const char *context, const char *exten)
Find hint for given extension in context.
Definition: pbx.c:3012

References ast_hint_extension_nolock(), ast_rdlock_contexts(), ast_unlock_contexts(), c, voicemailpwcheck::context, and ast_exten::exten.

Referenced by ast_get_hint(), ast_hint_presence_state(), ast_str_get_hint(), extension_state_add_destroy(), and internal_extension_state_extended().

◆ ast_hint_extension_nolock()

static struct ast_exten * ast_hint_extension_nolock ( struct ast_channel c,
const char *  context,
const char *  exten 
)
static

Find hint for given extension in context.

Definition at line 3012 of file pbx.c.

3013{
3014 struct pbx_find_info q = { .stacklen = 0 }; /* the rest is set in pbx_find_context */
3015 return pbx_find_extension(c, NULL, &q, context, exten, PRIORITY_HINT, NULL, "", E_MATCH);
3016}

References c, voicemailpwcheck::context, E_MATCH, NULL, pbx_find_extension(), PRIORITY_HINT, and pbx_find_info::stacklen.

Referenced by ast_hint_extension(), and ast_merge_contexts_and_delete().

◆ ast_hint_presence_state()

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.

Parameters
cthis is not important
contextwhich context to look in
extenwhich extension to get state
[out]subtypeFurther information regarding the presence returned
[out]messageCustom message further describing current presence
Note
The subtype and message are dynamically allocated and must be freed by the caller of this function.
Returns
returns the presence state value.

Definition at line 3247 of file pbx.c.

3248{
3249 struct ast_exten *e;
3250
3251 if (!(e = ast_hint_extension(c, context, exten))) { /* Do we have a hint for this extension ? */
3252 return -1; /* No hint, return -1 */
3253 }
3254
3255 if (e->exten[0] == '_') {
3256 /* Create this hint on-the-fly */
3257 ao2_lock(hints);
3259 e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr,
3260 e->registrar);
3262 if (!(e = ast_hint_extension(c, context, exten))) {
3263 /* Improbable, but not impossible */
3264 return -1;
3265 }
3266 }
3267
3268 return extension_presence_state_helper(e, subtype, message);
3269}
void ast_free_ptr(void *ptr)
free() wrapper
Definition: astmm.c:1739
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.
Definition: pbx.c:6949

References ao2_lock, ao2_unlock, ast_exten::app, ast_add_extension(), ast_free_ptr(), ast_hint_extension(), ast_strdup, c, ast_exten::cidmatch, voicemailpwcheck::context, ast_exten::data, ast_exten::exten, extension_presence_state_helper(), ast_exten::label, ast_exten::matchcid, ast_context::name, NULL, ast_exten::parent, ast_exten::priority, and ast_exten::registrar.

Referenced by exten_state_data_alloc().

◆ ast_ignore_pattern()

int ast_ignore_pattern ( const char *  context,
const char *  pattern 
)

Checks to see if a number should be ignored.

Parameters
contextcontext to search within
patternto check whether it should be ignored or not

Check if a number should be ignored with respect to dialtone cancellation.

Return values
0if the pattern should not be ignored
non-zeroif the pattern should be ignored

Definition at line 6900 of file pbx.c.

6901{
6902 int ret = 0;
6903 struct ast_context *con;
6904
6907 if (con) {
6908 int idx;
6909
6910 for (idx = 0; idx < ast_context_ignorepats_count(con); idx++) {
6911 const struct ast_ignorepat *pat = ast_context_ignorepats_get(con, idx);
6912
6914 ret = 1;
6915 break;
6916 }
6917 }
6918 }
6920
6921 return ret;
6922}
int ast_extension_match(const char *pattern, const char *extension)
Determine if a given extension matches a given pattern (in NXX format)
Definition: pbx.c:2442
const char pattern[0]
Definition: pbx_ignorepat.c:39

References ast_context_find(), ast_context_ignorepats_count(), ast_context_ignorepats_get(), ast_extension_match(), ast_get_ignorepat_name(), ast_rdlock_contexts(), ast_unlock_contexts(), voicemailpwcheck::context, and ast_ignorepat::pattern.

Referenced by __analog_ss_thread(), analog_ss_thread(), ast_app_dtget(), disa_exec(), dp_lookup(), and dundi_lookup_local().

◆ ast_matchmore_extension()

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)

Parameters
cnot really important XXX
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 match a valid extension in this context with some more digits, return non-zero. Does NOT return non-zero if this is an exact-match only. 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 4216 of file pbx.c.

4217{
4218 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE, 0, 0);
4219}

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

Referenced by __analog_ss_thread(), __ast_pbx_run(), analog_ss_thread(), ast_app_dtget(), collect_digits(), disa_exec(), dp_lookup(), dundi_lookup_local(), key_dial_page(), loopback_matchmore(), pbx_builtin_background(), and readexten_exec().

◆ ast_merge_contexts_and_delete()

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.

Parameters
extcontextspointer to the ast_context structure
exttablepointer to the ast_hashtab structure that contains all the elements in extcontexts
registrarof the context; if it's set the routine will delete all contexts that belong to that registrar; if NULL only the contexts that are specified in extcontexts

Definition at line 6447 of file pbx.c.

6448{
6449 double ft;
6450 struct ast_context *tmp;
6451 struct ast_context *oldcontextslist;
6452 struct ast_hashtab *oldtable;
6453 struct store_hints hints_stored = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
6454 struct store_hints hints_removed = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
6455 struct store_hint *saved_hint;
6456 struct ast_hint *hint;
6457 struct ast_exten *exten;
6458 int length;
6459 struct ast_state_cb *thiscb;
6460 struct ast_hashtab_iter *iter;
6461 struct ao2_iterator i;
6462 int ctx_count = 0;
6463 struct timeval begintime;
6464 struct timeval writelocktime;
6465 struct timeval endlocktime;
6466 struct timeval enddeltime;
6467
6468 /*
6469 * It is very important that this function hold the hints
6470 * container lock _and_ the conlock during its operation; not
6471 * only do we need to ensure that the list of contexts and
6472 * extensions does not change, but also that no hint callbacks
6473 * (watchers) are added or removed during the merge/delete
6474 * process
6475 *
6476 * In addition, the locks _must_ be taken in this order, because
6477 * there are already other code paths that use this order
6478 */
6479
6480 begintime = ast_tvnow();
6481 ast_mutex_lock(&context_merge_lock);/* Serialize ast_merge_contexts_and_delete */
6483
6484 if (!contexts_table) {
6485 /* Create any autohint contexts */
6487
6488 /* Well, that's odd. There are no contexts. */
6489 contexts_table = exttable;
6490 contexts = *extcontexts;
6493 return;
6494 }
6495
6497 while ((tmp = ast_hashtab_next(iter))) {
6498 ++ctx_count;
6499 context_merge(extcontexts, exttable, tmp, registrar);
6500 }
6502
6503 ao2_lock(hints);
6504 writelocktime = ast_tvnow();
6505
6506 /* preserve all watchers for hints */
6508 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
6509 if (ao2_container_count(hint->callbacks)) {
6510 size_t exten_len;
6511
6512 ao2_lock(hint);
6513 if (!hint->exten) {
6514 /* The extension has already been destroyed. (Should never happen here) */
6515 ao2_unlock(hint);
6516 continue;
6517 }
6518
6519 exten_len = strlen(hint->exten->exten) + 1;
6520 length = exten_len + strlen(hint->exten->parent->name) + 1
6521 + sizeof(*saved_hint);
6522 if (!(saved_hint = ast_calloc(1, length))) {
6523 ao2_unlock(hint);
6524 continue;
6525 }
6526
6527 /* This removes all the callbacks from the hint into saved_hint. */
6528 while ((thiscb = ao2_callback(hint->callbacks, OBJ_UNLINK, NULL, NULL))) {
6529 AST_LIST_INSERT_TAIL(&saved_hint->callbacks, thiscb, entry);
6530 /*
6531 * We intentionally do not unref thiscb to account for the
6532 * non-ao2 reference in saved_hint->callbacks
6533 */
6534 }
6535
6536 saved_hint->laststate = hint->laststate;
6537 saved_hint->context = saved_hint->data;
6538 strcpy(saved_hint->data, hint->exten->parent->name);
6539 saved_hint->exten = saved_hint->data + strlen(saved_hint->context) + 1;
6540 ast_copy_string(saved_hint->exten, hint->exten->exten, exten_len);
6541 if (hint->last_presence_subtype) {
6542 saved_hint->last_presence_subtype = ast_strdup(hint->last_presence_subtype);
6543 }
6544 if (hint->last_presence_message) {
6545 saved_hint->last_presence_message = ast_strdup(hint->last_presence_message);
6546 }
6547 saved_hint->last_presence_state = hint->last_presence_state;
6548 ao2_unlock(hint);
6549 AST_LIST_INSERT_HEAD(&hints_stored, saved_hint, list);
6550 }
6551 }
6553
6554 /* save the old table and list */
6555 oldtable = contexts_table;
6556 oldcontextslist = contexts;
6557
6558 /* move in the new table and list */
6559 contexts_table = exttable;
6560 contexts = *extcontexts;
6561
6562 /*
6563 * Restore the watchers for hints that can be found; notify
6564 * those that cannot be restored.
6565 */
6566 while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_stored, list))) {
6567 struct pbx_find_info q = { .stacklen = 0 };
6568
6569 exten = pbx_find_extension(NULL, NULL, &q, saved_hint->context, saved_hint->exten,
6570 PRIORITY_HINT, NULL, "", E_MATCH);
6571 /*
6572 * If this is a pattern, dynamically create a new extension for this
6573 * particular match. Note that this will only happen once for each
6574 * individual extension, because the pattern will no longer match first.
6575 */
6576 if (exten && exten->exten[0] == '_') {
6577 ast_add_extension_nolock(exten->parent->name, 0, saved_hint->exten,
6578 PRIORITY_HINT, NULL, 0, exten->app, ast_strdup(exten->data), ast_free_ptr,
6579 exten->registrar);
6580 /* rwlocks are not recursive locks */
6581 exten = ast_hint_extension_nolock(NULL, saved_hint->context,
6582 saved_hint->exten);
6583 }
6584
6585 /* Find the hint in the hints container */
6586 hint = exten ? ao2_find(hints, exten, 0) : NULL;
6587 if (!hint) {
6588 /*
6589 * Notify watchers of this removed hint later when we aren't
6590 * encumbered by so many locks.
6591 */
6592 AST_LIST_INSERT_HEAD(&hints_removed, saved_hint, list);
6593 } else {
6594 ao2_lock(hint);
6595 while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) {
6596 ao2_link(hint->callbacks, thiscb);
6597 /* Ref that we added when putting into saved_hint->callbacks */
6598 ao2_ref(thiscb, -1);
6599 }
6600 hint->laststate = saved_hint->laststate;
6601 hint->last_presence_state = saved_hint->last_presence_state;
6602 hint->last_presence_subtype = saved_hint->last_presence_subtype;
6603 hint->last_presence_message = saved_hint->last_presence_message;
6604 ao2_unlock(hint);
6605 ao2_ref(hint, -1);
6606 /*
6607 * The free of saved_hint->last_presence_subtype and
6608 * saved_hint->last_presence_message is not necessary here.
6609 */
6610 ast_free(saved_hint);
6611 }
6612 }
6613
6614 /* Create all applicable autohint contexts */
6616
6619
6620 /*
6621 * Notify watchers of all removed hints with the same lock
6622 * environment as device_state_cb().
6623 */
6624 while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_removed, list))) {
6625 /* this hint has been removed, notify the watchers */
6626 while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) {
6628 saved_hint->context,
6629 saved_hint->exten,
6630 thiscb->data,
6632 NULL,
6633 NULL);
6634 /* Ref that we added when putting into saved_hint->callbacks */
6635 ao2_ref(thiscb, -1);
6636 }
6637 ast_free(saved_hint->last_presence_subtype);
6638 ast_free(saved_hint->last_presence_message);
6639 ast_free(saved_hint);
6640 }
6641
6643 endlocktime = ast_tvnow();
6644
6645 /*
6646 * The old list and hashtab no longer are relevant, delete them
6647 * while the rest of asterisk is now freely using the new stuff
6648 * instead.
6649 */
6650
6651 ast_hashtab_destroy(oldtable, NULL);
6652
6653 for (tmp = oldcontextslist; tmp; ) {
6654 struct ast_context *next; /* next starting point */
6655
6656 next = tmp->next;
6658 tmp = next;
6659 }
6660 enddeltime = ast_tvnow();
6661
6662 ft = ast_tvdiff_us(writelocktime, begintime);
6663 ft /= 1000000.0;
6664 ast_verb(5,"Time to scan old dialplan and merge leftovers back into the new: %8.6f sec\n", ft);
6665
6666 ft = ast_tvdiff_us(endlocktime, writelocktime);
6667 ft /= 1000000.0;
6668 ast_verb(5,"Time to restore hints and swap in new dialplan: %8.6f sec\n", ft);
6669
6670 ft = ast_tvdiff_us(enddeltime, endlocktime);
6671 ft /= 1000000.0;
6672 ast_verb(5,"Time to delete the old dialplan: %8.6f sec\n", ft);
6673
6674 ft = ast_tvdiff_us(enddeltime, begintime);
6675 ft /= 1000000.0;
6676 ast_verb(5,"Total time merge_contexts_delete: %8.6f sec\n", ft);
6677 ast_verb(5, "%s successfully loaded %d contexts (enable debug for details).\n", registrar, ctx_count);
6678}
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
@ AO2_ITERATOR_DONTLOCK
Assume that the ao2_container is already locked.
Definition: astobj2.h:1852
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:731
#define AST_LIST_HEAD_NOLOCK_INIT_VALUE
Defines initial values for a declaration of AST_LIST_HEAD_NOLOCK.
Definition: linkedlists.h:252
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:711
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:833
#define ast_mutex_lock(a)
Definition: lock.h:196
static void context_table_create_autohints(struct ast_hashtab *table)
Definition: pbx.c:6311
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)
Definition: pbx.c:6929
static void context_merge(struct ast_context **extcontexts, struct ast_hashtab *exttable, struct ast_context *context, const char *registrar)
Definition: pbx.c:6348
int64_t ast_tvdiff_us(struct timeval end, struct timeval start)
Computes the difference (in microseconds) between two struct timeval instances.
Definition: time.h:87
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159

References __ast_internal_context_destroy(), ao2_callback, ao2_container_count(), ao2_find, ao2_iterator_destroy(), AO2_ITERATOR_DONTLOCK, ao2_iterator_init(), ao2_iterator_next, ao2_link, ao2_lock, ao2_ref, ao2_unlock, ast_exten::app, ast_add_extension_nolock(), ast_calloc, ast_copy_string(), ast_free, ast_free_ptr(), ast_hashtab_destroy(), ast_hashtab_end_traversal(), ast_hashtab_next(), ast_hashtab_start_traversal, ast_hint_extension_nolock(), AST_HINT_UPDATE_DEVICE, AST_LIST_HEAD_NOLOCK_INIT_VALUE, AST_LIST_INSERT_HEAD, AST_LIST_INSERT_TAIL, AST_LIST_REMOVE_HEAD, ast_mutex_lock, ast_mutex_unlock, ast_strdup, ast_tvdiff_us(), ast_tvnow(), ast_unlock_contexts(), ast_verb, ast_wrlock_contexts(), ast_hint::callbacks, store_hint::callbacks, ast_state_cb::change_cb, store_hint::context, context_merge(), context_merge_lock, context_table_create_autohints(), contexts, contexts_table, ast_exten::data, ast_state_cb::data, E_MATCH, execute_state_callback(), ast_exten::exten, ast_hint::exten, store_hint::exten, ast_hint::last_presence_message, store_hint::last_presence_message, ast_hint::last_presence_state, store_hint::last_presence_state, ast_hint::last_presence_subtype, store_hint::last_presence_subtype, ast_hint::laststate, store_hint::laststate, ast_context::name, ast_context::next, NULL, OBJ_UNLINK, ast_exten::parent, pbx_find_extension(), PRIORITY_HINT, ast_exten::registrar, registrar, and pbx_find_info::stacklen.

Referenced by lua_reload_extensions(), and pbx_load_module().

◆ ast_parseable_goto()

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

Definition at line 8891 of file pbx.c.

8892{
8893 return pbx_parseable_goto(chan, goto_string, 0);
8894}

References pbx_parseable_goto().

Referenced by _while_exec(), ast_bridge_setup_after_goto(), dial_exec_full(), gosub_exec(), if_helper(), ivr_dispatch(), pbx_builtin_goto(), and while_continue_exec().

◆ ast_pbx_h_exten_run()

void ast_pbx_h_exten_run ( struct ast_channel chan,
const char *  context 
)

Run the h exten from the given context.

Since
11.0
Parameters
chanChannel to run the h exten on.
contextContext the h exten is in.

Definition at line 4226 of file pbx.c.

4227{
4228 int autoloopflag;
4229 int found;
4230 int spawn_error;
4231
4232 ast_channel_lock(chan);
4233
4234 /*
4235 * Make sure that the channel is marked as hungup since we are
4236 * going to run the h exten on it.
4237 */
4239
4240 /* Set h exten location */
4241 if (context != ast_channel_context(chan)) {
4243 }
4244 ast_channel_exten_set(chan, "h");
4245 ast_channel_priority_set(chan, 1);
4246
4247 /* Save autoloop flag */
4250 ast_channel_unlock(chan);
4251
4252 for (;;) {
4253 spawn_error = ast_spawn_extension(chan, ast_channel_context(chan),
4255 S_COR(ast_channel_caller(chan)->id.number.valid,
4256 ast_channel_caller(chan)->id.number.str, NULL), &found, 1);
4257
4258 ast_channel_lock(chan);
4259 if (spawn_error) {
4260 /* The code after the loop needs the channel locked. */
4261 break;
4262 }
4264 ast_channel_unlock(chan);
4265 }
4266 if (found && spawn_error) {
4267 /* Something bad happened, or a hangup has been requested. */
4268 ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n",
4271 ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n",
4274 }
4275
4276 /* An "h" exten has been run, so indicate that one has been run. */
4278
4279 /* Restore autoloop flag */
4281 ast_channel_unlock(chan);
4282}
@ AST_SOFTHANGUP_HANGUP_EXEC
Definition: channel.h:1174

References ast_channel_caller(), ast_channel_context(), ast_channel_context_set(), ast_channel_exten(), ast_channel_exten_set(), ast_channel_flags(), ast_channel_lock, ast_channel_name(), ast_channel_priority(), ast_channel_priority_set(), ast_channel_unlock, ast_debug, AST_FLAG_BRIDGE_HANGUP_RUN, AST_FLAG_IN_AUTOLOOP, ast_set2_flag, ast_set_flag, AST_SOFTHANGUP_HANGUP_EXEC, ast_softhangup_nolock(), ast_spawn_extension(), ast_test_flag, ast_verb, voicemailpwcheck::context, NULL, and S_COR.

Referenced by __ast_pbx_run(), and ast_bridge_setup_after_goto().

◆ ast_pbx_init()

int ast_pbx_init ( void  )

Provided by pbx.c

Definition at line 9014 of file pbx.c.

9015{
9018 if (hints) {
9020 }
9023 if (hintdevices) {
9025 }
9026 /* This is protected by the context_and_merge lock */
9029 if (autohints) {
9031 }
9033 if (statecbs) {
9035 }
9036
9038
9039 if (STASIS_MESSAGE_TYPE_INIT(hint_change_message_type) != 0) {
9040 return -1;
9041 }
9042 if (STASIS_MESSAGE_TYPE_INIT(hint_remove_message_type) != 0) {
9043 return -1;
9044 }
9045
9046 return (hints && hintdevices && autohints && statecbs) ? 0 : -1;
9047}
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
Definition: clicompat.c:19
int ao2_container_register(const char *name, struct ao2_container *self, ao2_prnt_obj_fn *prnt_obj)
Register a container for CLI stats and integrity check.
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Allocate and initialize a hash container with the desired number of buckets.
Definition: astobj2.h:1303
static void print_autohint_key(void *v_obj, void *where, ao2_prnt_fn *prnt)
Definition: pbx.c:8994
static void print_statecbs_key(void *v_obj, void *where, ao2_prnt_fn *prnt)
Definition: pbx.c:9004
static int hint_cmp(void *obj, void *arg, int flags)
Definition: pbx.c:8921
static struct ao2_container * autohints
Container for autohint contexts.
Definition: pbx.c:402
static int hintdevice_hash_cb(const void *obj, const int flags)
Definition: pbx.c:417
static int hint_hash(const void *obj, const int flags)
Definition: pbx.c:8901
static int statecbs_cmp(void *obj, void *arg, int flags)
Definition: pbx.c:8929
static int autohint_hash_cb(const void *obj, const int flags)
Definition: pbx.c:475
static void print_hintdevices_key(void *v_obj, void *where, ao2_prnt_fn *prnt)
Definition: pbx.c:8982
static void print_hints_key(void *v_obj, void *where, ao2_prnt_fn *prnt)
Definition: pbx.c:8971
#define HASH_EXTENHINT_SIZE
Definition: pbx.c:380
static int hintdevice_cmp_multiple(void *obj, void *arg, int flags)
Definition: pbx.c:443
static void pbx_shutdown(void)
Definition: pbx.c:8941
static int autohint_cmp(void *obj, void *arg, int flags)
Definition: pbx.c:496
#define STASIS_MESSAGE_TYPE_INIT(name)
Boiler-plate messaging macro for initializing message types.
Definition: stasis.h:1493

References AO2_ALLOC_OPT_LOCK_MUTEX, AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_container_alloc_hash, ao2_container_alloc_list, ao2_container_register(), ast_register_cleanup(), autohint_cmp(), autohint_hash_cb(), autohints, HASH_EXTENHINT_SIZE, hint_cmp(), hint_hash(), hintdevice_cmp_multiple(), hintdevice_hash_cb(), hintdevices, NULL, pbx_shutdown(), print_autohint_key(), print_hintdevices_key(), print_hints_key(), print_statecbs_key(), STASIS_MESSAGE_TYPE_INIT, statecbs, and statecbs_cmp().

Referenced by asterisk_daemon().

◆ ast_pbx_outgoing_app()

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.

Note that when the application stops executing, the channel is hungup.

Parameters
typeThe channel technology to create
capThe format capabilities for the channel
addrAddress data to pass to the channel technology driver
timeoutHow long we should attempt to dial the outbound channel
appThe name of the application to execute
appdataData to pass to the application
reasonOptional. If provided, the dialed status of the outgoing channel. Codes are AST_CONTROL_xxx values. Valid only if synchronous is non-zero.
synchronousdefined by the ast_pbx_outgoing_sync enum. If AST_OUTGOING_NO_WAIT then don't wait for anything. If AST_OUTGOING_WAIT then block until the outbound channel answers or the call fails. If AST_OUTGOING_WAIT_COMPLETE then wait for the call to complete or fail.
cid_numThe caller ID number to set on the outbound channel
cid_nameThe caller ID name to set on the outbound channel
varsVariables to set on the outbound channel
accountThe accountcode for the outbound channel
locked_channelOptional. The outbound channel that was created if success is returned. Otherwise it is set to NULL. This is returned both locked and reference bumped.
assignedidsOptional. The uniqueid(s) to assign the channel(s) that are created.
Return values
0on success
-1on failure

Definition at line 8005 of file pbx.c.

8010{
8011 return ast_pbx_outgoing_app_predial(type, cap, addr, timeout, app, appdata, reason, synchronous,
8012 cid_num, cid_name, vars, account, locked_channel, assignedids, NULL);
8013}
static const char app[]
Definition: app_adsiprog.c:56
static const char type[]
Definition: chan_ooh323.c:109
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)
Definition: pbx.c:8015

References app, ast_pbx_outgoing_app_predial(), NULL, and type.

Referenced by action_originate(), attempt_thread(), fast_originate(), and orig_app().

◆ ast_pbx_outgoing_app_predial()

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 
)

Definition at line 8015 of file pbx.c.

8020{
8021 if (reason) {
8022 *reason = 0;
8023 }
8024 if (locked_channel) {
8025 *locked_channel = NULL;
8026 }
8027 if (ast_strlen_zero(app)) {
8028 return -1;
8029 }
8030
8031 return pbx_outgoing_attempt(type, cap, addr, timeout, NULL, NULL, 0, app, appdata,
8032 reason, synchronous, cid_num, cid_name, vars, account, locked_channel, 0,
8033 assignedids, predial_callee);
8034}
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)
Definition: pbx.c:7745

References app, ast_strlen_zero(), NULL, pbx_outgoing_attempt(), and type.

Referenced by ast_pbx_outgoing_app(), and originate_exec().

◆ ast_pbx_outgoing_exten()

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.

Parameters
typeThe channel technology to create
capThe format capabilities for the channel
addrAddress data to pass to the channel technology driver
timeoutHow long we should attempt to dial the outbound channel
contextThe destination context for the outbound channel
extenThe destination extension for the outbound channel
priorityThe destination priority for the outbound channel
reasonOptional. If provided, the dialed status of the outgoing channel. Codes are AST_CONTROL_xxx values. Valid only if synchronous is non-zero.
synchronousdefined by the ast_pbx_outgoing_sync enum. If AST_OUTGOING_NO_WAIT then don't wait for anything. If AST_OUTGOING_WAIT then block until the outbound channel answers or the call fails. If AST_OUTGOING_WAIT_COMPLETE then wait for the call to complete or fail. If AST_OUTGOING_WAIT or AST_OUTGOING_WAIT_COMPLETE is specified, the call doesn't answer, and failed@context exists then run a channel named OutgoingSpoolFailed at failed@context.
cid_numThe caller ID number to set on the outbound channel
cid_nameThe caller ID name to set on the outbound channel
varsVariables to set on the outbound channel
accountThe accountcode for the outbound channel
locked_channelOptional. The outbound channel that was created if success is returned. Otherwise it is set to NULL. This is returned both locked and reference bumped.
early_mediaIf non-zero the channel "answers" when progress is indicated.
assignedidsOptional. The uniqueid(s) to assign the channel(s) that are created.
Return values
0on success
-1on failure

Definition at line 7941 of file pbx.c.

7946{
7947 return ast_pbx_outgoing_exten_predial(type, cap, addr, timeout, context, exten, priority, reason,
7948 synchronous, cid_num, cid_name, vars, account, locked_channel, early_media, assignedids, NULL);
7949}
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)
Definition: pbx.c:7951

References ast_pbx_outgoing_exten_predial(), voicemailpwcheck::context, NULL, priority, and type.

Referenced by attempt_thread(), fast_originate(), hook_launch_thread(), and orig_exten().

◆ ast_pbx_outgoing_exten_predial()

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 
)
Todo:
XXX Not good. The channel name is not unique if more than one originate fails at a time.

Definition at line 7951 of file pbx.c.

7956{
7957 int res;
7958 int my_reason;
7959
7960 if (!reason) {
7961 reason = &my_reason;
7962 }
7963 *reason = 0;
7964 if (locked_channel) {
7965 *locked_channel = NULL;
7966 }
7967
7968 res = pbx_outgoing_attempt(type, cap, addr, timeout, context, exten, priority,
7969 NULL, NULL, reason, synchronous, cid_num, cid_name, vars, account, locked_channel,
7970 early_media, assignedids, predial_callee);
7971
7972 if (res < 0 /* Call failed to get connected for some reason. */
7973 && 0 < synchronous
7974 && ast_exists_extension(NULL, context, "failed", 1, NULL)) {
7975 struct ast_channel *failed;
7976
7977 /* We do not have to worry about a locked_channel if dialing failed. */
7978 ast_assert(!locked_channel || !*locked_channel);
7979
7980 /*!
7981 * \todo XXX Not good. The channel name is not unique if more than
7982 * one originate fails at a time.
7983 */
7984 failed = ast_channel_alloc(0, AST_STATE_DOWN, cid_num, cid_name, account,
7985 "failed", context, NULL, NULL, 0, "OutgoingSpoolFailed");
7986 if (failed) {
7987 char failed_reason[12];
7988
7989 ast_set_variables(failed, vars);
7990 snprintf(failed_reason, sizeof(failed_reason), "%d", *reason);
7991 pbx_builtin_setvar_helper(failed, "REASON", failed_reason);
7992 ast_channel_unlock(failed);
7993
7994 if (ast_pbx_run(failed)) {
7995 ast_log(LOG_ERROR, "Unable to run PBX on '%s'\n",
7996 ast_channel_name(failed));
7997 ast_hangup(failed);
7998 }
7999 }
8000 }
8001
8002 return res;
8003}
#define ast_channel_alloc(needqueue, state, cid_num, cid_name, acctcode, exten, context, assignedids, requestor, amaflag,...)
Create a channel structure.
Definition: channel.h:1299
void ast_set_variables(struct ast_channel *chan, struct ast_variable *vars)
adds a list of channel variables to a channel
Definition: channel.c:8129
@ AST_STATE_DOWN
Definition: channelstate.h:36
enum ast_pbx_result ast_pbx_run(struct ast_channel *c)
Execute the PBX in the current thread.
Definition: pbx.c:4776

References ast_assert, ast_channel_alloc, ast_channel_name(), ast_channel_unlock, ast_exists_extension(), ast_hangup(), ast_log, ast_pbx_run(), ast_set_variables(), AST_STATE_DOWN, voicemailpwcheck::context, LOG_ERROR, NULL, pbx_builtin_setvar_helper(), pbx_outgoing_attempt(), priority, and type.

Referenced by action_originate(), ast_pbx_outgoing_exten(), and originate_exec().

◆ ast_pbx_run()

enum ast_pbx_result ast_pbx_run ( struct ast_channel c)

Execute the PBX in the current thread.

Parameters
cchannel to run the pbx on

This executes the PBX on a given channel. It allocates a new PBX structure for the channel, and provides all PBX functionality. See ast_pbx_start for an asynchronous function to run the PBX in a new thread as opposed to the current one.

Return values
Zeroon success
non-zeroon failure

Definition at line 4776 of file pbx.c.

4777{
4778 return ast_pbx_run_args(c, NULL);
4779}
enum ast_pbx_result ast_pbx_run_args(struct ast_channel *c, struct ast_pbx_args *args)
Execute the PBX in the current thread.
Definition: pbx.c:4756

References ast_pbx_run_args(), c, and NULL.

Referenced by __analog_ss_thread(), analog_ss_thread(), ari_originate_dial(), ast_bridge_run_after_goto(), ast_pbx_outgoing_exten_predial(), do_notify(), pbx_outgoing_exec(), and unistim_ss().

◆ ast_pbx_run_args()

enum ast_pbx_result ast_pbx_run_args ( struct ast_channel c,
struct ast_pbx_args args 
)

Execute the PBX in the current thread.

Parameters
cchannel to run the pbx on
argsoptions for the pbx

This executes the PBX on a given channel. It allocates a new PBX structure for the channel, and provides all PBX functionality. See ast_pbx_start for an asynchronous function to run the PBX in a new thread as opposed to the current one.

Return values
Zeroon success
non-zeroon failure

Definition at line 4756 of file pbx.c.

4757{
4759
4760 if (!ast_fully_booted) {
4761 ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n");
4762 return AST_PBX_FAILED;
4763 }
4764
4765 if (increase_call_count(c)) {
4766 return AST_PBX_CALL_LIMIT;
4767 }
4768
4769 res = __ast_pbx_run(c, args);
4770
4772
4773 return res;
4774}
#define ast_fully_booted
Definition: options.h:127
static void decrease_call_count(void)
Definition: pbx.c:4687
static int increase_call_count(const struct ast_channel *c)
Increase call count for channel.
Definition: pbx.c:4638
static enum ast_pbx_result __ast_pbx_run(struct ast_channel *c, struct ast_pbx_args *args)
Definition: pbx.c:4327
ast_pbx_result
The result codes when starting the PBX on a channel with ast_pbx_start.
Definition: pbx.h:371
@ AST_PBX_CALL_LIMIT
Definition: pbx.h:374

References __ast_pbx_run(), args, ast_fully_booted, ast_log, AST_PBX_CALL_LIMIT, AST_PBX_FAILED, AST_PBX_SUCCESS, c, decrease_call_count(), increase_call_count(), and LOG_WARNING.

Referenced by action_dialplan_exec(), ast_pbx_run(), handle_gosub(), msg_route(), and stasis_app_exec().

◆ ast_pbx_start()

enum ast_pbx_result ast_pbx_start ( struct ast_channel c)

Create a new thread and start the PBX.

Parameters
cchannel to start the pbx on
See also
ast_pbx_run for a synchronous function to run the PBX in the current thread, as opposed to starting a new one.
Return values
Zeroon success
non-zeroon failure

Definition at line 4729 of file pbx.c.

4730{
4731 pthread_t t;
4732
4733 if (!c) {
4734 ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
4735 return AST_PBX_FAILED;
4736 }
4737
4738 if (!ast_fully_booted) {
4739 ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n");
4740 return AST_PBX_FAILED;
4741 }
4742
4744 return AST_PBX_CALL_LIMIT;
4745
4746 /* Start a new thread, and get something handling this channel. */
4748 ast_log(LOG_WARNING, "Failed to create new channel thread\n");
4750 return AST_PBX_FAILED;
4751 }
4752
4753 return AST_PBX_SUCCESS;
4754}
static void * pbx_thread(void *data)
Definition: pbx.c:4709
#define ast_pthread_create_detached(a, b, c, d)
Definition: utils.h:625

References ast_fully_booted, ast_log, AST_PBX_CALL_LIMIT, AST_PBX_FAILED, AST_PBX_SUCCESS, ast_pthread_create_detached, c, decrease_call_count(), increase_call_count(), LOG_WARNING, NULL, and pbx_thread().

Referenced by ast_async_goto(), ast_iax2_new(), bridge_failed_peer_goto(), console_new(), dahdi_new(), dial_exec_full(), do_monitor_headset(), generic_recall(), handle_response_clip(), handle_response_cmgr(), jingle_action_session_initiate(), local_call(), ooh323_new(), pbx_start_incoming_request(), and unistim_new().

◆ ast_processed_calls()

int ast_processed_calls ( void  )

Retrieve the total number of calls processed through the PBX since last restart.

Definition at line 4786 of file pbx.c.

4787{
4788 return totalcalls;
4789}
static int totalcalls
Definition: pbx.c:794

References totalcalls.

Referenced by action_corestatus(), ast_var_Config(), get_total_call_count(), handle_chanlist(), and handle_showcalls().

◆ ast_rdlock_context()

int ast_rdlock_context ( struct ast_context con)

Read locks a given context.

Parameters
concontext to lock
Return values
0on success
-1on failure

Definition at line 8511 of file pbx.c.

8512{
8513 return ast_rwlock_rdlock(&con->lock);
8514}
#define ast_rwlock_rdlock(a)
Definition: lock.h:242

References ast_rwlock_rdlock, and ast_context::lock.

Referenced by complete_dialplan_remove_ignorepat(), complete_dialplan_remove_include(), dundi_precache_full(), find_matching_endif(), find_matching_endwhile(), handle_cli_dialplan_save(), lookup_c_ip(), lookup_ci(), manager_show_dialplan_helper(), show_debug_helper(), and show_dialplan_helper().

◆ ast_rdlock_contexts()

int ast_rdlock_contexts ( void  )

◆ ast_remove_hint()

static int ast_remove_hint ( struct ast_exten e)
static

Remove hint from extension.

Definition at line 3962 of file pbx.c.

3963{
3964 /* Cleanup the Notifys if hint is removed */
3965 struct ast_hint *hint;
3966
3967 if (!e) {
3968 return -1;
3969 }
3970
3971 hint = ao2_find(hints, e, OBJ_UNLINK);
3972 if (!hint) {
3973 return -1;
3974 }
3975
3976 remove_hintdevice(hint);
3977
3978 /*
3979 * The extension is being destroyed so we must save some
3980 * information to notify that the extension is deactivated.
3981 */
3982 ao2_lock(hint);
3985 sizeof(hint->context_name));
3987 sizeof(hint->exten_name));
3988 hint->exten = NULL;
3989 ao2_unlock(hint);
3990
3991 publish_hint_remove(hint);
3992
3993 ao2_ref(hint, -1);
3994
3995 return 0;
3996}
static int publish_hint_remove(struct ast_hint *hint)
Publish a hint removed event
Definition: pbx.c:3941
char exten_name[AST_MAX_EXTENSION]
Definition: pbx.c:365
char context_name[AST_MAX_CONTEXT]
Definition: pbx.c:364

References ao2_find, ao2_lock, ao2_ref, ao2_unlock, ast_copy_string(), ast_get_context_name(), ast_get_extension_context(), ast_get_extension_name(), ast_hint::context_name, ast_hint::exten, ast_hint::exten_name, NULL, OBJ_UNLINK, publish_hint_remove(), and remove_hintdevice().

Referenced by destroy_exten().

◆ ast_spawn_extension()

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)

Parameters
cnot important
contextwhich context to generate the extension within
extennew extension to add
prioritypriority of new extension
calleridcallerid of extension
found
combined_find_spawn

This adds a new extension to the asterisk extension list.

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
Return values
0on success
-1on failure.

Definition at line 4221 of file pbx.c.

4222{
4223 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN, found, combined_find_spawn);
4224}
@ E_SPAWN
Definition: extconf.h:219

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

Referenced by __ast_pbx_run(), ast_pbx_h_exten_run(), gosub_run(), and loopback_exec().

◆ ast_str_get_hint()

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.

If an extension hint exists, return non-zero.

Definition at line 4176 of file pbx.c.

4177{
4179
4180 if (!e) {
4181 return 0;
4182 }
4183
4184 if (hint) {
4185 ast_str_set(hint, hintsize, "%s", ast_get_extension_app(e));
4186 }
4187 if (name) {
4188 const char *tmp = ast_get_extension_app_data(e);
4189 if (tmp) {
4190 ast_str_set(name, namesize, "%s", tmp);
4191 }
4192 }
4193 return -1;
4194}

References ast_get_extension_app(), ast_get_extension_app_data(), ast_hint_extension(), ast_str_set(), c, voicemailpwcheck::context, ast_exten::exten, and name.

Referenced by ast_str_retrieve_variable().

◆ ast_unlock_context()

int ast_unlock_context ( struct ast_context con)

◆ ast_unlock_contexts()

int ast_unlock_contexts ( void  )

◆ ast_walk_context_extensions()

struct ast_exten * ast_walk_context_extensions ( struct ast_context con,
struct ast_exten exten 
)

Definition at line 8621 of file pbx.c.

8623{
8624 if (!exten)
8625 return con ? con->root : NULL;
8626 else
8627 return exten->next;
8628}

References ast_exten::exten, NULL, and ast_context::root.

Referenced by manager_show_dialplan_helper(), pbx_find_extension(), show_dialplan_helper(), and unreference_cached_app().

◆ ast_walk_context_ignorepats()

const struct ast_ignorepat * ast_walk_context_ignorepats ( const struct ast_context con,
const struct ast_ignorepat ip 
)

Definition at line 8714 of file pbx.c.

8716{
8717 if (!con) {
8718 return NULL;
8719 }
8720
8721 if (ip) {
8722 int idx;
8723 int next = 0;
8724
8725 for (idx = 0; idx < ast_context_ignorepats_count(con); idx++) {
8726 const struct ast_ignorepat *i = ast_context_ignorepats_get(con, idx);
8727
8728 if (next) {
8729 return i;
8730 }
8731
8732 if (ip == i) {
8733 next = 1;
8734 }
8735 }
8736
8737 return NULL;
8738 }
8739
8740 if (!ast_context_ignorepats_count(con)) {
8741 return NULL;
8742 }
8743
8744 return ast_context_ignorepats_get(con, 0);
8745}
struct ast_ignorepat * next
Definition: extconf.c:2386

References ast_context_ignorepats_count(), ast_context_ignorepats_get(), ast_ignorepat::next, and NULL.

◆ ast_walk_context_includes()

const struct ast_include * ast_walk_context_includes ( const struct ast_context con,
const struct ast_include inc 
)

Definition at line 8675 of file pbx.c.

8677{
8678 if (inc) {
8679 int idx;
8680 int next = 0;
8681
8682 for (idx = 0; idx < ast_context_includes_count(con); idx++) {
8683 const struct ast_include *include = AST_VECTOR_GET(&con->includes, idx);
8684
8685 if (next) {
8686 return include;
8687 }
8688
8689 if (inc == include) {
8690 next = 1;
8691 }
8692 }
8693
8694 return NULL;
8695 }
8696
8697 if (!ast_context_includes_count(con)) {
8698 return NULL;
8699 }
8700
8701 return ast_context_includes_get(con, 0);
8702}
struct ast_include * next
Definition: extconf.c:2368

References ast_context_includes_count(), ast_context_includes_get(), AST_VECTOR_GET, ast_context::includes, ast_include::next, and NULL.

Referenced by context_included().

◆ ast_walk_context_switches()

const struct ast_sw * ast_walk_context_switches ( const struct ast_context con,
const struct ast_sw sw 
)

Definition at line 8630 of file pbx.c.

8632{
8633 if (sw) {
8634 int idx;
8635 int next = 0;
8636
8637 for (idx = 0; idx < ast_context_switches_count(con); idx++) {
8638 const struct ast_sw *s = ast_context_switches_get(con, idx);
8639
8640 if (next) {
8641 return s;
8642 }
8643
8644 if (sw == s) {
8645 next = 1;
8646 }
8647 }
8648
8649 return NULL;
8650 }
8651
8652 if (!ast_context_switches_count(con)) {
8653 return NULL;
8654 }
8655
8656 return ast_context_switches_get(con, 0);
8657}

References ast_context_switches_count(), ast_context_switches_get(), ast_sw::next, and NULL.

◆ ast_walk_contexts()

struct ast_context * ast_walk_contexts ( struct ast_context con)

◆ ast_walk_extension_priorities()

struct ast_exten * ast_walk_extension_priorities ( struct ast_exten exten,
struct ast_exten priority 
)

◆ ast_wrlock_context()

int ast_wrlock_context ( struct ast_context con)

◆ ast_wrlock_contexts()

int ast_wrlock_contexts ( void  )

◆ autohint_cmp()

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

Definition at line 496 of file pbx.c.

497{
498 struct ast_autohint *left = obj;
499 struct ast_autohint *right = arg;
500 const char *right_key = arg;
501 int cmp;
502
503 switch (flags & OBJ_SEARCH_MASK) {
505 right_key = right->context;
506 /* Fall through */
507 case OBJ_SEARCH_KEY:
508 cmp = strcasecmp(left->context, right_key);
509 break;
511 /*
512 * We could also use a partial key struct containing a length
513 * so strlen() does not get called for every comparison instead.
514 */
515 cmp = strncmp(left->context, right_key, strlen(right_key));
516 break;
517 default:
518 ast_assert(0);
519 cmp = 0;
520 break;
521 }
522 return cmp ? 0 : CMP_MATCH | CMP_STOP;
523}
@ CMP_MATCH
Definition: astobj2.h:1027
@ CMP_STOP
Definition: astobj2.h:1028
@ OBJ_SEARCH_PARTIAL_KEY
The arg parameter is a partial search key similar to OBJ_SEARCH_KEY.
Definition: astobj2.h:1116
@ OBJ_SEARCH_OBJECT
The arg parameter is an object of the same type.
Definition: astobj2.h:1087
@ OBJ_SEARCH_MASK
Search option field mask.
Definition: astobj2.h:1072
@ OBJ_SEARCH_KEY
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1101
Structure for dial plan autohints.
Definition: pbx.c:407
char context[1]
Name of the context.
Definition: pbx.c:411

References ast_assert, CMP_MATCH, CMP_STOP, ast_autohint::context, OBJ_SEARCH_KEY, OBJ_SEARCH_MASK, OBJ_SEARCH_OBJECT, and OBJ_SEARCH_PARTIAL_KEY.

Referenced by ast_pbx_init().

◆ autohint_hash_cb()

static int autohint_hash_cb ( const void *  obj,
const int  flags 
)
static
Note
Using the context name for hash

Definition at line 475 of file pbx.c.

476{
477 const struct ast_autohint *autohint;
478 const char *key;
479
480 switch (flags & OBJ_SEARCH_MASK) {
481 case OBJ_SEARCH_KEY:
482 key = obj;
483 break;
485 autohint = obj;
486 key = autohint->context;
487 break;
488 default:
489 ast_assert(0);
490 return 0;
491 }
492
493 return ast_str_case_hash(key);
494}
static force_inline int attribute_pure ast_str_case_hash(const char *str)
Compute a hash value on a case-insensitive string.
Definition: strings.h:1303

References ast_assert, ast_str_case_hash(), ast_autohint::context, OBJ_SEARCH_KEY, OBJ_SEARCH_MASK, and OBJ_SEARCH_OBJECT.

Referenced by ast_pbx_init().

◆ candidate_exten_advance()

static const char * candidate_exten_advance ( const char *  str)
static

Definition at line 1239 of file pbx.c.

1240{
1241 str++;
1242 while (*str == '-') {
1243 str++;
1244 }
1245 return str;
1246}

References str.

◆ cli_match_char_tree()

static void cli_match_char_tree ( struct match_char node,
char *  prefix,
int  fd 
)
static

Definition at line 1131 of file pbx.c.

1132{
1133 char extenstr[40];
1134 struct ast_str *my_prefix = ast_str_alloca(1024);
1135
1136 extenstr[0] = '\0';
1137
1138 if (node->exten) {
1139 snprintf(extenstr, sizeof(extenstr), "(%p)", node->exten);
1140 }
1141
1142 if (strlen(node->x) > 1) {
1143 ast_cli(fd, "%s[%s]:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N',
1144 node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "",
1145 node->exten ? node->exten->name : "", extenstr);
1146 } else {
1147 ast_cli(fd, "%s%s:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N',
1148 node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "",
1149 node->exten ? node->exten->name : "", extenstr);
1150 }
1151
1152 ast_str_set(&my_prefix, 0, "%s+ ", prefix);
1153
1154 if (node->next_char)
1155 cli_match_char_tree(node->next_char, ast_str_buffer(my_prefix), fd);
1156
1157 if (node->alt_char)
1158 cli_match_char_tree(node->alt_char, prefix, fd);
1159}
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
static char prefix[MAX_PREFIX]
Definition: http.c:144
static void cli_match_char_tree(struct match_char *node, char *prefix, int fd)
Definition: pbx.c:1131
#define ast_str_alloca(init_len)
Definition: strings.h:848
Definition: test_heap.c:38

References ast_cli(), ast_str_alloca, ast_str_buffer(), ast_str_set(), cli_match_char_tree(), and prefix.

Referenced by cli_match_char_tree(), and show_debug_helper().

◆ collect_digits()

static int collect_digits ( struct ast_channel c,
int  waittime,
char *  buf,
int  buflen,
int  pos 
)
static

collect digits from the channel into the buffer.

Parameters
c,buf,buflen,pos
waittimeis in milliseconds
Return values
0on timeout or done.
-1on error.

Definition at line 4300 of file pbx.c.

4301{
4302 int digit;
4303
4304 buf[pos] = '\0'; /* make sure it is properly terminated */
4306 S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4307 /* As long as we're willing to wait, and as long as it's not defined,
4308 keep reading digits until we can't possibly get a right answer anymore. */
4309 digit = ast_waitfordigit(c, waittime);
4312 } else {
4313 if (!digit) /* No entry */
4314 break;
4315 if (digit < 0) /* Error, maybe a hangup */
4316 return -1;
4317 if (pos < buflen - 1) { /* XXX maybe error otherwise ? */
4318 buf[pos++] = digit;
4319 buf[pos] = '\0';
4320 }
4321 waittime = ast_channel_pbx(c)->dtimeoutms;
4322 }
4323 }
4324 return 0;
4325}
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
Definition: channel.c:3145

References ast_channel_caller(), ast_channel_clear_softhangup(), ast_channel_context(), ast_channel_pbx(), ast_channel_softhangup_internal_flag(), ast_matchmore_extension(), AST_SOFTHANGUP_ASYNCGOTO, ast_waitfordigit(), buf, c, digit, ast_pbx::dtimeoutms, NULL, and S_COR.

Referenced by __ast_pbx_run().

◆ compare_char()

static int compare_char ( const void *  a,
const void *  b 
)
static

Definition at line 694 of file pbx.c.

695{
696 const unsigned char *ac = a;
697 const unsigned char *bc = b;
698
699 return *ac - *bc;
700}

References a, b, and bc.

Referenced by get_pattern_node().

◆ complete_core_show_hint()

static char * complete_core_show_hint ( const char *  line,
const char *  word,
int  pos,
int  state 
)
static

autocomplete for CLI command 'core show hint'

Definition at line 5240 of file pbx.c.

5241{
5242 struct ast_hint *hint;
5243 char *ret = NULL;
5244 int which = 0;
5245 int wordlen;
5246 struct ao2_iterator i;
5247
5248 if (pos != 3)
5249 return NULL;
5250
5251 wordlen = strlen(word);
5252
5253 /* walk through all hints */
5254 i = ao2_iterator_init(hints, 0);
5255 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
5256 ao2_lock(hint);
5257 if (!hint->exten) {
5258 /* The extension has already been destroyed */
5259 ao2_unlock(hint);
5260 continue;
5261 }
5262 if (!strncasecmp(word, ast_get_extension_name(hint->exten), wordlen) && ++which > state) {
5264 ao2_unlock(hint);
5265 ao2_ref(hint, -1);
5266 break;
5267 }
5268 ao2_unlock(hint);
5269 }
5271
5272 return ret;
5273}
short word

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ast_get_extension_name(), ast_strdup, ast_hint::exten, and NULL.

Referenced by handle_show_hint().

◆ complete_show_dialplan_context()

static char * complete_show_dialplan_context ( const char *  line,
const char *  word,
int  pos,
int  state 
)
static

Definition at line 5419 of file pbx.c.

5421{
5422 struct ast_context *c = NULL;
5423 char *ret = NULL;
5424 int which = 0;
5425 int wordlen;
5426
5427 /* we are do completion of [exten@]context on second position only */
5428 if (pos != 2)
5429 return NULL;
5430
5432
5433 wordlen = strlen(word);
5434
5435 /* walk through all contexts and return the n-th match */
5436 while ( (c = ast_walk_contexts(c)) ) {
5437 if (!strncasecmp(word, ast_get_context_name(c), wordlen) && ++which > state) {
5439 break;
5440 }
5441 }
5442
5444
5445 return ret;
5446}

References ast_get_context_name(), ast_rdlock_contexts(), ast_strdup, ast_unlock_contexts(), ast_walk_contexts(), c, and NULL.

Referenced by handle_debug_dialplan(), and handle_show_dialplan().

◆ context_merge()

static void context_merge ( struct ast_context **  extcontexts,
struct ast_hashtab exttable,
struct ast_context context,
const char *  registrar 
)
static

Definition at line 6348 of file pbx.c.

6349{
6350 struct ast_context *new = ast_hashtab_lookup(exttable, context); /* is there a match in the new set? */
6351 struct ast_exten *exten_item, *prio_item, *new_exten_item, *new_prio_item;
6352 struct ast_hashtab_iter *exten_iter;
6353 struct ast_hashtab_iter *prio_iter;
6354 int insert_count = 0;
6355 int first = 1;
6356
6357 /* We'll traverse all the extensions/prios, and see which are not registrar'd with
6358 the current registrar, and copy them to the new context. If the new context does not
6359 exist, we'll create it "on demand". If no items are in this context to copy, then we'll
6360 only create the empty matching context if the old one meets the criteria */
6361
6362 if (context->root_table) {
6363 exten_iter = ast_hashtab_start_traversal(context->root_table);
6364 while ((exten_item=ast_hashtab_next(exten_iter))) {
6365 if (new) {
6366 new_exten_item = ast_hashtab_lookup(new->root_table, exten_item);
6367 } else {
6368 new_exten_item = NULL;
6369 }
6370 prio_iter = ast_hashtab_start_traversal(exten_item->peer_table);
6371 while ((prio_item=ast_hashtab_next(prio_iter))) {
6372 int res1;
6373 char *dupdstr;
6374
6375 if (new_exten_item) {
6376 new_prio_item = ast_hashtab_lookup(new_exten_item->peer_table, prio_item);
6377 } else {
6378 new_prio_item = NULL;
6379 }
6380 if (strcmp(prio_item->registrar,registrar) == 0) {
6381 continue;
6382 }
6383 /* make sure the new context exists, so we have somewhere to stick this exten/prio */
6384 if (!new) {
6385 new = ast_context_find_or_create(extcontexts, exttable, context->name, prio_item->registrar); /* a new context created via priority from a different context in the old dialplan, gets its registrar from the prio's registrar */
6386 if (new) {
6387 new->autohints = context->autohints;
6388 }
6389 }
6390
6391 /* copy in the includes, switches, and ignorepats */
6392 if (first) { /* but, only need to do this once */
6394 first = 0;
6395 }
6396
6397 if (!new) {
6398 ast_log(LOG_ERROR,"Could not allocate a new context for %s in merge_and_delete! Danger!\n", context->name);
6399 ast_hashtab_end_traversal(prio_iter);
6400 ast_hashtab_end_traversal(exten_iter);
6401 return; /* no sense continuing. */
6402 }
6403 /* we will not replace existing entries in the new context with stuff from the old context.
6404 but, if this is because of some sort of registrar conflict, we ought to say something... */
6405
6406 dupdstr = ast_strdup(prio_item->data);
6407
6408 res1 = ast_add_extension2(new, 0, prio_item->name, prio_item->priority, prio_item->label,
6409 prio_item->matchcid ? prio_item->cidmatch : NULL, prio_item->app, dupdstr, ast_free_ptr, prio_item->registrar,
6410 prio_item->registrar_file, prio_item->registrar_line);
6411 if (!res1 && new_exten_item && new_prio_item){
6412 ast_verb(3,"Dropping old dialplan item %s/%s/%d [%s(%s)] (registrar=%s) due to conflict with new dialplan\n",
6413 context->name, prio_item->name, prio_item->priority, prio_item->app, (char*)prio_item->data, prio_item->registrar);
6414 } else {
6415 /* we do NOT pass the priority data from the old to the new -- we pass a copy of it, so no changes to the current dialplan take place,
6416 and no double frees take place, either! */
6417 insert_count++;
6418 }
6419 }
6420 ast_hashtab_end_traversal(prio_iter);
6421 }
6422 ast_hashtab_end_traversal(exten_iter);
6423 } else if (new) {
6424 /* If the context existed but had no extensions, we still want to merge
6425 * the includes, switches and ignore patterns.
6426 */
6428 }
6429
6430 if (!insert_count && !new && (strcmp(context->registrar, registrar) != 0 ||
6431 (strcmp(context->registrar, registrar) == 0 && context->refcount > 1))) {
6432 /* we could have given it the registrar of the other module who incremented the refcount,
6433 but that's not available, so we give it the registrar we know about */
6434 new = ast_context_find_or_create(extcontexts, exttable, context->name, context->registrar);
6435
6436 if (new) {
6437 new->autohints = context->autohints;
6438 }
6439
6440 /* copy in the includes, switches, and ignorepats */
6442 }
6443}
struct sla_ringing_trunk * first
Definition: app_sla.c:338
static void context_merge_incls_swits_igps_other_registrars(struct ast_context *new, struct ast_context *old, const char *registrar)
Definition: pbx.c:6273
struct ast_context * ast_context_find_or_create(struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *name, const char *registrar)
Register a new context or find an existing one.
Definition: pbx.c:6170

References ast_exten::app, ast_add_extension2(), ast_context_find_or_create(), ast_free_ptr(), ast_hashtab_end_traversal(), ast_hashtab_lookup(), ast_hashtab_next(), ast_hashtab_start_traversal, ast_log, ast_strdup, ast_verb, ast_exten::cidmatch, voicemailpwcheck::context, context_merge_incls_swits_igps_other_registrars(), ast_exten::data, first, ast_exten::label, LOG_ERROR, ast_exten::matchcid, ast_exten::name, NULL, ast_exten::peer_table, ast_exten::priority, ast_exten::registrar, registrar, ast_exten::registrar_file, and ast_exten::registrar_line.

Referenced by ast_merge_contexts_and_delete().

◆ context_merge_incls_swits_igps_other_registrars()

static void context_merge_incls_swits_igps_other_registrars ( struct ast_context new,
struct ast_context old,
const char *  registrar 
)
static

Definition at line 6273 of file pbx.c.

6274{
6275 int idx;
6276
6277 ast_debug(1, "merging incls/swits/igpats from old(%s) to new(%s) context, registrar = %s\n", ast_get_context_name(old), ast_get_context_name(new), registrar);
6278 /* copy in the includes, switches, and ignorepats */
6279 /* walk through includes */
6280 for (idx = 0; idx < ast_context_includes_count(old); idx++) {
6281 const struct ast_include *i = ast_context_includes_get(old, idx);
6282
6283 if (!strcmp(ast_get_include_registrar(i), registrar)) {
6284 continue; /* not mine */
6285 }
6287 }
6288
6289 /* walk through switches */
6290 for (idx = 0; idx < ast_context_switches_count(old); idx++) {
6291 const struct ast_sw *sw = ast_context_switches_get(old, idx);
6292
6293 if (!strcmp(ast_get_switch_registrar(sw), registrar)) {
6294 continue; /* not mine */
6295 }
6297 }
6298
6299 /* walk thru ignorepats ... */
6300 for (idx = 0; idx < ast_context_ignorepats_count(old); idx++) {
6301 const struct ast_ignorepat *ip = ast_context_ignorepats_get(old, idx);
6302
6303 if (strcmp(ast_get_ignorepat_registrar(ip), registrar) == 0) {
6304 continue; /* not mine */
6305 }
6307 }
6308}
int ast_get_switch_eval(const struct ast_sw *sw)
Definition: pbx_sw.c:58

References ast_context_add_ignorepat2(), ast_context_add_include2(), ast_context_add_switch2(), ast_context_ignorepats_count(), ast_context_ignorepats_get(), ast_context_includes_count(), ast_context_includes_get(), ast_context_switches_count(), ast_context_switches_get(), ast_debug, ast_get_context_name(), ast_get_ignorepat_name(), ast_get_ignorepat_registrar(), ast_get_include_name(), ast_get_include_registrar(), ast_get_switch_data(), ast_get_switch_eval(), ast_get_switch_name(), ast_get_switch_registrar(), and registrar.

Referenced by context_merge().

◆ context_table_create_autohints()

static void context_table_create_autohints ( struct ast_hashtab table)
static

Set up an autohint placeholder in the hints container

Definition at line 6311 of file pbx.c.

6312{
6313 struct ast_context *con;
6314 struct ast_hashtab_iter *iter;
6315
6316 /* Remove all autohints as the below iteration will recreate them */
6318
6320 while ((con = ast_hashtab_next(iter))) {
6321 size_t name_len = strlen(con->name) + 1;
6322 size_t registrar_len = strlen(con->registrar) + 1;
6323 struct ast_autohint *autohint;
6324
6325 if (!con->autohints) {
6326 continue;
6327 }
6328
6329 autohint = ao2_alloc_options(sizeof(*autohint) + name_len + registrar_len, NULL, AO2_ALLOC_OPT_LOCK_NOLOCK);
6330 if (!autohint) {
6331 continue;
6332 }
6333
6334 ast_copy_string(autohint->context, con->name, name_len);
6335 autohint->registrar = autohint->context + name_len;
6336 ast_copy_string(autohint->registrar, con->registrar, registrar_len);
6337
6338 ao2_link(autohints, autohint);
6339 ao2_ref(autohint, -1);
6340
6341 ast_verb(3, "Enabled autohints support on context '%s'\n", con->name);
6342 }
6344}
@ OBJ_NODATA
Definition: astobj2.h:1044
@ OBJ_MULTIPLE
Definition: astobj2.h:1049
static char * table
Definition: cdr_odbc.c:55
char * registrar
Name of the registrar.
Definition: pbx.c:409

References AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_alloc_options, ao2_callback, ao2_link, ao2_ref, ast_copy_string(), ast_hashtab_end_traversal(), ast_hashtab_next(), ast_hashtab_start_traversal, ast_verb, ast_context::autohints, autohints, ast_autohint::context, ast_context::name, NULL, OBJ_MULTIPLE, OBJ_NODATA, OBJ_UNLINK, ast_context::registrar, ast_autohint::registrar, and table.

Referenced by ast_merge_contexts_and_delete().

◆ create_match_char_tree()

static void create_match_char_tree ( struct ast_context con)
static

Definition at line 1785 of file pbx.c.

1786{
1787 struct ast_hashtab_iter *t1;
1788 struct ast_exten *e1;
1789#ifdef NEED_DEBUG
1790 int biggest_bucket, resizes, numobjs, numbucks;
1791
1792 ast_debug(1, "Creating Extension Trie for context %s(%p)\n", con->name, con);
1793 ast_hashtab_get_stats(con->root_table, &biggest_bucket, &resizes, &numobjs, &numbucks);
1794 ast_debug(1, "This tree has %d objects in %d bucket lists, longest list=%d objects, and has resized %d times\n",
1795 numobjs, numbucks, biggest_bucket, resizes);
1796#endif
1798 while ((e1 = ast_hashtab_next(t1))) {
1799 if (e1->exten) {
1800 add_exten_to_pattern_tree(con, e1, 0);
1801 } else {
1802 ast_log(LOG_ERROR, "Attempt to create extension with no extension name.\n");
1803 }
1804 }
1806}
void ast_hashtab_get_stats(struct ast_hashtab *tab, int *biggest_bucket_size, int *resize_count, int *num_objects, int *num_buckets)
Returns key stats for the table.
Definition: hashtab.c:563

References add_exten_to_pattern_tree(), ast_debug, ast_hashtab_end_traversal(), ast_hashtab_get_stats(), ast_hashtab_next(), ast_hashtab_start_traversal, ast_log, ast_exten::exten, LOG_ERROR, ast_context::name, and ast_context::root_table.

Referenced by pbx_find_extension().

◆ decrease_call_count()

static void decrease_call_count ( void  )
static

Definition at line 4687 of file pbx.c.

4688{
4690 if (countcalls > 0)
4691 countcalls--;
4693}
static ast_mutex_t maxcalllock
Definition: pbx.c:792

References ast_mutex_lock, ast_mutex_unlock, countcalls, and maxcalllock.

Referenced by ast_pbx_run_args(), ast_pbx_start(), and pbx_thread().

◆ destroy_exten()

static void destroy_exten ( struct ast_exten e)
static

Definition at line 4695 of file pbx.c.

4696{
4697 if (e->priority == PRIORITY_HINT)
4698 ast_remove_hint(e);
4699
4700 if (e->peer_table)
4702 if (e->peer_label_table)
4704 if (e->datad)
4705 e->datad(e->data);
4706 ast_free(e);
4707}
static int ast_remove_hint(struct ast_exten *e)
Remove hint from extension.
Definition: pbx.c:3962

References ast_free, ast_hashtab_destroy(), ast_remove_hint(), ast_exten::data, ast_exten::datad, ast_exten::peer_label_table, ast_exten::peer_table, ast_exten::priority, and PRIORITY_HINT.

Referenced by __ast_internal_context_destroy(), and ast_context_remove_extension_callerid2().

◆ destroy_hint()

static void destroy_hint ( void *  obj)
static

Definition at line 3924 of file pbx.c.

3925{
3926 struct ast_hint *hint = obj;
3927 int i;
3928
3929 ao2_cleanup(hint->callbacks);
3930
3931 for (i = 0; i < AST_VECTOR_SIZE(&hint->devices); i++) {
3932 char *device = AST_VECTOR_GET(&hint->devices, i);
3933 ast_free(device);
3934 }
3935 AST_VECTOR_FREE(&hint->devices);
3938}
#define ao2_cleanup(obj)
Definition: astobj2.h:1934

References ao2_cleanup, ast_free, AST_VECTOR_FREE, AST_VECTOR_GET, AST_VECTOR_SIZE, ast_hint::callbacks, ast_hint::devices, ast_hint::last_presence_message, and ast_hint::last_presence_subtype.

Referenced by ast_add_hint().

◆ destroy_pattern_tree()

static void destroy_pattern_tree ( struct match_char pattern_tree)
static

Definition at line 1808 of file pbx.c.

1809{
1810 /* destroy all the alternates */
1811 if (pattern_tree->alt_char) {
1812 destroy_pattern_tree(pattern_tree->alt_char);
1813 pattern_tree->alt_char = 0;
1814 }
1815 /* destroy all the nexts */
1816 if (pattern_tree->next_char) {
1817 destroy_pattern_tree(pattern_tree->next_char);
1818 pattern_tree->next_char = 0;
1819 }
1820 pattern_tree->exten = 0; /* never hurts to make sure there's no pointers laying around */
1821 ast_free(pattern_tree);
1822}

References match_char::alt_char, ast_free, destroy_pattern_tree(), match_char::exten, and match_char::next_char.

Referenced by __ast_internal_context_destroy(), and destroy_pattern_tree().

◆ destroy_state_cb()

static void destroy_state_cb ( void *  doomed)
static

Definition at line 3735 of file pbx.c.

3736{
3737 struct ast_state_cb *state_cb = doomed;
3738
3739 if (state_cb->destroy_cb) {
3740 state_cb->destroy_cb(state_cb->id, state_cb->data);
3741 }
3742}
int id
Definition: pbx.c:325
ast_state_cb_destroy_type destroy_cb
Definition: pbx.c:333

References ast_state_cb::data, ast_state_cb::destroy_cb, and ast_state_cb::id.

Referenced by extension_state_add_destroy().

◆ device_state_cb()

static void device_state_cb ( void *  unused,
struct stasis_subscription sub,
struct stasis_message msg 
)
static

Definition at line 3605 of file pbx.c.

3606{
3607 struct ast_device_state_message *dev_state;
3608 struct ast_str *hint_app;
3609 struct ast_hintdevice *device;
3610 struct ast_hintdevice *cmpdevice;
3611 struct ao2_iterator *dev_iter;
3612 struct ao2_iterator auto_iter;
3613 struct ast_autohint *autohint;
3614 char *virtual_device;
3615 char *type;
3616 char *device_name;
3617
3619 return;
3620 }
3621
3622 if (hint_remove_message_type() == stasis_message_type(msg)) {
3623 /* The extension has already been destroyed */
3624 struct ast_state_cb *state_cb;
3625 struct ao2_iterator cb_iter;
3626 struct ast_hint *hint = stasis_message_data(msg);
3627
3628 ao2_lock(hint);
3630 ao2_unlock(hint);
3631
3632 cb_iter = ao2_iterator_init(hint->callbacks, 0);
3633 for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_ref(state_cb, -1)) {
3635 hint->context_name,
3636 hint->exten_name,
3637 state_cb->data,
3639 hint,
3640 NULL);
3641 }
3642 ao2_iterator_destroy(&cb_iter);
3643 return;
3644 }
3645
3647 return;
3648 }
3649
3650 dev_state = stasis_message_data(msg);
3651 if (dev_state->eid) {
3652 /* ignore non-aggregate states */
3653 return;
3654 }
3655
3657 /* There are no hints monitoring devices. */
3658 return;
3659 }
3660
3661 hint_app = ast_str_create(1024);
3662 if (!hint_app) {
3663 return;
3664 }
3665
3666 cmpdevice = ast_alloca(sizeof(*cmpdevice) + strlen(dev_state->device));
3667 strcpy(cmpdevice->hintdevice, dev_state->device);
3668
3669 ast_mutex_lock(&context_merge_lock);/* Hold off ast_merge_contexts_and_delete */
3670
3671 /* Initially we find all hints for the device and notify them */
3672 dev_iter = ao2_t_callback(hintdevices,
3675 cmpdevice,
3676 "find devices in container");
3677 if (dev_iter) {
3678 for (; (device = ao2_iterator_next(dev_iter)); ao2_t_ref(device, -1, "Next device")) {
3679 if (device->hint) {
3680 device_state_notify_callbacks(device->hint, &hint_app);
3681 }
3682 }
3683 ao2_iterator_destroy(dev_iter);
3684 }
3685
3686 /* Second stage we look for any autohint contexts and if the device is not already in the hints
3687 * we create it.
3688 */
3689 type = ast_strdupa(dev_state->device);
3690 if (ast_strlen_zero(type)) {
3691 goto end;
3692 }
3693
3694 /* Determine if this is a virtual/custom device or a real device */
3695 virtual_device = strchr(type, ':');
3696 device_name = strchr(type, '/');
3697 if (virtual_device && (!device_name || (virtual_device < device_name))) {
3698 device_name = virtual_device;
3699 }
3700
3701 /* Invalid device state name - not a virtual/custom device and not a real device */
3702 if (ast_strlen_zero(device_name)) {
3703 goto end;
3704 }
3705
3706 *device_name++ = '\0';
3707
3708 auto_iter = ao2_iterator_init(autohints, 0);
3709 for (; (autohint = ao2_iterator_next(&auto_iter)); ao2_t_ref(autohint, -1, "Next autohint")) {
3710 if (ast_get_hint(NULL, 0, NULL, 0, NULL, autohint->context, device_name)) {
3711 continue;
3712 }
3713
3714 /* The device has no hint in the context referenced by this autohint so create one */
3715 ast_add_extension(autohint->context, 0, device_name,
3716 PRIORITY_HINT, NULL, NULL, dev_state->device,
3717 ast_strdup(dev_state->device), ast_free_ptr, autohint->registrar);
3718
3719 /* Since this hint was just created there are no watchers, so we don't need to notify anyone */
3720 }
3721 ao2_iterator_destroy(&auto_iter);
3722
3723end:
3725 ast_free(hint_app);
3726 return;
3727}
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:288
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#define ao2_t_callback(c, flags, cb_fn, arg, tag)
Definition: astobj2.h:1696
struct stasis_message_type * ast_device_state_message_type(void)
Get the Stasis message type for device state messages.
static int handle_hint_change_message_type(struct stasis_message *msg, enum ast_state_cb_update_reason reason)
Definition: pbx.c:3558
static void device_state_notify_callbacks(struct ast_hint *hint, struct ast_str **hint_app)
Definition: pbx.c:3391
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.
Definition: pbx.c:4158
@ AST_EXTENSION_DEACTIVATED
Definition: pbx.h:63
struct stasis_message_type * stasis_message_type(const struct stasis_message *msg)
Get the message type for a stasis_message.
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659
The structure that contains device state.
Definition: devicestate.h:238
const struct ast_eid * eid
The EID of the server where this message originated.
Definition: devicestate.h:246

References ao2_container_count(), ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_t_callback, ao2_t_ref, ao2_unlock, ast_add_extension(), ast_alloca, ast_device_state_message_type(), AST_EXTENSION_DEACTIVATED, ast_free, ast_free_ptr(), ast_get_hint(), AST_HINT_UPDATE_DEVICE, ast_mutex_lock, ast_mutex_unlock, ast_str_create, ast_strdup, ast_strdupa, ast_strlen_zero(), autohints, ast_hint::callbacks, ast_state_cb::change_cb, ast_autohint::context, context_merge_lock, ast_hint::context_name, ast_state_cb::data, ast_device_state_message::device, device_state_notify_callbacks(), ast_device_state_message::eid, end, execute_state_callback(), ast_hint::exten_name, handle_hint_change_message_type(), ast_hintdevice::hint, ast_hintdevice::hintdevice, hintdevice_cmp_multiple(), hintdevices, ast_hint::laststate, NULL, OBJ_MULTIPLE, OBJ_SEARCH_OBJECT, PRIORITY_HINT, ast_autohint::registrar, stasis_message_data(), stasis_message_type(), and type.

Referenced by load_pbx().

◆ device_state_info_dt()

static void device_state_info_dt ( void *  obj)
static

Definition at line 3090 of file pbx.c.

3091{
3092 struct ast_device_state_info *info = obj;
3093
3094 ao2_cleanup(info->causing_channel);
3095}
def info(msg)

References ao2_cleanup, and sip_to_pjsip::info().

Referenced by ast_extension_state3().

◆ device_state_notify_callbacks()

static void device_state_notify_callbacks ( struct ast_hint hint,
struct ast_str **  hint_app 
)
static

Definition at line 3391 of file pbx.c.

3392{
3393 struct ao2_iterator cb_iter;
3394 struct ast_state_cb *state_cb;
3395 int state;
3396 int same_state;
3397 struct ao2_container *device_state_info;
3398 int first_extended_cb_call = 1;
3401
3402 ao2_lock(hint);
3403 if (!hint->exten) {
3404 /* The extension has already been destroyed */
3405 ao2_unlock(hint);
3406 return;
3407 }
3408
3409 /*
3410 * Save off strings in case the hint extension gets destroyed
3411 * while we are notifying the watchers.
3412 */
3415 sizeof(context_name));
3417 sizeof(exten_name));
3418 ast_str_set(hint_app, 0, "%s", ast_get_extension_app(hint->exten));
3419 ao2_unlock(hint);
3420
3421 /*
3422 * Get device state for this hint.
3423 *
3424 * NOTE: We cannot hold any locks while determining the hint
3425 * device state or notifying the watchers without causing a
3426 * deadlock. (conlock, hints, and hint)
3427 */
3428
3429 /* Make a container so state3 can fill it if we wish.
3430 * If that failed we simply do not provide the extended state info.
3431 */
3432 device_state_info = alloc_device_state_info();
3433
3434 state = ast_extension_state3(*hint_app, device_state_info);
3435 same_state = state == hint->laststate;
3436 if (same_state && (~state & AST_EXTENSION_RINGING)) {
3437 ao2_cleanup(device_state_info);
3438 return;
3439 }
3440
3441 /* Device state changed since last check - notify the watchers. */
3442 hint->laststate = state; /* record we saw the change */
3443
3444 /* For general callbacks */
3445 if (!same_state) {
3446 cb_iter = ao2_iterator_init(statecbs, 0);
3447 for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_ref(state_cb, -1)) {
3450 exten_name,
3451 state_cb->data,
3453 hint,
3454 NULL);
3455 }
3456 ao2_iterator_destroy(&cb_iter);
3457 }
3458
3459 /* For extension callbacks */
3460 /* extended callbacks are called when the state changed or when AST_STATE_RINGING is
3461 * included. Normal callbacks are only called when the state changed.
3462 */
3463 cb_iter = ao2_iterator_init(hint->callbacks, 0);
3464 for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_ref(state_cb, -1)) {
3465 if (state_cb->extended && first_extended_cb_call) {
3466 /* Fill detailed device_state_info now that we know it is used by extd. callback */
3467 first_extended_cb_call = 0;
3468 get_device_state_causing_channels(device_state_info);
3469 }
3470 if (state_cb->extended || !same_state) {
3473 exten_name,
3474 state_cb->data,
3476 hint,
3477 state_cb->extended ? device_state_info : NULL);
3478 }
3479 }
3480 ao2_iterator_destroy(&cb_iter);
3481
3482 ao2_cleanup(device_state_info);
3483}
#define AST_MAX_CONTEXT
Definition: channel.h:135
static const char exten_name[]
static const char context_name[]
int extended
Definition: pbx.c:329

References alloc_device_state_info(), ao2_cleanup, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ast_copy_string(), AST_EXTENSION_RINGING, ast_extension_state3(), ast_get_context_name(), ast_get_extension_app(), ast_get_extension_context(), ast_get_extension_name(), AST_HINT_UPDATE_DEVICE, AST_MAX_CONTEXT, AST_MAX_EXTENSION, ast_str_set(), ast_hint::callbacks, ast_state_cb::change_cb, context_name, ast_state_cb::data, execute_state_callback(), ast_hint::exten, exten_name, ast_state_cb::extended, get_device_state_causing_channels(), ast_hint::laststate, NULL, state, and statecbs.

Referenced by device_state_cb(), and handle_hint_change_message_type().

◆ exception_store_free()

static void exception_store_free ( void *  data)
static

Definition at line 2798 of file pbx.c.

2799{
2800 struct pbx_exception *exception = data;
2802 ast_free(exception);
2803}
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:374

References ast_free, and ast_string_field_free_memory.

◆ execute_state_callback()

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

Definition at line 3271 of file pbx.c.

3278{
3279 int res = 0;
3280 struct ast_state_cb_info info = { 0, };
3281
3282 info.reason = reason;
3283
3284 /* Copy over current hint data */
3285 if (hint) {
3286 ao2_lock(hint);
3287 info.exten_state = hint->laststate;
3288 info.device_state_info = device_state_info;
3289 info.presence_state = hint->last_presence_state;
3290 if (!(ast_strlen_zero(hint->last_presence_subtype))) {
3291 info.presence_subtype = ast_strdupa(hint->last_presence_subtype);
3292 } else {
3293 info.presence_subtype = "";
3294 }
3295 if (!(ast_strlen_zero(hint->last_presence_message))) {
3296 info.presence_message = ast_strdupa(hint->last_presence_message);
3297 } else {
3298 info.presence_message = "";
3299 }
3300 ao2_unlock(hint);
3301 } else {
3302 info.exten_state = AST_EXTENSION_REMOVED;
3303 }
3304
3305 res = cb(context, exten, &info, data);
3306
3307 return res;
3308}
@ AST_EXTENSION_REMOVED
Definition: pbx.h:62
enum ast_state_cb_update_reason reason
Definition: pbx.h:103
struct ao2_container * device_state_info
Definition: pbx.h:105

References ao2_lock, ao2_unlock, AST_EXTENSION_REMOVED, ast_strdupa, ast_strlen_zero(), voicemailpwcheck::context, ast_state_cb_info::device_state_info, sip_to_pjsip::info(), ast_hint::last_presence_message, ast_hint::last_presence_state, ast_hint::last_presence_subtype, ast_hint::laststate, and ast_state_cb_info::reason.

Referenced by ast_add_hint(), ast_merge_contexts_and_delete(), device_state_cb(), device_state_notify_callbacks(), and presence_state_notify_callbacks().

◆ ext_cmp()

static int ext_cmp ( const char *  left,
const char *  right 
)
static

Definition at line 2155 of file pbx.c.

2156{
2157 /* Make sure non-pattern extens come first. */
2158 if (left[0] != '_') {
2159 if (right[0] == '_') {
2160 return -1;
2161 }
2162 /* Compare two non-pattern extens. */
2163 return ext_cmp_exten(left, right);
2164 }
2165 if (right[0] != '_') {
2166 return 1;
2167 }
2168
2169 /*
2170 * OK, we need full pattern sorting routine.
2171 *
2172 * Skip past the underscores
2173 */
2174 return ext_cmp_pattern(left + 1, right + 1);
2175}

References ext_cmp_exten(), and ext_cmp_pattern().

Referenced by ast_add_extension2_lockopt(), and ast_extension_cmp().

◆ ext_cmp_exten()

static int ext_cmp_exten ( const char *  left,
const char *  right 
)
static

Definition at line 1905 of file pbx.c.

1906{
1907 int cmp;
1908
1909 for (;;) {
1910 /* Ignore '-' chars as eye candy fluff. */
1911 while (*left == '-') {
1912 ++left;
1913 }
1914 while (*right == '-') {
1915 ++right;
1916 }
1917
1918 cmp = *left - *right;
1919 if (cmp) {
1920 break;
1921 }
1922 if (!*left) {
1923 /*
1924 * Get here only if both strings ended at the same time. cmp
1925 * would be non-zero if only one string ended.
1926 */
1927 break;
1928 }
1929 ++left;
1930 ++right;
1931 }
1932 return cmp;
1933}

Referenced by _extension_match_core(), and ext_cmp().

◆ ext_cmp_exten_partial()

static int ext_cmp_exten_partial ( const char *  left,
const char *  right 
)
static

Definition at line 1862 of file pbx.c.

1863{
1864 int cmp;
1865
1866 for (;;) {
1867 /* Ignore '-' chars as eye candy fluff. */
1868 while (*left == '-') {
1869 ++left;
1870 }
1871 while (*right == '-') {
1872 ++right;
1873 }
1874
1875 if (!*right) {
1876 /*
1877 * Right ended first for partial match or both ended at the same
1878 * time for a match.
1879 */
1880 cmp = 0;
1881 break;
1882 }
1883
1884 cmp = *left - *right;
1885 if (cmp) {
1886 break;
1887 }
1888 ++left;
1889 ++right;
1890 }
1891 return cmp;
1892}

Referenced by _extension_match_core().

◆ ext_cmp_exten_strlen()

static int ext_cmp_exten_strlen ( const char *  str)
static

Definition at line 1832 of file pbx.c.

1833{
1834 int len;
1835
1836 len = 0;
1837 for (;;) {
1838 /* Ignore '-' chars as eye candy fluff. */
1839 while (*str == '-') {
1840 ++str;
1841 }
1842 if (!*str) {
1843 break;
1844 }
1845 ++str;
1846 ++len;
1847 }
1848 return len;
1849}
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)

References len(), and str.

Referenced by _extension_match_core().

◆ ext_cmp_pattern()

static int ext_cmp_pattern ( const char *  left,
const char *  right 
)
static

Definition at line 2107 of file pbx.c.

2108{
2109 int cmp;
2110 int left_pos;
2111 int right_pos;
2112
2113 for (;;) {
2114 unsigned char left_bitwise[32] = { 0, };
2115 unsigned char right_bitwise[32] = { 0, };
2116
2117 left_pos = ext_cmp_pattern_pos(&left, left_bitwise);
2118 right_pos = ext_cmp_pattern_pos(&right, right_bitwise);
2119 cmp = left_pos - right_pos;
2120 if (!cmp) {
2121 /*
2122 * Are the character sets different, even though they score the same?
2123 *
2124 * Note: Must swap left and right to get the sense of the
2125 * comparison correct. Otherwise, we would need to multiply by
2126 * -1 instead.
2127 */
2128 cmp = memcmp(right_bitwise, left_bitwise, ARRAY_LEN(left_bitwise));
2129 }
2130 if (cmp) {
2131 break;
2132 }
2133 if (!left) {
2134 /*
2135 * Get here only if both patterns ended at the same time. cmp
2136 * would be non-zero if only one pattern ended.
2137 */
2138 break;
2139 }
2140 }
2141 return cmp;
2142}
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...
Definition: pbx.c:1992

References ARRAY_LEN, and ext_cmp_pattern_pos().

Referenced by _extension_match_core(), and ext_cmp().

◆ ext_cmp_pattern_pos()

static int ext_cmp_pattern_pos ( const char **  p,
unsigned char *  bitwise 
)
static

helper functions to sort extension patterns in the desired way, so that more specific patterns appear first.

The function compares individual characters (or sets of), returning an int where bits 0-7 are the ASCII code of the first char in the set, bits 8-15 are the number of characters in the set, and bits 16-20 are for special cases. This way more specific patterns (smaller character sets) appear first. Wildcards have a special value, so that we can directly compare them to sets by subtracting the two values. In particular: 0x001xx one character, character set starting with xx 0x0yyxx yy characters, character set starting with xx 0x18000 '.' (one or more of anything) 0x28000 '!' (zero or more of anything) 0x30000 NUL (end of string) 0x40000 error in set. The pointer to the string is advanced according to needs. NOTES:

  1. the empty set is ignored.
  2. given that a full set has always 0 as the first element, we could encode the special cases as 0xffXX where XX is 1, 2, 3, 4 as used above.

Definition at line 1992 of file pbx.c.

1993{
1994#define BITS_PER 8 /* Number of bits per unit (byte). */
1995 unsigned char c;
1996 unsigned char cmin;
1997 int count;
1998 const char *end;
1999
2000 do {
2001 /* Get character and advance. (Ignore '-' chars as eye candy fluff.) */
2002 do {
2003 c = *(*p)++;
2004 } while (c == '-');
2005
2006 /* always return unless we have a set of chars */
2007 switch (c) {
2008 default:
2009 /* ordinary character */
2010 bitwise[c / BITS_PER] = 1 << ((BITS_PER - 1) - (c % BITS_PER));
2011 return 0x0100 | c;
2012
2013 case 'n':
2014 case 'N':
2015 /* 2..9 */
2016 bitwise[6] = 0x3f;
2017 bitwise[7] = 0xc0;
2018 return 0x0800 | '2';
2019
2020 case 'x':
2021 case 'X':
2022 /* 0..9 */
2023 bitwise[6] = 0xff;
2024 bitwise[7] = 0xc0;
2025 return 0x0A00 | '0';
2026
2027 case 'z':
2028 case 'Z':
2029 /* 1..9 */
2030 bitwise[6] = 0x7f;
2031 bitwise[7] = 0xc0;
2032 return 0x0900 | '1';
2033
2034 case '.':
2035 /* wildcard */
2036 return 0x18000;
2037
2038 case '!':
2039 /* earlymatch */
2040 return 0x28000; /* less specific than '.' */
2041
2042 case '\0':
2043 /* empty string */
2044 *p = NULL;
2045 return 0x30000;
2046
2047 case '[':
2048 /* char set */
2049 break;
2050 }
2051 /* locate end of set */
2052 end = strchr(*p, ']');
2053
2054 if (!end) {
2055 ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n");
2056 return 0x40000; /* XXX make this entry go last... */
2057 }
2058
2059 count = 0;
2060 cmin = 0xFF;
2061 for (; *p < end; ++*p) {
2062 unsigned char c1; /* first char in range */
2063 unsigned char c2; /* last char in range */
2064
2065 c1 = (*p)[0];
2066 if (*p + 2 < end && (*p)[1] == '-') { /* this is a range */
2067 c2 = (*p)[2];
2068 *p += 2; /* skip a total of 3 chars */
2069 } else { /* individual character */
2070 c2 = c1;
2071 }
2072 if (c1 < cmin) {
2073 cmin = c1;
2074 }
2075 for (; c1 <= c2; ++c1) {
2076 unsigned char mask = 1 << ((BITS_PER - 1) - (c1 % BITS_PER));
2077
2078 /*
2079 * Note: If two character sets score the same, the one with the
2080 * lowest ASCII values will compare as coming first. Must fill
2081 * in most significant bits for lower ASCII values to accomplish
2082 * the desired sort order.
2083 */
2084 if (!(bitwise[c1 / BITS_PER] & mask)) {
2085 /* Add the character to the set. */
2086 bitwise[c1 / BITS_PER] |= mask;
2087 count += 0x100;
2088 }
2089 }
2090 }
2091 ++*p;
2092 } while (!count);/* While the char set was empty. */
2093 return count | cmin;
2094}
#define BITS_PER

References ast_log, BITS_PER, c, end, LOG_WARNING, and NULL.

Referenced by ext_cmp_pattern().

◆ ext_fluff_count()

static int ext_fluff_count ( const char *  exten)
static

Definition at line 2177 of file pbx.c.

2178{
2179 int fluff = 0;
2180
2181 if (*exten != '_') {
2182 /* not a pattern, simple check. */
2183 while (*exten) {
2184 if (*exten == '-') {
2185 fluff++;
2186 }
2187 exten++;
2188 }
2189
2190 return fluff;
2191 }
2192
2193 /* do pattern check */
2194 while (*exten) {
2195 if (*exten == '-') {
2196 fluff++;
2197 } else if (*exten == '[') {
2198 /* skip set, dashes here matter. */
2199 exten = strchr(exten, ']');
2200
2201 if (!exten) {
2202 /* we'll end up warning about this later, don't spam logs */
2203 return fluff;
2204 }
2205 }
2206 exten++;
2207 }
2208
2209 return fluff;
2210}

References ast_exten::exten.

Referenced by ast_add_extension2_lockopt().

◆ ext_strncpy()

static unsigned int ext_strncpy ( char *  dst,
const char *  src,
size_t  dst_size,
int  nofluff 
)
static

Definition at line 7051 of file pbx.c.

7052{
7053 unsigned int count;
7054 unsigned int insquares;
7055 unsigned int is_pattern;
7056
7057 if (!dst_size--) {
7058 /* There really is no dst buffer */
7059 return 0;
7060 }
7061
7062 count = 0;
7063 insquares = 0;
7064 is_pattern = *src == '_';
7065 while (*src && count < dst_size) {
7066 if (*src == '[') {
7067 if (is_pattern) {
7068 insquares = 1;
7069 }
7070 } else if (*src == ']') {
7071 insquares = 0;
7072 } else if (*src == ' ' && !insquares) {
7073 ++src;
7074 continue;
7075 } else if (*src == '-' && !insquares && nofluff) {
7076 ++src;
7077 continue;
7078 }
7079 *dst++ = *src++;
7080 ++count;
7081 }
7082 *dst = '\0';
7083
7084 return count + 1;
7085}

Referenced by ast_add_extension2_lockopt(), and ast_context_remove_extension_callerid2().

◆ extension_match_core()

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

Definition at line 2429 of file pbx.c.

2430{
2431 int i;
2432 static int prof_id = -2; /* marker for 'unallocated' id */
2433 if (prof_id == -2) {
2434 prof_id = ast_add_profile("ext_match", 0);
2435 }
2436 ast_mark(prof_id, 1);
2437 i = _extension_match_core(ast_strlen_zero(pattern) ? "" : pattern, ast_strlen_zero(data) ? "" : data, mode);
2438 ast_mark(prof_id, 0);
2439 return i;
2440}
int ast_add_profile(const char *, uint64_t scale)
support for event profiling
Definition: astman.c:92
int64_t ast_mark(int, int start1_stop0)
Definition: astman.c:103
static int _extension_match_core(const char *pattern, const char *data, enum ext_match_t mode)
Definition: pbx.c:2238

References _extension_match_core(), ast_add_profile(), ast_mark(), ast_strlen_zero(), and ast_exten::data.

Referenced by ast_extension_close(), ast_extension_match(), and pbx_find_extension().

◆ extension_presence_state_helper()

static int extension_presence_state_helper ( struct ast_exten e,
char **  subtype,
char **  message 
)
static

Definition at line 3221 of file pbx.c.

3222{
3223 struct ast_str *hint_app = ast_str_thread_get(&extensionstate_buf, 32);
3224 char *presence_provider;
3225 const char *app;
3226
3227 if (!e || !hint_app) {
3228 return -1;
3229 }
3230
3232 if (ast_strlen_zero(app)) {
3233 return -1;
3234 }
3235
3236 ast_str_set(&hint_app, 0, "%s", app);
3237 presence_provider = parse_hint_presence(hint_app);
3238
3239 if (ast_strlen_zero(presence_provider)) {
3240 /* No presence string in the hint */
3241 return 0;
3242 }
3243
3244 return ast_presence_state(presence_provider, subtype, message);
3245}
static char * parse_hint_presence(struct ast_str *hint_args)
Definition: pbx.c:3058
ast_presence_state
Definition: presencestate.h:26

References app, ast_get_extension_app(), ast_str_set(), ast_str_thread_get(), ast_strlen_zero(), extensionstate_buf, and parse_hint_presence().

Referenced by ast_add_hint(), ast_hint_presence_state(), and handle_hint_change_message_type().

◆ extension_state_add_destroy()

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

Definition at line 3748 of file pbx.c.

3750{
3751 struct ast_hint *hint;
3752 struct ast_state_cb *state_cb;
3753 struct ast_exten *e;
3754 int id;
3755
3756 /* If there's no context and extension: add callback to statecbs list */
3757 if (!context && !exten) {
3758 /* Prevent multiple adds from adding the same change_cb at the same time. */
3760
3761 /* Remove any existing change_cb. */
3762 ao2_find(statecbs, change_cb, OBJ_UNLINK | OBJ_NODATA);
3763
3764 /* Now insert the change_cb */
3765 if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) {
3767 return -1;
3768 }
3769 state_cb->id = 0;
3770 state_cb->change_cb = change_cb;
3771 state_cb->destroy_cb = destroy_cb;
3772 state_cb->data = data;
3773 state_cb->extended = extended;
3774 ao2_link(statecbs, state_cb);
3775
3776 ao2_ref(state_cb, -1);
3778 return 0;
3779 }
3780
3781 if (!context || !exten)
3782 return -1;
3783
3784 /* This callback type is for only one hint, so get the hint */
3786 if (!e) {
3787 return -1;
3788 }
3789
3790 /* If this is a pattern, dynamically create a new extension for this
3791 * particular match. Note that this will only happen once for each
3792 * individual extension, because the pattern will no longer match first.
3793 */
3794 if (e->exten[0] == '_') {
3795 ao2_lock(hints);
3797 e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr,
3798 e->registrar);
3801 if (!e || e->exten[0] == '_') {
3802 return -1;
3803 }
3804 }
3805
3806 /* Find the hint in the hints container */
3807 ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */
3808 hint = ao2_find(hints, e, 0);
3809 if (!hint) {
3811 return -1;
3812 }
3813
3814 /* Now insert the callback in the callback list */
3815 if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) {
3816 ao2_ref(hint, -1);
3818 return -1;
3819 }
3820 do {
3821 id = stateid++; /* Unique ID for this callback */
3822 /* Do not allow id to ever be -1 or 0. */
3823 } while (id == -1 || id == 0);
3824 state_cb->id = id;
3825 state_cb->change_cb = change_cb; /* Pointer to callback routine */
3826 state_cb->destroy_cb = destroy_cb;
3827 state_cb->data = data; /* Data for the callback */
3828 state_cb->extended = extended;
3829 ao2_link(hint->callbacks, state_cb);
3830
3831 ao2_ref(state_cb, -1);
3832 ao2_ref(hint, -1);
3834
3835 return id;
3836}
enum queue_result id
Definition: app_queue.c:1767
static int stateid
Definition: pbx.c:812
static void destroy_state_cb(void *doomed)
Definition: pbx.c:3735

References ao2_alloc, ao2_find, ao2_link, ao2_lock, ao2_ref, ao2_unlock, ast_exten::app, ast_add_extension(), ast_free_ptr(), ast_hint_extension(), ast_strdup, ast_hint::callbacks, ast_state_cb::change_cb, ast_exten::cidmatch, voicemailpwcheck::context, ast_exten::data, ast_state_cb::data, ast_state_cb::destroy_cb, destroy_state_cb(), ast_exten::exten, ast_state_cb::extended, id, ast_state_cb::id, ast_exten::label, ast_exten::matchcid, ast_context::name, NULL, OBJ_NODATA, OBJ_UNLINK, ast_exten::parent, ast_exten::priority, ast_exten::registrar, statecbs, and stateid.

Referenced by ast_extension_state_add(), ast_extension_state_add_destroy(), ast_extension_state_add_destroy_extended(), and ast_extension_state_add_extended().

◆ find_context()

static struct ast_context * find_context ( const char *  context)
static

lookup for a context with a given name,

Return values
foundcontext or NULL if not found.

Definition at line 4821 of file pbx.c.

4822{
4823 struct ast_context item = {
4824 .name = context,
4825 };
4826
4828}

References ast_hashtab_lookup(), voicemailpwcheck::context, contexts_table, item, and aco_type::name.

Referenced by ast_add_extension_nolock(), and pbx_find_extension().

◆ find_context_locked()

static struct ast_context * find_context_locked ( const char *  context)
static

lookup for a context with a given name,

Return values
withconlock held if found.
NULLif not found.

Definition at line 4835 of file pbx.c.

4836{
4837 struct ast_context *c;
4838 struct ast_context item = {
4839 .name = context,
4840 };
4841
4844 if (!c) {
4846 }
4847
4848 return c;
4849}

References ast_hashtab_lookup(), ast_rdlock_contexts(), ast_unlock_contexts(), c, voicemailpwcheck::context, contexts_table, item, and aco_type::name.

Referenced by ast_add_extension(), ast_context_add_ignorepat(), ast_context_add_include(), ast_context_add_switch(), ast_context_remove_extension_callerid(), ast_context_remove_ignorepat(), ast_context_remove_include(), and ast_context_remove_switch().

◆ find_hint_by_cb_id()

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

Find Hint by callback id.

Definition at line 3863 of file pbx.c.

3864{
3865 struct ast_state_cb *state_cb;
3866 const struct ast_hint *hint = obj;
3867 int *id = arg;
3868
3869 if ((state_cb = ao2_find(hint->callbacks, id, 0))) {
3870 ao2_ref(state_cb, -1);
3871 return CMP_MATCH | CMP_STOP;
3872 }
3873
3874 return 0;
3875}

References ao2_find, ao2_ref, ast_hint::callbacks, CMP_MATCH, and CMP_STOP.

Referenced by ast_extension_state_del().

◆ get_canmatch_exten()

static struct ast_exten * get_canmatch_exten ( struct match_char node)
static

Definition at line 1161 of file pbx.c.

1162{
1163 /* find the exten at the end of the rope */
1164 struct match_char *node2 = node;
1165
1166 for (node2 = node; node2; node2 = node2->next_char) {
1167 if (node2->exten) {
1168#ifdef NEED_DEBUG_HERE
1169 ast_log(LOG_NOTICE,"CanMatch_exten returns exten %s(%p)\n", node2->exten->exten, node2->exten);
1170#endif
1171 return node2->exten;
1172 }
1173 }
1174#ifdef NEED_DEBUG_HERE
1175 ast_log(LOG_NOTICE,"CanMatch_exten returns NULL, match_char=%s\n", node->x);
1176#endif
1177 return 0;
1178}

References ast_log, ast_exten::exten, match_char::exten, LOG_NOTICE, and match_char::next_char.

◆ get_device_state_causing_channels()

static void get_device_state_causing_channels ( struct ao2_container c)
static

Definition at line 3317 of file pbx.c.

3318{
3319 struct ao2_iterator iter;
3321 struct ast_channel *chan;
3322
3323 if (!c || !ao2_container_count(c)) {
3324 return;
3325 }
3326 iter = ao2_iterator_init(c, 0);
3327 for (; (info = ao2_iterator_next(&iter)); ao2_ref(info, -1)) {
3328 enum ast_channel_state search_state = 0; /* prevent false uninit warning */
3329 char match[AST_CHANNEL_NAME];
3330 struct ast_channel_iterator *chan_iter;
3331 struct timeval chantime = {0, }; /* prevent false uninit warning */
3332
3333 switch (info->device_state) {
3334 case AST_DEVICE_RINGING:
3336 /* find ringing channel */
3337 search_state = AST_STATE_RINGING;
3338 break;
3339 case AST_DEVICE_BUSY:
3340 /* find busy channel */
3341 search_state = AST_STATE_BUSY;
3342 break;
3343 case AST_DEVICE_ONHOLD:
3344 case AST_DEVICE_INUSE:
3345 /* find up channel */
3346 search_state = AST_STATE_UP;
3347 break;
3348 case AST_DEVICE_UNKNOWN:
3350 case AST_DEVICE_INVALID:
3352 case AST_DEVICE_TOTAL /* not a state */:
3353 /* no channels are of interest */
3354 continue;
3355 }
3356
3357 /* iterate over all channels of the device */
3358 snprintf(match, sizeof(match), "%s-", info->device_name);
3359 chan_iter = ast_channel_iterator_by_name_new(match, strlen(match));
3360 for (; (chan = ast_channel_iterator_next(chan_iter)); ast_channel_unref(chan)) {
3361 ast_channel_lock(chan);
3362 /* this channel's state doesn't match */
3363 if (search_state != ast_channel_state(chan)) {
3364 ast_channel_unlock(chan);
3365 continue;
3366 }
3367 /* any non-ringing channel will fit */
3368 if (search_state != AST_STATE_RINGING) {
3369 ast_channel_unlock(chan);
3370 info->causing_channel = chan; /* is kept ref'd! */
3371 break;
3372 }
3373 /* but we need the oldest ringing channel of the device to match with undirected pickup */
3374 if (!info->causing_channel) {
3375 chantime = ast_channel_creationtime(chan);
3376 ast_channel_ref(chan); /* must ref it! */
3377 info->causing_channel = chan;
3378 } else if (ast_tvcmp(ast_channel_creationtime(chan), chantime) < 0) {
3379 chantime = ast_channel_creationtime(chan);
3380 ast_channel_unref(info->causing_channel);
3381 ast_channel_ref(chan); /* must ref it! */
3382 info->causing_channel = chan;
3383 }
3384 ast_channel_unlock(chan);
3385 }
3387 }
3388 ao2_iterator_destroy(&iter);
3389}
static int match(struct ast_sockaddr *addr, unsigned short callno, unsigned short dcallno, const struct chan_iax2_pvt *cur, int check_dcallno)
Definition: chan_iax2.c:2388
struct ast_channel_iterator * ast_channel_iterator_by_name_new(const char *name, size_t name_len)
Create a new channel iterator based on name.
Definition: channel.c:1349
struct ast_channel_iterator * ast_channel_iterator_destroy(struct ast_channel_iterator *i)
Destroy a channel iterator.
Definition: channel.c:1330
struct ast_channel * ast_channel_iterator_next(struct ast_channel_iterator *i)
Get the next channel for a channel iterator.
Definition: channel.c:1369
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2997
struct timeval ast_channel_creationtime(struct ast_channel *chan)
#define AST_CHANNEL_NAME
Definition: channel.h:173
ast_channel_state
ast_channel states
Definition: channelstate.h:35
@ AST_STATE_RINGING
Definition: channelstate.h:41
@ AST_STATE_BUSY
Definition: channelstate.h:43
@ AST_STATE_UP
Definition: channelstate.h:42
int ast_tvcmp(struct timeval _a, struct timeval _b)
Compress two struct timeval instances returning -1, 0, 1 if the first arg is smaller,...
Definition: time.h:137

References ao2_container_count(), ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_channel_creationtime(), ast_channel_iterator_by_name_new(), ast_channel_iterator_destroy(), ast_channel_iterator_next(), ast_channel_lock, AST_CHANNEL_NAME, ast_channel_ref, ast_channel_unlock, ast_channel_unref, 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_STATE_BUSY, AST_STATE_RINGING, AST_STATE_UP, ast_tvcmp(), c, sip_to_pjsip::info(), and match().

Referenced by ast_extension_state_extended(), and device_state_notify_callbacks().

◆ get_pattern_node()

static const char * get_pattern_node ( struct pattern_node node,
const char *  src,
int  pattern,
const char *  extenbuf 
)
static

Definition at line 1533 of file pbx.c.

1534{
1535#define INC_DST_OVERFLOW_CHECK \
1536 do { \
1537 if (dst - node->buf < sizeof(node->buf) - 1) { \
1538 ++dst; \
1539 } else { \
1540 overflow = 1; \
1541 } \
1542 } while (0)
1543
1544 node->specif = 0;
1545 node->buf[0] = '\0';
1546 while (*src) {
1547 if (*src == '[' && pattern) {
1548 char *dst = node->buf;
1549 const char *src_next;
1550 int length;
1551 int overflow = 0;
1552
1553 /* get past the '[' */
1554 ++src;
1555 for (;;) {
1556 if (*src == '\\') {
1557 /* Escaped character. */
1558 ++src;
1559 if (*src == '[' || *src == '\\' || *src == '-' || *src == ']') {
1560 *dst = *src++;
1562 }
1563 } else if (*src == '-') {
1564 unsigned char first;
1565 unsigned char last;
1566
1567 src_next = src;
1568 first = *(src_next - 1);
1569 last = *++src_next;
1570
1571 if (last == '\\') {
1572 /* Escaped character. */
1573 last = *++src_next;
1574 }
1575
1576 /* Possible char range. */
1577 if (node->buf[0] && last) {
1578 /* Expand the char range. */
1579 while (++first <= last) {
1580 *dst = first;
1582 }
1583 src = src_next + 1;
1584 } else {
1585 /*
1586 * There was no left or right char for the range.
1587 * It is just a '-'.
1588 */
1589 *dst = *src++;
1591 }
1592 } else if (*src == '\0') {
1594 "A matching ']' was not found for '[' in exten pattern '%s'\n",
1595 extenbuf);
1596 break;
1597 } else if (*src == ']') {
1598 ++src;
1599 break;
1600 } else {
1601 *dst = *src++;
1603 }
1604 }
1605 /* null terminate the exploded range */
1606 *dst = '\0';
1607
1608 if (overflow) {
1610 "Expanded character set too large to deal with in exten pattern '%s'. Ignoring character set.\n",
1611 extenbuf);
1612 node->buf[0] = '\0';
1613 continue;
1614 }
1615
1616 /* Sort the characters in character set. */
1617 length = strlen(node->buf);
1618 if (!length) {
1619 ast_log(LOG_WARNING, "Empty character set in exten pattern '%s'. Ignoring.\n",
1620 extenbuf);
1621 node->buf[0] = '\0';
1622 continue;
1623 }
1624 qsort(node->buf, length, 1, compare_char);
1625
1626 /* Remove duplicate characters from character set. */
1627 dst = node->buf;
1628 src_next = node->buf;
1629 while (*src_next++) {
1630 if (*dst != *src_next) {
1631 *++dst = *src_next;
1632 }
1633 }
1634
1635 length = strlen(node->buf);
1636 length <<= 8;
1637 node->specif = length | (unsigned char) node->buf[0];
1638 break;
1639 } else if (*src == '-') {
1640 /* Skip dashes in all extensions. */
1641 ++src;
1642 } else {
1643 if (*src == '\\') {
1644 /*
1645 * XXX The escape character here does not remove any special
1646 * meaning to characters except the '[', '\\', and '-'
1647 * characters since they are special only in this function.
1648 */
1649 node->buf[0] = *++src;
1650 if (!node->buf[0]) {
1651 break;
1652 }
1653 } else {
1654 node->buf[0] = *src;
1655 if (pattern) {
1656 /* make sure n,x,z patterns are canonicalized to N,X,Z */
1657 if (node->buf[0] == 'n') {
1658 node->buf[0] = 'N';
1659 } else if (node->buf[0] == 'x') {
1660 node->buf[0] = 'X';
1661 } else if (node->buf[0] == 'z') {
1662 node->buf[0] = 'Z';
1663 }
1664 }
1665 }
1666 node->buf[1] = '\0';
1667 node->specif = 1;
1668 ++src;
1669 break;
1670 }
1671 }
1672 return src;
1673
1674#undef INC_DST_OVERFLOW_CHECK
1675}
struct sla_ringing_trunk * last
Definition: app_sla.c:338
static int compare_char(const void *a, const void *b)
Definition: pbx.c:694
#define INC_DST_OVERFLOW_CHECK

References ast_log, compare_char(), first, INC_DST_OVERFLOW_CHECK, last, LOG_ERROR, and LOG_WARNING.

Referenced by add_exten_to_pattern_tree().

◆ handle_debug_dialplan()

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

Send ack once.

Definition at line 5771 of file pbx.c.

5772{
5773 char *exten = NULL, *context = NULL;
5774 /* Variables used for different counters */
5775 struct dialplan_counters counters;
5776 const char *incstack[AST_PBX_MAX_STACK];
5777
5778 switch (cmd) {
5779 case CLI_INIT:
5780 e->command = "dialplan debug";
5781 e->usage =
5782 "Usage: dialplan debug [context]\n"
5783 " Show dialplan context Trie(s). Usually only useful to folks debugging the deep internals of the fast pattern matcher\n";
5784 return NULL;
5785 case CLI_GENERATE:
5786 return complete_show_dialplan_context(a->line, a->word, a->pos, a->n);
5787 }
5788
5789 memset(&counters, 0, sizeof(counters));
5790
5791 if (a->argc != 2 && a->argc != 3)
5792 return CLI_SHOWUSAGE;
5793
5794 /* we obtain [exten@]context? if yes, split them ... */
5795 /* note: we ignore the exten totally here .... */
5796 if (a->argc == 3) {
5797 if (strchr(a->argv[2], '@')) { /* split into exten & context */
5798 context = ast_strdupa(a->argv[2]);
5799 exten = strsep(&context, "@");
5800 /* change empty strings to NULL */
5801 if (ast_strlen_zero(exten))
5802 exten = NULL;
5803 } else { /* no '@' char, only context given */
5804 context = ast_strdupa(a->argv[2]);
5805 }
5807 context = NULL;
5808 }
5809 /* else Show complete dial plan, context and exten are NULL */
5810 show_debug_helper(a->fd, context, exten, &counters, NULL, 0, incstack);
5811
5812 /* check for input failure and throw some error messages */
5813 if (context && !counters.context_existence) {
5814 ast_cli(a->fd, "There is no existence of '%s' context\n", context);
5815 return CLI_FAILURE;
5816 }
5817
5818
5819 ast_cli(a->fd,"-= %d %s. =-\n",
5820 counters.total_context, counters.total_context == 1 ? "context" : "contexts");
5821
5822 /* everything ok */
5823 return CLI_SUCCESS;
5824}
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define CLI_SUCCESS
Definition: cli.h:44
@ CLI_INIT
Definition: cli.h:152
@ CLI_GENERATE
Definition: cli.h:153
#define CLI_FAILURE
Definition: cli.h:46
static char * complete_show_dialplan_context(const char *line, const char *word, int pos, int state)
Definition: pbx.c:5419
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[])
Definition: pbx.c:5649
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
Counters for the show dialplan manager command.
Definition: pbx.c:5449

References a, ast_cli(), AST_PBX_MAX_STACK, ast_strdupa, ast_strlen_zero(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_show_dialplan_context(), voicemailpwcheck::context, dialplan_counters::context_existence, NULL, show_debug_helper(), strsep(), dialplan_counters::total_context, and ast_cli_entry::usage.

◆ handle_hint_change_message_type()

static int handle_hint_change_message_type ( struct stasis_message msg,
enum ast_state_cb_update_reason  reason 
)
static

Definition at line 3558 of file pbx.c.

3559{
3560 struct ast_hint *hint;
3561 struct ast_str *hint_app;
3562
3563 if (hint_change_message_type() != stasis_message_type(msg)) {
3564 return 0;
3565 }
3566
3567 if (!(hint_app = ast_str_create(1024))) {
3568 return -1;
3569 }
3570
3571 hint = stasis_message_data(msg);
3572
3573 switch (reason) {
3575 device_state_notify_callbacks(hint, &hint_app);
3576 break;
3578 {
3579 char *presence_subtype = NULL;
3580 char *presence_message = NULL;
3581 int state;
3582
3584 hint->exten, &presence_subtype, &presence_message);
3585 {
3586 struct ast_presence_state_message presence_state = {
3588 .subtype = presence_subtype,
3589 .message = presence_message
3590 };
3591
3592 presence_state_notify_callbacks(hint, &hint_app, &presence_state);
3593 }
3594
3595 ast_free(presence_subtype);
3596 ast_free(presence_message);
3597 }
3598 break;
3599 }
3600
3601 ast_free(hint_app);
3602 return 1;
3603}
static void presence_state_notify_callbacks(struct ast_hint *hint, struct ast_str **hint_app, struct ast_presence_state_message *presence_state)
Definition: pbx.c:3485
@ AST_HINT_UPDATE_PRESENCE
Definition: pbx.h:93
Stasis message payload representing a presence state update.
enum ast_presence_state state

References ast_free, AST_HINT_UPDATE_DEVICE, AST_HINT_UPDATE_PRESENCE, AST_PRESENCE_INVALID, ast_str_create, device_state_notify_callbacks(), ast_hint::exten, extension_presence_state_helper(), NULL, presence_state_notify_callbacks(), stasis_message_data(), stasis_message_type(), ast_presence_state_message::state, and state.

Referenced by device_state_cb().

◆ handle_set_extenpatternmatchnew()

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

Definition at line 6077 of file pbx.c.

6078{
6079 int oldval = 0;
6080
6081 switch (cmd) {
6082 case CLI_INIT:
6083 e->command = "dialplan set extenpatternmatchnew true";
6084 e->usage =
6085 "Usage: dialplan set extenpatternmatchnew true|false\n"
6086 " Use the NEW extension pattern matching algorithm, true or false.\n";
6087 return NULL;
6088 case CLI_GENERATE:
6089 return NULL;
6090 }
6091
6092 if (a->argc != 4)
6093 return CLI_SHOWUSAGE;
6094
6095 oldval = pbx_set_extenpatternmatchnew(1);
6096
6097 if (oldval)
6098 ast_cli(a->fd, "\n -- Still using the NEW pattern match algorithm for extension names in the dialplan.\n");
6099 else
6100 ast_cli(a->fd, "\n -- Switched to using the NEW pattern match algorithm for extension names in the dialplan.\n");
6101
6102 return CLI_SUCCESS;
6103}
int pbx_set_extenpatternmatchnew(int newval)
Definition: pbx.c:4798

References a, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, NULL, pbx_set_extenpatternmatchnew(), and ast_cli_entry::usage.

◆ handle_show_dialplan()

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

Definition at line 5704 of file pbx.c.

5705{
5706 char *exten = NULL, *context = NULL;
5707 /* Variables used for different counters */
5708 struct dialplan_counters counters;
5709 const char *incstack[AST_PBX_MAX_STACK];
5710
5711 switch (cmd) {
5712 case CLI_INIT:
5713 e->command = "dialplan show";
5714 e->usage =
5715 "Usage: dialplan show [[exten@]context]\n"
5716 " Show dialplan\n";
5717 return NULL;
5718 case CLI_GENERATE:
5719 return complete_show_dialplan_context(a->line, a->word, a->pos, a->n);
5720 }
5721
5722 memset(&counters, 0, sizeof(counters));
5723
5724 if (a->argc != 2 && a->argc != 3)
5725 return CLI_SHOWUSAGE;
5726
5727 /* we obtain [exten@]context? if yes, split them ... */
5728 if (a->argc == 3) {
5729 if (strchr(a->argv[2], '@')) { /* split into exten & context */
5730 context = ast_strdupa(a->argv[2]);
5731 exten = strsep(&context, "@");
5732 /* change empty strings to NULL */
5733 if (ast_strlen_zero(exten))
5734 exten = NULL;
5735 } else { /* no '@' char, only context given */
5736 context = ast_strdupa(a->argv[2]);
5737 }
5739 context = NULL;
5740 }
5741 /* else Show complete dial plan, context and exten are NULL */
5742 show_dialplan_helper(a->fd, context, exten, &counters, NULL, 0, incstack);
5743
5744 /* check for input failure and throw some error messages */
5745 if (context && !counters.context_existence) {
5746 ast_cli(a->fd, "There is no existence of '%s' context\n", context);
5747 return CLI_FAILURE;
5748 }
5749
5750 if (exten && !counters.extension_existence) {
5751 if (context)
5752 ast_cli(a->fd, "There is no existence of %s@%s extension\n",
5753 exten, context);
5754 else
5755 ast_cli(a->fd,
5756 "There is no existence of '%s' extension in all contexts\n",
5757 exten);
5758 return CLI_FAILURE;
5759 }
5760
5761 ast_cli(a->fd,"-= %d %s (%d %s) in %d %s. =-\n",
5762 counters.total_exten, counters.total_exten == 1 ? "extension" : "extensions",
5763 counters.total_prio, counters.total_prio == 1 ? "priority" : "priorities",
5764 counters.total_context, counters.total_context == 1 ? "context" : "contexts");
5765
5766 /* everything ok */
5767 return CLI_SUCCESS;
5768}
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[])
Definition: pbx.c:5488

References a, ast_cli(), AST_PBX_MAX_STACK, ast_strdupa, ast_strlen_zero(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_show_dialplan_context(), voicemailpwcheck::context, dialplan_counters::context_existence, dialplan_counters::extension_existence, NULL, show_dialplan_helper(), strsep(), dialplan_counters::total_context, dialplan_counters::total_exten, dialplan_counters::total_prio, and ast_cli_entry::usage.

◆ handle_show_hint()

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

handle_show_hint: CLI support for listing registered dial plan hint

Definition at line 5276 of file pbx.c.

5277{
5278 struct ast_hint *hint;
5279 int watchers;
5280 int num = 0, extenlen;
5281 struct ao2_iterator i;
5283
5284 switch (cmd) {
5285 case CLI_INIT:
5286 e->command = "core show hint";
5287 e->usage =
5288 "Usage: core show hint <exten>\n"
5289 " List registered hint.\n"
5290 " Hint details are shown in five columns. In order from left to right, they are:\n"
5291 " 1. Hint extension URI.\n"
5292 " 2. List of mapped device or presence state identifiers.\n"
5293 " 3. Current extension state. The aggregate of mapped device states.\n"
5294 " 4. Current presence state for the mapped presence state provider.\n"
5295 " 5. Watchers - number of subscriptions and other entities watching this hint.\n";
5296 return NULL;
5297 case CLI_GENERATE:
5298 return complete_core_show_hint(a->line, a->word, a->pos, a->n);
5299 }
5300
5301 if (a->argc < 4)
5302 return CLI_SHOWUSAGE;
5303
5304 if (ao2_container_count(hints) == 0) {
5305 ast_cli(a->fd, "There are no registered dialplan hints\n");
5306 return CLI_SUCCESS;
5307 }
5308
5309 extenlen = strlen(a->argv[3]);
5310 i = ao2_iterator_init(hints, 0);
5311 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
5312 ao2_lock(hint);
5313 if (!hint->exten) {
5314 /* The extension has already been destroyed */
5315 ao2_unlock(hint);
5316 continue;
5317 }
5318 if (!strncasecmp(ast_get_extension_name(hint->exten), a->argv[3], extenlen)) {
5319 watchers = ao2_container_count(hint->callbacks);
5320 sprintf(buf, "%s@%s",
5323 ast_cli(a->fd, "%-30.30s: %-60.60s State:%-15.15s Presence:%-15.15s Watchers %2d\n",
5324 buf,
5328 watchers);
5329 num++;
5330 }
5331 ao2_unlock(hint);
5332 }
5334 if (!num)
5335 ast_cli(a->fd, "No hints matching extension %s\n", a->argv[3]);
5336 else
5337 ast_cli(a->fd, "%d hint%s matching extension %s\n", num, (num!=1 ? "s":""), a->argv[3]);
5338 return CLI_SUCCESS;
5339}
static char * complete_core_show_hint(const char *line, const char *word, int pos, int state)
autocomplete for CLI command 'core show hint'
Definition: pbx.c:5240
const char * ast_presence_state2str(enum ast_presence_state state)
Convert presence state to text string for output.

References a, ao2_container_count(), ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ast_cli(), ast_extension_state2str(), ast_get_context_name(), ast_get_extension_app(), ast_get_extension_context(), ast_get_extension_name(), AST_MAX_CONTEXT, AST_MAX_EXTENSION, ast_presence_state2str(), buf, ast_hint::callbacks, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_core_show_hint(), ast_hint::exten, ast_hint::last_presence_state, ast_hint::laststate, NULL, and ast_cli_entry::usage.

◆ handle_show_hints()

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

handle_show_hints: CLI support for listing registered dial plan hints

Definition at line 5177 of file pbx.c.

5178{
5179 struct ast_hint *hint;
5180 int num = 0;
5181 int watchers;
5182 struct ao2_iterator i;
5184
5185 switch (cmd) {
5186 case CLI_INIT:
5187 e->command = "core show hints";
5188 e->usage =
5189 "Usage: core show hints\n"
5190 " List registered hints.\n"
5191 " Hint details are shown in five columns. In order from left to right, they are:\n"
5192 " 1. Hint extension URI.\n"
5193 " 2. List of mapped device or presence state identifiers.\n"
5194 " 3. Current extension state. The aggregate of mapped device states.\n"
5195 " 4. Current presence state for the mapped presence state provider.\n"
5196 " 5. Watchers - number of subscriptions and other entities watching this hint.\n";
5197 return NULL;
5198 case CLI_GENERATE:
5199 return NULL;
5200 }
5201
5202 if (ao2_container_count(hints) == 0) {
5203 ast_cli(a->fd, "There are no registered dialplan hints\n");
5204 return CLI_SUCCESS;
5205 }
5206 /* ... we have hints ... */
5207 ast_cli(a->fd, "\n -= Registered Asterisk Dial Plan Hints =-\n");
5208
5209 i = ao2_iterator_init(hints, 0);
5210 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
5211 ao2_lock(hint);
5212 if (!hint->exten) {
5213 /* The extension has already been destroyed */
5214 ao2_unlock(hint);
5215 continue;
5216 }
5217 watchers = ao2_container_count(hint->callbacks);
5218 snprintf(buf, sizeof(buf), "%s@%s",
5221
5222 ast_cli(a->fd, "%-30.30s: %-60.60s State:%-15.15s Presence:%-15.15s Watchers %2d\n",
5223 buf,
5227 watchers);
5228
5229 ao2_unlock(hint);
5230 num++;
5231 }
5233
5234 ast_cli(a->fd, "----------------\n");
5235 ast_cli(a->fd, "- %d hints registered\n", num);
5236 return CLI_SUCCESS;
5237}

References a, ao2_container_count(), ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ast_cli(), ast_extension_state2str(), ast_get_context_name(), ast_get_extension_app(), ast_get_extension_context(), ast_get_extension_name(), AST_MAX_CONTEXT, AST_MAX_EXTENSION, ast_presence_state2str(), buf, ast_hint::callbacks, CLI_GENERATE, CLI_INIT, CLI_SUCCESS, ast_cli_entry::command, ast_hint::exten, ast_hint::last_presence_state, ast_hint::laststate, NULL, and ast_cli_entry::usage.

◆ handle_unset_extenpatternmatchnew()

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

Definition at line 6105 of file pbx.c.

6106{
6107 int oldval = 0;
6108
6109 switch (cmd) {
6110 case CLI_INIT:
6111 e->command = "dialplan set extenpatternmatchnew false";
6112 e->usage =
6113 "Usage: dialplan set extenpatternmatchnew true|false\n"
6114 " Use the NEW extension pattern matching algorithm, true or false.\n";
6115 return NULL;
6116 case CLI_GENERATE:
6117 return NULL;
6118 }
6119
6120 if (a->argc != 4)
6121 return CLI_SHOWUSAGE;
6122
6123 oldval = pbx_set_extenpatternmatchnew(0);
6124
6125 if (!oldval)
6126 ast_cli(a->fd, "\n -- Still using the OLD pattern match algorithm for extension names in the dialplan.\n");
6127 else
6128 ast_cli(a->fd, "\n -- Switched to using the OLD pattern match algorithm for extension names in the dialplan.\n");
6129
6130 return CLI_SUCCESS;
6131}

References a, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, NULL, pbx_set_extenpatternmatchnew(), and ast_cli_entry::usage.

◆ hashtab_compare_exten_labels()

static int hashtab_compare_exten_labels ( const void *  ah_a,
const void *  ah_b 
)
static

Definition at line 748 of file pbx.c.

749{
750 const struct ast_exten *ac = ah_a;
751 const struct ast_exten *bc = ah_b;
752 return strcmp(S_OR(ac->label, ""), S_OR(bc->label, ""));
753}
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition: strings.h:80

References bc, ast_exten::label, and S_OR.

Referenced by ast_add_extension2_lockopt().

◆ hashtab_compare_exten_numbers()

static int hashtab_compare_exten_numbers ( const void *  ah_a,
const void *  ah_b 
)
static

Definition at line 741 of file pbx.c.

742{
743 const struct ast_exten *ac = ah_a;
744 const struct ast_exten *bc = ah_b;
745 return ac->priority != bc->priority;
746}

References bc, and ast_exten::priority.

Referenced by ast_add_extension2_lockopt().

◆ hashtab_compare_extens()

static int hashtab_compare_extens ( const void *  ha_a,
const void *  ah_b 
)
static

Definition at line 713 of file pbx.c.

714{
715 const struct ast_exten *ac = ah_a;
716 const struct ast_exten *bc = ah_b;
717 int x = strcmp(ac->exten, bc->exten);
718 if (x) { /* if exten names are diff, then return */
719 return x;
720 }
721
722 /* but if they are the same, do the cidmatch values match? */
723 /* not sure which side may be using ast_ext_matchcid_types, so check both */
724 if (ac->matchcid == AST_EXT_MATCHCID_ANY || bc->matchcid == AST_EXT_MATCHCID_ANY) {
725 return 0;
726 }
727 if (ac->matchcid == AST_EXT_MATCHCID_OFF && bc->matchcid == AST_EXT_MATCHCID_OFF) {
728 return 0;
729 }
730 if (ac->matchcid != bc->matchcid) {
731 return 1;
732 }
733 /* all other cases already disposed of, match now required on callerid string (cidmatch) */
734 /* although ast_add_extension2_lockopt() enforces non-zero ptr, caller may not have */
735 if (ast_strlen_zero(ac->cidmatch) && ast_strlen_zero(bc->cidmatch)) {
736 return 0;
737 }
738 return strcmp(ac->cidmatch, bc->cidmatch);
739}

References AST_EXT_MATCHCID_ANY, AST_EXT_MATCHCID_OFF, ast_strlen_zero(), bc, ast_exten::cidmatch, ast_exten::exten, and ast_exten::matchcid.

Referenced by ast_add_extension2_lockopt().

◆ hashtab_hash_extens()

static unsigned int hashtab_hash_extens ( const void *  obj)
static

Definition at line 761 of file pbx.c.

762{
763 const struct ast_exten *ac = obj;
764 unsigned int x = ast_hashtab_hash_string(ac->exten);
765 unsigned int y = 0;
766 if (ac->matchcid == AST_EXT_MATCHCID_ON)
768 return x+y;
769}

References AST_EXT_MATCHCID_ON, ast_hashtab_hash_string(), ast_exten::cidmatch, ast_exten::exten, and ast_exten::matchcid.

Referenced by ast_add_extension2_lockopt().

◆ hashtab_hash_labels()

static unsigned int hashtab_hash_labels ( const void *  obj)
static

Definition at line 777 of file pbx.c.

778{
779 const struct ast_exten *ac = obj;
780 return ast_hashtab_hash_string(S_OR(ac->label, ""));
781}

References ast_hashtab_hash_string(), ast_exten::label, and S_OR.

Referenced by ast_add_extension2_lockopt().

◆ hashtab_hash_priority()

static unsigned int hashtab_hash_priority ( const void *  obj)
static

Definition at line 771 of file pbx.c.

772{
773 const struct ast_exten *ac = obj;
774 return ast_hashtab_hash_int(ac->priority);
775}
unsigned int ast_hashtab_hash_int(const int num)
Definition: hashtab.c:205

References ast_hashtab_hash_int(), and ast_exten::priority.

Referenced by ast_add_extension2_lockopt().

◆ hint_cmp()

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

Definition at line 8921 of file pbx.c.

8922{
8923 const struct ast_hint *hint = obj;
8924 const struct ast_exten *exten = arg;
8925
8926 return (hint->exten == exten) ? CMP_MATCH | CMP_STOP : 0;
8927}

References CMP_MATCH, CMP_STOP, ast_exten::exten, and ast_hint::exten.

Referenced by ast_pbx_init().

◆ hint_hash()

static int hint_hash ( const void *  obj,
const int  flags 
)
static

Definition at line 8901 of file pbx.c.

8902{
8903 const struct ast_hint *hint = obj;
8904 const char *exten_name;
8905 int res;
8906
8909 /*
8910 * If the exten or extension name isn't set, return 0 so that
8911 * the ao2_find() search will start in the first bucket.
8912 */
8913 res = 0;
8914 } else {
8916 }
8917
8918 return res;
8919}

References ast_get_extension_name(), ast_str_case_hash(), ast_strlen_zero(), ast_hint::exten, and exten_name.

Referenced by ast_pbx_init().

◆ hint_id_cmp()

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

Definition at line 3910 of file pbx.c.

3911{
3912 const struct ast_state_cb *cb = obj;
3913 int *id = arg;
3914
3915 return (cb->id == *id) ? CMP_MATCH | CMP_STOP : 0;
3916}

References CMP_MATCH, CMP_STOP, and ast_state_cb::id.

Referenced by ast_add_hint().

◆ hintdevice_cmp_multiple()

static int hintdevice_cmp_multiple ( void *  obj,
void *  arg,
int  flags 
)
static
Note
Devices on hints are not unique so no CMP_STOP is returned Dont use ao2_find against hintdevices container cause there always could be more than one result.

Definition at line 443 of file pbx.c.

444{
445 struct ast_hintdevice *left = obj;
446 struct ast_hintdevice *right = arg;
447 const char *right_key = arg;
448 int cmp;
449
450 switch (flags & OBJ_SEARCH_MASK) {
452 right_key = right->hintdevice;
453 /* Fall through */
454 case OBJ_SEARCH_KEY:
455 cmp = strcasecmp(left->hintdevice, right_key);
456 break;
458 /*
459 * We could also use a partial key struct containing a length
460 * so strlen() does not get called for every comparison instead.
461 */
462 cmp = strncmp(left->hintdevice, right_key, strlen(right_key));
463 break;
464 default:
465 ast_assert(0);
466 cmp = 0;
467 break;
468 }
469 return cmp ? 0 : CMP_MATCH;
470}

References ast_assert, CMP_MATCH, ast_hintdevice::hintdevice, OBJ_SEARCH_KEY, OBJ_SEARCH_MASK, OBJ_SEARCH_OBJECT, and OBJ_SEARCH_PARTIAL_KEY.

Referenced by ast_pbx_init(), device_state_cb(), and presence_state_cb().

◆ hintdevice_destroy()

static void hintdevice_destroy ( void *  obj)
static

Definition at line 560 of file pbx.c.

561{
562 struct ast_hintdevice *doomed = obj;
563
564 if (doomed->hint) {
565 ao2_ref(doomed->hint, -1);
566 doomed->hint = NULL;
567 }
568}

References ao2_ref, ast_hintdevice::hint, and NULL.

Referenced by add_hintdevice().

◆ hintdevice_hash_cb()

static int hintdevice_hash_cb ( const void *  obj,
const int  flags 
)
static
Note
Using the device for hash

Definition at line 417 of file pbx.c.

418{
419 const struct ast_hintdevice *ext;
420 const char *key;
421
422 switch (flags & OBJ_SEARCH_MASK) {
423 case OBJ_SEARCH_KEY:
424 key = obj;
425 break;
427 ext = obj;
428 key = ext->hintdevice;
429 break;
430 default:
431 ast_assert(0);
432 return 0;
433 }
434
435 return ast_str_case_hash(key);
436}
const char * ext
Definition: http.c:150

References ast_assert, ast_str_case_hash(), ext, OBJ_SEARCH_KEY, OBJ_SEARCH_MASK, and OBJ_SEARCH_OBJECT.

Referenced by ast_pbx_init().

◆ hintdevice_remove_cb()

static int hintdevice_remove_cb ( void *  obj,
void *  arg,
void *  data,
int  flags 
)
static

Definition at line 526 of file pbx.c.

527{
528 struct ast_hintdevice *candidate = obj;
529 char *device = arg;
530 struct ast_hint *hint = data;
531
532 if (!strcasecmp(candidate->hintdevice, device)
533 && candidate->hint == hint) {
534 return CMP_MATCH;
535 }
536 return 0;
537}

References CMP_MATCH, ast_hintdevice::hint, and ast_hintdevice::hintdevice.

Referenced by remove_hintdevice().

◆ increase_call_count()

static int increase_call_count ( const struct ast_channel c)
static

Increase call count for channel.

Return values
0on success
non-zeroif a configured limit (maxcalls, maxload, minmemfree) was reached

Definition at line 4638 of file pbx.c.

4639{
4640 int failed = 0;
4641 double curloadavg;
4642#if defined(HAVE_SYSINFO)
4643 struct sysinfo sys_info;
4644#endif
4645
4647 if (ast_option_maxcalls) {
4649 ast_log(LOG_WARNING, "Maximum call limit of %d calls exceeded by '%s'!\n", ast_option_maxcalls, ast_channel_name(c));
4650 failed = -1;
4651 }
4652 }
4653 if (ast_option_maxload) {
4654 getloadavg(&curloadavg, 1);
4655 if (curloadavg >= ast_option_maxload) {
4656 ast_log(LOG_WARNING, "Maximum loadavg limit of %f load exceeded by '%s' (currently %f)!\n", ast_option_maxload, ast_channel_name(c), curloadavg);
4657 failed = -1;
4658 }
4659 }
4660#if defined(HAVE_SYSINFO)
4661 if (option_minmemfree) {
4662 /* Make sure that the free system memory is above the configured low watermark */
4663 if (!sysinfo(&sys_info)) {
4664 /* Convert the amount of available RAM from mem_units to MB. The calculation
4665 * was done this way to avoid overflow problems */
4666 uint64_t curfreemem = sys_info.freeram + sys_info.bufferram;
4667 curfreemem *= sys_info.mem_unit;
4668 curfreemem /= 1024 * 1024;
4669 if (curfreemem < option_minmemfree) {
4670 ast_log(LOG_WARNING, "Available system memory (~%" PRIu64 "MB) is below the configured low watermark (%ldMB)\n",
4671 curfreemem, option_minmemfree);
4672 failed = -1;
4673 }
4674 }
4675 }
4676#endif
4677
4678 if (!failed) {
4679 countcalls++;
4680 totalcalls++;
4681 }
4683
4684 return failed;
4685}
int getloadavg(double *list, int nelem)
int ast_option_maxcalls
Definition: options.c:80
double ast_option_maxload
Definition: options.c:78
long option_minmemfree
Definition: options.c:87

References ast_channel_name(), ast_log, ast_mutex_lock, ast_mutex_unlock, ast_option_maxcalls, ast_option_maxload, c, countcalls, getloadavg(), LOG_WARNING, maxcalllock, option_minmemfree, and totalcalls.

Referenced by ast_pbx_run_args(), and ast_pbx_start().

◆ insert_in_next_chars_alt_char_list()

static void insert_in_next_chars_alt_char_list ( struct match_char **  parent_ptr,
struct match_char node 
)
static

Definition at line 1438 of file pbx.c.

1439{
1440 struct match_char *curr, *lcurr;
1441
1442 /* insert node into the tree at "current", so the alt_char list from current is
1443 sorted in increasing value as you go to the leaves */
1444 if (!(*parent_ptr)) {
1445 *parent_ptr = node;
1446 return;
1447 }
1448
1449 if ((*parent_ptr)->specificity > node->specificity) {
1450 /* insert at head */
1451 node->alt_char = (*parent_ptr);
1452 *parent_ptr = node;
1453 return;
1454 }
1455
1456 lcurr = *parent_ptr;
1457 for (curr = (*parent_ptr)->alt_char; curr; curr = curr->alt_char) {
1458 if (curr->specificity > node->specificity) {
1459 node->alt_char = curr;
1460 lcurr->alt_char = node;
1461 break;
1462 }
1463 lcurr = curr;
1464 }
1465
1466 if (!curr) {
1467 lcurr->alt_char = node;
1468 }
1469
1470}

References match_char::alt_char, and match_char::specificity.

Referenced by add_pattern_node().

◆ internal_extension_state_extended()

static int internal_extension_state_extended ( struct ast_channel c,
const char *  context,
const char *  exten,
struct ao2_container device_state_info 
)
static

Definition at line 3162 of file pbx.c.

3164{
3165 struct ast_exten *e;
3166
3167 if (!(e = ast_hint_extension(c, context, exten))) { /* Do we have a hint for this extension ? */
3168 return -1; /* No hint, return -1 */
3169 }
3170
3171 if (e->exten[0] == '_') {
3172 /* Create this hint on-the-fly, we explicitly lock hints here to ensure the
3173 * same locking order as if this were done through configuration file - that is
3174 * hints is locked first and then (if needed) contexts is locked
3175 */
3176 ao2_lock(hints);
3178 e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr,
3179 e->registrar);
3181 if (!(e = ast_hint_extension(c, context, exten))) {
3182 /* Improbable, but not impossible */
3183 return -1;
3184 }
3185 }
3186
3187 return ast_extension_state2(e, device_state_info); /* Check all devices in the hint */
3188}

References ao2_lock, ao2_unlock, ast_exten::app, ast_add_extension(), ast_extension_state2(), ast_free_ptr(), ast_hint_extension(), ast_strdup, c, ast_exten::cidmatch, voicemailpwcheck::context, ast_exten::data, ast_exten::exten, ast_exten::label, ast_exten::matchcid, ast_context::name, NULL, ast_exten::parent, ast_exten::priority, and ast_exten::registrar.

Referenced by ast_extension_state(), and ast_extension_state_extended().

◆ load_pbx()

int load_pbx ( void  )

Provided by pbx.c

Definition at line 8446 of file pbx.c.

8447{
8448 int res = 0;
8449
8451
8452 /* Initialize the PBX */
8453 ast_verb(1, "Asterisk PBX Core Initializing\n");
8454
8455 ast_verb(5, "Registering builtin functions:\n");
8459
8460 /* Register manager application */
8463
8464 if (res) {
8465 return -1;
8466 }
8467
8469 return -1;
8470 }
8472 stasis_subscription_accept_message_type(device_state_sub, hint_change_message_type());
8473 stasis_subscription_accept_message_type(device_state_sub, hint_remove_message_type());
8475
8477 return -1;
8478 }
8481
8482 return 0;
8483}
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
struct stasis_topic * ast_device_state_topic_all(void)
Get the Stasis topic for device state messages.
Definition: devicestate.c:671
#define EVENT_FLAG_REPORTING
Definition: manager.h:84
#define ast_manager_register_xml_core(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
Definition: manager.h:203
#define EVENT_FLAG_CONFIG
Definition: manager.h:82
#define EVENT_FLAG_CALL
Definition: manager.h:76
static int manager_show_dialplan(struct mansession *s, const struct message *m)
Manager listing of dial plan.
Definition: pbx.c:5991
static int action_extensionstatelist(struct mansession *s, const struct message *m)
Definition: pbx.c:8369
static struct stasis_subscription * presence_state_sub
Subscription for presence state change events.
Definition: pbx.c:790
static void presence_state_cb(void *unused, struct stasis_subscription *sub, struct stasis_message *msg)
Definition: pbx.c:8319
static void unload_pbx(void)
Definition: pbx.c:8434
static struct ast_custom_function testtime_function
Definition: pbx.c:8302
static void device_state_cb(void *unused, struct stasis_subscription *sub, struct stasis_message *msg)
Definition: pbx.c:3605
static struct ast_cli_entry pbx_cli[]
Definition: pbx.c:6136
static struct stasis_subscription * device_state_sub
Subscription for device state change events.
Definition: pbx.c:788
static struct ast_custom_function exception_function
Definition: pbx.c:2867
int __ast_custom_function_register(struct ast_custom_function *acf, struct ast_module *mod)
Register a custom function.
struct stasis_topic * ast_presence_state_topic_all(void)
Get presence state topic.
struct stasis_message_type * ast_presence_state_message_type(void)
Get presence state message type.
@ STASIS_SUBSCRIPTION_FILTER_SELECTIVE
Definition: stasis.h:297
int stasis_subscription_accept_message_type(struct stasis_subscription *subscription, const struct stasis_message_type *type)
Indicate to a subscription that we are interested in a message type.
Definition: stasis.c:1090
int stasis_subscription_set_filter(struct stasis_subscription *subscription, enum stasis_subscription_message_filter filter)
Set the message type filtering level on a subscription.
Definition: stasis.c:1144
#define stasis_subscribe(topic, callback, data)
Definition: stasis.h:649

References __ast_custom_function_register(), action_extensionstatelist(), ARRAY_LEN, ast_cli_register_multiple, ast_device_state_message_type(), ast_device_state_topic_all(), ast_manager_register_xml_core, ast_presence_state_message_type(), ast_presence_state_topic_all(), ast_register_cleanup(), ast_verb, device_state_cb(), device_state_sub, EVENT_FLAG_CALL, EVENT_FLAG_CONFIG, EVENT_FLAG_REPORTING, exception_function, manager_show_dialplan(), NULL, pbx_cli, presence_state_cb(), presence_state_sub, stasis_subscribe, stasis_subscription_accept_message_type(), STASIS_SUBSCRIPTION_FILTER_SELECTIVE, stasis_subscription_set_filter(), testtime_function, and unload_pbx().

Referenced by asterisk_daemon().

◆ manager_dpsendack()

static void manager_dpsendack ( struct mansession s,
const struct message m 
)
static

Send ack once.

Definition at line 5827 of file pbx.c.

5828{
5829 astman_send_listack(s, m, "DialPlan list will follow", "start");
5830}

References astman_send_listack().

Referenced by manager_show_dialplan(), and manager_show_dialplan_helper().

◆ manager_show_dialplan()

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

Manager listing of dial plan.

Definition at line 5991 of file pbx.c.

5992{
5993 const char *exten, *context;
5994 const char *id = astman_get_header(m, "ActionID");
5995 const char *incstack[AST_PBX_MAX_STACK];
5996 char idtext[256];
5997
5998 /* Variables used for different counters */
5999 struct dialplan_counters counters;
6000
6001 if (!ast_strlen_zero(id))
6002 snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id);
6003 else
6004 idtext[0] = '\0';
6005
6006 memset(&counters, 0, sizeof(counters));
6007
6008 exten = astman_get_header(m, "Extension");
6009 context = astman_get_header(m, "Context");
6010
6011 manager_show_dialplan_helper(s, m, idtext, context, exten, &counters, NULL, 0, incstack);
6012
6013 if (!ast_strlen_zero(context) && !counters.context_existence) {
6014 char errorbuf[BUFSIZ];
6015
6016 snprintf(errorbuf, sizeof(errorbuf), "Did not find context %s", context);
6017 astman_send_error(s, m, errorbuf);
6018 return 0;
6019 }
6020 if (!ast_strlen_zero(exten) && !counters.extension_existence) {
6021 char errorbuf[BUFSIZ];
6022
6024 snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s@%s", exten, context);
6025 else
6026 snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s in any context", exten);
6027 astman_send_error(s, m, errorbuf);
6028 return 0;
6029 }
6030
6031 if (!counters.total_items) {
6032 manager_dpsendack(s, m);
6033 }
6034
6035 astman_send_list_complete_start(s, m, "ShowDialPlanComplete", counters.total_items);
6036 astman_append(s,
6037 "ListExtensions: %d\r\n"
6038 "ListPriorities: %d\r\n"
6039 "ListContexts: %d\r\n",
6040 counters.total_exten, counters.total_prio, counters.total_context);
6042
6043 /* everything ok */
6044 return 0;
6045}
static void manager_dpsendack(struct mansession *s, const struct message *m)
Send ack once.
Definition: pbx.c:5827
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 dial...
Definition: pbx.c:5836

References AST_PBX_MAX_STACK, ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_error(), astman_send_list_complete_end(), astman_send_list_complete_start(), voicemailpwcheck::context, dialplan_counters::context_existence, dialplan_counters::extension_existence, manager_dpsendack(), manager_show_dialplan_helper(), NULL, dialplan_counters::total_context, dialplan_counters::total_exten, dialplan_counters::total_items, and dialplan_counters::total_prio.

Referenced by load_pbx().

◆ manager_show_dialplan_helper()

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[] 
)
static

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.

Definition at line 5836 of file pbx.c.

5841{
5842 struct ast_context *c;
5843 int res = 0, old_total_exten = dpc->total_exten;
5844
5845 if (ast_strlen_zero(exten))
5846 exten = NULL;
5848 context = NULL;
5849
5850 ast_debug(3, "manager_show_dialplan: Context: -%s- Extension: -%s-\n", context, exten);
5851
5852 /* try to lock contexts */
5853 if (ast_rdlock_contexts()) {
5854 astman_send_error(s, m, "Failed to lock contexts");
5855 ast_log(LOG_WARNING, "Failed to lock contexts list for manager: listdialplan\n");
5856 return -1;
5857 }
5858
5859 c = NULL; /* walk all contexts ... */
5860 while ( (c = ast_walk_contexts(c)) ) {
5861 int idx;
5862 struct ast_exten *e;
5863
5864 if (context && strcmp(ast_get_context_name(c), context) != 0)
5865 continue; /* not the name we want */
5866
5867 dpc->context_existence = 1;
5868 dpc->total_context++;
5869
5870 ast_debug(3, "manager_show_dialplan: Found Context: %s \n", ast_get_context_name(c));
5871
5872 if (ast_rdlock_context(c)) { /* failed to lock */
5873 ast_debug(3, "manager_show_dialplan: Failed to lock context\n");
5874 continue;
5875 }
5876
5877 /* XXX note- an empty context is not printed */
5878 e = NULL; /* walk extensions in context */
5879 while ( (e = ast_walk_context_extensions(c, e)) ) {
5880 struct ast_exten *p;
5881
5882 /* looking for extension? is this our extension? */
5884 /* not the one we are looking for, continue */
5885 ast_debug(3, "manager_show_dialplan: Skipping extension %s\n", ast_get_extension_name(e));
5886 continue;
5887 }
5888 ast_debug(3, "manager_show_dialplan: Found Extension: %s \n", ast_get_extension_name(e));
5889
5890 dpc->extension_existence = 1;
5891
5892 dpc->total_exten++;
5893
5894 p = NULL; /* walk next extension peers */
5895 while ( (p = ast_walk_extension_priorities(e, p)) ) {
5896 int prio = ast_get_extension_priority(p);
5897
5898 dpc->total_prio++;
5899 if (!dpc->total_items++)
5900 manager_dpsendack(s, m);
5901 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
5902 astman_append(s, "Context: %s\r\nExtension: %s\r\n", ast_get_context_name(c), ast_get_extension_name(e) );
5903
5904 /* XXX maybe make this conditional, if p != e ? */
5906 astman_append(s, "ExtensionLabel: %s\r\n", ast_get_extension_label(p));
5907
5908 if (prio == PRIORITY_HINT) {
5909 astman_append(s, "Priority: hint\r\nApplication: %s\r\n", ast_get_extension_app(p));
5910 } else {
5911 astman_append(s, "Priority: %d\r\nApplication: %s\r\nAppData: %s\r\n", prio, ast_get_extension_app(p), (char *) ast_get_extension_app_data(p));
5912 }
5913 astman_append(s, "Registrar: %s\r\n\r\n", ast_get_extension_registrar(e));
5914 }
5915 }
5916
5917 for (idx = 0; idx < ast_context_includes_count(c); idx++) {
5918 const struct ast_include *i = ast_context_includes_get(c, idx);
5919
5920 if (exten) {
5921 /* Check all includes for the requested extension */
5922 if (includecount >= AST_PBX_MAX_STACK) {
5923 ast_log(LOG_WARNING, "Maximum include depth exceeded!\n");
5924 } else {
5925 int dupe = 0;
5926 int x;
5927 for (x = 0; x < includecount; x++) {
5928 if (!strcasecmp(includes[x], ast_get_include_name(i))) {
5929 dupe++;
5930 break;
5931 }
5932 }
5933 if (!dupe) {
5934 includes[includecount] = ast_get_include_name(i);
5935 manager_show_dialplan_helper(s, m, actionidtext, ast_get_include_name(i), exten, dpc, i, includecount + 1, includes);
5936 } else {
5937 ast_log(LOG_WARNING, "Avoiding circular include of %s within %s\n", ast_get_include_name(i), context);
5938 }
5939 }
5940 } else {
5941 if (!dpc->total_items++)
5942 manager_dpsendack(s, m);
5943 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
5944 astman_append(s, "Context: %s\r\nIncludeContext: %s\r\nRegistrar: %s\r\n", ast_get_context_name(c), ast_get_include_name(i), ast_get_include_registrar(i));
5945 astman_append(s, "\r\n");
5946 ast_debug(3, "manager_show_dialplan: Found Included context: %s \n", ast_get_include_name(i));
5947 }
5948 }
5949
5950 for (idx = 0; idx < ast_context_ignorepats_count(c); idx++) {
5951 const struct ast_ignorepat *ip = ast_context_ignorepats_get(c, idx);
5952 const char *ipname = ast_get_ignorepat_name(ip);
5953 char ignorepat[AST_MAX_EXTENSION];
5954
5955 snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname);
5956 if (!exten || ast_extension_match(ignorepat, exten)) {
5957 if (!dpc->total_items++)
5958 manager_dpsendack(s, m);
5959 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
5960 astman_append(s, "Context: %s\r\nIgnorePattern: %s\r\nRegistrar: %s\r\n", ast_get_context_name(c), ipname, ast_get_ignorepat_registrar(ip));
5961 astman_append(s, "\r\n");
5962 }
5963 }
5964 if (!rinclude) {
5965 for (idx = 0; idx < ast_context_switches_count(c); idx++) {
5966 const struct ast_sw *sw = ast_context_switches_get(c, idx);
5967
5968 if (!dpc->total_items++)
5969 manager_dpsendack(s, m);
5970 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
5971 astman_append(s, "Context: %s\r\nSwitch: %s/%s\r\nRegistrar: %s\r\n", ast_get_context_name(c), ast_get_switch_name(sw), ast_get_switch_data(sw), ast_get_switch_registrar(sw));
5972 astman_append(s, "\r\n");
5973 ast_debug(3, "manager_show_dialplan: Found Switch : %s \n", ast_get_switch_name(sw));
5974 }
5975 }
5976
5978 }
5980
5981 if (dpc->total_exten == old_total_exten) {
5982 ast_debug(3, "manager_show_dialplan: Found nothing new\n");
5983 /* Nothing new under the sun */
5984 return -1;
5985 } else {
5986 return res;
5987 }
5988}
int ast_get_extension_priority(struct ast_exten *exten)
Definition: pbx.c:8544
const char * ast_get_extension_label(struct ast_exten *exten)
Definition: pbx.c:8539
struct ast_exten * ast_walk_extension_priorities(struct ast_exten *exten, struct ast_exten *priority)
Definition: pbx.c:8669
struct ast_exten * ast_walk_context_extensions(struct ast_context *con, struct ast_exten *exten)
Definition: pbx.c:8621
int ast_rdlock_context(struct ast_context *con)
Read locks a given context.
Definition: pbx.c:8511
const char * ast_get_extension_registrar(struct ast_exten *e)
Definition: pbx.c:8557
int total_items
Definition: pbx.c:5450
int total_context
Definition: pbx.c:5451
int context_existence
Definition: pbx.c:5454
int total_exten
Definition: pbx.c:5452
int total_prio
Definition: pbx.c:5453
int extension_existence
Definition: pbx.c:5455

References ast_context_ignorepats_count(), ast_context_ignorepats_get(), ast_context_includes_count(), ast_context_includes_get(), ast_context_switches_count(), ast_context_switches_get(), ast_debug, ast_extension_match(), ast_get_context_name(), ast_get_extension_app(), ast_get_extension_app_data(), ast_get_extension_label(), ast_get_extension_name(), ast_get_extension_priority(), ast_get_extension_registrar(), ast_get_ignorepat_name(), ast_get_ignorepat_registrar(), ast_get_include_name(), ast_get_include_registrar(), ast_get_switch_data(), ast_get_switch_name(), ast_get_switch_registrar(), ast_log, AST_MAX_EXTENSION, AST_PBX_MAX_STACK, ast_rdlock_context(), ast_rdlock_contexts(), ast_strlen_zero(), ast_unlock_context(), ast_unlock_contexts(), ast_walk_context_extensions(), ast_walk_contexts(), ast_walk_extension_priorities(), astman_append(), astman_send_error(), c, voicemailpwcheck::context, dialplan_counters::context_existence, ast_exten::exten, dialplan_counters::extension_existence, LOG_WARNING, manager_dpsendack(), manager_show_dialplan_helper(), NULL, PRIORITY_HINT, dialplan_counters::total_context, dialplan_counters::total_exten, dialplan_counters::total_items, and dialplan_counters::total_prio.

Referenced by manager_show_dialplan(), and manager_show_dialplan_helper().

◆ matchcid()

static int matchcid ( const char *  cidpattern,
const char *  callerid 
)
static

Definition at line 2485 of file pbx.c.

2486{
2487 /* If the Caller*ID pattern is empty, then we're matching NO Caller*ID, so
2488 failing to get a number should count as a match, otherwise not */
2489
2490 if (ast_strlen_zero(callerid)) {
2491 return ast_strlen_zero(cidpattern) ? 1 : 0;
2492 }
2493
2494 return ast_extension_match(cidpattern, callerid);
2495}

References ast_extension_match(), and ast_strlen_zero().

Referenced by pbx_find_extension().

◆ new_find_extension()

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

Definition at line 1251 of file pbx.c.

1252{
1253 struct match_char *p; /* note minimal stack storage requirements */
1254 struct ast_exten pattern = { .label = label };
1255#ifdef DEBUG_THIS
1256 if (tree)
1257 ast_log(LOG_NOTICE,"new_find_extension called with %s on (sub)tree %s action=%s\n", str, tree->x, action2str(action));
1258 else
1259 ast_log(LOG_NOTICE,"new_find_extension called with %s on (sub)tree NULL action=%s\n", str, action2str(action));
1260#endif
1261 for (p = tree; p; p = p->alt_char) {
1262 if (p->is_pattern) {
1263 if (p->x[0] == 'N') {
1264 if (p->x[1] == 0 && *str >= '2' && *str <= '9' ) {
1265#define NEW_MATCHER_CHK_MATCH \
1266 if (p->exten && !MORE(str)) { /* if a shorter pattern matches along the way, might as well report it */ \
1267 if (action == E_MATCH || action == E_SPAWN || action == E_FINDLABEL) { /* if in CANMATCH/MATCHMORE, don't let matches get in the way */ \
1268 update_scoreboard(score, length + 1, spec + p->specificity, p->exten, 0, callerid, p->deleted, p); \
1269 if (!p->deleted) { \
1270 if (action == E_FINDLABEL) { \
1271 if (ast_hashtab_lookup(score->exten->peer_label_table, &pattern)) { \
1272 ast_debug(4, "Found label in preferred extension\n"); \
1273 return; \
1274 } \
1275 } else { \
1276 ast_debug(4, "returning an exact match-- first found-- %s\n", p->exten->name); \
1277 return; /* the first match, by definition, will be the best, because of the sorted tree */ \
1278 } \
1279 } \
1280 } \
1281 }
1282
1283#define NEW_MATCHER_RECURSE \
1284 if (p->next_char && (MORE(str) || (p->next_char->x[0] == '/' && p->next_char->x[1] == 0) \
1285 || p->next_char->x[0] == '!')) { \
1286 if (MORE(str) || p->next_char->x[0] == '!') { \
1287 new_find_extension(ADVANCE(str), score, p->next_char, length + 1, spec + p->specificity, callerid, label, action); \
1288 if (score->exten) { \
1289 ast_debug(4 ,"returning an exact match-- %s\n", score->exten->name); \
1290 return; /* the first match is all we need */ \
1291 } \
1292 } else { \
1293 new_find_extension("/", score, p->next_char, length + 1, spec + p->specificity, callerid, label, action); \
1294 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { \
1295 ast_debug(4,"returning a (can/more) match--- %s\n", score->exten ? score->exten->name : \
1296 "NULL"); \
1297 return; /* the first match is all we need */ \
1298 } \
1299 } \
1300 } else if ((p->next_char || action == E_CANMATCH) && !MORE(str)) { \
1301 score->canmatch = 1; \
1302 score->canmatch_exten = get_canmatch_exten(p); \
1303 if (action == E_CANMATCH || action == E_MATCHMORE) { \
1304 ast_debug(4, "returning a canmatch/matchmore--- str=%s\n", str); \
1305 return; \
1306 } \
1307 }
1308
1311 }
1312 } else if (p->x[0] == 'Z') {
1313 if (p->x[1] == 0 && *str >= '1' && *str <= '9' ) {
1316 }
1317 } else if (p->x[0] == 'X') {
1318 if (p->x[1] == 0 && *str >= '0' && *str <= '9' ) {
1321 }
1322 } else if (p->x[0] == '.' && p->x[1] == 0) {
1323 /* how many chars will the . match against? */
1324 int i = 0;
1325 const char *str2 = str;
1326 while (*str2 && *str2 != '/') {
1327 str2++;
1328 i++;
1329 }
1330 if (p->exten && *str2 != '/') {
1331 update_scoreboard(score, length + i, spec + (i * p->specificity), p->exten, '.', callerid, p->deleted, p);
1332 if (score->exten) {
1333 ast_debug(4, "return because scoreboard has a match with '/'--- %s\n",
1334 score->exten->name);
1335 return; /* the first match is all we need */
1336 }
1337 }
1338 if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) {
1339 new_find_extension("/", score, p->next_char, length + i, spec+(p->specificity*i), callerid, label, action);
1340 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) {
1341 ast_debug(4, "return because scoreboard has exact match OR "
1342 "CANMATCH/MATCHMORE & canmatch set--- %s\n",
1343 score->exten ? score->exten->name : "NULL");
1344 return; /* the first match is all we need */
1345 }
1346 }
1347 } else if (p->x[0] == '!' && p->x[1] == 0) {
1348 /* how many chars will the . match against? */
1349 int i = 1;
1350 const char *str2 = str;
1351 while (*str2 && *str2 != '/') {
1352 str2++;
1353 i++;
1354 }
1355 if (p->exten && *str2 != '/') {
1356 update_scoreboard(score, length + 1, spec + (p->specificity * i), p->exten, '!', callerid, p->deleted, p);
1357 if (score->exten) {
1358 ast_debug(4, "return because scoreboard has a '!' match--- %s\n",
1359 score->exten->name);
1360 return; /* the first match is all we need */
1361 }
1362 }
1363 if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) {
1364 new_find_extension("/", score, p->next_char, length + i, spec + (p->specificity * i), callerid, label, action);
1365 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) {
1366 ast_debug(4, "return because scoreboard has exact match OR "
1367 "CANMATCH/MATCHMORE & canmatch set with '/' and '!'--- %s\n",
1368 score->exten ? score->exten->name : "NULL");
1369 return; /* the first match is all we need */
1370 }
1371 }
1372 } else if (p->x[0] == '/' && p->x[1] == 0) {
1373 /* the pattern in the tree includes the cid match! */
1374 if (p->next_char && callerid && *callerid) {
1375 new_find_extension(callerid, score, p->next_char, length + 1, spec, callerid, label, action);
1376 if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) {
1377 ast_debug(4, "return because scoreboard has exact match OR "
1378 "CANMATCH/MATCHMORE & canmatch set with '/'--- %s\n",
1379 score->exten ? score->exten->name : "NULL");
1380 return; /* the first match is all we need */
1381 }
1382 }
1383 } else if (strchr(p->x, *str)) {
1384 ast_debug(4, "Nothing strange about this match\n");
1387 }
1388 } else if (strchr(p->x, *str)) {
1389 ast_debug(4, "Nothing strange about this match\n");
1392 }
1393 }
1394 ast_debug(4, "return at end of func\n");
1395}
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)
Definition: pbx.c:1084
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)
Definition: pbx.c:1251
#define NEW_MATCHER_RECURSE
#define NEW_MATCHER_CHK_MATCH
int canmatch
Definition: pbx.c:292
struct ast_exten * exten
Definition: pbx.c:295

References match_char::alt_char, ast_debug, ast_log, scoreboard::canmatch, match_char::deleted, E_CANMATCH, E_MATCHMORE, match_char::exten, scoreboard::exten, match_char::is_pattern, ast_exten::label, LOG_NOTICE, ast_exten::name, new_find_extension(), NEW_MATCHER_CHK_MATCH, NEW_MATCHER_RECURSE, match_char::next_char, match_char::specificity, str, update_scoreboard(), and match_char::x.

Referenced by new_find_extension(), and pbx_find_extension().

◆ parse_hint_device()

static char * parse_hint_device ( struct ast_str hint_args)
static

Definition at line 3077 of file pbx.c.

3078{
3079 char *copy = ast_strdupa(ast_str_buffer(hint_args));
3080 char *tmp;
3081
3082 if ((tmp = strrchr(copy, ','))) {
3083 *tmp = '\0';
3084 }
3085
3086 ast_str_set(&hint_args, 0, "%s", copy);
3087 return ast_str_buffer(hint_args);
3088}
static int copy(char *infile, char *outfile)
Utility function to copy a file.

References ast_str_buffer(), ast_str_set(), ast_strdupa, and copy().

Referenced by ast_extension_state3().

◆ parse_hint_presence()

static char * parse_hint_presence ( struct ast_str hint_args)
static

Definition at line 3058 of file pbx.c.

3059{
3060 char *copy = ast_strdupa(ast_str_buffer(hint_args));
3061 char *tmp = "";
3062
3063 if ((tmp = strrchr(copy, ','))) {
3064 *tmp = '\0';
3065 tmp++;
3066 } else {
3067 return NULL;
3068 }
3069 ast_str_set(&hint_args, 0, "%s", tmp);
3070 return ast_str_buffer(hint_args);
3071}

References ast_str_buffer(), ast_str_set(), ast_strdupa, copy(), and NULL.

Referenced by extension_presence_state_helper().

◆ pbx_checkcondition()

int pbx_checkcondition ( const char *  condition)

Evaluate a condition.

Return values
0if the condition is NULL or of zero length
intIf the string is an integer, the integer representation of the integer is returned
1Any other non-empty string

Definition at line 8307 of file pbx.c.

8308{
8309 int res;
8310 if (ast_strlen_zero(condition)) { /* NULL or empty strings are false */
8311 return 0;
8312 } else if (sscanf(condition, "%30d", &res) == 1) { /* Numbers are evaluated for truth */
8313 return res;
8314 } else { /* Strings are true */
8315 return 1;
8316 }
8317}

References ast_strlen_zero().

Referenced by _while_exec(), acf_if(), execif_exec(), gosubif_exec(), if_helper(), pbx_builtin_gotoif(), testtime_write(), and waitforcond_exec().

◆ pbx_destroy()

static void pbx_destroy ( struct ast_pbx p)
static

Definition at line 1005 of file pbx.c.

1006{
1007 ast_free(p);
1008}

References ast_free.

Referenced by __ast_pbx_run().

◆ pbx_dial_reason()

static enum ast_control_frame_type pbx_dial_reason ( enum ast_dial_result  dial_result,
int  cause 
)
static

Attempt to convert disconnect cause to old originate reason.

Todo:
XXX The old originate reasons need to be trashed and replaced with normal disconnect cause codes if the call was not answered. The internal consumers of the reason values would also need to be updated: app_originate, call files, and AMI OriginateResponse.

Definition at line 7706 of file pbx.c.

7707{
7708 enum ast_control_frame_type pbx_reason;
7709
7710 if (dial_result == AST_DIAL_RESULT_ANSWERED) {
7711 /* Remote end answered. */
7712 pbx_reason = AST_CONTROL_ANSWER;
7713 } else if (dial_result == AST_DIAL_RESULT_HANGUP) {
7714 /* Caller hungup */
7715 pbx_reason = AST_CONTROL_HANGUP;
7716 } else {
7717 switch (cause) {
7719 pbx_reason = AST_CONTROL_BUSY;
7720 break;
7727 pbx_reason = AST_CONTROL_CONGESTION;
7728 break;
7731 /* Remote end was ringing (but isn't anymore) */
7732 pbx_reason = AST_CONTROL_RINGING;
7733 break;
7735 default:
7736 /* Call Failure (not BUSY, and not NO_ANSWER, maybe Circuit busy or down?) */
7737 pbx_reason = 0;
7738 break;
7739 }
7740 }
7741
7742 return pbx_reason;
7743}
#define AST_CAUSE_SWITCH_CONGESTION
Definition: causes.h:123
#define AST_CAUSE_UNALLOCATED
Definition: causes.h:98
#define AST_CAUSE_DESTINATION_OUT_OF_ORDER
Definition: causes.h:115
#define AST_CAUSE_NORMAL_TEMPORARY_FAILURE
Definition: causes.h:122
#define AST_CAUSE_NORMAL_CIRCUIT_CONGESTION
Definition: causes.h:120
#define AST_CAUSE_CALL_REJECTED
Definition: causes.h:111
#define AST_CAUSE_NETWORK_OUT_OF_ORDER
Definition: causes.h:121
#define AST_CAUSE_ANSWERED_ELSEWHERE
Definition: causes.h:114
#define AST_CAUSE_NO_ANSWER
Definition: causes.h:109
#define AST_CAUSE_USER_BUSY
Definition: causes.h:107
@ AST_DIAL_RESULT_HANGUP
Definition: dial.h:63
@ AST_DIAL_RESULT_ANSWERED
Definition: dial.h:61
ast_control_frame_type
Internal control frame subtype field values.
@ AST_CONTROL_BUSY
@ AST_CONTROL_CONGESTION
@ AST_CONTROL_ANSWER
@ AST_CONTROL_RINGING
@ AST_CONTROL_HANGUP

References AST_CAUSE_ANSWERED_ELSEWHERE, AST_CAUSE_CALL_REJECTED, AST_CAUSE_DESTINATION_OUT_OF_ORDER, AST_CAUSE_NETWORK_OUT_OF_ORDER, AST_CAUSE_NO_ANSWER, AST_CAUSE_NORMAL_CIRCUIT_CONGESTION, AST_CAUSE_NORMAL_TEMPORARY_FAILURE, AST_CAUSE_SWITCH_CONGESTION, AST_CAUSE_UNALLOCATED, AST_CAUSE_USER_BUSY, AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HANGUP, AST_CONTROL_RINGING, AST_DIAL_RESULT_ANSWERED, and AST_DIAL_RESULT_HANGUP.

Referenced by pbx_outgoing_attempt().

◆ pbx_extension_helper()

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 
)
static

The return value depends on the action:

E_MATCH, E_CANMATCH, E_MATCHMORE require a real match, and return 0 on failure, -1 on match; E_FINDLABEL maps the label to a priority, and returns the priority on success, ... XXX E_SPAWN, spawn an application,

Return values
0on success.
-1on failure.
Note
The channel is auto-serviced in this function, because doing an extension match may block for a long time. For example, if the lookup has to use a network dialplan switch, such as DUNDi or IAX2, it may take a while. However, the channel auto-service code will queue up any important signalling frames to be processed after this is done.

Definition at line 2890 of file pbx.c.

2893{
2894 struct ast_exten *e;
2895 struct ast_app *app;
2896 char *substitute = NULL;
2897 struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */
2898 char passdata[EXT_DATA_SIZE];
2899 int matching_action = (action == E_MATCH || action == E_CANMATCH || action == E_MATCHMORE);
2900
2902
2903 if (!context) {
2904 context = con->name;
2905 }
2906
2907 if (found)
2908 *found = 0;
2909
2910 e = pbx_find_extension(c, con, &q, context, exten, priority, label, callerid, action);
2911 if (e) {
2912 if (found)
2913 *found = 1;
2914 if (matching_action) {
2916 return -1; /* success, we found it */
2917 } else if (action == E_FINDLABEL) { /* map the label to a priority */
2918 int res = e->priority;
2919
2921
2922 /* the priority we were looking for */
2923 return res;
2924 } else { /* spawn */
2925 if (!e->cached_app)
2926 e->cached_app = pbx_findapp(e->app);
2927 app = e->cached_app;
2928 if (ast_strlen_zero(e->data)) {
2929 *passdata = '\0';
2930 } else {
2931 const char *tmp;
2932 if ((!(tmp = strchr(e->data, '$'))) || (!strstr(tmp, "${") && !strstr(tmp, "$["))) {
2933 /* no variables to substitute, copy on through */
2934 ast_copy_string(passdata, e->data, sizeof(passdata));
2935 } else {
2936 /* save e->data on stack for later processing after lock released */
2937 substitute = ast_strdupa(e->data);
2938 }
2939 }
2941 if (!app) {
2942 ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority);
2943 return -1;
2944 }
2948 return 0;
2949 }
2952 if (ast_channel_exten(c) != exten)
2953 ast_channel_exten_set(c, exten);
2956 if (substitute) {
2957 pbx_substitute_variables_helper(c, substitute, passdata, sizeof(passdata)-1);
2958 }
2959 ast_debug(1, "Launching '%s'\n", app_name(app));
2960 if (VERBOSITY_ATLEAST(3)) {
2961 ast_verb(3, "Executing [%s@%s:%d] " COLORIZE_FMT "(\"" COLORIZE_FMT "\", \"" COLORIZE_FMT "\") %s\n",
2962 exten, context, priority,
2965 COLORIZE(COLOR_BRMAGENTA, 0, passdata),
2966 "in new stack");
2967 }
2968 return pbx_exec(c, app, passdata); /* 0 on success, -1 on failure */
2969 }
2970 } else if (q.swo) { /* not found here, but in another switch */
2971 if (found)
2972 *found = 1;
2974 if (matching_action) {
2975 return -1;
2976 } else {
2977 if (!q.swo->exec) {
2978 ast_log(LOG_WARNING, "No execution engine for switch %s\n", q.swo->name);
2979 return -1;
2980 }
2981 return q.swo->exec(c, q.foundcontext ? q.foundcontext : context, exten, priority, callerid, q.data);
2982 }
2983 } else { /* not found anywhere, see what happened */
2985 /* Using S_OR here because Solaris doesn't like NULL being passed to ast_log */
2986 switch (q.status) {
2987 case STATUS_NO_CONTEXT:
2988 if (!matching_action && !combined_find_spawn)
2989 ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", S_OR(context, ""));
2990 break;
2992 if (!matching_action && !combined_find_spawn)
2993 ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, S_OR(context, ""));
2994 break;
2995 case STATUS_NO_PRIORITY:
2996 if (!matching_action && !combined_find_spawn)
2997 ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, S_OR(context, ""));
2998 break;
2999 case STATUS_NO_LABEL:
3000 if (context && !combined_find_spawn)
3001 ast_log(LOG_NOTICE, "No such label '%s' in extension '%s' in context '%s'\n", S_OR(label, ""), exten, S_OR(context, ""));
3002 break;
3003 default:
3004 ast_debug(1, "Shouldn't happen!\n");
3005 }
3006
3007 return (matching_action) ? 0 : -1;
3008 }
3009}
#define VERBOSITY_ATLEAST(level)
#define STATUS_NO_LABEL
Definition: pbx.c:2482
#define STATUS_NO_EXTENSION
Definition: pbx.c:2480
#define STATUS_NO_CONTEXT
Definition: pbx.c:2479
#define EXT_DATA_SIZE
Definition: pbx.c:231
#define STATUS_NO_PRIORITY
Definition: pbx.c:2481
int pbx_exec(struct ast_channel *c, struct ast_app *app, const char *data)
Execute an application.
Definition: pbx_app.c:471
struct ast_app * pbx_findapp(const char *app)
Look up an application.
Definition: ael_main.c:165
const char * app_name(struct ast_app *app)
Definition: pbx_app.c:463
ast_app: A registered application
Definition: pbx_app.c:45
struct ast_app * cached_app
Definition: pbx.c:262
ast_switch_f * exec
Definition: pbx.h:168
const char * name
Definition: pbx.h:163
struct ast_switch * swo
Definition: extconf.h:239
const char * foundcontext
Definition: extconf.h:241
const char * data
Definition: extconf.h:240
#define COLOR_BRCYAN
Definition: term.h:63
#define COLORIZE(fg, bg, str)
Definition: term.h:72
#define COLORIZE_FMT
Shortcut macros for coloring a set of text.
Definition: term.h:71
#define COLOR_BRMAGENTA
Definition: term.h:61

References app, ast_exten::app, app_name(), ast_channel_context(), ast_channel_context_set(), ast_channel_exten(), ast_channel_exten_set(), ast_channel_lock, ast_channel_name(), ast_channel_priority_set(), ast_channel_softhangup_internal_flag(), ast_channel_unlock, ast_copy_string(), ast_debug, ast_log, ast_rdlock_contexts(), AST_SOFTHANGUP_ASYNCGOTO, ast_strdupa, ast_strlen_zero(), ast_unlock_contexts(), ast_verb, c, ast_exten::cached_app, COLOR_BRCYAN, COLOR_BRMAGENTA, COLORIZE, COLORIZE_FMT, voicemailpwcheck::context, pbx_find_info::data, ast_exten::data, E_CANMATCH, E_FINDLABEL, E_MATCH, E_MATCHMORE, ast_switch::exec, EXT_DATA_SIZE, pbx_find_info::foundcontext, LOG_NOTICE, LOG_WARNING, ast_switch::name, ast_context::name, NULL, pbx_exec(), pbx_find_extension(), pbx_findapp(), pbx_substitute_variables_helper(), priority, ast_exten::priority, S_OR, pbx_find_info::stacklen, pbx_find_info::status, STATUS_NO_CONTEXT, STATUS_NO_EXTENSION, STATUS_NO_LABEL, STATUS_NO_PRIORITY, pbx_find_info::swo, and VERBOSITY_ATLEAST.

Referenced by ast_canmatch_extension(), ast_exists_extension(), ast_findlabel_extension(), ast_findlabel_extension2(), ast_matchmore_extension(), and ast_spawn_extension().

◆ pbx_find_extension()

struct ast_exten * pbx_find_extension ( struct ast_channel chan,
struct ast_context bypass,
struct pbx_find_info q,
const char *  context,
const char *  exten,
int  priority,
const char *  label,
const char *  callerid,
enum ext_match_t  action 
)

Definition at line 2497 of file pbx.c.

2501{
2502 int x, res;
2503 struct ast_context *tmp = NULL;
2504 struct ast_exten *e = NULL, *eroot = NULL;
2505 struct ast_exten pattern = {NULL, };
2506 struct scoreboard score = {0, };
2507 struct ast_str *tmpdata = NULL;
2508 int idx;
2509
2510 pattern.label = label;
2511 pattern.priority = priority;
2512#ifdef NEED_DEBUG_HERE
2513 ast_log(LOG_NOTICE, "Looking for cont/ext/prio/label/action = %s/%s/%d/%s/%d\n", context, exten, priority, label, (int) action);
2514#endif
2515
2516 /* Initialize status if appropriate */
2517 if (q->stacklen == 0) {
2519 q->swo = NULL;
2520 q->data = NULL;
2521 q->foundcontext = NULL;
2522 } else if (q->stacklen >= AST_PBX_MAX_STACK) {
2523 ast_log(LOG_WARNING, "Maximum PBX stack (%d) exceeded. Too many includes?\n", AST_PBX_MAX_STACK);
2524 return NULL;
2525 }
2526
2527 /* Check first to see if we've already been checked */
2528 for (x = 0; x < q->stacklen; x++) {
2529 if (!strcasecmp(q->incstack[x], context))
2530 return NULL;
2531 }
2532
2533 if (bypass) { /* bypass means we only look there */
2534 tmp = bypass;
2535 } else { /* look in contexts */
2536 tmp = find_context(context);
2537 if (!tmp) {
2538 return NULL;
2539 }
2540 }
2541
2542 if (q->status < STATUS_NO_EXTENSION)
2544
2545 /* Do a search for matching extension */
2546
2547 eroot = NULL;
2548 score.total_specificity = 0;
2549 score.exten = 0;
2550 score.total_length = 0;
2551 if (!tmp->pattern_tree && tmp->root_table) {
2553#ifdef NEED_DEBUG
2554 ast_debug(1, "Tree Created in context %s:\n", context);
2555 log_match_char_tree(tmp->pattern_tree," ");
2556#endif
2557 }
2558#ifdef NEED_DEBUG
2559 ast_log(LOG_NOTICE, "The Trie we are searching in:\n");
2560 log_match_char_tree(tmp->pattern_tree, ":: ");
2561#endif
2562
2563 do {
2565 char *osw = ast_strdupa(overrideswitch), *name;
2566 struct ast_switch *asw;
2567 ast_switch_f *aswf = NULL;
2568 char *datap;
2569 int eval = 0;
2570
2571 name = strsep(&osw, "/");
2572 asw = pbx_findswitch(name);
2573
2574 if (!asw) {
2575 ast_log(LOG_WARNING, "No such switch '%s'\n", name);
2576 break;
2577 }
2578
2579 if (osw && strchr(osw, '$')) {
2580 eval = 1;
2581 }
2582
2583 if (eval && !(tmpdata = ast_str_thread_get(&switch_data, 512))) {
2584 ast_log(LOG_WARNING, "Can't evaluate overrideswitch?!\n");
2585 break;
2586 } else if (eval) {
2587 /* Substitute variables now */
2588 pbx_substitute_variables_helper(chan, osw, ast_str_buffer(tmpdata), ast_str_size(tmpdata));
2589 datap = ast_str_buffer(tmpdata);
2590 } else {
2591 datap = osw;
2592 }
2593
2594 /* equivalent of extension_match_core() at the switch level */
2595 if (action == E_CANMATCH)
2596 aswf = asw->canmatch;
2597 else if (action == E_MATCHMORE)
2598 aswf = asw->matchmore;
2599 else /* action == E_MATCH */
2600 aswf = asw->exists;
2601 if (!aswf) {
2602 res = 0;
2603 } else {
2604 if (chan) {
2606 }
2607 res = aswf(chan, context, exten, priority, callerid, datap);
2608 if (chan) {
2610 }
2611 }
2612 if (res) { /* Got a match */
2613 q->swo = asw;
2614 q->data = datap;
2615 q->foundcontext = context;
2616 /* XXX keep status = STATUS_NO_CONTEXT ? */
2617 return NULL;
2618 }
2619 }
2620 } while (0);
2621
2623 new_find_extension(exten, &score, tmp->pattern_tree, 0, 0, callerid, label, action);
2624 eroot = score.exten;
2625
2626 if (score.last_char == '!' && action == E_MATCHMORE) {
2627 /* We match an extension ending in '!'.
2628 * The decision in this case is final and is NULL (no match).
2629 */
2630#ifdef NEED_DEBUG_HERE
2631 ast_log(LOG_NOTICE,"Returning MATCHMORE NULL with exclamation point.\n");
2632#endif
2633 return NULL;
2634 }
2635
2636 if (!eroot && (action == E_CANMATCH || action == E_MATCHMORE) && score.canmatch_exten) {
2638#ifdef NEED_DEBUG_HERE
2639 ast_log(LOG_NOTICE,"Returning CANMATCH exten %s\n", score.canmatch_exten->exten);
2640#endif
2641 return score.canmatch_exten;
2642 }
2643
2644 if ((action == E_MATCHMORE || action == E_CANMATCH) && eroot) {
2645 if (score.node) {
2646 struct ast_exten *z = trie_find_next_match(score.node);
2647 if (z) {
2648#ifdef NEED_DEBUG_HERE
2649 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten %s\n", z->exten);
2650#endif
2651 } else {
2652 if (score.canmatch_exten) {
2653#ifdef NEED_DEBUG_HERE
2654 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE canmatchmatch exten %s(%p)\n", score.canmatch_exten->exten, score.canmatch_exten);
2655#endif
2656 return score.canmatch_exten;
2657 } else {
2658#ifdef NEED_DEBUG_HERE
2659 ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten NULL\n");
2660#endif
2661 }
2662 }
2663 return z;
2664 }
2665#ifdef NEED_DEBUG_HERE
2666 ast_log(LOG_NOTICE, "Returning CANMATCH/MATCHMORE NULL (no next_match)\n");
2667#endif
2668 return NULL; /* according to the code, complete matches are null matches in MATCHMORE mode */
2669 }
2670
2671 if (eroot) {
2672 /* found entry, now look for the right priority */
2673 if (q->status < STATUS_NO_PRIORITY)
2675 e = NULL;
2676 if (action == E_FINDLABEL && label ) {
2677 if (q->status < STATUS_NO_LABEL)
2679 e = ast_hashtab_lookup(eroot->peer_label_table, &pattern);
2680 } else {
2681 e = ast_hashtab_lookup(eroot->peer_table, &pattern);
2682 }
2683 if (e) { /* found a valid match */
2685 q->foundcontext = context;
2686#ifdef NEED_DEBUG_HERE
2687 ast_log(LOG_NOTICE,"Returning complete match of exten %s\n", e->exten);
2688#endif
2689 return e;
2690 }
2691 }
2692 } else { /* the old/current default exten pattern match algorithm */
2693
2694 /* scan the list trying to match extension and CID */
2695 eroot = NULL;
2696 while ( (eroot = ast_walk_context_extensions(tmp, eroot)) ) {
2697 int match = extension_match_core(eroot->exten, exten, action);
2698 /* 0 on fail, 1 on match, 2 on earlymatch */
2699
2700 if (!match || (eroot->matchcid && !matchcid(eroot->cidmatch, callerid)))
2701 continue; /* keep trying */
2702 if (match == 2 && action == E_MATCHMORE) {
2703 /* We match an extension ending in '!'.
2704 * The decision in this case is final and is NULL (no match).
2705 */
2706 return NULL;
2707 }
2708 /* found entry, now look for the right priority */
2709 if (q->status < STATUS_NO_PRIORITY)
2711 e = NULL;
2712 if (action == E_FINDLABEL && label ) {
2713 if (q->status < STATUS_NO_LABEL)
2715 e = ast_hashtab_lookup(eroot->peer_label_table, &pattern);
2716 } else {
2717 e = ast_hashtab_lookup(eroot->peer_table, &pattern);
2718 }
2719 if (e) { /* found a valid match */
2721 q->foundcontext = context;
2722 return e;
2723 }
2724 }
2725 }
2726
2727 /* Check alternative switches */
2728 for (idx = 0; idx < ast_context_switches_count(tmp); idx++) {
2729 const struct ast_sw *sw = ast_context_switches_get(tmp, idx);
2731 ast_switch_f *aswf = NULL;
2732 const char *datap;
2733
2734 if (!asw) {
2735 ast_log(LOG_WARNING, "No such switch '%s'\n", ast_get_switch_name(sw));
2736 continue;
2737 }
2738
2739 /* Substitute variables now */
2740 if (ast_get_switch_eval(sw)) {
2741 if (!(tmpdata = ast_str_thread_get(&switch_data, 512))) {
2742 ast_log(LOG_WARNING, "Can't evaluate switch?!\n");
2743 continue;
2744 }
2746 ast_str_buffer(tmpdata), ast_str_size(tmpdata));
2747 datap = ast_str_buffer(tmpdata);
2748 } else {
2749 datap = ast_get_switch_data(sw);
2750 }
2751
2752 /* equivalent of extension_match_core() at the switch level */
2753 if (action == E_CANMATCH)
2754 aswf = asw->canmatch;
2755 else if (action == E_MATCHMORE)
2756 aswf = asw->matchmore;
2757 else /* action == E_MATCH */
2758 aswf = asw->exists;
2759 if (!aswf)
2760 res = 0;
2761 else {
2762 if (chan)
2764 res = aswf(chan, context, exten, priority, callerid, datap);
2765 if (chan)
2767 }
2768 if (res) { /* Got a match */
2769 q->swo = asw;
2770 q->data = datap;
2771 q->foundcontext = context;
2772 /* XXX keep status = STATUS_NO_CONTEXT ? */
2773 return NULL;
2774 }
2775 }
2776 /* Technically we should be using tmp->name here, but if we used that we
2777 * would have to cast away the constness of the 'name' pointer and I do
2778 * not want to do that. */
2779 q->incstack[q->stacklen++] = tmp->data; /* Setup the stack */
2780 /* Now try any includes we have in this context */
2781 for (idx = 0; idx < ast_context_includes_count(tmp); idx++) {
2782 const struct ast_include *i = ast_context_includes_get(tmp, idx);
2783
2784 if (include_valid(i)) {
2785 if ((e = pbx_find_extension(chan, bypass, q, include_rname(i), exten, priority, label, callerid, action))) {
2786#ifdef NEED_DEBUG_HERE
2787 ast_log(LOG_NOTICE,"Returning recursive match of %s\n", e->exten);
2788#endif
2789 return e;
2790 }
2791 if (q->swo)
2792 return NULL;
2793 }
2794 }
2795 return NULL;
2796}
int ast_autoservice_stop(struct ast_channel *chan)
Stop servicing a channel for us...
Definition: autoservice.c:266
int ast_autoservice_start(struct ast_channel *chan)
Automatically service a channel for us...
Definition: autoservice.c:200
static struct ast_exten * trie_find_next_match(struct match_char *node)
Definition: pbx.c:1180
static struct ast_threadstorage switch_data
Definition: pbx.c:243
static int extenpatternmatchnew
Definition: pbx.c:784
static void create_match_char_tree(struct ast_context *con)
Definition: pbx.c:1785
static char * overrideswitch
Definition: pbx.c:785
static int matchcid(const char *cidpattern, const char *callerid)
Definition: pbx.c:2485
#define STATUS_SUCCESS
Definition: pbx.c:2483
int() ast_switch_f(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
All switch functions have the same interface, so define a type for them.
Definition: pbx.h:157
int include_valid(const struct ast_include *inc)
Definition: pbx_include.c:65
struct ast_switch * pbx_findswitch(const char *sw)
Definition: pbx_switch.c:40
size_t ast_str_size(const struct ast_str *buf)
Returns the current maximum length (without reallocation) of the current buffer.
Definition: strings.h:742
ast_switch_f * canmatch
Definition: pbx.h:167
ast_switch_f * exists
Definition: pbx.h:166
ast_switch_f * matchmore
Definition: pbx.h:169
char * incstack[AST_PBX_MAX_STACK]
Definition: extconf.h:236
int total_length
Definition: pbx.c:290
int total_specificity
Definition: pbx.c:289
char last_char
Definition: pbx.c:291
struct match_char * node
Definition: pbx.c:293
struct ast_exten * canmatch_exten
Definition: pbx.c:294

References ast_autoservice_start(), ast_autoservice_stop(), ast_context_includes_count(), ast_context_includes_get(), ast_context_switches_count(), ast_context_switches_get(), ast_debug, ast_get_switch_data(), ast_get_switch_eval(), ast_get_switch_name(), ast_hashtab_lookup(), ast_log, AST_PBX_MAX_STACK, ast_str_buffer(), ast_str_size(), ast_str_thread_get(), ast_strdupa, ast_strlen_zero(), ast_walk_context_extensions(), ast_switch::canmatch, scoreboard::canmatch_exten, voicemailpwcheck::context, create_match_char_tree(), pbx_find_info::data, ast_context::data, E_CANMATCH, E_FINDLABEL, E_MATCHMORE, ast_switch::exists, ast_exten::exten, scoreboard::exten, extenpatternmatchnew, extension_match_core(), find_context(), pbx_find_info::foundcontext, include_rname(), include_valid(), pbx_find_info::incstack, ast_exten::label, scoreboard::last_char, LOG_NOTICE, LOG_WARNING, match(), matchcid(), ast_switch::matchmore, name, new_find_extension(), scoreboard::node, NULL, overrideswitch, ast_context::pattern_tree, pbx_find_extension(), pbx_findswitch(), pbx_substitute_variables_helper(), priority, ast_exten::priority, ast_context::root_table, pbx_find_info::stacklen, pbx_find_info::status, STATUS_NO_CONTEXT, STATUS_NO_EXTENSION, STATUS_NO_LABEL, STATUS_NO_PRIORITY, STATUS_SUCCESS, strsep(), switch_data, pbx_find_info::swo, scoreboard::total_length, scoreboard::total_specificity, and trie_find_next_match().

Referenced by ast_get_extension_data(), ast_hint_extension_nolock(), ast_merge_contexts_and_delete(), pbx_extension_helper(), and pbx_find_extension().

◆ pbx_outgoing_attempt()

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

Definition at line 7745 of file pbx.c.

7751{
7753 struct ast_channel *dialed;
7754 pthread_t thread;
7755 char tmp_cid_name[128];
7756 char tmp_cid_num[128];
7757
7759 if (!outgoing) {
7760 return -1;
7761 }
7762 ast_cond_init(&outgoing->cond, NULL);
7763
7764 if (!ast_strlen_zero(app)) {
7766 outgoing->appdata = ast_strdup(appdata);
7767 } else {
7771 }
7772
7773 if (!(outgoing->dial = ast_dial_create())) {
7774 return -1;
7775 }
7776
7777 if (ast_dial_append(outgoing->dial, type, addr, assignedids)) {
7778 return -1;
7779 }
7780
7781 ast_dial_set_global_timeout(outgoing->dial, timeout);
7782
7783 if (!ast_strlen_zero(predial_callee)) {
7784 /* note casting to void * here to suppress compiler warning message (passing const to non-const function) */
7785 ast_dial_option_global_enable(outgoing->dial, AST_DIAL_OPTION_PREDIAL, (void *)predial_callee);
7786 }
7787
7788 if (ast_dial_prerun(outgoing->dial, NULL, cap)) {
7789 if (synchronous && reason) {
7791 ast_dial_reason(outgoing->dial, 0));
7792 }
7793 return -1;
7794 }
7795
7797 if (!dialed) {
7798 return -1;
7799 }
7800
7802 if (vars) {
7804 }
7805 if (!ast_strlen_zero(account)) {
7807 ast_channel_accountcode_set(dialed, account);
7808 ast_channel_peeraccount_set(dialed, account);
7810 }
7812
7813 if (!ast_strlen_zero(predial_callee)) {
7814 char *tmp = NULL;
7815 /*
7816 * The predial sub routine may have set callerid so set this into the new channel
7817 * Note... cid_num and cid_name parameters to this function will always be NULL if
7818 * predial_callee is non-NULL so we are not overwriting anything here.
7819 */
7821 if (tmp) {
7822 ast_copy_string(tmp_cid_num, tmp, sizeof(tmp_cid_num));
7823 cid_num = tmp_cid_num;
7824 }
7826 if (tmp) {
7827 ast_copy_string(tmp_cid_name, tmp, sizeof(tmp_cid_name));
7828 cid_name = tmp_cid_name;
7829 }
7830 }
7832
7833 if (!ast_strlen_zero(cid_num) || !ast_strlen_zero(cid_name)) {
7835
7836 /*
7837 * It seems strange to set the CallerID on an outgoing call leg
7838 * to whom we are calling, but this function's callers are doing
7839 * various Originate methods. This call leg goes to the local
7840 * user. Once the called party answers, the dialplan needs to
7841 * be able to access the CallerID from the CALLERID function as
7842 * if the called party had placed this call.
7843 */
7844 ast_set_callerid(dialed, cid_num, cid_name, cid_num);
7845
7847 if (!ast_strlen_zero(cid_num)) {
7848 connected.id.number.valid = 1;
7849 connected.id.number.str = (char *) cid_num;
7851 }
7852 if (!ast_strlen_zero(cid_name)) {
7853 connected.id.name.valid = 1;
7854 connected.id.name.str = (char *) cid_name;
7856 }
7858 }
7859
7860 if (early_media) {
7862 }
7863
7864 if (locked_channel) {
7865 /*
7866 * Keep a dialed channel ref since the caller wants
7867 * the channel returned. We must get the ref before
7868 * spawning off pbx_outgoing_exec().
7869 */
7870 ast_channel_ref(dialed);
7871 if (!synchronous) {
7872 /*
7873 * Lock it now to hold off pbx_outgoing_exec() in case the
7874 * calling function needs the channel state/snapshot before
7875 * dialing actually happens.
7876 */
7877 ast_channel_lock(dialed);
7878 }
7879 }
7880
7881 /* This extra reference is dereferenced by pbx_outgoing_exec */
7882 ao2_ref(outgoing, +1);
7883
7884 if (synchronous == AST_OUTGOING_WAIT_COMPLETE) {
7885 /*
7886 * Because we are waiting until this is complete anyway, there is no
7887 * sense in creating another thread that we will just need to wait
7888 * for, so instead we commandeer the current thread.
7889 */
7891 } else {
7892 outgoing->in_separate_thread = 1;
7893
7895 ast_log(LOG_WARNING, "Unable to spawn dialing thread for '%s/%s'\n", type, addr);
7896 ao2_ref(outgoing, -1);
7897 if (locked_channel) {
7898 if (!synchronous) {
7899 ast_channel_unlock(dialed);
7900 }
7901 ast_channel_unref(dialed);
7902 }
7903 return -1;
7904 }
7905
7906 if (synchronous) {
7908 /* Wait for dialing to complete */
7909 while (!outgoing->dialed) {
7911 }
7913 }
7914 }
7915
7916 if (synchronous) {
7917 /* Determine the outcome of the dialing attempt up to it being answered. */
7918 if (reason) {
7919 *reason = pbx_dial_reason(outgoing->dial_res,
7920 ast_dial_reason(outgoing->dial, 0));
7921 }
7922
7923 if (outgoing->dial_res != AST_DIAL_RESULT_ANSWERED) {
7924 /* The dial operation failed. */
7925 if (locked_channel) {
7926 ast_channel_unref(dialed);
7927 }
7928 return -1;
7929 }
7930 if (locked_channel) {
7931 ast_channel_lock(dialed);
7932 }
7933 }
7934
7935 if (locked_channel) {
7936 *locked_channel = dialed;
7937 }
7938 return 0;
7939}
pthread_t thread
Definition: app_sla.c:335
void * ao2_object_get_lockaddr(void *obj)
Return the mutex lock address of an object.
Definition: astobj2.c:476
#define AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED
Definition: callerid.h:437
void ast_channel_set_connected_line(struct ast_channel *chan, const struct ast_party_connected_line *connected, const struct ast_set_party_connected_line *update)
Set the connected line information in the Asterisk channel.
Definition: channel.c:8322
struct ast_party_connected_line * ast_channel_connected(struct ast_channel *chan)
@ AST_FLAG_ORIGINATED
Definition: channel.h:1059
void ast_set_callerid(struct ast_channel *chan, const char *cid_num, const char *cid_name, const char *cid_ani)
Set caller ID number, name and ANI and generate AMI event.
Definition: channel.c:7316
void ast_party_connected_line_set_init(struct ast_party_connected_line *init, const struct ast_party_connected_line *guide)
Initialize the given connected line structure using the given guide for a set update operation.
Definition: channel.c:2013
@ AST_DIAL_RESULT_FAILED
Definition: dial.h:56
void ast_dial_set_state_callback(struct ast_dial *dial, ast_dial_state_callback callback)
Set a callback for state changes.
Definition: dial.c:1269
int ast_dial_append(struct ast_dial *dial, const char *tech, const char *device, const struct ast_assigned_ids *assignedids)
Append a channel.
Definition: dial.c:280
struct ast_dial * ast_dial_create(void)
New dialing structure.
Definition: dial.c:223
int ast_dial_prerun(struct ast_dial *dial, struct ast_channel *chan, struct ast_format_cap *cap)
Request all appended channels, but do not dial.
Definition: dial.c:431
void ast_dial_set_global_timeout(struct ast_dial *dial, int timeout)
Set the maximum time (globally) allowed for trying to ring phones.
Definition: dial.c:1284
int ast_dial_reason(struct ast_dial *dial, int num)
Get the reason an outgoing channel has failed.
Definition: dial.c:1247
@ AST_DIAL_OPTION_PREDIAL
Definition: dial.h:47
struct ast_channel * ast_dial_get_channel(struct ast_dial *dial, int num)
Get the dialing channel, if prerun has been executed.
Definition: dial.c:1258
int ast_dial_option_global_enable(struct ast_dial *dial, enum ast_dial_option option, void *data)
Enables an option globally.
Definition: dial.c:1145
char connected
Definition: eagi_proxy.c:82
void ast_channel_stage_snapshot_done(struct ast_channel *chan)
Clear flag to indicate channel snapshot is being staged, and publish snapshot.
void ast_channel_stage_snapshot(struct ast_channel *chan)
Set flag to indicate channel snapshot is being staged.
#define ast_cond_wait(cond, mutex)
Definition: lock.h:212
#define ast_cond_init(cond, attr)
Definition: lock.h:208
static void pbx_outgoing_state_callback(struct ast_dial *dial)
Internal dialing state callback which causes early media to trigger an answer.
Definition: pbx.c:7680
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.
Definition: pbx.c:7706
static void * pbx_outgoing_exec(void *data)
Internal function which dials an outgoing leg and sends it to a provided extension or application.
Definition: pbx.c:7617
static void pbx_outgoing_destroy(void *obj)
Destructor for outgoing structure.
Definition: pbx.c:7603
@ AST_OUTGOING_WAIT_COMPLETE
Definition: pbx.h:1145
struct ast_party_dialed dialed
Dialed/Called information.
Connected Line/Party information.
Definition: channel.h:458
const ast_string_field app
Definition: pbx_spool.c:95
const ast_string_field context
Definition: pbx_spool.c:95
const ast_string_field exten
Definition: pbx_spool.c:95
int priority
Definition: pbx_spool.c:96
Structure which contains information about an outgoing dial.
Definition: pbx.c:7579
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:978

References ao2_alloc, ao2_cleanup, ao2_lock, ao2_object_get_lockaddr(), ao2_ref, ao2_unlock, app, outgoing::app, ast_channel_caller(), ast_channel_connected(), ast_channel_flags(), ast_channel_lock, ast_channel_ref, ast_channel_set_connected_line(), ast_channel_stage_snapshot(), ast_channel_stage_snapshot_done(), ast_channel_unlock, ast_channel_unref, ast_cond_init, ast_cond_wait, ast_copy_string(), ast_dial_append(), ast_dial_create(), ast_dial_get_channel(), ast_dial_option_global_enable(), AST_DIAL_OPTION_PREDIAL, ast_dial_prerun(), ast_dial_reason(), AST_DIAL_RESULT_ANSWERED, AST_DIAL_RESULT_FAILED, ast_dial_set_global_timeout(), ast_dial_set_state_callback(), AST_FLAG_ORIGINATED, ast_log, AST_OUTGOING_WAIT_COMPLETE, ast_party_connected_line_set_init(), AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED, ast_pthread_create_detached, ast_set_callerid(), ast_set_flag, ast_set_variables(), ast_strdup, ast_strlen_zero(), connected, voicemailpwcheck::context, outgoing::context, ast_channel::dialed, ast_channel::exten, outgoing::exten, LOG_WARNING, name, NULL, pbx_dial_reason(), pbx_outgoing_destroy(), pbx_outgoing_exec(), pbx_outgoing_state_callback(), priority, outgoing::priority, RAII_VAR, S_COR, thread, and type.

Referenced by ast_pbx_outgoing_app_predial(), and ast_pbx_outgoing_exten_predial().

◆ pbx_outgoing_destroy()

static void pbx_outgoing_destroy ( void *  obj)
static

Destructor for outgoing structure.

Definition at line 7603 of file pbx.c.

7604{
7605 struct pbx_outgoing *outgoing = obj;
7606
7607 if (outgoing->dial) {
7609 }
7610
7611 ast_cond_destroy(&outgoing->cond);
7612
7613 ast_free(outgoing->appdata);
7614}
int ast_dial_destroy(struct ast_dial *dial)
Destroys a dialing structure.
Definition: dial.c:1091
#define ast_cond_destroy(cond)
Definition: lock.h:209

References ast_cond_destroy, ast_dial_destroy(), and ast_free.

Referenced by pbx_outgoing_attempt().

◆ pbx_outgoing_exec()

static void * pbx_outgoing_exec ( void *  data)
static

Internal function which dials an outgoing leg and sends it to a provided extension or application.

Definition at line 7617 of file pbx.c.

7618{
7619 RAII_VAR(struct pbx_outgoing *, outgoing, data, ao2_cleanup);
7620 enum ast_dial_result res;
7621 struct ast_channel *chan;
7622
7623 res = ast_dial_run(outgoing->dial, NULL, 0);
7624
7625 if (outgoing->in_separate_thread) {
7626 /* Notify anyone interested that dialing is complete */
7628 outgoing->dial_res = res;
7629 outgoing->dialed = 1;
7630 ast_cond_signal(&outgoing->cond);
7632 } else {
7633 /* We still need the dial result, but we don't need to lock */
7634 outgoing->dial_res = res;
7635 }
7636
7637 /* If the outgoing leg was not answered we can immediately return and go no further */
7638 if (res != AST_DIAL_RESULT_ANSWERED) {
7639 return NULL;
7640 }
7641
7642 /* We steal the channel so we get ownership of when it is hung up */
7643 chan = ast_dial_answered_steal(outgoing->dial);
7644
7645 if (!ast_strlen_zero(outgoing->app)) {
7646 struct ast_app *app = pbx_findapp(outgoing->app);
7647
7648 if (app) {
7649 ast_verb(4, "Launching %s(%s) on %s\n", outgoing->app, S_OR(outgoing->appdata, ""),
7650 ast_channel_name(chan));
7651 pbx_exec(chan, app, outgoing->appdata);
7652 } else {
7653 ast_log(LOG_WARNING, "No such application '%s'\n", outgoing->app);
7654 }
7655
7656 ast_hangup(chan);
7657 } else {
7660 }
7661
7664 }
7665
7666 if (outgoing->priority > 0) {
7668 }
7669
7670 if (ast_pbx_run(chan)) {
7671 ast_log(LOG_ERROR, "Failed to start PBX on %s\n", ast_channel_name(chan));
7672 ast_hangup(chan);
7673 }
7674 }
7675
7676 return NULL;
7677}
ast_dial_result
List of return codes for dial run API calls.
Definition: dial.h:54
enum ast_dial_result ast_dial_run(struct ast_dial *dial, struct ast_channel *chan, int async)
Execute dialing synchronously or asynchronously.
Definition: dial.c:935
struct ast_channel * ast_dial_answered_steal(struct ast_dial *dial)
Steal the channel that answered.
Definition: dial.c:989
#define ast_cond_signal(cond)
Definition: lock.h:210

References ao2_cleanup, ao2_lock, ao2_unlock, app, outgoing::app, ast_channel_context_set(), ast_channel_exten_set(), ast_channel_name(), ast_channel_priority_set(), ast_cond_signal, ast_dial_answered_steal(), AST_DIAL_RESULT_ANSWERED, ast_dial_run(), ast_hangup(), ast_log, ast_pbx_run(), ast_strlen_zero(), ast_verb, outgoing::context, outgoing::exten, LOG_ERROR, LOG_WARNING, NULL, pbx_exec(), pbx_findapp(), outgoing::priority, RAII_VAR, and S_OR.

Referenced by pbx_outgoing_attempt().

◆ pbx_outgoing_state_callback()

static void pbx_outgoing_state_callback ( struct ast_dial dial)
static

Internal dialing state callback which causes early media to trigger an answer.

Definition at line 7680 of file pbx.c.

7681{
7682 struct ast_channel *channel;
7683
7685 return;
7686 }
7687
7688 if (!(channel = ast_dial_get_channel(dial, 0))) {
7689 return;
7690 }
7691
7692 ast_verb(4, "Treating progress as answer on '%s' due to early media option\n",
7693 ast_channel_name(channel));
7694
7696}
int ast_queue_control(struct ast_channel *chan, enum ast_control_frame_type control)
Queue a control frame without payload.
Definition: channel.c:1270
enum ast_dial_result ast_dial_state(struct ast_dial *dial)
Return state of dial.
Definition: dial.c:1008
@ AST_DIAL_RESULT_PROGRESS
Definition: dial.h:59

References ast_channel_name(), AST_CONTROL_ANSWER, ast_dial_get_channel(), AST_DIAL_RESULT_PROGRESS, ast_dial_state(), ast_queue_control(), and ast_verb.

Referenced by pbx_outgoing_attempt().

◆ pbx_parse_location()

int pbx_parse_location ( struct ast_channel chan,
char **  context,
char **  exten,
char **  pri,
int *  ipri,
int *  mode,
char *  rest 
)

Parses a dialplan location into context, extension, priority.

Parameters
chanChannel to execute on
contextPointer to initial value for context.
extenPointer to initial value for exten.
priPointer to initial value for pri
ipriPointer to integer value of priority
modePointer to mode (or NULL if mode is not used)
restPointer to buffer to capture rest of parsing (or NULL if not used)

strsep should be used to initially populate context, exten, and pri prior to calling this function. All arguments are modified in place.

Return values
0success
non-zerofailure

Definition at line 8816 of file pbx.c.

8817{
8818 char *context, *exten, *pri;
8819 /* do the strsep before here, so we don't have to alloc and free */
8820 if (!*extenp) {
8821 /* Only a priority in this one */
8822 *prip = *contextp;
8823 *extenp = NULL;
8824 *contextp = NULL;
8825 } else if (!*prip) {
8826 /* Only an extension and priority in this one */
8827 *prip = *extenp;
8828 *extenp = *contextp;
8829 *contextp = NULL;
8830 }
8831 context = *contextp;
8832 exten = *extenp;
8833 pri = *prip;
8834 if (mode) {
8835 if (*pri == '+') {
8836 *mode = 1;
8837 pri++;
8838 } else if (*pri == '-') {
8839 *mode = -1;
8840 pri++;
8841 }
8842 }
8843 if ((rest && sscanf(pri, "%30d%1s", ipri, rest) != 1) || sscanf(pri, "%30d", ipri) != 1) {
8845 exten ? exten : ast_channel_exten(chan), pri,
8846 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL));
8847 if (*ipri < 1) {
8848 ast_log(LOG_WARNING, "Priority '%s' must be a number > 0, or valid label\n", pri);
8849 return -1;
8850 } else if (mode) {
8851 *mode = 0;
8852 }
8853 }
8854 return 0;
8855}
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.
Definition: pbx.c:4201

References ast_channel_caller(), ast_channel_context(), ast_channel_exten(), ast_findlabel_extension(), ast_log, voicemailpwcheck::context, ast_channel::exten, LOG_WARNING, NULL, and S_COR.

Referenced by eval_exten_read(), and pbx_parseable_goto().

◆ pbx_parseable_goto()

static int pbx_parseable_goto ( struct ast_channel chan,
const char *  goto_string,
int  async 
)
static

Definition at line 8857 of file pbx.c.

8858{
8859 char *exten, *pri, *context;
8860 char *stringp;
8861 int ipri;
8862 int mode = 0;
8863 char rest[2] = "";
8864
8865 if (ast_strlen_zero(goto_string)) {
8866 ast_log(LOG_WARNING, "Goto requires an argument ([[context,]extension,]priority)\n");
8867 return -1;
8868 }
8869 stringp = ast_strdupa(goto_string);
8870 context = strsep(&stringp, ","); /* guaranteed non-null */
8871 exten = strsep(&stringp, ",");
8872 pri = strsep(&stringp, ",");
8873
8874 if (pbx_parse_location(chan, &context, &exten, &pri, &ipri, &mode, rest)) {
8875 return -1;
8876 }
8877 /* At this point we have a priority and maybe an extension and a context */
8878
8879 if (mode)
8880 ipri = ast_channel_priority(chan) + (ipri * mode);
8881
8882 if (async)
8883 ast_async_goto(chan, context, exten, ipri);
8884 else
8885 ast_explicit_goto(chan, context, exten, ipri);
8886
8887 return 0;
8888
8889}
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.
Definition: pbx.c:8816

References ast_async_goto(), ast_channel_priority(), ast_explicit_goto(), ast_log, ast_strdupa, ast_strlen_zero(), voicemailpwcheck::context, ast_channel::exten, LOG_WARNING, pbx_parse_location(), and strsep().

Referenced by ast_async_parseable_goto(), and ast_parseable_goto().

◆ pbx_set_autofallthrough()

int pbx_set_autofallthrough ( int  newval)

Set "autofallthrough" flag, if newval is <0, does not actually set. If set to 1, sets to auto fall through. If newval set to 0, sets to no auto fall through (reads extension instead). Returns previous value.

Definition at line 4791 of file pbx.c.

4792{
4793 int oldval = autofallthrough;
4794 autofallthrough = newval;
4795 return oldval;
4796}

References autofallthrough.

Referenced by pbx_load_module().

◆ pbx_set_extenpatternmatchnew()

int pbx_set_extenpatternmatchnew ( int  newval)

Set "extenpatternmatchnew" flag, if newval is <0, does not actually set. If set to 1, sets to use the new Trie-based pattern matcher. If newval set to 0, sets to use the old linear-search algorithm. Returns previous value.

Definition at line 4798 of file pbx.c.

4799{
4800 int oldval = extenpatternmatchnew;
4801 extenpatternmatchnew = newval;
4802 return oldval;
4803}

References extenpatternmatchnew.

Referenced by AST_TEST_DEFINE(), handle_set_extenpatternmatchnew(), handle_unset_extenpatternmatchnew(), and pbx_load_module().

◆ pbx_set_overrideswitch()

void pbx_set_overrideswitch ( const char *  newval)

Set "overrideswitch" field. If set and of nonzero length, all contexts will be tried directly through the named switch prior to any other matching within that context.

Since
1.6.1

Definition at line 4805 of file pbx.c.

4806{
4807 if (overrideswitch) {
4809 }
4810 if (!ast_strlen_zero(newval)) {
4811 overrideswitch = ast_strdup(newval);
4812 } else {
4814 }
4815}

References ast_free, ast_strdup, ast_strlen_zero(), NULL, and overrideswitch.

Referenced by pbx_load_module().

◆ pbx_shutdown()

static void pbx_shutdown ( void  )
static

Definition at line 8941 of file pbx.c.

8942{
8943 STASIS_MESSAGE_TYPE_CLEANUP(hint_change_message_type);
8944 STASIS_MESSAGE_TYPE_CLEANUP(hint_remove_message_type);
8945
8946 if (hints) {
8947 ao2_container_unregister("hints");
8948 ao2_ref(hints, -1);
8949 hints = NULL;
8950 }
8951 if (hintdevices) {
8952 ao2_container_unregister("hintdevices");
8953 ao2_ref(hintdevices, -1);
8954 hintdevices = NULL;
8955 }
8956 if (autohints) {
8957 ao2_container_unregister("autohints");
8958 ao2_ref(autohints, -1);
8959 autohints = NULL;
8960 }
8961 if (statecbs) {
8962 ao2_container_unregister("statecbs");
8963 ao2_ref(statecbs, -1);
8964 statecbs = NULL;
8965 }
8966 if (contexts_table) {
8968 }
8969}
void ao2_container_unregister(const char *name)
Unregister a container for CLI stats and integrity check.
#define STASIS_MESSAGE_TYPE_CLEANUP(name)
Boiler-plate messaging macro for cleaning up message types.
Definition: stasis.h:1515

References ao2_container_unregister(), ao2_ref, ast_hashtab_destroy(), autohints, contexts_table, hintdevices, NULL, STASIS_MESSAGE_TYPE_CLEANUP, and statecbs.

Referenced by ast_pbx_init().

◆ pbx_thread()

static void * pbx_thread ( void *  data)
static

Definition at line 4709 of file pbx.c.

4710{
4711 /* Oh joyous kernel, we're a new thread, with nothing to do but
4712 answer this channel and get it going.
4713 */
4714 /* NOTE:
4715 The launcher of this function _MUST_ increment 'countcalls'
4716 before invoking the function; it will be decremented when the
4717 PBX has finished running on the channel
4718 */
4719 struct ast_channel *c = data;
4720
4723
4724 pthread_exit(NULL);
4725
4726 return NULL;
4727}
const char * data

References __ast_pbx_run(), c, ast_channel::data, decrease_call_count(), and NULL.

Referenced by ast_pbx_start().

◆ presence_state_cb()

static void presence_state_cb ( void *  unused,
struct stasis_subscription sub,
struct stasis_message msg 
)
static

Definition at line 8319 of file pbx.c.

8320{
8321 struct ast_presence_state_message *presence_state;
8322 struct ast_str *hint_app = NULL;
8323 struct ast_hintdevice *device;
8324 struct ast_hintdevice *cmpdevice;
8325 struct ao2_iterator *dev_iter;
8326
8328 return;
8329 }
8330
8331 presence_state = stasis_message_data(msg);
8332
8333 if (ao2_container_count(hintdevices) == 0) {
8334 /* There are no hints monitoring devices. */
8335 return;
8336 }
8337
8338 hint_app = ast_str_create(1024);
8339 if (!hint_app) {
8340 return;
8341 }
8342
8343 cmpdevice = ast_alloca(sizeof(*cmpdevice) + strlen(presence_state->provider));
8344 strcpy(cmpdevice->hintdevice, presence_state->provider);
8345
8346 ast_mutex_lock(&context_merge_lock);/* Hold off ast_merge_contexts_and_delete */
8347 dev_iter = ao2_t_callback(hintdevices,
8350 cmpdevice,
8351 "find devices in container");
8352 if (!dev_iter) {
8354 ast_free(hint_app);
8355 return;
8356 }
8357
8358 for (; (device = ao2_iterator_next(dev_iter)); ao2_t_ref(device, -1, "Next device")) {
8359 if (device->hint) {
8360 presence_state_notify_callbacks(device->hint, &hint_app, presence_state);
8361 }
8362 }
8363 ao2_iterator_destroy(dev_iter);
8365
8366 ast_free(hint_app);
8367}
#define OBJ_POINTER
Definition: astobj2.h:1150

References ao2_container_count(), ao2_iterator_destroy(), ao2_iterator_next, ao2_t_callback, ao2_t_ref, ast_alloca, ast_free, ast_mutex_lock, ast_mutex_unlock, ast_presence_state_message_type(), ast_str_create, context_merge_lock, ast_hintdevice::hint, ast_hintdevice::hintdevice, hintdevice_cmp_multiple(), hintdevices, NULL, OBJ_MULTIPLE, OBJ_POINTER, presence_state_notify_callbacks(), stasis_message_data(), and stasis_message_type().

Referenced by load_pbx().

◆ presence_state_notify_callbacks()

static void presence_state_notify_callbacks ( struct ast_hint hint,
struct ast_str **  hint_app,
struct ast_presence_state_message presence_state 
)
static

Definition at line 3485 of file pbx.c.

3487{
3488 struct ao2_iterator cb_iter;
3489 struct ast_state_cb *state_cb;
3492
3493 ao2_lock(hint);
3494 if (!hint->exten) {
3495 /* The extension has already been destroyed */
3496 ao2_unlock(hint);
3497 return;
3498 }
3499
3500 /*
3501 * Save off strings in case the hint extension gets destroyed
3502 * while we are notifying the watchers.
3503 */
3506 sizeof(context_name));
3508 sizeof(exten_name));
3509 ast_str_set(hint_app, 0, "%s", ast_get_extension_app(hint->exten));
3510 ao2_unlock(hint);
3511
3512 /* Check to see if update is necessary */
3513 if ((hint->last_presence_state == presence_state->state) &&
3514 ((hint->last_presence_subtype && presence_state->subtype &&
3515 !strcmp(hint->last_presence_subtype, presence_state->subtype)) ||
3516 (!hint->last_presence_subtype && !presence_state->subtype)) &&
3517 ((hint->last_presence_message && presence_state->message &&
3518 !strcmp(hint->last_presence_message, presence_state->message)) ||
3519 (!hint->last_presence_message && !presence_state->message))) {
3520 /* this update is the same as the last, do nothing */
3521 return;
3522 }
3523
3524 /* update new values */
3527 hint->last_presence_state = presence_state->state;
3528 hint->last_presence_subtype = presence_state->subtype ? ast_strdup(presence_state->subtype) : NULL;
3529 hint->last_presence_message = presence_state->message ? ast_strdup(presence_state->message) : NULL;
3530
3531 /* For general callbacks */
3532 cb_iter = ao2_iterator_init(statecbs, 0);
3533 for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_ref(state_cb, -1)) {
3536 exten_name,
3537 state_cb->data,
3539 hint,
3540 NULL);
3541 }
3542 ao2_iterator_destroy(&cb_iter);
3543
3544 /* For extension callbacks */
3545 cb_iter = ao2_iterator_init(hint->callbacks, 0);
3546 for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_cleanup(state_cb)) {
3549 exten_name,
3550 state_cb->data,
3552 hint,
3553 NULL);
3554 }
3555 ao2_iterator_destroy(&cb_iter);
3556}

References ao2_cleanup, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ast_copy_string(), ast_free, ast_get_context_name(), ast_get_extension_app(), ast_get_extension_context(), ast_get_extension_name(), AST_HINT_UPDATE_PRESENCE, AST_MAX_CONTEXT, AST_MAX_EXTENSION, ast_str_set(), ast_strdup, ast_hint::callbacks, ast_state_cb::change_cb, context_name, ast_state_cb::data, execute_state_callback(), ast_hint::exten, exten_name, ast_hint::last_presence_message, ast_hint::last_presence_state, ast_hint::last_presence_subtype, NULL, ast_presence_state_message::state, and statecbs.

Referenced by handle_hint_change_message_type(), and presence_state_cb().

◆ print_autohint_key()

static void print_autohint_key ( void *  v_obj,
void *  where,
ao2_prnt_fn prnt 
)
static

Definition at line 8994 of file pbx.c.

8995{
8996 struct ast_autohint *autohint = v_obj;
8997
8998 if (!autohint) {
8999 return;
9000 }
9001 prnt(where, "%s", autohint->context);
9002}

References ast_autohint::context.

Referenced by ast_pbx_init().

◆ print_ext()

static void print_ext ( struct ast_exten e,
char *  buf,
int  buflen 
)
static

helper function to print an extension

Definition at line 5459 of file pbx.c.

5460{
5461 int prio = ast_get_extension_priority(e);
5462 if (prio == PRIORITY_HINT) {
5463 snprintf(buf, buflen, "hint: %s",
5465 } else {
5466 snprintf(buf, buflen, "%d. %s(%s)",
5467 prio, ast_get_extension_app(e),
5469 }
5470}

References ast_get_extension_app(), ast_get_extension_app_data(), ast_get_extension_priority(), ast_strlen_zero(), buf, and PRIORITY_HINT.

Referenced by show_dialplan_helper().

◆ print_hintdevices_key()

static void print_hintdevices_key ( void *  v_obj,
void *  where,
ao2_prnt_fn prnt 
)
static

Definition at line 8982 of file pbx.c.

8983{
8984 struct ast_hintdevice *hintdevice = v_obj;
8985
8986 if (!hintdevice) {
8987 return;
8988 }
8989 prnt(where, "%s => %s@%s", hintdevice->hintdevice,
8990 ast_get_extension_name(hintdevice->hint->exten),
8992}

References ast_get_context_name(), ast_get_extension_context(), ast_get_extension_name(), and ast_hintdevice::hintdevice.

Referenced by ast_pbx_init().

◆ print_hints_key()

static void print_hints_key ( void *  v_obj,
void *  where,
ao2_prnt_fn prnt 
)
static

Definition at line 8971 of file pbx.c.

8972{
8973 struct ast_hint *hint = v_obj;
8974
8975 if (!hint) {
8976 return;
8977 }
8978 prnt(where, "%s@%s", ast_get_extension_name(hint->exten),
8980}

References ast_get_context_name(), ast_get_extension_context(), ast_get_extension_name(), and ast_hint::exten.

Referenced by ast_pbx_init().

◆ print_statecbs_key()

static void print_statecbs_key ( void *  v_obj,
void *  where,
ao2_prnt_fn prnt 
)
static

Definition at line 9004 of file pbx.c.

9005{
9006 struct ast_state_cb *state_cb = v_obj;
9007
9008 if (!state_cb) {
9009 return;
9010 }
9011 prnt(where, "%d", state_cb->id);
9012}

References ast_state_cb::id.

Referenced by ast_pbx_init().

◆ publish_hint_change()

static int publish_hint_change ( struct ast_hint hint,
struct ast_exten ne 
)
static

Publish a hint changed event

Definition at line 4091 of file pbx.c.

4092{
4093 struct stasis_message *message;
4094
4095 if (!hint_change_message_type()) {
4096 return -1;
4097 }
4098
4099 if (!(message = stasis_message_create(hint_change_message_type(), hint))) {
4100 ao2_ref(hint, -1);
4101 return -1;
4102 }
4103
4106
4107 ao2_ref(message, -1);
4108
4109 return 0;
4110}
struct stasis_message * stasis_message_create(struct stasis_message_type *type, void *data)
Create a new message.
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic's subscribers.
Definition: stasis.c:1578

References ao2_ref, ast_device_state_topic_all(), ast_presence_state_topic_all(), stasis_message_create(), and stasis_publish().

Referenced by ast_change_hint().

◆ publish_hint_remove()

static int publish_hint_remove ( struct ast_hint hint)
static

Publish a hint removed event

Definition at line 3941 of file pbx.c.

3942{
3943 struct stasis_message *message;
3944
3945 if (!hint_remove_message_type()) {
3946 return -1;
3947 }
3948
3949 if (!(message = stasis_message_create(hint_remove_message_type(), hint))) {
3950 ao2_ref(hint, -1);
3951 return -1;
3952 }
3953
3955
3956 ao2_ref(message, -1);
3957
3958 return 0;
3959}

References ao2_ref, ast_device_state_topic_all(), stasis_message_create(), and stasis_publish().

Referenced by ast_remove_hint().

◆ raise_exception()

int raise_exception ( struct ast_channel chan,
const char *  reason,
int  priority 
)

pbx.c functions needed by pbx_builtins.c

Definition at line 2821 of file pbx.c.

2822{
2824 struct pbx_exception *exception = NULL;
2825
2826 if (!ds) {
2828 if (!ds)
2829 return -1;
2830 if (!(exception = ast_calloc_with_stringfields(1, struct pbx_exception, 128))) {
2832 return -1;
2833 }
2834 ds->data = exception;
2835 ast_channel_datastore_add(chan, ds);
2836 } else
2837 exception = ds->data;
2838
2839 ast_string_field_set(exception, reason, reason);
2841 ast_string_field_set(exception, exten, ast_channel_exten(chan));
2842 exception->priority = ast_channel_priority(chan);
2843 set_ext_pri(chan, "e", priority);
2844 return 0;
2845}
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2355
#define ast_datastore_alloc(info, uid)
Definition: datastore.h:85
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:68
#define ast_calloc_with_stringfields(n, type, size)
Allocate a structure with embedded stringfields in a single allocation.
Definition: stringfields.h:432
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:521

References ast_calloc_with_stringfields, ast_channel_context(), ast_channel_datastore_add(), ast_channel_datastore_find(), ast_channel_exten(), ast_channel_priority(), ast_datastore_alloc, ast_datastore_free(), ast_string_field_set, voicemailpwcheck::context, ast_datastore::data, exception_store_info, pbx_exception::exten, NULL, priority, pbx_exception::priority, pbx_exception::reason, and set_ext_pri().

Referenced by __ast_pbx_run(), pbx_builtin_raise_exception(), and pbx_builtin_waitexten().

◆ remove_hintdevice()

static int remove_hintdevice ( struct ast_hint hint)
static

Definition at line 539 of file pbx.c.

540{
541 while (AST_VECTOR_SIZE(&hint->devices) > 0) {
542 char *device = AST_VECTOR_GET(&hint->devices, 0);
543
545 hintdevice_remove_cb, device, hint, "Remove device from container");
547 ast_free(device);
548 }
549
550 return 0;
551}
#define ao2_t_callback_data(container, flags, cb_fn, arg, data, tag)
ao2_callback_data() is a generic function that applies cb_fn() to all objects in a container....
Definition: astobj2.h:1721
static int hintdevice_remove_cb(void *obj, void *arg, void *data, int flags)
Definition: pbx.c:526
#define AST_VECTOR_REMOVE_UNORDERED(vec, idx)
Remove an element from an unordered vector by index.
Definition: vector.h:449

References ao2_t_callback_data, ast_free, AST_VECTOR_GET, AST_VECTOR_REMOVE_UNORDERED, AST_VECTOR_SIZE, ast_hint::devices, hintdevice_remove_cb(), hintdevices, OBJ_NODATA, OBJ_SEARCH_KEY, and OBJ_UNLINK.

Referenced by ast_change_hint(), and ast_remove_hint().

◆ set_ext_pri()

void set_ext_pri ( struct ast_channel c,
const char *  exten,
int  pri 
)

helper function to set extension and priority

Definition at line 4285 of file pbx.c.

4286{
4288 ast_channel_exten_set(c, exten);
4291}

References ast_channel_exten_set(), ast_channel_lock, ast_channel_priority_set(), ast_channel_unlock, c, and ast_exten::exten.

Referenced by __ast_pbx_run(), pbx_builtin_waitexten(), and raise_exception().

◆ show_debug_helper()

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

Definition at line 5649 of file pbx.c.

5650{
5651 struct ast_context *c = NULL;
5652 int res = 0, old_total_exten = dpc->total_exten;
5653
5654 ast_cli(fd,"\n In-mem exten Trie for Fast Extension Pattern Matching:\n\n");
5655
5656 ast_cli(fd,"\n Explanation: Node Contents Format = <char(s) to match>:<pattern?>:<specif>:[matched extension]\n");
5657 ast_cli(fd, " Where <char(s) to match> is a set of chars, any one of which should match the current character\n");
5658 ast_cli(fd, " <pattern?>: Y if this a pattern match (eg. _XZN[5-7]), N otherwise\n");
5659 ast_cli(fd, " <specif>: an assigned 'exactness' number for this matching char. The lower the number, the more exact the match\n");
5660 ast_cli(fd, " [matched exten]: If all chars matched to this point, which extension this matches. In form: EXTEN:<exten string>\n");
5661 ast_cli(fd, " In general, you match a trie node to a string character, from left to right. All possible matching chars\n");
5662 ast_cli(fd, " are in a string vertically, separated by an unbroken string of '+' characters.\n\n");
5664
5665 /* walk all contexts ... */
5666 while ( (c = ast_walk_contexts(c)) ) {
5667 int context_info_printed = 0;
5668
5669 if (context && strcmp(ast_get_context_name(c), context))
5670 continue; /* skip this one, name doesn't match */
5671
5672 dpc->context_existence = 1;
5673
5674 if (!c->pattern_tree) {
5675 /* Ignore check_return warning from Coverity for ast_exists_extension below */
5676 ast_exists_extension(NULL, c->name, "s", 1, ""); /* do this to force the trie to built, if it is not already */
5677 }
5678
5680
5681 dpc->total_context++;
5682 ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
5684 context_info_printed = 1;
5685
5686 if (c->pattern_tree)
5687 {
5688 cli_match_char_tree(c->pattern_tree, " ", fd);
5689 } else {
5690 ast_cli(fd,"\n No Pattern Trie present. Perhaps the context is empty...or there is trouble...\n\n");
5691 }
5692
5694
5695 /* if we print something in context, make an empty line */
5696 if (context_info_printed)
5697 ast_cli(fd, "\n");
5698 }
5700
5701 return (dpc->total_exten == old_total_exten) ? -1 : res;
5702}
const char * ast_get_context_registrar(struct ast_context *c)
Definition: pbx.c:8552
const char * name

References ast_cli(), ast_exists_extension(), ast_get_context_name(), ast_get_context_registrar(), ast_rdlock_context(), ast_rdlock_contexts(), ast_unlock_context(), ast_unlock_contexts(), ast_walk_contexts(), c, cli_match_char_tree(), voicemailpwcheck::context, dialplan_counters::context_existence, test_val::name, NULL, dialplan_counters::total_context, and dialplan_counters::total_exten.

Referenced by handle_debug_dialplan().

◆ show_dialplan_helper()

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

Definition at line 5488 of file pbx.c.

5489{
5490 struct ast_context *c = NULL;
5491 int res = 0, old_total_exten = dpc->total_exten;
5492
5494
5495 /* walk all contexts ... */
5496 while ( (c = ast_walk_contexts(c)) ) {
5497 int idx;
5498 struct ast_exten *e;
5499#ifndef LOW_MEMORY
5500 char buf[1024], buf2[1024];
5501#else
5502 char buf[256], buf2[256];
5503#endif
5504 int context_info_printed = 0;
5505
5506 if (context && strcmp(ast_get_context_name(c), context))
5507 continue; /* skip this one, name doesn't match */
5508
5509 dpc->context_existence = 1;
5510
5512
5513 /* are we looking for exten too? if yes, we print context
5514 * only if we find our extension.
5515 * Otherwise print context even if empty ?
5516 * XXX i am not sure how the rinclude is handled.
5517 * I think it ought to go inside.
5518 */
5519 if (!exten) {
5520 dpc->total_context++;
5521 ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
5523 if (c->autohints) {
5524 ast_cli(fd, "Autohints support enabled\n");
5525 }
5526 context_info_printed = 1;
5527 }
5528
5529 /* walk extensions ... */
5530 e = NULL;
5531 while ( (e = ast_walk_context_extensions(c, e)) ) {
5532 struct ast_exten *p;
5533
5535 continue; /* skip, extension match failed */
5536
5537 dpc->extension_existence = 1;
5538
5539 /* may we print context info? */
5540 if (!context_info_printed) {
5541 dpc->total_context++;
5542 if (rinclude) { /* TODO Print more info about rinclude */
5543 ast_cli(fd, "[ Included context '%s' created by '%s' ]\n",
5545 } else {
5546 ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
5548 if (c->autohints) {
5549 ast_cli(fd, "Autohints support enabled\n");
5550 }
5551 }
5552 context_info_printed = 1;
5553 }
5554 dpc->total_prio++;
5555
5556 /* write extension name and first peer */
5557 if (e->matchcid == AST_EXT_MATCHCID_ON)
5558 snprintf(buf, sizeof(buf), "'%s' (CID match '%s') => ", ast_get_extension_name(e), e->cidmatch);
5559 else
5560 snprintf(buf, sizeof(buf), "'%s' =>", ast_get_extension_name(e));
5561
5562 print_ext(e, buf2, sizeof(buf2));
5563
5565
5566 dpc->total_exten++;
5567 /* walk next extension peers */
5568 p = e; /* skip the first one, we already got it */
5569 while ( (p = ast_walk_extension_priorities(e, p)) ) {
5570 const char *el = ast_get_extension_label(p);
5571 dpc->total_prio++;
5572 if (el)
5573 snprintf(buf, sizeof(buf), " [%s]", el);
5574 else
5575 buf[0] = '\0';
5576 print_ext(p, buf2, sizeof(buf2));
5577
5579 }
5580 }
5581
5582 /* walk included and write info ... */
5583 for (idx = 0; idx < ast_context_includes_count(c); idx++) {
5584 const struct ast_include *i = ast_context_includes_get(c, idx);
5585
5586 snprintf(buf, sizeof(buf), "'%s'", ast_get_include_name(i));
5587 if (exten) {
5588 /* Check all includes for the requested extension */
5589 if (includecount >= AST_PBX_MAX_STACK) {
5590 ast_log(LOG_WARNING, "Maximum include depth exceeded!\n");
5591 } else {
5592 int dupe = 0;
5593 int x;
5594 for (x = 0; x < includecount; x++) {
5595 if (!strcasecmp(includes[x], ast_get_include_name(i))) {
5596 dupe++;
5597 break;
5598 }
5599 }
5600 if (!dupe) {
5601 includes[includecount] = ast_get_include_name(i);
5602 show_dialplan_helper(fd, ast_get_include_name(i), exten, dpc, i, includecount + 1, includes);
5603 } else {
5604 ast_log(LOG_WARNING, "Avoiding circular include of %s within %s\n", ast_get_include_name(i), context);
5605 }
5606 }
5607 } else {
5608 ast_cli(fd, " Include => %-45s [%s]\n",
5610 }
5611 }
5612
5613 /* walk ignore patterns and write info ... */
5614 for (idx = 0; idx < ast_context_ignorepats_count(c); idx++) {
5615 const struct ast_ignorepat *ip = ast_context_ignorepats_get(c, idx);
5616 const char *ipname = ast_get_ignorepat_name(ip);
5617 char ignorepat[AST_MAX_EXTENSION];
5618
5619 snprintf(buf, sizeof(buf), "'%s'", ipname);
5620 snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname);
5621 if (!exten || ast_extension_match(ignorepat, exten)) {
5622 ast_cli(fd, " Ignore pattern => %-45s [%s]\n",
5624 }
5625 }
5626 if (!rinclude) {
5627 for (idx = 0; idx < ast_context_switches_count(c); idx++) {
5628 const struct ast_sw *sw = ast_context_switches_get(c, idx);
5629
5630 snprintf(buf, sizeof(buf), "'%s/%s'",
5633 ast_cli(fd, " Alt. Switch => %-45s [%s]\n",
5635 }
5636 }
5637
5639
5640 /* if we print something in context, make an empty line */
5641 if (context_info_printed)
5642 ast_cli(fd, "\n");
5643 }
5645
5646 return (dpc->total_exten == old_total_exten) ? -1 : res;
5647}
static struct ast_threadstorage buf2
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.
Definition: pbx.c:5473
static void print_ext(struct ast_exten *e, char *buf, int buflen)
helper function to print an extension
Definition: pbx.c:5459

References ast_cli(), ast_context_ignorepats_count(), ast_context_ignorepats_get(), ast_context_includes_count(), ast_context_includes_get(), ast_context_switches_count(), ast_context_switches_get(), AST_EXT_MATCHCID_ON, ast_extension_match(), ast_get_context_name(), ast_get_context_registrar(), ast_get_extension_label(), ast_get_extension_name(), ast_get_ignorepat_name(), ast_get_ignorepat_registrar(), ast_get_include_name(), ast_get_include_registrar(), ast_get_switch_data(), ast_get_switch_name(), ast_get_switch_registrar(), ast_log, AST_MAX_EXTENSION, AST_PBX_MAX_STACK, ast_rdlock_context(), ast_rdlock_contexts(), ast_unlock_context(), ast_unlock_contexts(), ast_walk_context_extensions(), ast_walk_contexts(), ast_walk_extension_priorities(), buf, buf2, c, ast_exten::cidmatch, voicemailpwcheck::context, dialplan_counters::context_existence, el, ast_exten::exten, dialplan_counters::extension_existence, LOG_WARNING, ast_exten::matchcid, NULL, print_ext(), show_dialplan_helper(), show_dialplan_helper_extension_output(), dialplan_counters::total_context, dialplan_counters::total_exten, and dialplan_counters::total_prio.

Referenced by handle_show_dialplan(), and show_dialplan_helper().

◆ show_dialplan_helper_extension_output()

static void show_dialplan_helper_extension_output ( int  fd,
char *  buf1,
char *  buf2,
struct ast_exten exten 
)
static

Writes CLI output of a single extension for show dialplan.

Definition at line 5473 of file pbx.c.

5474{
5476 ast_cli(fd, " %-17s %-45s [%s:%d]\n",
5477 buf1, buf2,
5480 return;
5481 }
5482
5483 ast_cli(fd, " %-17s %-45s [%s]\n",
5485}
static struct ast_threadstorage buf1
int ast_get_extension_registrar_line(struct ast_exten *e)
Get line number of configuration file used by registrar to register this extension.
Definition: pbx.c:8567
const char * ast_get_extension_registrar_file(struct ast_exten *e)
Get name of configuration file used by registrar to register this extension.
Definition: pbx.c:8562

References ast_cli(), ast_get_extension_registrar(), ast_get_extension_registrar_file(), ast_get_extension_registrar_line(), buf1, and buf2.

Referenced by show_dialplan_helper().

◆ STASIS_MESSAGE_TYPE_DEFN_LOCAL() [1/2]

STASIS_MESSAGE_TYPE_DEFN_LOCAL ( hint_change_message_type  )

◆ STASIS_MESSAGE_TYPE_DEFN_LOCAL() [2/2]

STASIS_MESSAGE_TYPE_DEFN_LOCAL ( hint_remove_message_type  )

◆ statecbs_cmp()

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

Definition at line 8929 of file pbx.c.

8930{
8931 const struct ast_state_cb *state_cb = obj;
8933
8934 return (state_cb->change_cb == change_cb) ? CMP_MATCH | CMP_STOP : 0;
8935}
int(* ast_state_cb_type)(const char *context, const char *exten, struct ast_state_cb_info *info, void *data)
Typedef for devicestate and hint callbacks.
Definition: pbx.h:112

References ast_state_cb::change_cb, CMP_MATCH, and CMP_STOP.

Referenced by ast_pbx_init().

◆ trie_find_next_match()

static struct ast_exten * trie_find_next_match ( struct match_char node)
static

Definition at line 1180 of file pbx.c.

1181{
1182 struct match_char *m3;
1183 struct match_char *m4;
1184 struct ast_exten *e3;
1185
1186 if (node && node->x[0] == '.' && !node->x[1]) { /* dot and ! will ALWAYS be next match in a matchmore */
1187 return node->exten;
1188 }
1189
1190 if (node && node->x[0] == '!' && !node->x[1]) {
1191 return node->exten;
1192 }
1193
1194 if (!node || !node->next_char) {
1195 return NULL;
1196 }
1197
1198 m3 = node->next_char;
1199
1200 if (m3->exten) {
1201 return m3->exten;
1202 }
1203 for (m4 = m3->alt_char; m4; m4 = m4->alt_char) {
1204 if (m4->exten) {
1205 return m4->exten;
1206 }
1207 }
1208 for (m4 = m3; m4; m4 = m4->alt_char) {
1209 e3 = trie_find_next_match(m3);
1210 if (e3) {
1211 return e3;
1212 }
1213 }
1214
1215 return NULL;
1216}

References match_char::alt_char, match_char::exten, NULL, and trie_find_next_match().

Referenced by pbx_find_extension(), and trie_find_next_match().

◆ unload_pbx()

static void unload_pbx ( void  )
static

Definition at line 8434 of file pbx.c.

8435{
8438
8439 ast_manager_unregister("ShowDialPlan");
8440 ast_manager_unregister("ExtensionStateList");
8444}
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition: manager.c:7698
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
struct stasis_subscription * stasis_unsubscribe_and_join(struct stasis_subscription *subscription)
Cancel a subscription, blocking until the last message is processed.
Definition: stasis.c:1201

References ARRAY_LEN, ast_cli_unregister_multiple(), ast_custom_function_unregister(), ast_manager_unregister(), device_state_sub, exception_function, pbx_cli, presence_state_sub, stasis_unsubscribe_and_join(), and testtime_function.

Referenced by load_pbx().

◆ unreference_cached_app()

void unreference_cached_app ( struct ast_app app)

pbx.c function needed by pbx_app.c

Definition at line 6151 of file pbx.c.

6152{
6153 struct ast_context *context = NULL;
6154 struct ast_exten *eroot = NULL, *e = NULL;
6155
6157 while ((context = ast_walk_contexts(context))) {
6158 while ((eroot = ast_walk_context_extensions(context, eroot))) {
6159 while ((e = ast_walk_extension_priorities(eroot, e))) {
6160 if (e->cached_app == app)
6161 e->cached_app = NULL;
6162 }
6163 }
6164 }
6166
6167 return;
6168}

References app, ast_rdlock_contexts(), ast_unlock_contexts(), ast_walk_context_extensions(), ast_walk_contexts(), ast_walk_extension_priorities(), voicemailpwcheck::context, and NULL.

Referenced by ast_unregister_application().

◆ update_scoreboard()

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 
)
static

Definition at line 1084 of file pbx.c.

1085{
1086 /* if this extension is marked as deleted, then skip this -- if it never shows
1087 on the scoreboard, it will never be found, nor will halt the traversal. */
1088 if (deleted)
1089 return;
1090 board->total_specificity = spec;
1091 board->total_length = length;
1092 board->exten = exten;
1093 board->last_char = last;
1094 board->node = node;
1095#ifdef NEED_DEBUG_HERE
1096 ast_log(LOG_NOTICE,"Scoreboarding (LONGER) %s, len=%d, score=%d\n", exten->exten, length, spec);
1097#endif
1098}

References ast_log, ast_exten::exten, scoreboard::exten, last, scoreboard::last_char, LOG_NOTICE, scoreboard::node, scoreboard::total_length, and scoreboard::total_specificity.

Referenced by new_find_extension().

◆ wait_for_hangup()

void wait_for_hangup ( struct ast_channel chan,
const void *  data 
)

Definition at line 8253 of file pbx.c.

8254{
8255 int res;
8256 struct ast_frame *f;
8257 double waitsec;
8258 int waittime;
8259
8260 if (ast_strlen_zero(data) || (sscanf(data, "%30lg", &waitsec) != 1) || (waitsec < 0))
8261 waitsec = -1;
8262 if (waitsec > -1) {
8263 waittime = waitsec * 1000.0;
8264 ast_safe_sleep_without_silence(chan, waittime);
8265 } else do {
8266 res = ast_waitfor(chan, -1);
8267 if (res < 0)
8268 return;
8269 f = ast_read(chan);
8270 if (f)
8271 ast_frfree(f);
8272 } while(f);
8273}
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3132
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4223
int ast_safe_sleep_without_silence(struct ast_channel *chan, int ms)
Wait for a specified amount of time, looking for hangups, and do not generate silence.
Definition: channel.c:1547
#define ast_frfree(fr)
Data structure associated with a single frame of data.
union ast_frame::@231 data

References ast_frfree, ast_read(), ast_safe_sleep_without_silence(), ast_strlen_zero(), ast_waitfor(), and ast_frame::data.

Referenced by indicate_busy(), and indicate_congestion().

Variable Documentation

◆ autofallthrough

int autofallthrough = 1
static

Definition at line 783 of file pbx.c.

Referenced by __ast_pbx_run(), and pbx_set_autofallthrough().

◆ autohints

struct ao2_container* autohints
static

Container for autohint contexts.

Definition at line 402 of file pbx.c.

Referenced by ast_pbx_init(), context_table_create_autohints(), device_state_cb(), and pbx_shutdown().

◆ conlock

ast_mutex_t conlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
static

Lock for the ast_context list.

Note
This lock MUST be recursive, or a deadlock on reload may result. See https://issues.asterisk.org/view.php?id=17643

Definition at line 805 of file pbx.c.

Referenced by ast_rdlock_contexts(), ast_unlock_contexts(), and ast_wrlock_contexts().

◆ context_merge_lock

ast_mutex_t context_merge_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
static

Lock to hold off restructuring of hints by ast_merge_contexts_and_delete.

Definition at line 810 of file pbx.c.

Referenced by ast_change_hint(), ast_merge_contexts_and_delete(), device_state_cb(), and presence_state_cb().

◆ contexts

struct ast_context* contexts
static

◆ contexts_table

struct ast_hashtab* contexts_table = NULL
static

◆ countcalls

int countcalls
static

Definition at line 793 of file pbx.c.

Referenced by ast_active_calls(), decrease_call_count(), and increase_call_count().

◆ device_state_sub

struct stasis_subscription* device_state_sub
static

Subscription for device state change events.

Definition at line 788 of file pbx.c.

Referenced by load_pbx(), and unload_pbx().

◆ exception_function

struct ast_custom_function exception_function
static
Initial value:
= {
.name = "EXCEPTION",
}
static int acf_exception_read(struct ast_channel *chan, const char *name, char *data, char *buf, size_t buflen)
Definition: pbx.c:2847

Definition at line 2867 of file pbx.c.

Referenced by load_pbx(), and unload_pbx().

◆ exception_store_info

const struct ast_datastore_info exception_store_info
static
Initial value:
= {
.type = "EXCEPTION",
}
static void exception_store_free(void *data)
Definition: pbx.c:2798

Definition at line 2805 of file pbx.c.

Referenced by acf_exception_read(), and raise_exception().

◆ extenpatternmatchnew

int extenpatternmatchnew = 0
static

Definition at line 784 of file pbx.c.

Referenced by pbx_find_extension(), and pbx_set_extenpatternmatchnew().

◆ extension_states

const struct cfextension_states extension_states[]
static

Referenced by ast_extension_state2str().

◆ extensionstate_buf

struct ast_threadstorage extensionstate_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_extensionstate_buf , .custom_init = NULL , }
static

Definition at line 244 of file pbx.c.

Referenced by ast_extension_state2(), and extension_presence_state_helper().

◆ hintdevice_data

struct ast_threadstorage hintdevice_data = { .once = PTHREAD_ONCE_INIT , .key_init = __init_hintdevice_data , .custom_init = NULL , }
static

Definition at line 374 of file pbx.c.

Referenced by add_hintdevice().

◆ hintdevices

struct ao2_container* hintdevices
static

Container for hint devices.

Definition at line 385 of file pbx.c.

Referenced by add_hintdevice(), ast_pbx_init(), device_state_cb(), pbx_shutdown(), presence_state_cb(), and remove_hintdevice().

◆ hints

struct ao2_container* hints
static
Note
When holding this container's lock, do not do anything that will cause conlock to be taken, unless you already hold it. The ast_merge_contexts_and_delete function will take the locks in conlock/hints order, so any other paths that require both locks must also take them in that order.

Definition at line 821 of file pbx.c.

Referenced by lua_register_hints(), and pvalExtenSetHints().

◆ maxcalllock

ast_mutex_t maxcalllock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
static

Definition at line 792 of file pbx.c.

Referenced by decrease_call_count(), and increase_call_count().

◆ overrideswitch

char* overrideswitch = NULL
static

Definition at line 785 of file pbx.c.

Referenced by handle_cli_dialplan_save(), pbx_find_extension(), and pbx_set_overrideswitch().

◆ pbx_cli

struct ast_cli_entry pbx_cli[]
static

Definition at line 6136 of file pbx.c.

Referenced by load_pbx(), and unload_pbx().

◆ presence_state_sub

struct stasis_subscription* presence_state_sub
static

Subscription for presence state change events.

Definition at line 790 of file pbx.c.

Referenced by load_pbx(), and unload_pbx().

◆ statecbs

struct ao2_container* statecbs
static

◆ stateid

int stateid = 1
static

Definition at line 812 of file pbx.c.

Referenced by extension_state_add_destroy().

◆ switch_data

struct ast_threadstorage switch_data = { .once = PTHREAD_ONCE_INIT , .key_init = __init_switch_data , .custom_init = NULL , }
static

Definition at line 243 of file pbx.c.

Referenced by pbx_find_extension().

◆ testtime_function

struct ast_custom_function testtime_function
static
Initial value:
= {
.name = "TESTTIME",
.write = testtime_write,
}
static int testtime_write(struct ast_channel *chan, const char *cmd, char *var, const char *value)
Definition: pbx.c:8278

Definition at line 8302 of file pbx.c.

Referenced by load_pbx(), and unload_pbx().

◆ totalcalls

int totalcalls
static

Definition at line 794 of file pbx.c.

Referenced by ast_processed_calls(), increase_call_count(), and timing_read().