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

Core PBX routines. More...

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

Go to the source code of this file.

Data Structures

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

Macros

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

Functions

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

Variables

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

Detailed Description

Core PBX routines.

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

Definition in file pbx.c.

Macro Definition Documentation

◆ ADVANCE

#define ADVANCE (   s)    candidate_exten_advance(s)

Definition at line 1234 of file pbx.c.

◆ BITS_PER

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

◆ EXT_DATA_SIZE

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

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

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

Definition at line 216 of file pbx.c.

◆ HASH_EXTENHINT_SIZE

#define HASH_EXTENHINT_SIZE   563

Definition at line 365 of file pbx.c.

◆ HINTDEVICE_DATA_LENGTH

#define HINTDEVICE_DATA_LENGTH   16

Definition at line 358 of file pbx.c.

◆ INC_DST_OVERFLOW_CHECK

#define INC_DST_OVERFLOW_CHECK

◆ MAX_EXTENBUF_SIZE

#define MAX_EXTENBUF_SIZE   512

Definition at line 1662 of file pbx.c.

◆ MORE

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

Definition at line 1233 of file pbx.c.

◆ NEW_MATCHER_CHK_MATCH

#define NEW_MATCHER_CHK_MATCH

◆ NEW_MATCHER_RECURSE

#define NEW_MATCHER_RECURSE

◆ SAY_STUBS

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

Definition at line 57 of file pbx.c.

◆ STATUS_NO_CONTEXT

#define STATUS_NO_CONTEXT   1

Definition at line 2464 of file pbx.c.

◆ STATUS_NO_EXTENSION

#define STATUS_NO_EXTENSION   2

Definition at line 2465 of file pbx.c.

◆ STATUS_NO_LABEL

#define STATUS_NO_LABEL   4

Definition at line 2467 of file pbx.c.

◆ STATUS_NO_PRIORITY

#define STATUS_NO_PRIORITY   3

Definition at line 2466 of file pbx.c.

◆ STATUS_SUCCESS

#define STATUS_SUCCESS   5

Definition at line 2468 of file pbx.c.

◆ SWITCH_DATA_LENGTH

#define SWITCH_DATA_LENGTH   256

Definition at line 219 of file pbx.c.

◆ VAR_HARDTRAN

#define VAR_HARDTRAN   3

Definition at line 223 of file pbx.c.

◆ VAR_NORMAL

#define VAR_NORMAL   1

Definition at line 221 of file pbx.c.

◆ VAR_SOFTTRAN

#define VAR_SOFTTRAN   2

Definition at line 222 of file pbx.c.

Function Documentation

◆ __ast_context_destroy()

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

Definition at line 8056 of file pbx.c.

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

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

Referenced by ast_context_destroy().

◆ __ast_goto_if_exists()

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

Definition at line 8760 of file pbx.c.

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

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

Referenced by ast_async_goto_if_exists(), and ast_goto_if_exists().

◆ __ast_internal_context_destroy()

static void __ast_internal_context_destroy ( struct ast_context con)
static

Definition at line 8015 of file pbx.c.

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

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

Referenced by __ast_context_destroy(), and ast_merge_contexts_and_delete().

◆ __ast_pbx_run()

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

Definition at line 4306 of file pbx.c.

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

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

Referenced by ast_pbx_run_args(), and pbx_thread().

◆ __init_extensionstate_buf()

static void __init_extensionstate_buf ( void  )
static

Definition at line 229 of file pbx.c.

237{

◆ __init_hintdevice_data()

static void __init_hintdevice_data ( void  )
static

Definition at line 359 of file pbx.c.

376{

◆ __init_switch_data()

static void __init_switch_data ( void  )
static

Definition at line 228 of file pbx.c.

237{

◆ _extension_match_core()

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

Definition at line 2223 of file pbx.c.

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

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

Referenced by extension_match_core().

◆ acf_exception_read()

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

Definition at line 2832 of file pbx.c.

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

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

◆ action_extensionstatelist()

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

Definition at line 8344 of file pbx.c.

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

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

Referenced by load_pbx().

◆ add_exten_to_pattern_tree()

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

Definition at line 1663 of file pbx.c.

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

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

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

◆ add_hintdevice()

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

add hintdevice structure and link it into the container.

Definition at line 557 of file pbx.c.

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

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

Referenced by ast_add_hint(), and ast_change_hint().

◆ add_pattern_node()

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

Definition at line 1464 of file pbx.c.

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

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

Referenced by add_exten_to_pattern_tree().

◆ add_priority()

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

add the extension in the priority chain.

Return values
0on success.
-1on failure.

Definition at line 7067 of file pbx.c.

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

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

Referenced by ast_add_extension2_lockopt().

◆ alloc_device_state_info()

static struct ao2_container * alloc_device_state_info ( void  )
static

Definition at line 3076 of file pbx.c.

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

References AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_container_alloc_list, and NULL.

Referenced by ast_extension_state_extended(), and device_state_notify_callbacks().

◆ already_in_tree()

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

Definition at line 1402 of file pbx.c.

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

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

Referenced by add_exten_to_pattern_tree().

◆ ast_active_calls()

int ast_active_calls ( void  )

Retrieve the number of active calls.

Definition at line 4760 of file pbx.c.

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

References countcalls.

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

◆ ast_add_extension()

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

Add and extension to an extension context.

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

Definition at line 6928 of file pbx.c.

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

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

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

◆ ast_add_extension2()

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

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

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

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

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

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

Definition at line 7257 of file pbx.c.

7261{
7262 return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid,
7263 application, data, datad, registrar, registrar_file, registrar_line, 1);
7264}
static int ast_add_extension2_lockopt(struct ast_context *con, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar, const char *registrar_file, int registrar_line, int lock_context)
Same as ast_add_extension2() but controls the context locking.
Definition: pbx.c:7283

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

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

◆ ast_add_extension2_lockopt()

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

Same as ast_add_extension2() but controls the context locking.

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

Definition at line 7283 of file pbx.c.

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

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

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

◆ ast_add_extension2_nolock()

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

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

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

Definition at line 7266 of file pbx.c.

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

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

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

◆ ast_add_extension_nolock()

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

Definition at line 6908 of file pbx.c.

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

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

Referenced by ast_merge_contexts_and_delete().

◆ ast_add_hint()

static int ast_add_hint ( struct ast_exten e)
static

Add hint to hint list, check initial extension state.

Definition at line 3978 of file pbx.c.

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

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

Referenced by add_priority(), and ast_add_extension2_lockopt().

◆ ast_async_goto()

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

Set the channel to next execute the specified dialplan location.

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

Definition at line 6969 of file pbx.c.

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

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

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

◆ ast_async_goto_by_name()

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

Set the channel to next execute the specified dialplan location.

Definition at line 7002 of file pbx.c.

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

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

◆ ast_async_goto_if_exists()

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

Definition at line 8786 of file pbx.c.

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

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

◆ ast_async_parseable_goto()

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

Definition at line 8871 of file pbx.c.

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

References pbx_parseable_goto().

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

◆ ast_canmatch_extension()

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

Looks for a valid matching extension.

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

Definition at line 4190 of file pbx.c.

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

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

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

◆ ast_change_hint()

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

Change hint for an extension.

Definition at line 4092 of file pbx.c.

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

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

Referenced by add_priority().

◆ ast_context_add_ignorepat()

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

Add an ignorepat.

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

Adds an ignore pattern to a particular context.

Return values
0on success
-1on failure

Definition at line 6835 of file pbx.c.

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

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

Referenced by handle_cli_dialplan_add_ignorepat().

◆ ast_context_add_ignorepat2()

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

Definition at line 6848 of file pbx.c.

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

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

Referenced by ast_context_add_ignorepat(), and context_merge_incls_swits_igps_other_registrars().

◆ ast_context_add_include()

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

Add a context include.

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

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

Return values
0on success
-1on error

Definition at line 6664 of file pbx.c.

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

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

Referenced by AST_TEST_DEFINE(), and handle_cli_dialplan_add_include().

◆ ast_context_add_include2()

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

Add a context include.

Adds an include taking a struct ast_context as the first parameter

Note
See ast_context_add_include for information on arguments

Definition at line 6684 of file pbx.c.

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

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

Referenced by ast_context_add_include(), and context_merge_incls_swits_igps_other_registrars().

◆ ast_context_add_switch()

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

Add a switch.

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

This function registers a switch with the asterisk switch architecture

Return values
0on success
-1on failure

Definition at line 6729 of file pbx.c.

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

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

◆ ast_context_add_switch2()

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

Adds a switch (first param is a ast_context)

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

Definition at line 6749 of file pbx.c.

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

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

Referenced by ast_context_add_switch(), and context_merge_incls_swits_igps_other_registrars().

◆ ast_context_destroy()

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

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

Parameters
concontext to destroy
registrarwho registered it

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

Definition at line 8221 of file pbx.c.

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

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

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

◆ ast_context_destroy_by_name()

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

Destroy a context by name.

Parameters
contextName of the context to destroy
registrarwho registered it

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

Return values
-1context not found
0Success

Definition at line 8205 of file pbx.c.

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

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

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

◆ ast_context_find()

struct ast_context * ast_context_find ( const char *  name)

Find a context.

Parameters
namename of the context to find

Will search for the context with the given name.

Returns
the ast_context on success, NULL on failure.

Definition at line 2439 of file pbx.c.

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

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

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

◆ ast_context_find_or_create()

struct ast_context * ast_context_find_or_create ( struct ast_context **  extcontexts,
struct ast_hashtab exttable,
const char *  name,
const char *  registrar 
)

Register a new context or find an existing one.

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

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

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

Returns
NULL on failure, and an ast_context structure on success

Definition at line 6149 of file pbx.c.

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

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

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

◆ ast_context_ignorepats_count()

int ast_context_ignorepats_count ( const struct ast_context con)

◆ ast_context_ignorepats_get()

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

◆ ast_context_includes_count()

int ast_context_includes_count ( const struct ast_context con)

◆ ast_context_includes_get()

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

◆ ast_context_remove_extension()

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

Simply remove extension from context.

Note
This function will lock conlock.

Definition at line 4948 of file pbx.c.

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

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

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

◆ ast_context_remove_extension2()

int ast_context_remove_extension2 ( struct ast_context con,
const char *  extension,
int  priority,
const char *  registrar,
int  already_locked 
)

This functionc locks given context, search for the right extension and fires out all peer in this extensions with given priority. If priority is set to 0, all peers are removed. After that, unlock context and return.

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

Definition at line 4978 of file pbx.c.

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

Referenced by add_extension(), and add_hints().

◆ ast_context_remove_extension_callerid()

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

Definition at line 4953 of file pbx.c.

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

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

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

◆ ast_context_remove_extension_callerid2()

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

Definition at line 4983 of file pbx.c.

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

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

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

◆ ast_context_remove_ignorepat()

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

Remove an ignorepat.

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

This removes the given ignorepattern

Return values
0on success
-1on failure

Definition at line 6795 of file pbx.c.

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

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

Referenced by handle_cli_dialplan_remove_ignorepat().

◆ ast_context_remove_ignorepat2()

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

Definition at line 6808 of file pbx.c.

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

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

Referenced by ast_context_remove_ignorepat().

◆ ast_context_remove_include()

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

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

Remove a context include.

Definition at line 4836 of file pbx.c.

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

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

Referenced by handle_cli_dialplan_remove_include().

◆ ast_context_remove_include2()

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

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

Removes an include by an ast_context structure.

Return values
0on success.
-1on failure.

Definition at line 4859 of file pbx.c.

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

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

Referenced by ast_context_remove_include().

◆ ast_context_remove_switch()

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

Remove a switch.

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

Definition at line 4894 of file pbx.c.

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

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

◆ ast_context_remove_switch2()

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

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

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

Definition at line 4916 of file pbx.c.

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

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

Referenced by ast_context_remove_switch().

◆ ast_context_set_autohints()

void ast_context_set_autohints ( struct ast_context con,
int  enabled 
)

Enable or disable autohints support on a context.

Parameters
conpointer to the context
enabledwhether autohints are enabled

Definition at line 6230 of file pbx.c.

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

References ast_context::autohints, and enabled.

Referenced by pbx_load_config().

◆ ast_context_switches_count()

int ast_context_switches_count ( const struct ast_context con)

◆ ast_context_switches_get()

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

◆ ast_context_verify_includes()

int ast_context_verify_includes ( struct ast_context con)

Verifies includes in an ast_contect structure.

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

Definition at line 8732 of file pbx.c.

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

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

Referenced by pbx_load_module().

◆ ast_devstate_to_extenstate()

enum ast_extension_states ast_devstate_to_extenstate ( enum ast_device_state  devstate)

Map devstate to an extension state.

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

Definition at line 3006 of file pbx.c.

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

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

Referenced by ast_extension_state3(), and AST_TEST_DEFINE().

◆ ast_exists_extension()

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

Determine whether an extension exists.

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

Definition at line 4175 of file pbx.c.

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

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

Referenced by __analog_ss_thread(), __ast_goto_if_exists(), __ast_pbx_run(), acf_isexten_exec(), action_originate(), add_to_regcontext(), analog_ss_thread(), ast_app_dtget(), ast_bridge_setup_after_goto(), ast_pbx_outgoing_exten_predial(), ast_sip_persistent_endpoint_update_state(), chan_pjsip_cng_tone_detected(), cli_console_dial(), comeback_goto(), conf_run(), dahdi_handle_dtmf(), dial_exec_full(), dialplan_has_destination_cb(), disa_exec(), dp_lookup(), dundi_lookup_local(), fax_detect_framehook(), findmeexec(), get_destination(), gosub_exec(), grab_transfer(), handle_gosub(), isexten_function_read(), jingle_new(), 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.

Definition at line 6945 of file pbx.c.

6946{
6947 if (!chan)
6948 return -1;
6949
6950 ast_channel_lock(chan);
6951
6954 if (!ast_strlen_zero(exten))
6955 ast_channel_exten_set(chan, exten);
6956 if (priority > -1) {
6957 /* see flag description in channel.h for explanation */
6959 --priority;
6960 }
6962 }
6963
6964 ast_channel_unlock(chan);
6965
6966 return 0;
6967}

References ast_channel_context_set(), ast_channel_exten_set(), ast_channel_flags(), ast_channel_lock, ast_channel_priority_set(), ast_channel_unlock, AST_FLAG_IN_AUTOLOOP, 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 2432 of file pbx.c.

2433{
2434 if (needmore != E_MATCHMORE && needmore != E_CANMATCH)
2435 ast_log(LOG_WARNING, "invalid argument %d\n", needmore);
2436 return extension_match_core(pattern, data, needmore);
2437}
static int extension_match_core(const char *pattern, const char *data, enum ext_match_t mode)
Definition: pbx.c:2414

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

2198{
2199 int cmp;
2200
2201 cmp = ext_cmp(a, b);
2202 if (cmp < 0) {
2203 return -1;
2204 }
2205 if (cmp > 0) {
2206 return 1;
2207 }
2208 return 0;
2209}
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 2427 of file pbx.c.

2428{
2429 return extension_match_core(pattern, extension, E_MATCH);
2430}

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

3171{
3173}
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:3141

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

3114{
3115 struct ast_str *hint_app = ast_str_thread_get(&extensionstate_buf, 32);
3116
3117 if (!e || !hint_app) {
3118 return -1;
3119 }
3120
3121 ast_str_set(&hint_app, 0, "%s", ast_get_extension_app(e));
3122 return ast_extension_state3(hint_app, device_state_info);
3123}
static int ast_extension_state3(struct ast_str *hint_app, struct ao2_container *device_state_info)
Definition: pbx.c:3081
static struct ast_threadstorage extensionstate_buf
Definition: pbx.c:229

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

3127{
3128 int i;
3129
3130 for (i = 0; (i < ARRAY_LEN(extension_states)); i++) {
3131 if (extension_states[i].extension_state == extension_state)
3132 return extension_states[i].text;
3133 }
3134 return "Unknown";
3135}
static const struct cfextension_states extension_states[]
const char *const text
Definition: pbx.c:613

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

3082{
3083 char *cur;
3084 char *rest;
3085 struct ast_devstate_aggregate agg;
3086
3087 /* One or more devices separated with a & character */
3088 rest = parse_hint_device(hint_app);
3089
3091 while ((cur = strsep(&rest, "&"))) {
3093
3095 if (device_state_info) {
3096 struct ast_device_state_info *obj;
3097
3098 obj = ao2_alloc_options(sizeof(*obj) + strlen(cur), device_state_info_dt, AO2_ALLOC_OPT_LOCK_NOLOCK);
3099 /* if failed we cannot add this device */
3100 if (obj) {
3101 obj->device_state = state;
3102 strcpy(obj->device_name, cur);
3103 ao2_link(device_state_info, obj);
3104 ao2_ref(obj, -1);
3105 }
3106 }
3107 }
3108
3110}
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:404
enum cc_state state
Definition: ccss.c:393
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:636
void ast_devstate_aggregate_init(struct ast_devstate_aggregate *agg)
Initialize aggregate device state.
Definition: devicestate.c:630
enum ast_device_state ast_devstate_aggregate_result(struct ast_devstate_aggregate *agg)
Get the aggregate device state result.
Definition: devicestate.c:663
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:3006
static char * parse_hint_device(struct ast_str *hint_args)
Definition: pbx.c:3056
static void device_state_info_dt(void *obj)
Definition: pbx.c:3069
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 3823 of file pbx.c.

3825{
3826 return extension_state_add_destroy(context, exten, change_cb, NULL, data, 0);
3827}
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:3727

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

3819{
3820 return extension_state_add_destroy(context, exten, change_cb, destroy_cb, data, 0);
3821}

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

3831{
3832 return extension_state_add_destroy(context, exten, change_cb, destroy_cb, data, 1);
3833}

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

3837{
3838 return extension_state_add_destroy(context, exten, change_cb, NULL, data, 1);
3839}

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

3857{
3858 struct ast_state_cb *p_cur;
3859 int ret = -1;
3860
3861 if (!id) { /* id == 0 is a callback without extension */
3862 if (!change_cb) {
3863 return ret;
3864 }
3866 if (p_cur) {
3867 ret = 0;
3868 ao2_ref(p_cur, -1);
3869 }
3870 } else { /* callback with extension, find the callback based on ID */
3871 struct ast_hint *hint;
3872
3873 ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */
3874 hint = ao2_callback(hints, 0, find_hint_by_cb_id, &id);
3875 if (hint) {
3876 p_cur = ao2_find(hint->callbacks, &id, OBJ_UNLINK);
3877 if (p_cur) {
3878 ret = 0;
3879 ao2_ref(p_cur, -1);
3880 }
3881 ao2_ref(hint, -1);
3882 }
3884 }
3885
3886 return ret;
3887}
#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:3842

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

3178{
3179 struct ao2_container *container = NULL;
3180 int ret;
3181
3182 if (device_state_info) {
3184 }
3185
3187 if (ret < 0 && container) {
3188 ao2_ref(container, -1);
3189 container = NULL;
3190 }
3191
3192 if (device_state_info) {
3194 *device_state_info = container;
3195 }
3196
3197 return ret;
3198}
static struct ao2_container * alloc_device_state_info(void)
Definition: pbx.c:3076
static void get_device_state_causing_channels(struct ao2_container *c)
Definition: pbx.c:3296
struct ao2_container * container
Definition: res_fax.c:501
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 4180 of file pbx.c.

4181{
4182 return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
4183}
@ 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 4185 of file pbx.c.

4186{
4187 return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
4188}

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

8528{
8529 return c ? c->registrar : NULL;
8530}

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

8553{
8554 return e ? e->cidmatch_display : NULL;
8555}
const char * cidmatch_display
Definition: pbx.c:242

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

8569{
8570 struct ast_exten *e;
8571 struct pbx_find_info q = { .stacklen = 0 }; /* the rest is set in pbx_find_context */
8573 e = pbx_find_extension(c, NULL, &q, context, exten, priority, NULL, "", E_MATCH);
8574 if (e) {
8575 if (buf) {
8576 const char *tmp = ast_get_extension_app_data(e);
8577 if (tmp) {
8578 ast_copy_string(buf, tmp, bufsize);
8579 }
8580 }
8582 return 0;
8583 }
8585 return -1;
8586}
void * ast_get_extension_app_data(struct ast_exten *e)
Definition: pbx.c:8562
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:2482
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, pbx_find_info::stacklen, and tmp().

Referenced by eval_exten_read().

◆ ast_get_extension_label()

const char * ast_get_extension_label ( struct ast_exten exten)

Definition at line 8514 of file pbx.c.

8515{
8516 return exten ? exten->label : NULL;
8517}

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

8548{
8549 return e ? e->matchcid : 0;
8550}

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

8520{
8521 return exten ? exten->priority : -1;
8522}

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

8538{
8539 return e ? e->registrar_file : NULL;
8540}

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

8543{
8544 return e ? e->registrar_line : 0;
8545}

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

4138{
4140
4141 if (e) {
4142 if (hint)
4143 ast_copy_string(hint, ast_get_extension_app(e), hintsize);
4144 if (name) {
4145 const char *tmp = ast_get_extension_app_data(e);
4146 if (tmp)
4147 ast_copy_string(name, tmp, namesize);
4148 }
4149 return -1;
4150 }
4151 return 0;
4152}
static struct ast_exten * ast_hint_extension(struct ast_channel *c, const char *context, const char *exten)
Definition: pbx.c:2997

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

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

8782{
8783 return __ast_goto_if_exists(chan, context, exten, priority, 0);
8784}

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

689{
690 const struct ast_context *ac = ah_a;
691 const struct ast_context *bc = ah_b;
692 if (!ac || !bc) /* safety valve, but it might prevent a crash you'd rather have happen */
693 return 1;
694 /* assume context names are registered in a string table! */
695 return strcmp(ac->name, bc->name);
696}
#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 740 of file pbx.c.

741{
742 const struct ast_context *ac = obj;
743 return ast_hashtab_hash_string(ac->name);
744}
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 2997 of file pbx.c.

2998{
2999 struct ast_exten *e;
3003 return e;
3004}
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:2991

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

2992{
2993 struct pbx_find_info q = { .stacklen = 0 }; /* the rest is set in pbx_find_context */
2994 return pbx_find_extension(c, NULL, &q, context, exten, PRIORITY_HINT, NULL, "", E_MATCH);
2995}

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

3227{
3228 struct ast_exten *e;
3229
3230 if (!(e = ast_hint_extension(c, context, exten))) { /* Do we have a hint for this extension ? */
3231 return -1; /* No hint, return -1 */
3232 }
3233
3234 if (e->exten[0] == '_') {
3235 /* Create this hint on-the-fly */
3236 ao2_lock(hints);
3238 e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr,
3239 e->registrar);
3241 if (!(e = ast_hint_extension(c, context, exten))) {
3242 /* Improbable, but not impossible */
3243 return -1;
3244 }
3245 }
3246
3247 return extension_presence_state_helper(e, subtype, message);
3248}
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:6928

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

6880{
6881 int ret = 0;
6882 struct ast_context *con;
6883
6886 if (con) {
6887 int idx;
6888
6889 for (idx = 0; idx < ast_context_ignorepats_count(con); idx++) {
6890 const struct ast_ignorepat *pat = ast_context_ignorepats_get(con, idx);
6891
6893 ret = 1;
6894 break;
6895 }
6896 }
6897 }
6899
6900 return ret;
6901}
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:2427
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 4195 of file pbx.c.

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

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

6427{
6428 double ft;
6429 struct ast_context *tmp;
6430 struct ast_context *oldcontextslist;
6431 struct ast_hashtab *oldtable;
6432 struct store_hints hints_stored = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
6433 struct store_hints hints_removed = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
6434 struct store_hint *saved_hint;
6435 struct ast_hint *hint;
6436 struct ast_exten *exten;
6437 int length;
6438 struct ast_state_cb *thiscb;
6439 struct ast_hashtab_iter *iter;
6440 struct ao2_iterator i;
6441 int ctx_count = 0;
6442 struct timeval begintime;
6443 struct timeval writelocktime;
6444 struct timeval endlocktime;
6445 struct timeval enddeltime;
6446
6447 /*
6448 * It is very important that this function hold the hints
6449 * container lock _and_ the conlock during its operation; not
6450 * only do we need to ensure that the list of contexts and
6451 * extensions does not change, but also that no hint callbacks
6452 * (watchers) are added or removed during the merge/delete
6453 * process
6454 *
6455 * In addition, the locks _must_ be taken in this order, because
6456 * there are already other code paths that use this order
6457 */
6458
6459 begintime = ast_tvnow();
6460 ast_mutex_lock(&context_merge_lock);/* Serialize ast_merge_contexts_and_delete */
6462
6463 if (!contexts_table) {
6464 /* Create any autohint contexts */
6466
6467 /* Well, that's odd. There are no contexts. */
6468 contexts_table = exttable;
6469 contexts = *extcontexts;
6472 return;
6473 }
6474
6476 while ((tmp = ast_hashtab_next(iter))) {
6477 ++ctx_count;
6478 context_merge(extcontexts, exttable, tmp, registrar);
6479 }
6481
6482 ao2_lock(hints);
6483 writelocktime = ast_tvnow();
6484
6485 /* preserve all watchers for hints */
6487 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
6488 if (ao2_container_count(hint->callbacks)) {
6489 size_t exten_len;
6490
6491 ao2_lock(hint);
6492 if (!hint->exten) {
6493 /* The extension has already been destroyed. (Should never happen here) */
6494 ao2_unlock(hint);
6495 continue;
6496 }
6497
6498 exten_len = strlen(hint->exten->exten) + 1;
6499 length = exten_len + strlen(hint->exten->parent->name) + 1
6500 + sizeof(*saved_hint);
6501 if (!(saved_hint = ast_calloc(1, length))) {
6502 ao2_unlock(hint);
6503 continue;
6504 }
6505
6506 /* This removes all the callbacks from the hint into saved_hint. */
6507 while ((thiscb = ao2_callback(hint->callbacks, OBJ_UNLINK, NULL, NULL))) {
6508 AST_LIST_INSERT_TAIL(&saved_hint->callbacks, thiscb, entry);
6509 /*
6510 * We intentionally do not unref thiscb to account for the
6511 * non-ao2 reference in saved_hint->callbacks
6512 */
6513 }
6514
6515 saved_hint->laststate = hint->laststate;
6516 saved_hint->context = saved_hint->data;
6517 strcpy(saved_hint->data, hint->exten->parent->name);
6518 saved_hint->exten = saved_hint->data + strlen(saved_hint->context) + 1;
6519 ast_copy_string(saved_hint->exten, hint->exten->exten, exten_len);
6520 if (hint->last_presence_subtype) {
6521 saved_hint->last_presence_subtype = ast_strdup(hint->last_presence_subtype);
6522 }
6523 if (hint->last_presence_message) {
6524 saved_hint->last_presence_message = ast_strdup(hint->last_presence_message);
6525 }
6526 saved_hint->last_presence_state = hint->last_presence_state;
6527 ao2_unlock(hint);
6528 AST_LIST_INSERT_HEAD(&hints_stored, saved_hint, list);
6529 }
6530 }
6532
6533 /* save the old table and list */
6534 oldtable = contexts_table;
6535 oldcontextslist = contexts;
6536
6537 /* move in the new table and list */
6538 contexts_table = exttable;
6539 contexts = *extcontexts;
6540
6541 /*
6542 * Restore the watchers for hints that can be found; notify
6543 * those that cannot be restored.
6544 */
6545 while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_stored, list))) {
6546 struct pbx_find_info q = { .stacklen = 0 };
6547
6548 exten = pbx_find_extension(NULL, NULL, &q, saved_hint->context, saved_hint->exten,
6549 PRIORITY_HINT, NULL, "", E_MATCH);
6550 /*
6551 * If this is a pattern, dynamically create a new extension for this
6552 * particular match. Note that this will only happen once for each
6553 * individual extension, because the pattern will no longer match first.
6554 */
6555 if (exten && exten->exten[0] == '_') {
6556 ast_add_extension_nolock(exten->parent->name, 0, saved_hint->exten,
6557 PRIORITY_HINT, NULL, 0, exten->app, ast_strdup(exten->data), ast_free_ptr,
6558 exten->registrar);
6559 /* rwlocks are not recursive locks */
6560 exten = ast_hint_extension_nolock(NULL, saved_hint->context,
6561 saved_hint->exten);
6562 }
6563
6564 /* Find the hint in the hints container */
6565 hint = exten ? ao2_find(hints, exten, 0) : NULL;
6566 if (!hint) {
6567 /*
6568 * Notify watchers of this removed hint later when we aren't
6569 * encumbered by so many locks.
6570 */
6571 AST_LIST_INSERT_HEAD(&hints_removed, saved_hint, list);
6572 } else {
6573 ao2_lock(hint);
6574 while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) {
6575 ao2_link(hint->callbacks, thiscb);
6576 /* Ref that we added when putting into saved_hint->callbacks */
6577 ao2_ref(thiscb, -1);
6578 }
6579 hint->laststate = saved_hint->laststate;
6580 hint->last_presence_state = saved_hint->last_presence_state;
6581 hint->last_presence_subtype = saved_hint->last_presence_subtype;
6582 hint->last_presence_message = saved_hint->last_presence_message;
6583 ao2_unlock(hint);
6584 ao2_ref(hint, -1);
6585 /*
6586 * The free of saved_hint->last_presence_subtype and
6587 * saved_hint->last_presence_message is not necessary here.
6588 */
6589 ast_free(saved_hint);
6590 }
6591 }
6592
6593 /* Create all applicable autohint contexts */
6595
6598
6599 /*
6600 * Notify watchers of all removed hints with the same lock
6601 * environment as device_state_cb().
6602 */
6603 while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_removed, list))) {
6604 /* this hint has been removed, notify the watchers */
6605 while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) {
6607 saved_hint->context,
6608 saved_hint->exten,
6609 thiscb->data,
6611 NULL,
6612 NULL);
6613 /* Ref that we added when putting into saved_hint->callbacks */
6614 ao2_ref(thiscb, -1);
6615 }
6616 ast_free(saved_hint->last_presence_subtype);
6617 ast_free(saved_hint->last_presence_message);
6618 ast_free(saved_hint);
6619 }
6620
6622 endlocktime = ast_tvnow();
6623
6624 /*
6625 * The old list and hashtab no longer are relevant, delete them
6626 * while the rest of asterisk is now freely using the new stuff
6627 * instead.
6628 */
6629
6630 ast_hashtab_destroy(oldtable, NULL);
6631
6632 for (tmp = oldcontextslist; tmp; ) {
6633 struct ast_context *next; /* next starting point */
6634
6635 next = tmp->next;
6637 tmp = next;
6638 }
6639 enddeltime = ast_tvnow();
6640
6641 ft = ast_tvdiff_us(writelocktime, begintime);
6642 ft /= 1000000.0;
6643 ast_verb(5,"Time to scan old dialplan and merge leftovers back into the new: %8.6f sec\n", ft);
6644
6645 ft = ast_tvdiff_us(endlocktime, writelocktime);
6646 ft /= 1000000.0;
6647 ast_verb(5,"Time to restore hints and swap in new dialplan: %8.6f sec\n", ft);
6648
6649 ft = ast_tvdiff_us(enddeltime, endlocktime);
6650 ft /= 1000000.0;
6651 ast_verb(5,"Time to delete the old dialplan: %8.6f sec\n", ft);
6652
6653 ft = ast_tvdiff_us(enddeltime, begintime);
6654 ft /= 1000000.0;
6655 ast_verb(5,"Total time merge_contexts_delete: %8.6f sec\n", ft);
6656 ast_verb(5, "%s successfully loaded %d contexts (enable debug for details).\n", registrar, ctx_count);
6657}
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:189
static void context_table_create_autohints(struct ast_hashtab *table)
Definition: pbx.c:6290
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:6908
static void context_merge(struct ast_context **extcontexts, struct ast_hashtab *exttable, struct ast_context *context, const char *registrar)
Definition: pbx.c:6327
Definition: search.h:40
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, pbx_find_info::stacklen, and tmp().

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

8867{
8868 return pbx_parseable_goto(chan, goto_string, 0);
8869}

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

4206{
4207 int autoloopflag;
4208 int found;
4209 int spawn_error;
4210
4211 ast_channel_lock(chan);
4212
4213 /*
4214 * Make sure that the channel is marked as hungup since we are
4215 * going to run the h exten on it.
4216 */
4218
4219 /* Set h exten location */
4220 if (context != ast_channel_context(chan)) {
4222 }
4223 ast_channel_exten_set(chan, "h");
4224 ast_channel_priority_set(chan, 1);
4225
4226 /* Save autoloop flag */
4229 ast_channel_unlock(chan);
4230
4231 for (;;) {
4232 spawn_error = ast_spawn_extension(chan, ast_channel_context(chan),
4234 S_COR(ast_channel_caller(chan)->id.number.valid,
4235 ast_channel_caller(chan)->id.number.str, NULL), &found, 1);
4236
4237 ast_channel_lock(chan);
4238 if (spawn_error) {
4239 /* The code after the loop needs the channel locked. */
4240 break;
4241 }
4243 ast_channel_unlock(chan);
4244 }
4245 if (found && spawn_error) {
4246 /* Something bad happened, or a hangup has been requested. */
4247 ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n",
4250 ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n",
4253 }
4254
4255 /* An "h" exten has been run, so indicate that one has been run. */
4257
4258 /* Restore autoloop flag */
4260 ast_channel_unlock(chan);
4261}
@ AST_SOFTHANGUP_HANGUP_EXEC
Definition: channel.h:1154

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

8990{
8993 if (hints) {
8995 }
8998 if (hintdevices) {
9000 }
9001 /* This is protected by the context_and_merge lock */
9004 if (autohints) {
9006 }
9008 if (statecbs) {
9010 }
9011
9013
9014 if (STASIS_MESSAGE_TYPE_INIT(hint_change_message_type) != 0) {
9015 return -1;
9016 }
9017 if (STASIS_MESSAGE_TYPE_INIT(hint_remove_message_type) != 0) {
9018 return -1;
9019 }
9020
9021 return (hints && hintdevices && autohints && statecbs) ? 0 : -1;
9022}
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:8969
static void print_statecbs_key(void *v_obj, void *where, ao2_prnt_fn *prnt)
Definition: pbx.c:8979
static int hint_cmp(void *obj, void *arg, int flags)
Definition: pbx.c:8896
static struct ao2_container * autohints
Container for autohint contexts.
Definition: pbx.c:387
static int hintdevice_hash_cb(const void *obj, const int flags)
Definition: pbx.c:402
static int hint_hash(const void *obj, const int flags)
Definition: pbx.c:8876
static int statecbs_cmp(void *obj, void *arg, int flags)
Definition: pbx.c:8904
static int autohint_hash_cb(const void *obj, const int flags)
Definition: pbx.c:460
static void print_hintdevices_key(void *v_obj, void *where, ao2_prnt_fn *prnt)
Definition: pbx.c:8957
static void print_hints_key(void *v_obj, void *where, ao2_prnt_fn *prnt)
Definition: pbx.c:8946
#define HASH_EXTENHINT_SIZE
Definition: pbx.c:365
static int hintdevice_cmp_multiple(void *obj, void *arg, int flags)
Definition: pbx.c:428
static void pbx_shutdown(void)
Definition: pbx.c:8916
static int autohint_cmp(void *obj, void *arg, int flags)
Definition: pbx.c:481
#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 7980 of file pbx.c.

7985{
7986 return ast_pbx_outgoing_app_predial(type, cap, addr, timeout, app, appdata, reason, synchronous,
7987 cid_num, cid_name, vars, account, locked_channel, assignedids, NULL);
7988}
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:7990

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

7995{
7996 if (reason) {
7997 *reason = 0;
7998 }
7999 if (locked_channel) {
8000 *locked_channel = NULL;
8001 }
8002 if (ast_strlen_zero(app)) {
8003 return -1;
8004 }
8005
8006 return pbx_outgoing_attempt(type, cap, addr, timeout, NULL, NULL, 0, app, appdata,
8007 reason, synchronous, cid_num, cid_name, vars, account, locked_channel, 0,
8008 assignedids, predial_callee);
8009}
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:7720

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

7921{
7922 return ast_pbx_outgoing_exten_predial(type, cap, addr, timeout, context, exten, priority, reason,
7923 synchronous, cid_num, cid_name, vars, account, locked_channel, early_media, assignedids, NULL);
7924}
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:7926

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

7931{
7932 int res;
7933 int my_reason;
7934
7935 if (!reason) {
7936 reason = &my_reason;
7937 }
7938 *reason = 0;
7939 if (locked_channel) {
7940 *locked_channel = NULL;
7941 }
7942
7943 res = pbx_outgoing_attempt(type, cap, addr, timeout, context, exten, priority,
7944 NULL, NULL, reason, synchronous, cid_num, cid_name, vars, account, locked_channel,
7945 early_media, assignedids, predial_callee);
7946
7947 if (res < 0 /* Call failed to get connected for some reason. */
7948 && 0 < synchronous
7949 && ast_exists_extension(NULL, context, "failed", 1, NULL)) {
7950 struct ast_channel *failed;
7951
7952 /* We do not have to worry about a locked_channel if dialing failed. */
7953 ast_assert(!locked_channel || !*locked_channel);
7954
7955 /*!
7956 * \todo XXX Not good. The channel name is not unique if more than
7957 * one originate fails at a time.
7958 */
7959 failed = ast_channel_alloc(0, AST_STATE_DOWN, cid_num, cid_name, account,
7960 "failed", context, NULL, NULL, 0, "OutgoingSpoolFailed");
7961 if (failed) {
7962 char failed_reason[12];
7963
7964 ast_set_variables(failed, vars);
7965 snprintf(failed_reason, sizeof(failed_reason), "%d", *reason);
7966 pbx_builtin_setvar_helper(failed, "REASON", failed_reason);
7967 ast_channel_unlock(failed);
7968
7969 if (ast_pbx_run(failed)) {
7970 ast_log(LOG_ERROR, "Unable to run PBX on '%s'\n",
7971 ast_channel_name(failed));
7972 ast_hangup(failed);
7973 }
7974 }
7975 }
7976
7977 return res;
7978}
#define ast_channel_alloc(needqueue, state, cid_num, cid_name, acctcode, exten, context, assignedids, requestor, amaflag,...)
Create a channel structure.
Definition: channel.h:1258
void ast_set_variables(struct ast_channel *chan, struct ast_variable *vars)
adds a list of channel variables to a channel
Definition: channel.c:8114
@ 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:4755

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

4756{
4757 return ast_pbx_run_args(c, NULL);
4758}
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:4735

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

4736{
4738
4740 ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n");
4741 return AST_PBX_FAILED;
4742 }
4743
4744 if (increase_call_count(c)) {
4745 return AST_PBX_CALL_LIMIT;
4746 }
4747
4748 res = __ast_pbx_run(c, args);
4749
4751
4752 return res;
4753}
struct ast_flags ast_options
Definition: options.c:61
@ AST_OPT_FLAG_FULLY_BOOTED
Definition: options.h:58
static void decrease_call_count(void)
Definition: pbx.c:4666
static int increase_call_count(const struct ast_channel *c)
Increase call count for channel.
Definition: pbx.c:4617
static enum ast_pbx_result __ast_pbx_run(struct ast_channel *c, struct ast_pbx_args *args)
Definition: pbx.c:4306
ast_pbx_result
The result codes when starting the PBX on a channel with ast_pbx_start.
Definition: pbx.h:370
@ AST_PBX_CALL_LIMIT
Definition: pbx.h:373

References __ast_pbx_run(), args, ast_log, AST_OPT_FLAG_FULLY_BOOTED, ast_options, AST_PBX_CALL_LIMIT, AST_PBX_FAILED, AST_PBX_SUCCESS, ast_test_flag, 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 4708 of file pbx.c.

4709{
4710 pthread_t t;
4711
4712 if (!c) {
4713 ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
4714 return AST_PBX_FAILED;
4715 }
4716
4718 ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n");
4719 return AST_PBX_FAILED;
4720 }
4721
4723 return AST_PBX_CALL_LIMIT;
4724
4725 /* Start a new thread, and get something handling this channel. */
4727 ast_log(LOG_WARNING, "Failed to create new channel thread\n");
4729 return AST_PBX_FAILED;
4730 }
4731
4732 return AST_PBX_SUCCESS;
4733}
static void * pbx_thread(void *data)
Definition: pbx.c:4688
#define ast_pthread_create_detached(a, b, c, d)
Definition: utils.h:588

References ast_log, AST_OPT_FLAG_FULLY_BOOTED, ast_options, AST_PBX_CALL_LIMIT, AST_PBX_FAILED, AST_PBX_SUCCESS, ast_pthread_create_detached, ast_test_flag, 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 4765 of file pbx.c.

4766{
4767 return totalcalls;
4768}
static int totalcalls
Definition: pbx.c:779

References totalcalls.

Referenced by 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 8486 of file pbx.c.

8487{
8488 return ast_rwlock_rdlock(&con->lock);
8489}
#define ast_rwlock_rdlock(a)
Definition: lock.h:235
ast_rwlock_t lock
Definition: pbx.c:288

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

3942{
3943 /* Cleanup the Notifys if hint is removed */
3944 struct ast_hint *hint;
3945
3946 if (!e) {
3947 return -1;
3948 }
3949
3950 hint = ao2_find(hints, e, OBJ_UNLINK);
3951 if (!hint) {
3952 return -1;
3953 }
3954
3955 remove_hintdevice(hint);
3956
3957 /*
3958 * The extension is being destroyed so we must save some
3959 * information to notify that the extension is deactivated.
3960 */
3961 ao2_lock(hint);
3964 sizeof(hint->context_name));
3966 sizeof(hint->exten_name));
3967 hint->exten = NULL;
3968 ao2_unlock(hint);
3969
3970 publish_hint_remove(hint);
3971
3972 ao2_ref(hint, -1);
3973
3974 return 0;
3975}
static int publish_hint_remove(struct ast_hint *hint)
Publish a hint removed event
Definition: pbx.c:3920
char exten_name[AST_MAX_EXTENSION]
Definition: pbx.c:350
char context_name[AST_MAX_CONTEXT]
Definition: pbx.c:349

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

4201{
4202 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN, found, combined_find_spawn);
4203}
@ 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 4155 of file pbx.c.

4156{
4158
4159 if (!e) {
4160 return 0;
4161 }
4162
4163 if (hint) {
4164 ast_str_set(hint, hintsize, "%s", ast_get_extension_app(e));
4165 }
4166 if (name) {
4167 const char *tmp = ast_get_extension_app_data(e);
4168 if (tmp) {
4169 ast_str_set(name, namesize, "%s", tmp);
4170 }
4171 }
4172 return -1;
4173}

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

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

8598{
8599 if (!exten)
8600 return con ? con->root : NULL;
8601 else
8602 return exten->next;
8603}

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

8691{
8692 if (!con) {
8693 return NULL;
8694 }
8695
8696 if (ip) {
8697 int idx;
8698 int next = 0;
8699
8700 for (idx = 0; idx < ast_context_ignorepats_count(con); idx++) {
8701 const struct ast_ignorepat *i = ast_context_ignorepats_get(con, idx);
8702
8703 if (next) {
8704 return i;
8705 }
8706
8707 if (ip == i) {
8708 next = 1;
8709 }
8710 }
8711
8712 return NULL;
8713 }
8714
8715 if (!ast_context_ignorepats_count(con)) {
8716 return NULL;
8717 }
8718
8719 return ast_context_ignorepats_get(con, 0);
8720}
struct ast_ignorepat * next
Definition: extconf.c:2388

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

8652{
8653 if (inc) {
8654 int idx;
8655 int next = 0;
8656
8657 for (idx = 0; idx < ast_context_includes_count(con); idx++) {
8658 const struct ast_include *include = AST_VECTOR_GET(&con->includes, idx);
8659
8660 if (next) {
8661 return include;
8662 }
8663
8664 if (inc == include) {
8665 next = 1;
8666 }
8667 }
8668
8669 return NULL;
8670 }
8671
8672 if (!ast_context_includes_count(con)) {
8673 return NULL;
8674 }
8675
8676 return ast_context_includes_get(con, 0);
8677}
struct ast_include * next
Definition: extconf.c:2370

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

8607{
8608 if (sw) {
8609 int idx;
8610 int next = 0;
8611
8612 for (idx = 0; idx < ast_context_switches_count(con); idx++) {
8613 const struct ast_sw *s = ast_context_switches_get(con, idx);
8614
8615 if (next) {
8616 return s;
8617 }
8618
8619 if (sw == s) {
8620 next = 1;
8621 }
8622 }
8623
8624 return NULL;
8625 }
8626
8627 if (!ast_context_switches_count(con)) {
8628 return NULL;
8629 }
8630
8631 return ast_context_switches_get(con, 0);
8632}

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

482{
483 struct ast_autohint *left = obj;
484 struct ast_autohint *right = arg;
485 const char *right_key = arg;
486 int cmp;
487
488 switch (flags & OBJ_SEARCH_MASK) {
490 right_key = right->context;
491 /* Fall through */
492 case OBJ_SEARCH_KEY:
493 cmp = strcasecmp(left->context, right_key);
494 break;
496 /*
497 * We could also use a partial key struct containing a length
498 * so strlen() does not get called for every comparison instead.
499 */
500 cmp = strncmp(left->context, right_key, strlen(right_key));
501 break;
502 default:
503 ast_assert(0);
504 cmp = 0;
505 break;
506 }
507 return cmp ? 0 : CMP_MATCH | CMP_STOP;
508}
@ 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:392
char context[1]
Name of the context.
Definition: pbx.c:396

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

461{
462 const struct ast_autohint *autohint;
463 const char *key;
464
465 switch (flags & OBJ_SEARCH_MASK) {
466 case OBJ_SEARCH_KEY:
467 key = obj;
468 break;
470 autohint = obj;
471 key = autohint->context;
472 break;
473 default:
474 ast_assert(0);
475 return 0;
476 }
477
478 return ast_str_case_hash(key);
479}
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 1224 of file pbx.c.

1225{
1226 str++;
1227 while (*str == '-') {
1228 str++;
1229 }
1230 return str;
1231}

References str.

◆ cli_match_char_tree()

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

Definition at line 1116 of file pbx.c.

1117{
1118 char extenstr[40];
1119 struct ast_str *my_prefix = ast_str_alloca(1024);
1120
1121 extenstr[0] = '\0';
1122
1123 if (node->exten) {
1124 snprintf(extenstr, sizeof(extenstr), "(%p)", node->exten);
1125 }
1126
1127 if (strlen(node->x) > 1) {
1128 ast_cli(fd, "%s[%s]:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N',
1129 node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "",
1130 node->exten ? node->exten->name : "", extenstr);
1131 } else {
1132 ast_cli(fd, "%s%s:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N',
1133 node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "",
1134 node->exten ? node->exten->name : "", extenstr);
1135 }
1136
1137 ast_str_set(&my_prefix, 0, "%s+ ", prefix);
1138
1139 if (node->next_char)
1140 cli_match_char_tree(node->next_char, ast_str_buffer(my_prefix), fd);
1141
1142 if (node->alt_char)
1143 cli_match_char_tree(node->alt_char, prefix, fd);
1144}
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:1116
#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 4279 of file pbx.c.

4280{
4281 int digit;
4282
4283 buf[pos] = '\0'; /* make sure it is properly terminated */
4285 S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4286 /* As long as we're willing to wait, and as long as it's not defined,
4287 keep reading digits until we can't possibly get a right answer anymore. */
4288 digit = ast_waitfordigit(c, waittime);
4291 } else {
4292 if (!digit) /* No entry */
4293 break;
4294 if (digit < 0) /* Error, maybe a hangup */
4295 return -1;
4296 if (pos < buflen - 1) { /* XXX maybe error otherwise ? */
4297 buf[pos++] = digit;
4298 buf[pos] = '\0';
4299 }
4300 waittime = ast_channel_pbx(c)->dtimeoutms;
4301 }
4302 }
4303 return 0;
4304}
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
Definition: channel.c:3175

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

680{
681 const unsigned char *ac = a;
682 const unsigned char *bc = b;
683
684 return *ac - *bc;
685}

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

5220{
5221 struct ast_hint *hint;
5222 char *ret = NULL;
5223 int which = 0;
5224 int wordlen;
5225 struct ao2_iterator i;
5226
5227 if (pos != 3)
5228 return NULL;
5229
5230 wordlen = strlen(word);
5231
5232 /* walk through all hints */
5233 i = ao2_iterator_init(hints, 0);
5234 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
5235 ao2_lock(hint);
5236 if (!hint->exten) {
5237 /* The extension has already been destroyed */
5238 ao2_unlock(hint);
5239 continue;
5240 }
5241 if (!strncasecmp(word, ast_get_extension_name(hint->exten), wordlen) && ++which > state) {
5243 ao2_unlock(hint);
5244 ao2_ref(hint, -1);
5245 break;
5246 }
5247 ao2_unlock(hint);
5248 }
5250
5251 return ret;
5252}
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 5398 of file pbx.c.

5400{
5401 struct ast_context *c = NULL;
5402 char *ret = NULL;
5403 int which = 0;
5404 int wordlen;
5405
5406 /* we are do completion of [exten@]context on second position only */
5407 if (pos != 2)
5408 return NULL;
5409
5411
5412 wordlen = strlen(word);
5413
5414 /* walk through all contexts and return the n-th match */
5415 while ( (c = ast_walk_contexts(c)) ) {
5416 if (!strncasecmp(word, ast_get_context_name(c), wordlen) && ++which > state) {
5418 break;
5419 }
5420 }
5421
5423
5424 return ret;
5425}

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

6328{
6329 struct ast_context *new = ast_hashtab_lookup(exttable, context); /* is there a match in the new set? */
6330 struct ast_exten *exten_item, *prio_item, *new_exten_item, *new_prio_item;
6331 struct ast_hashtab_iter *exten_iter;
6332 struct ast_hashtab_iter *prio_iter;
6333 int insert_count = 0;
6334 int first = 1;
6335
6336 /* We'll traverse all the extensions/prios, and see which are not registrar'd with
6337 the current registrar, and copy them to the new context. If the new context does not
6338 exist, we'll create it "on demand". If no items are in this context to copy, then we'll
6339 only create the empty matching context if the old one meets the criteria */
6340
6341 if (context->root_table) {
6342 exten_iter = ast_hashtab_start_traversal(context->root_table);
6343 while ((exten_item=ast_hashtab_next(exten_iter))) {
6344 if (new) {
6345 new_exten_item = ast_hashtab_lookup(new->root_table, exten_item);
6346 } else {
6347 new_exten_item = NULL;
6348 }
6349 prio_iter = ast_hashtab_start_traversal(exten_item->peer_table);
6350 while ((prio_item=ast_hashtab_next(prio_iter))) {
6351 int res1;
6352 char *dupdstr;
6353
6354 if (new_exten_item) {
6355 new_prio_item = ast_hashtab_lookup(new_exten_item->peer_table, prio_item);
6356 } else {
6357 new_prio_item = NULL;
6358 }
6359 if (strcmp(prio_item->registrar,registrar) == 0) {
6360 continue;
6361 }
6362 /* make sure the new context exists, so we have somewhere to stick this exten/prio */
6363 if (!new) {
6364 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 */
6365 if (new) {
6366 new->autohints = context->autohints;
6367 }
6368 }
6369
6370 /* copy in the includes, switches, and ignorepats */
6371 if (first) { /* but, only need to do this once */
6373 first = 0;
6374 }
6375
6376 if (!new) {
6377 ast_log(LOG_ERROR,"Could not allocate a new context for %s in merge_and_delete! Danger!\n", context->name);
6378 ast_hashtab_end_traversal(prio_iter);
6379 ast_hashtab_end_traversal(exten_iter);
6380 return; /* no sense continuing. */
6381 }
6382 /* we will not replace existing entries in the new context with stuff from the old context.
6383 but, if this is because of some sort of registrar conflict, we ought to say something... */
6384
6385 dupdstr = ast_strdup(prio_item->data);
6386
6387 res1 = ast_add_extension2(new, 0, prio_item->name, prio_item->priority, prio_item->label,
6388 prio_item->matchcid ? prio_item->cidmatch : NULL, prio_item->app, dupdstr, ast_free_ptr, prio_item->registrar,
6389 prio_item->registrar_file, prio_item->registrar_line);
6390 if (!res1 && new_exten_item && new_prio_item){
6391 ast_verb(3,"Dropping old dialplan item %s/%s/%d [%s(%s)] (registrar=%s) due to conflict with new dialplan\n",
6392 context->name, prio_item->name, prio_item->priority, prio_item->app, (char*)prio_item->data, prio_item->registrar);
6393 } else {
6394 /* 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,
6395 and no double frees take place, either! */
6396 insert_count++;
6397 }
6398 }
6399 ast_hashtab_end_traversal(prio_iter);
6400 }
6401 ast_hashtab_end_traversal(exten_iter);
6402 } else if (new) {
6403 /* If the context existed but had no extensions, we still want to merge
6404 * the includes, switches and ignore patterns.
6405 */
6407 }
6408
6409 if (!insert_count && !new && (strcmp(context->registrar, registrar) != 0 ||
6410 (strcmp(context->registrar, registrar) == 0 && context->refcount > 1))) {
6411 /* we could have given it the registrar of the other module who incremented the refcount,
6412 but that's not available, so we give it the registrar we know about */
6413 new = ast_context_find_or_create(extcontexts, exttable, context->name, context->registrar);
6414
6415 if (new) {
6416 new->autohints = context->autohints;
6417 }
6418
6419 /* copy in the includes, switches, and ignorepats */
6421 }
6422}
struct sla_ringing_trunk * first
Definition: app_sla.c:332
static void context_merge_incls_swits_igps_other_registrars(struct ast_context *new, struct ast_context *old, const char *registrar)
Definition: pbx.c:6252
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:6149

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

6253{
6254 int idx;
6255
6256 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);
6257 /* copy in the includes, switches, and ignorepats */
6258 /* walk through includes */
6259 for (idx = 0; idx < ast_context_includes_count(old); idx++) {
6260 const struct ast_include *i = ast_context_includes_get(old, idx);
6261
6262 if (!strcmp(ast_get_include_registrar(i), registrar)) {
6263 continue; /* not mine */
6264 }
6266 }
6267
6268 /* walk through switches */
6269 for (idx = 0; idx < ast_context_switches_count(old); idx++) {
6270 const struct ast_sw *sw = ast_context_switches_get(old, idx);
6271
6272 if (!strcmp(ast_get_switch_registrar(sw), registrar)) {
6273 continue; /* not mine */
6274 }
6276 }
6277
6278 /* walk thru ignorepats ... */
6279 for (idx = 0; idx < ast_context_ignorepats_count(old); idx++) {
6280 const struct ast_ignorepat *ip = ast_context_ignorepats_get(old, idx);
6281
6282 if (strcmp(ast_get_ignorepat_registrar(ip), registrar) == 0) {
6283 continue; /* not mine */
6284 }
6286 }
6287}
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 6290 of file pbx.c.

6291{
6292 struct ast_context *con;
6293 struct ast_hashtab_iter *iter;
6294
6295 /* Remove all autohints as the below iteration will recreate them */
6297
6299 while ((con = ast_hashtab_next(iter))) {
6300 size_t name_len = strlen(con->name) + 1;
6301 size_t registrar_len = strlen(con->registrar) + 1;
6302 struct ast_autohint *autohint;
6303
6304 if (!con->autohints) {
6305 continue;
6306 }
6307
6308 autohint = ao2_alloc_options(sizeof(*autohint) + name_len + registrar_len, NULL, AO2_ALLOC_OPT_LOCK_NOLOCK);
6309 if (!autohint) {
6310 continue;
6311 }
6312
6313 ast_copy_string(autohint->context, con->name, name_len);
6314 autohint->registrar = autohint->context + name_len;
6315 ast_copy_string(autohint->registrar, con->registrar, registrar_len);
6316
6317 ao2_link(autohints, autohint);
6318 ao2_ref(autohint, -1);
6319
6320 ast_verb(3, "Enabled autohints support on context '%s'\n", con->name);
6321 }
6323}
@ 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:394
const char * registrar
Definition: pbx.c:286

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

1771{
1772 struct ast_hashtab_iter *t1;
1773 struct ast_exten *e1;
1774#ifdef NEED_DEBUG
1775 int biggest_bucket, resizes, numobjs, numbucks;
1776
1777 ast_debug(1, "Creating Extension Trie for context %s(%p)\n", con->name, con);
1778 ast_hashtab_get_stats(con->root_table, &biggest_bucket, &resizes, &numobjs, &numbucks);
1779 ast_debug(1, "This tree has %d objects in %d bucket lists, longest list=%d objects, and has resized %d times\n",
1780 numobjs, numbucks, biggest_bucket, resizes);
1781#endif
1783 while ((e1 = ast_hashtab_next(t1))) {
1784 if (e1->exten) {
1785 add_exten_to_pattern_tree(con, e1, 0);
1786 } else {
1787 ast_log(LOG_ERROR, "Attempt to create extension with no extension name.\n");
1788 }
1789 }
1791}
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 4666 of file pbx.c.

4667{
4669 if (countcalls > 0)
4670 countcalls--;
4672}
static ast_mutex_t maxcalllock
Definition: pbx.c:777

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

4675{
4676 if (e->priority == PRIORITY_HINT)
4677 ast_remove_hint(e);
4678
4679 if (e->peer_table)
4681 if (e->peer_label_table)
4683 if (e->datad)
4684 e->datad(e->data);
4685 ast_free(e);
4686}
static int ast_remove_hint(struct ast_exten *e)
Remove hint from extension.
Definition: pbx.c:3941

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

3904{
3905 struct ast_hint *hint = obj;
3906 int i;
3907
3908 ao2_cleanup(hint->callbacks);
3909
3910 for (i = 0; i < AST_VECTOR_SIZE(&hint->devices); i++) {
3911 char *device = AST_VECTOR_GET(&hint->devices, i);
3912 ast_free(device);
3913 }
3914 AST_VECTOR_FREE(&hint->devices);
3917}
#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 1793 of file pbx.c.

1794{
1795 /* destroy all the alternates */
1796 if (pattern_tree->alt_char) {
1797 destroy_pattern_tree(pattern_tree->alt_char);
1798 pattern_tree->alt_char = 0;
1799 }
1800 /* destroy all the nexts */
1801 if (pattern_tree->next_char) {
1802 destroy_pattern_tree(pattern_tree->next_char);
1803 pattern_tree->next_char = 0;
1804 }
1805 pattern_tree->exten = 0; /* never hurts to make sure there's no pointers laying around */
1806 ast_free(pattern_tree);
1807}

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

3715{
3716 struct ast_state_cb *state_cb = doomed;
3717
3718 if (state_cb->destroy_cb) {
3719 state_cb->destroy_cb(state_cb->id, state_cb->data);
3720 }
3721}
int id
Definition: pbx.c:310
ast_state_cb_destroy_type destroy_cb
Definition: pbx.c:318

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

3585{
3586 struct ast_device_state_message *dev_state;
3587 struct ast_str *hint_app;
3588 struct ast_hintdevice *device;
3589 struct ast_hintdevice *cmpdevice;
3590 struct ao2_iterator *dev_iter;
3591 struct ao2_iterator auto_iter;
3592 struct ast_autohint *autohint;
3593 char *virtual_device;
3594 char *type;
3595 char *device_name;
3596
3598 return;
3599 }
3600
3601 if (hint_remove_message_type() == stasis_message_type(msg)) {
3602 /* The extension has already been destroyed */
3603 struct ast_state_cb *state_cb;
3604 struct ao2_iterator cb_iter;
3605 struct ast_hint *hint = stasis_message_data(msg);
3606
3607 ao2_lock(hint);
3609 ao2_unlock(hint);
3610
3611 cb_iter = ao2_iterator_init(hint->callbacks, 0);
3612 for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_ref(state_cb, -1)) {
3614 hint->context_name,
3615 hint->exten_name,
3616 state_cb->data,
3618 hint,
3619 NULL);
3620 }
3621 ao2_iterator_destroy(&cb_iter);
3622 return;
3623 }
3624
3626 return;
3627 }
3628
3629 dev_state = stasis_message_data(msg);
3630 if (dev_state->eid) {
3631 /* ignore non-aggregate states */
3632 return;
3633 }
3634
3636 /* There are no hints monitoring devices. */
3637 return;
3638 }
3639
3640 hint_app = ast_str_create(1024);
3641 if (!hint_app) {
3642 return;
3643 }
3644
3645 cmpdevice = ast_alloca(sizeof(*cmpdevice) + strlen(dev_state->device));
3646 strcpy(cmpdevice->hintdevice, dev_state->device);
3647
3648 ast_mutex_lock(&context_merge_lock);/* Hold off ast_merge_contexts_and_delete */
3649
3650 /* Initially we find all hints for the device and notify them */
3651 dev_iter = ao2_t_callback(hintdevices,
3654 cmpdevice,
3655 "find devices in container");
3656 if (dev_iter) {
3657 for (; (device = ao2_iterator_next(dev_iter)); ao2_t_ref(device, -1, "Next device")) {
3658 if (device->hint) {
3659 device_state_notify_callbacks(device->hint, &hint_app);
3660 }
3661 }
3662 ao2_iterator_destroy(dev_iter);
3663 }
3664
3665 /* Second stage we look for any autohint contexts and if the device is not already in the hints
3666 * we create it.
3667 */
3668 type = ast_strdupa(dev_state->device);
3669 if (ast_strlen_zero(type)) {
3670 goto end;
3671 }
3672
3673 /* Determine if this is a virtual/custom device or a real device */
3674 virtual_device = strchr(type, ':');
3675 device_name = strchr(type, '/');
3676 if (virtual_device && (!device_name || (virtual_device < device_name))) {
3677 device_name = virtual_device;
3678 }
3679
3680 /* Invalid device state name - not a virtual/custom device and not a real device */
3681 if (ast_strlen_zero(device_name)) {
3682 goto end;
3683 }
3684
3685 *device_name++ = '\0';
3686
3687 auto_iter = ao2_iterator_init(autohints, 0);
3688 for (; (autohint = ao2_iterator_next(&auto_iter)); ao2_t_ref(autohint, -1, "Next autohint")) {
3689 if (ast_get_hint(NULL, 0, NULL, 0, NULL, autohint->context, device_name)) {
3690 continue;
3691 }
3692
3693 /* The device has no hint in the context referenced by this autohint so create one */
3694 ast_add_extension(autohint->context, 0, device_name,
3695 PRIORITY_HINT, NULL, NULL, dev_state->device,
3696 ast_strdup(dev_state->device), ast_free_ptr, autohint->registrar);
3697
3698 /* Since this hint was just created there are no watchers, so we don't need to notify anyone */
3699 }
3700 ao2_iterator_destroy(&auto_iter);
3701
3702end:
3704 ast_free(hint_app);
3705 return;
3706}
#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:3537
static void device_state_notify_callbacks(struct ast_hint *hint, struct ast_str **hint_app)
Definition: pbx.c:3370
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:4137
@ 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 3069 of file pbx.c.

3070{
3071 struct ast_device_state_info *info = obj;
3072
3073 ao2_cleanup(info->causing_channel);
3074}
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 3370 of file pbx.c.

3371{
3372 struct ao2_iterator cb_iter;
3373 struct ast_state_cb *state_cb;
3374 int state;
3375 int same_state;
3376 struct ao2_container *device_state_info;
3377 int first_extended_cb_call = 1;
3380
3381 ao2_lock(hint);
3382 if (!hint->exten) {
3383 /* The extension has already been destroyed */
3384 ao2_unlock(hint);
3385 return;
3386 }
3387
3388 /*
3389 * Save off strings in case the hint extension gets destroyed
3390 * while we are notifying the watchers.
3391 */
3394 sizeof(context_name));
3396 sizeof(exten_name));
3397 ast_str_set(hint_app, 0, "%s", ast_get_extension_app(hint->exten));
3398 ao2_unlock(hint);
3399
3400 /*
3401 * Get device state for this hint.
3402 *
3403 * NOTE: We cannot hold any locks while determining the hint
3404 * device state or notifying the watchers without causing a
3405 * deadlock. (conlock, hints, and hint)
3406 */
3407
3408 /* Make a container so state3 can fill it if we wish.
3409 * If that failed we simply do not provide the extended state info.
3410 */
3411 device_state_info = alloc_device_state_info();
3412
3413 state = ast_extension_state3(*hint_app, device_state_info);
3414 same_state = state == hint->laststate;
3415 if (same_state && (~state & AST_EXTENSION_RINGING)) {
3416 ao2_cleanup(device_state_info);
3417 return;
3418 }
3419
3420 /* Device state changed since last check - notify the watchers. */
3421 hint->laststate = state; /* record we saw the change */
3422
3423 /* For general callbacks */
3424 if (!same_state) {
3425 cb_iter = ao2_iterator_init(statecbs, 0);
3426 for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_ref(state_cb, -1)) {
3429 exten_name,
3430 state_cb->data,
3432 hint,
3433 NULL);
3434 }
3435 ao2_iterator_destroy(&cb_iter);
3436 }
3437
3438 /* For extension callbacks */
3439 /* extended callbacks are called when the state changed or when AST_STATE_RINGING is
3440 * included. Normal callbacks are only called when the state changed.
3441 */
3442 cb_iter = ao2_iterator_init(hint->callbacks, 0);
3443 for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_ref(state_cb, -1)) {
3444 if (state_cb->extended && first_extended_cb_call) {
3445 /* Fill detailed device_state_info now that we know it is used by extd. callback */
3446 first_extended_cb_call = 0;
3447 get_device_state_causing_channels(device_state_info);
3448 }
3449 if (state_cb->extended || !same_state) {
3452 exten_name,
3453 state_cb->data,
3455 hint,
3456 state_cb->extended ? device_state_info : NULL);
3457 }
3458 }
3459 ao2_iterator_destroy(&cb_iter);
3460
3461 ao2_cleanup(device_state_info);
3462}
#define AST_MAX_CONTEXT
Definition: channel.h:135
static const char exten_name[]
static const char context_name[]
int extended
Definition: pbx.c:314

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

2784{
2785 struct pbx_exception *exception = data;
2787 ast_free(exception);
2788}
#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 3250 of file pbx.c.

3257{
3258 int res = 0;
3259 struct ast_state_cb_info info = { 0, };
3260
3261 info.reason = reason;
3262
3263 /* Copy over current hint data */
3264 if (hint) {
3265 ao2_lock(hint);
3266 info.exten_state = hint->laststate;
3267 info.device_state_info = device_state_info;
3268 info.presence_state = hint->last_presence_state;
3269 if (!(ast_strlen_zero(hint->last_presence_subtype))) {
3270 info.presence_subtype = ast_strdupa(hint->last_presence_subtype);
3271 } else {
3272 info.presence_subtype = "";
3273 }
3274 if (!(ast_strlen_zero(hint->last_presence_message))) {
3275 info.presence_message = ast_strdupa(hint->last_presence_message);
3276 } else {
3277 info.presence_message = "";
3278 }
3279 ao2_unlock(hint);
3280 } else {
3281 info.exten_state = AST_EXTENSION_REMOVED;
3282 }
3283
3284 res = cb(context, exten, &info, data);
3285
3286 return res;
3287}
@ 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 2140 of file pbx.c.

2141{
2142 /* Make sure non-pattern extens come first. */
2143 if (left[0] != '_') {
2144 if (right[0] == '_') {
2145 return -1;
2146 }
2147 /* Compare two non-pattern extens. */
2148 return ext_cmp_exten(left, right);
2149 }
2150 if (right[0] != '_') {
2151 return 1;
2152 }
2153
2154 /*
2155 * OK, we need full pattern sorting routine.
2156 *
2157 * Skip past the underscores
2158 */
2159 return ext_cmp_pattern(left + 1, right + 1);
2160}

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

1891{
1892 int cmp;
1893
1894 for (;;) {
1895 /* Ignore '-' chars as eye candy fluff. */
1896 while (*left == '-') {
1897 ++left;
1898 }
1899 while (*right == '-') {
1900 ++right;
1901 }
1902
1903 cmp = *left - *right;
1904 if (cmp) {
1905 break;
1906 }
1907 if (!*left) {
1908 /*
1909 * Get here only if both strings ended at the same time. cmp
1910 * would be non-zero if only one string ended.
1911 */
1912 break;
1913 }
1914 ++left;
1915 ++right;
1916 }
1917 return cmp;
1918}

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

1848{
1849 int cmp;
1850
1851 for (;;) {
1852 /* Ignore '-' chars as eye candy fluff. */
1853 while (*left == '-') {
1854 ++left;
1855 }
1856 while (*right == '-') {
1857 ++right;
1858 }
1859
1860 if (!*right) {
1861 /*
1862 * Right ended first for partial match or both ended at the same
1863 * time for a match.
1864 */
1865 cmp = 0;
1866 break;
1867 }
1868
1869 cmp = *left - *right;
1870 if (cmp) {
1871 break;
1872 }
1873 ++left;
1874 ++right;
1875 }
1876 return cmp;
1877}

Referenced by _extension_match_core().

◆ ext_cmp_exten_strlen()

static int ext_cmp_exten_strlen ( const char *  str)
static

Definition at line 1817 of file pbx.c.

1818{
1819 int len;
1820
1821 len = 0;
1822 for (;;) {
1823 /* Ignore '-' chars as eye candy fluff. */
1824 while (*str == '-') {
1825 ++str;
1826 }
1827 if (!*str) {
1828 break;
1829 }
1830 ++str;
1831 ++len;
1832 }
1833 return len;
1834}
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 2092 of file pbx.c.

2093{
2094 int cmp;
2095 int left_pos;
2096 int right_pos;
2097
2098 for (;;) {
2099 unsigned char left_bitwise[32] = { 0, };
2100 unsigned char right_bitwise[32] = { 0, };
2101
2102 left_pos = ext_cmp_pattern_pos(&left, left_bitwise);
2103 right_pos = ext_cmp_pattern_pos(&right, right_bitwise);
2104 cmp = left_pos - right_pos;
2105 if (!cmp) {
2106 /*
2107 * Are the character sets different, even though they score the same?
2108 *
2109 * Note: Must swap left and right to get the sense of the
2110 * comparison correct. Otherwise, we would need to multiply by
2111 * -1 instead.
2112 */
2113 cmp = memcmp(right_bitwise, left_bitwise, ARRAY_LEN(left_bitwise));
2114 }
2115 if (cmp) {
2116 break;
2117 }
2118 if (!left) {
2119 /*
2120 * Get here only if both patterns ended at the same time. cmp
2121 * would be non-zero if only one pattern ended.
2122 */
2123 break;
2124 }
2125 }
2126 return cmp;
2127}
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:1977

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

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

2163{
2164 int fluff = 0;
2165
2166 if (*exten != '_') {
2167 /* not a pattern, simple check. */
2168 while (*exten) {
2169 if (*exten == '-') {
2170 fluff++;
2171 }
2172 exten++;
2173 }
2174
2175 return fluff;
2176 }
2177
2178 /* do pattern check */
2179 while (*exten) {
2180 if (*exten == '-') {
2181 fluff++;
2182 } else if (*exten == '[') {
2183 /* skip set, dashes here matter. */
2184 exten = strchr(exten, ']');
2185
2186 if (!exten) {
2187 /* we'll end up warning about this later, don't spam logs */
2188 return fluff;
2189 }
2190 }
2191 exten++;
2192 }
2193
2194 return fluff;
2195}

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

7027{
7028 unsigned int count;
7029 unsigned int insquares;
7030 unsigned int is_pattern;
7031
7032 if (!dst_size--) {
7033 /* There really is no dst buffer */
7034 return 0;
7035 }
7036
7037 count = 0;
7038 insquares = 0;
7039 is_pattern = *src == '_';
7040 while (*src && count < dst_size) {
7041 if (*src == '[') {
7042 if (is_pattern) {
7043 insquares = 1;
7044 }
7045 } else if (*src == ']') {
7046 insquares = 0;
7047 } else if (*src == ' ' && !insquares) {
7048 ++src;
7049 continue;
7050 } else if (*src == '-' && !insquares && nofluff) {
7051 ++src;
7052 continue;
7053 }
7054 *dst++ = *src++;
7055 ++count;
7056 }
7057 *dst = '\0';
7058
7059 return count + 1;
7060}

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

2415{
2416 int i;
2417 static int prof_id = -2; /* marker for 'unallocated' id */
2418 if (prof_id == -2) {
2419 prof_id = ast_add_profile("ext_match", 0);
2420 }
2421 ast_mark(prof_id, 1);
2422 i = _extension_match_core(ast_strlen_zero(pattern) ? "" : pattern, ast_strlen_zero(data) ? "" : data, mode);
2423 ast_mark(prof_id, 0);
2424 return i;
2425}
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:2223

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

3201{
3202 struct ast_str *hint_app = ast_str_thread_get(&extensionstate_buf, 32);
3203 char *presence_provider;
3204 const char *app;
3205
3206 if (!e || !hint_app) {
3207 return -1;
3208 }
3209
3211 if (ast_strlen_zero(app)) {
3212 return -1;
3213 }
3214
3215 ast_str_set(&hint_app, 0, "%s", app);
3216 presence_provider = parse_hint_presence(hint_app);
3217
3218 if (ast_strlen_zero(presence_provider)) {
3219 /* No presence string in the hint */
3220 return 0;
3221 }
3222
3223 return ast_presence_state(presence_provider, subtype, message);
3224}
static char * parse_hint_presence(struct ast_str *hint_args)
Definition: pbx.c:3037
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 3727 of file pbx.c.

3729{
3730 struct ast_hint *hint;
3731 struct ast_state_cb *state_cb;
3732 struct ast_exten *e;
3733 int id;
3734
3735 /* If there's no context and extension: add callback to statecbs list */
3736 if (!context && !exten) {
3737 /* Prevent multiple adds from adding the same change_cb at the same time. */
3739
3740 /* Remove any existing change_cb. */
3741 ao2_find(statecbs, change_cb, OBJ_UNLINK | OBJ_NODATA);
3742
3743 /* Now insert the change_cb */
3744 if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) {
3746 return -1;
3747 }
3748 state_cb->id = 0;
3749 state_cb->change_cb = change_cb;
3750 state_cb->destroy_cb = destroy_cb;
3751 state_cb->data = data;
3752 state_cb->extended = extended;
3753 ao2_link(statecbs, state_cb);
3754
3755 ao2_ref(state_cb, -1);
3757 return 0;
3758 }
3759
3760 if (!context || !exten)
3761 return -1;
3762
3763 /* This callback type is for only one hint, so get the hint */
3765 if (!e) {
3766 return -1;
3767 }
3768
3769 /* If this is a pattern, dynamically create a new extension for this
3770 * particular match. Note that this will only happen once for each
3771 * individual extension, because the pattern will no longer match first.
3772 */
3773 if (e->exten[0] == '_') {
3774 ao2_lock(hints);
3776 e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr,
3777 e->registrar);
3780 if (!e || e->exten[0] == '_') {
3781 return -1;
3782 }
3783 }
3784
3785 /* Find the hint in the hints container */
3786 ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */
3787 hint = ao2_find(hints, e, 0);
3788 if (!hint) {
3790 return -1;
3791 }
3792
3793 /* Now insert the callback in the callback list */
3794 if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) {
3795 ao2_ref(hint, -1);
3797 return -1;
3798 }
3799 do {
3800 id = stateid++; /* Unique ID for this callback */
3801 /* Do not allow id to ever be -1 or 0. */
3802 } while (id == -1 || id == 0);
3803 state_cb->id = id;
3804 state_cb->change_cb = change_cb; /* Pointer to callback routine */
3805 state_cb->destroy_cb = destroy_cb;
3806 state_cb->data = data; /* Data for the callback */
3807 state_cb->extended = extended;
3808 ao2_link(hint->callbacks, state_cb);
3809
3810 ao2_ref(state_cb, -1);
3811 ao2_ref(hint, -1);
3813
3814 return id;
3815}
enum queue_result id
Definition: app_queue.c:1638
static int stateid
Definition: pbx.c:797
static void destroy_state_cb(void *doomed)
Definition: pbx.c:3714

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

4801{
4802 struct ast_context item = {
4803 .name = context,
4804 };
4805
4807}

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

4815{
4816 struct ast_context *c;
4817 struct ast_context item = {
4818 .name = context,
4819 };
4820
4823 if (!c) {
4825 }
4826
4827 return c;
4828}

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

3843{
3844 struct ast_state_cb *state_cb;
3845 const struct ast_hint *hint = obj;
3846 int *id = arg;
3847
3848 if ((state_cb = ao2_find(hint->callbacks, id, 0))) {
3849 ao2_ref(state_cb, -1);
3850 return CMP_MATCH | CMP_STOP;
3851 }
3852
3853 return 0;
3854}

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

1147{
1148 /* find the exten at the end of the rope */
1149 struct match_char *node2 = node;
1150
1151 for (node2 = node; node2; node2 = node2->next_char) {
1152 if (node2->exten) {
1153#ifdef NEED_DEBUG_HERE
1154 ast_log(LOG_NOTICE,"CanMatch_exten returns exten %s(%p)\n", node2->exten->exten, node2->exten);
1155#endif
1156 return node2->exten;
1157 }
1158 }
1159#ifdef NEED_DEBUG_HERE
1160 ast_log(LOG_NOTICE,"CanMatch_exten returns NULL, match_char=%s\n", node->x);
1161#endif
1162 return 0;
1163}

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

3297{
3298 struct ao2_iterator iter;
3300 struct ast_channel *chan;
3301
3302 if (!c || !ao2_container_count(c)) {
3303 return;
3304 }
3305 iter = ao2_iterator_init(c, 0);
3306 for (; (info = ao2_iterator_next(&iter)); ao2_ref(info, -1)) {
3307 enum ast_channel_state search_state = 0; /* prevent false uninit warning */
3308 char match[AST_CHANNEL_NAME];
3309 struct ast_channel_iterator *chan_iter;
3310 struct timeval chantime = {0, }; /* prevent false uninit warning */
3311
3312 switch (info->device_state) {
3313 case AST_DEVICE_RINGING:
3315 /* find ringing channel */
3316 search_state = AST_STATE_RINGING;
3317 break;
3318 case AST_DEVICE_BUSY:
3319 /* find busy channel */
3320 search_state = AST_STATE_BUSY;
3321 break;
3322 case AST_DEVICE_ONHOLD:
3323 case AST_DEVICE_INUSE:
3324 /* find up channel */
3325 search_state = AST_STATE_UP;
3326 break;
3327 case AST_DEVICE_UNKNOWN:
3329 case AST_DEVICE_INVALID:
3331 case AST_DEVICE_TOTAL /* not a state */:
3332 /* no channels are of interest */
3333 continue;
3334 }
3335
3336 /* iterate over all channels of the device */
3337 snprintf(match, sizeof(match), "%s-", info->device_name);
3338 chan_iter = ast_channel_iterator_by_name_new(match, strlen(match));
3339 for (; (chan = ast_channel_iterator_next(chan_iter)); ast_channel_unref(chan)) {
3340 ast_channel_lock(chan);
3341 /* this channel's state doesn't match */
3342 if (search_state != ast_channel_state(chan)) {
3343 ast_channel_unlock(chan);
3344 continue;
3345 }
3346 /* any non-ringing channel will fit */
3347 if (search_state != AST_STATE_RINGING) {
3348 ast_channel_unlock(chan);
3349 info->causing_channel = chan; /* is kept ref'd! */
3350 break;
3351 }
3352 /* but we need the oldest ringing channel of the device to match with undirected pickup */
3353 if (!info->causing_channel) {
3354 chantime = ast_channel_creationtime(chan);
3355 ast_channel_ref(chan); /* must ref it! */
3356 info->causing_channel = chan;
3357 } else if (ast_tvcmp(ast_channel_creationtime(chan), chantime) < 0) {
3358 chantime = ast_channel_creationtime(chan);
3359 ast_channel_unref(info->causing_channel);
3360 ast_channel_ref(chan); /* must ref it! */
3361 info->causing_channel = chan;
3362 }
3363 ast_channel_unlock(chan);
3364 }
3366 }
3367 ao2_iterator_destroy(&iter);
3368}
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:2365
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:1388
struct ast_channel_iterator * ast_channel_iterator_destroy(struct ast_channel_iterator *i)
Destroy a channel iterator.
Definition: channel.c:1360
struct ast_channel * ast_channel_iterator_next(struct ast_channel_iterator *i)
Get the next channel for a channel iterator.
Definition: channel.c:1422
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2947
struct timeval ast_channel_creationtime(struct ast_channel *chan)
#define AST_CHANNEL_NAME
Definition: channel.h:171
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 1518 of file pbx.c.

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

5751{
5752 char *exten = NULL, *context = NULL;
5753 /* Variables used for different counters */
5754 struct dialplan_counters counters;
5755 const char *incstack[AST_PBX_MAX_STACK];
5756
5757 switch (cmd) {
5758 case CLI_INIT:
5759 e->command = "dialplan debug";
5760 e->usage =
5761 "Usage: dialplan debug [context]\n"
5762 " Show dialplan context Trie(s). Usually only useful to folks debugging the deep internals of the fast pattern matcher\n";
5763 return NULL;
5764 case CLI_GENERATE:
5765 return complete_show_dialplan_context(a->line, a->word, a->pos, a->n);
5766 }
5767
5768 memset(&counters, 0, sizeof(counters));
5769
5770 if (a->argc != 2 && a->argc != 3)
5771 return CLI_SHOWUSAGE;
5772
5773 /* we obtain [exten@]context? if yes, split them ... */
5774 /* note: we ignore the exten totally here .... */
5775 if (a->argc == 3) {
5776 if (strchr(a->argv[2], '@')) { /* split into exten & context */
5777 context = ast_strdupa(a->argv[2]);
5778 exten = strsep(&context, "@");
5779 /* change empty strings to NULL */
5780 if (ast_strlen_zero(exten))
5781 exten = NULL;
5782 } else { /* no '@' char, only context given */
5783 context = ast_strdupa(a->argv[2]);
5784 }
5786 context = NULL;
5787 }
5788 /* else Show complete dial plan, context and exten are NULL */
5789 show_debug_helper(a->fd, context, exten, &counters, NULL, 0, incstack);
5790
5791 /* check for input failure and throw some error messages */
5792 if (context && !counters.context_existence) {
5793 ast_cli(a->fd, "There is no existence of '%s' context\n", context);
5794 return CLI_FAILURE;
5795 }
5796
5797
5798 ast_cli(a->fd,"-= %d %s. =-\n",
5799 counters.total_context, counters.total_context == 1 ? "context" : "contexts");
5800
5801 /* everything ok */
5802 return CLI_SUCCESS;
5803}
#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:5398
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:5628
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
Counters for the show dialplan manager command.
Definition: pbx.c:5428

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

3538{
3539 struct ast_hint *hint;
3540 struct ast_str *hint_app;
3541
3542 if (hint_change_message_type() != stasis_message_type(msg)) {
3543 return 0;
3544 }
3545
3546 if (!(hint_app = ast_str_create(1024))) {
3547 return -1;
3548 }
3549
3550 hint = stasis_message_data(msg);
3551
3552 switch (reason) {
3554 device_state_notify_callbacks(hint, &hint_app);
3555 break;
3557 {
3558 char *presence_subtype = NULL;
3559 char *presence_message = NULL;
3560 int state;
3561
3563 hint->exten, &presence_subtype, &presence_message);
3564 {
3565 struct ast_presence_state_message presence_state = {
3567 .subtype = presence_subtype,
3568 .message = presence_message
3569 };
3570
3571 presence_state_notify_callbacks(hint, &hint_app, &presence_state);
3572 }
3573
3574 ast_free(presence_subtype);
3575 ast_free(presence_message);
3576 }
3577 break;
3578 }
3579
3580 ast_free(hint_app);
3581 return 1;
3582}
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:3464
@ 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 6056 of file pbx.c.

6057{
6058 int oldval = 0;
6059
6060 switch (cmd) {
6061 case CLI_INIT:
6062 e->command = "dialplan set extenpatternmatchnew true";
6063 e->usage =
6064 "Usage: dialplan set extenpatternmatchnew true|false\n"
6065 " Use the NEW extension pattern matching algorithm, true or false.\n";
6066 return NULL;
6067 case CLI_GENERATE:
6068 return NULL;
6069 }
6070
6071 if (a->argc != 4)
6072 return CLI_SHOWUSAGE;
6073
6074 oldval = pbx_set_extenpatternmatchnew(1);
6075
6076 if (oldval)
6077 ast_cli(a->fd, "\n -- Still using the NEW pattern match algorithm for extension names in the dialplan.\n");
6078 else
6079 ast_cli(a->fd, "\n -- Switched to using the NEW pattern match algorithm for extension names in the dialplan.\n");
6080
6081 return CLI_SUCCESS;
6082}
int pbx_set_extenpatternmatchnew(int newval)
Definition: pbx.c:4777

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

5684{
5685 char *exten = NULL, *context = NULL;
5686 /* Variables used for different counters */
5687 struct dialplan_counters counters;
5688 const char *incstack[AST_PBX_MAX_STACK];
5689
5690 switch (cmd) {
5691 case CLI_INIT:
5692 e->command = "dialplan show";
5693 e->usage =
5694 "Usage: dialplan show [[exten@]context]\n"
5695 " Show dialplan\n";
5696 return NULL;
5697 case CLI_GENERATE:
5698 return complete_show_dialplan_context(a->line, a->word, a->pos, a->n);
5699 }
5700
5701 memset(&counters, 0, sizeof(counters));
5702
5703 if (a->argc != 2 && a->argc != 3)
5704 return CLI_SHOWUSAGE;
5705
5706 /* we obtain [exten@]context? if yes, split them ... */
5707 if (a->argc == 3) {
5708 if (strchr(a->argv[2], '@')) { /* split into exten & context */
5709 context = ast_strdupa(a->argv[2]);
5710 exten = strsep(&context, "@");
5711 /* change empty strings to NULL */
5712 if (ast_strlen_zero(exten))
5713 exten = NULL;
5714 } else { /* no '@' char, only context given */
5715 context = ast_strdupa(a->argv[2]);
5716 }
5718 context = NULL;
5719 }
5720 /* else Show complete dial plan, context and exten are NULL */
5721 show_dialplan_helper(a->fd, context, exten, &counters, NULL, 0, incstack);
5722
5723 /* check for input failure and throw some error messages */
5724 if (context && !counters.context_existence) {
5725 ast_cli(a->fd, "There is no existence of '%s' context\n", context);
5726 return CLI_FAILURE;
5727 }
5728
5729 if (exten && !counters.extension_existence) {
5730 if (context)
5731 ast_cli(a->fd, "There is no existence of %s@%s extension\n",
5732 exten, context);
5733 else
5734 ast_cli(a->fd,
5735 "There is no existence of '%s' extension in all contexts\n",
5736 exten);
5737 return CLI_FAILURE;
5738 }
5739
5740 ast_cli(a->fd,"-= %d %s (%d %s) in %d %s. =-\n",
5741 counters.total_exten, counters.total_exten == 1 ? "extension" : "extensions",
5742 counters.total_prio, counters.total_prio == 1 ? "priority" : "priorities",
5743 counters.total_context, counters.total_context == 1 ? "context" : "contexts");
5744
5745 /* everything ok */
5746 return CLI_SUCCESS;
5747}
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:5467

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

5256{
5257 struct ast_hint *hint;
5258 int watchers;
5259 int num = 0, extenlen;
5260 struct ao2_iterator i;
5262
5263 switch (cmd) {
5264 case CLI_INIT:
5265 e->command = "core show hint";
5266 e->usage =
5267 "Usage: core show hint <exten>\n"
5268 " List registered hint.\n"
5269 " Hint details are shown in five columns. In order from left to right, they are:\n"
5270 " 1. Hint extension URI.\n"
5271 " 2. List of mapped device or presence state identifiers.\n"
5272 " 3. Current extension state. The aggregate of mapped device states.\n"
5273 " 4. Current presence state for the mapped presence state provider.\n"
5274 " 5. Watchers - number of subscriptions and other entities watching this hint.\n";
5275 return NULL;
5276 case CLI_GENERATE:
5277 return complete_core_show_hint(a->line, a->word, a->pos, a->n);
5278 }
5279
5280 if (a->argc < 4)
5281 return CLI_SHOWUSAGE;
5282
5283 if (ao2_container_count(hints) == 0) {
5284 ast_cli(a->fd, "There are no registered dialplan hints\n");
5285 return CLI_SUCCESS;
5286 }
5287
5288 extenlen = strlen(a->argv[3]);
5289 i = ao2_iterator_init(hints, 0);
5290 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
5291 ao2_lock(hint);
5292 if (!hint->exten) {
5293 /* The extension has already been destroyed */
5294 ao2_unlock(hint);
5295 continue;
5296 }
5297 if (!strncasecmp(ast_get_extension_name(hint->exten), a->argv[3], extenlen)) {
5298 watchers = ao2_container_count(hint->callbacks);
5299 sprintf(buf, "%s@%s",
5302 ast_cli(a->fd, "%-20.20s: %-20.20s State:%-15.15s Presence:%-15.15s Watchers %2d\n",
5303 buf,
5307 watchers);
5308 num++;
5309 }
5310 ao2_unlock(hint);
5311 }
5313 if (!num)
5314 ast_cli(a->fd, "No hints matching extension %s\n", a->argv[3]);
5315 else
5316 ast_cli(a->fd, "%d hint%s matching extension %s\n", num, (num!=1 ? "s":""), a->argv[3]);
5317 return CLI_SUCCESS;
5318}
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:5219
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 5156 of file pbx.c.

5157{
5158 struct ast_hint *hint;
5159 int num = 0;
5160 int watchers;
5161 struct ao2_iterator i;
5163
5164 switch (cmd) {
5165 case CLI_INIT:
5166 e->command = "core show hints";
5167 e->usage =
5168 "Usage: core show hints\n"
5169 " List registered hints.\n"
5170 " Hint details are shown in five columns. In order from left to right, they are:\n"
5171 " 1. Hint extension URI.\n"
5172 " 2. List of mapped device or presence state identifiers.\n"
5173 " 3. Current extension state. The aggregate of mapped device states.\n"
5174 " 4. Current presence state for the mapped presence state provider.\n"
5175 " 5. Watchers - number of subscriptions and other entities watching this hint.\n";
5176 return NULL;
5177 case CLI_GENERATE:
5178 return NULL;
5179 }
5180
5181 if (ao2_container_count(hints) == 0) {
5182 ast_cli(a->fd, "There are no registered dialplan hints\n");
5183 return CLI_SUCCESS;
5184 }
5185 /* ... we have hints ... */
5186 ast_cli(a->fd, "\n -= Registered Asterisk Dial Plan Hints =-\n");
5187
5188 i = ao2_iterator_init(hints, 0);
5189 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
5190 ao2_lock(hint);
5191 if (!hint->exten) {
5192 /* The extension has already been destroyed */
5193 ao2_unlock(hint);
5194 continue;
5195 }
5196 watchers = ao2_container_count(hint->callbacks);
5197 snprintf(buf, sizeof(buf), "%s@%s",
5200
5201 ast_cli(a->fd, "%-20.20s: %-20.20s State:%-15.15s Presence:%-15.15s Watchers %2d\n",
5202 buf,
5206 watchers);
5207
5208 ao2_unlock(hint);
5209 num++;
5210 }
5212
5213 ast_cli(a->fd, "----------------\n");
5214 ast_cli(a->fd, "- %d hints registered\n", num);
5215 return CLI_SUCCESS;
5216}

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

6085{
6086 int oldval = 0;
6087
6088 switch (cmd) {
6089 case CLI_INIT:
6090 e->command = "dialplan set extenpatternmatchnew false";
6091 e->usage =
6092 "Usage: dialplan set extenpatternmatchnew true|false\n"
6093 " Use the NEW extension pattern matching algorithm, true or false.\n";
6094 return NULL;
6095 case CLI_GENERATE:
6096 return NULL;
6097 }
6098
6099 if (a->argc != 4)
6100 return CLI_SHOWUSAGE;
6101
6102 oldval = pbx_set_extenpatternmatchnew(0);
6103
6104 if (!oldval)
6105 ast_cli(a->fd, "\n -- Still using the OLD pattern match algorithm for extension names in the dialplan.\n");
6106 else
6107 ast_cli(a->fd, "\n -- Switched to using the OLD pattern match algorithm for extension names in the dialplan.\n");
6108
6109 return CLI_SUCCESS;
6110}

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

734{
735 const struct ast_exten *ac = ah_a;
736 const struct ast_exten *bc = ah_b;
737 return strcmp(S_OR(ac->label, ""), S_OR(bc->label, ""));
738}
#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 726 of file pbx.c.

727{
728 const struct ast_exten *ac = ah_a;
729 const struct ast_exten *bc = ah_b;
730 return ac->priority != bc->priority;
731}

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

699{
700 const struct ast_exten *ac = ah_a;
701 const struct ast_exten *bc = ah_b;
702 int x = strcmp(ac->exten, bc->exten);
703 if (x) { /* if exten names are diff, then return */
704 return x;
705 }
706
707 /* but if they are the same, do the cidmatch values match? */
708 /* not sure which side may be using ast_ext_matchcid_types, so check both */
709 if (ac->matchcid == AST_EXT_MATCHCID_ANY || bc->matchcid == AST_EXT_MATCHCID_ANY) {
710 return 0;
711 }
712 if (ac->matchcid == AST_EXT_MATCHCID_OFF && bc->matchcid == AST_EXT_MATCHCID_OFF) {
713 return 0;
714 }
715 if (ac->matchcid != bc->matchcid) {
716 return 1;
717 }
718 /* all other cases already disposed of, match now required on callerid string (cidmatch) */
719 /* although ast_add_extension2_lockopt() enforces non-zero ptr, caller may not have */
720 if (ast_strlen_zero(ac->cidmatch) && ast_strlen_zero(bc->cidmatch)) {
721 return 0;
722 }
723 return strcmp(ac->cidmatch, bc->cidmatch);
724}

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

747{
748 const struct ast_exten *ac = obj;
749 unsigned int x = ast_hashtab_hash_string(ac->exten);
750 unsigned int y = 0;
751 if (ac->matchcid == AST_EXT_MATCHCID_ON)
753 return x+y;
754}

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

763{
764 const struct ast_exten *ac = obj;
765 return ast_hashtab_hash_string(S_OR(ac->label, ""));
766}

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

757{
758 const struct ast_exten *ac = obj;
759 return ast_hashtab_hash_int(ac->priority);
760}
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 8896 of file pbx.c.

8897{
8898 const struct ast_hint *hint = obj;
8899 const struct ast_exten *exten = arg;
8900
8901 return (hint->exten == exten) ? CMP_MATCH | CMP_STOP : 0;
8902}

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

8877{
8878 const struct ast_hint *hint = obj;
8879 const char *exten_name;
8880 int res;
8881
8884 /*
8885 * If the exten or extension name isn't set, return 0 so that
8886 * the ao2_find() search will start in the first bucket.
8887 */
8888 res = 0;
8889 } else {
8891 }
8892
8893 return res;
8894}

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

3890{
3891 const struct ast_state_cb *cb = obj;
3892 int *id = arg;
3893
3894 return (cb->id == *id) ? CMP_MATCH | CMP_STOP : 0;
3895}

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

429{
430 struct ast_hintdevice *left = obj;
431 struct ast_hintdevice *right = arg;
432 const char *right_key = arg;
433 int cmp;
434
435 switch (flags & OBJ_SEARCH_MASK) {
437 right_key = right->hintdevice;
438 /* Fall through */
439 case OBJ_SEARCH_KEY:
440 cmp = strcasecmp(left->hintdevice, right_key);
441 break;
443 /*
444 * We could also use a partial key struct containing a length
445 * so strlen() does not get called for every comparison instead.
446 */
447 cmp = strncmp(left->hintdevice, right_key, strlen(right_key));
448 break;
449 default:
450 ast_assert(0);
451 cmp = 0;
452 break;
453 }
454 return cmp ? 0 : CMP_MATCH;
455}

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

546{
547 struct ast_hintdevice *doomed = obj;
548
549 if (doomed->hint) {
550 ao2_ref(doomed->hint, -1);
551 doomed->hint = NULL;
552 }
553}

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

403{
404 const struct ast_hintdevice *ext;
405 const char *key;
406
407 switch (flags & OBJ_SEARCH_MASK) {
408 case OBJ_SEARCH_KEY:
409 key = obj;
410 break;
412 ext = obj;
413 key = ext->hintdevice;
414 break;
415 default:
416 ast_assert(0);
417 return 0;
418 }
419
420 return ast_str_case_hash(key);
421}
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 511 of file pbx.c.

512{
513 struct ast_hintdevice *candidate = obj;
514 char *device = arg;
515 struct ast_hint *hint = data;
516
517 if (!strcasecmp(candidate->hintdevice, device)
518 && candidate->hint == hint) {
519 return CMP_MATCH;
520 }
521 return 0;
522}

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

4618{
4619 int failed = 0;
4620 double curloadavg;
4621#if defined(HAVE_SYSINFO)
4622 struct sysinfo sys_info;
4623#endif
4624
4626 if (ast_option_maxcalls) {
4628 ast_log(LOG_WARNING, "Maximum call limit of %d calls exceeded by '%s'!\n", ast_option_maxcalls, ast_channel_name(c));
4629 failed = -1;
4630 }
4631 }
4632 if (ast_option_maxload) {
4633 getloadavg(&curloadavg, 1);
4634 if (curloadavg >= ast_option_maxload) {
4635 ast_log(LOG_WARNING, "Maximum loadavg limit of %f load exceeded by '%s' (currently %f)!\n", ast_option_maxload, ast_channel_name(c), curloadavg);
4636 failed = -1;
4637 }
4638 }
4639#if defined(HAVE_SYSINFO)
4640 if (option_minmemfree) {
4641 /* Make sure that the free system memory is above the configured low watermark */
4642 if (!sysinfo(&sys_info)) {
4643 /* Convert the amount of available RAM from mem_units to MB. The calculation
4644 * was done this way to avoid overflow problems */
4645 uint64_t curfreemem = sys_info.freeram + sys_info.bufferram;
4646 curfreemem *= sys_info.mem_unit;
4647 curfreemem /= 1024 * 1024;
4648 if (curfreemem < option_minmemfree) {
4649 ast_log(LOG_WARNING, "Available system memory (~%" PRIu64 "MB) is below the configured low watermark (%ldMB)\n",
4650 curfreemem, option_minmemfree);
4651 failed = -1;
4652 }
4653 }
4654 }
4655#endif
4656
4657 if (!failed) {
4658 countcalls++;
4659 totalcalls++;
4660 }
4662
4663 return failed;
4664}
int ast_option_maxcalls
Definition: options.c:79
double ast_option_maxload
Definition: options.c:77
long option_minmemfree
Definition: options.c:86
int getloadavg(double *list, int nelem)

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

1424{
1425 struct match_char *curr, *lcurr;
1426
1427 /* insert node into the tree at "current", so the alt_char list from current is
1428 sorted in increasing value as you go to the leaves */
1429 if (!(*parent_ptr)) {
1430 *parent_ptr = node;
1431 return;
1432 }
1433
1434 if ((*parent_ptr)->specificity > node->specificity) {
1435 /* insert at head */
1436 node->alt_char = (*parent_ptr);
1437 *parent_ptr = node;
1438 return;
1439 }
1440
1441 lcurr = *parent_ptr;
1442 for (curr = (*parent_ptr)->alt_char; curr; curr = curr->alt_char) {
1443 if (curr->specificity > node->specificity) {
1444 node->alt_char = curr;
1445 lcurr->alt_char = node;
1446 break;
1447 }
1448 lcurr = curr;
1449 }
1450
1451 if (!curr) {
1452 lcurr->alt_char = node;
1453 }
1454
1455}

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

3143{
3144 struct ast_exten *e;
3145
3146 if (!(e = ast_hint_extension(c, context, exten))) { /* Do we have a hint for this extension ? */
3147 return -1; /* No hint, return -1 */
3148 }
3149
3150 if (e->exten[0] == '_') {
3151 /* Create this hint on-the-fly, we explicitly lock hints here to ensure the
3152 * same locking order as if this were done through configuration file - that is
3153 * hints is locked first and then (if needed) contexts is locked
3154 */
3155 ao2_lock(hints);
3157 e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr,
3158 e->registrar);
3160 if (!(e = ast_hint_extension(c, context, exten))) {
3161 /* Improbable, but not impossible */
3162 return -1;
3163 }
3164 }
3165
3166 return ast_extension_state2(e, device_state_info); /* Check all devices in the hint */
3167}

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

8422{
8423 int res = 0;
8424
8426
8427 /* Initialize the PBX */
8428 ast_verb(1, "Asterisk PBX Core Initializing\n");
8429
8430 ast_verb(5, "Registering builtin functions:\n");
8434
8435 /* Register manager application */
8438
8439 if (res) {
8440 return -1;
8441 }
8442
8444 return -1;
8445 }
8447 stasis_subscription_accept_message_type(device_state_sub, hint_change_message_type());
8448 stasis_subscription_accept_message_type(device_state_sub, hint_remove_message_type());
8450
8452 return -1;
8453 }
8456
8457 return 0;
8458}
#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:668
#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:202
#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:5970
static int action_extensionstatelist(struct mansession *s, const struct message *m)
Definition: pbx.c:8344
static struct stasis_subscription * presence_state_sub
Subscription for presence state change events.
Definition: pbx.c:775
static void presence_state_cb(void *unused, struct stasis_subscription *sub, struct stasis_message *msg)
Definition: pbx.c:8294
static void unload_pbx(void)
Definition: pbx.c:8409
static struct ast_custom_function testtime_function
Definition: pbx.c:8277
static void device_state_cb(void *unused, struct stasis_subscription *sub, struct stasis_message *msg)
Definition: pbx.c:3584
static struct ast_cli_entry pbx_cli[]
Definition: pbx.c:6115
static struct stasis_subscription * device_state_sub
Subscription for device state change events.
Definition: pbx.c:773
static struct ast_custom_function exception_function
Definition: pbx.c:2852
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:1023
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:1077
#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 5806 of file pbx.c.

5807{
5808 astman_send_listack(s, m, "DialPlan list will follow", "start");
5809}

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

5971{
5972 const char *exten, *context;
5973 const char *id = astman_get_header(m, "ActionID");
5974 const char *incstack[AST_PBX_MAX_STACK];
5975 char idtext[256];
5976
5977 /* Variables used for different counters */
5978 struct dialplan_counters counters;
5979
5980 if (!ast_strlen_zero(id))
5981 snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id);
5982 else
5983 idtext[0] = '\0';
5984
5985 memset(&counters, 0, sizeof(counters));
5986
5987 exten = astman_get_header(m, "Extension");
5988 context = astman_get_header(m, "Context");
5989
5990 manager_show_dialplan_helper(s, m, idtext, context, exten, &counters, NULL, 0, incstack);
5991
5992 if (!ast_strlen_zero(context) && !counters.context_existence) {
5993 char errorbuf[BUFSIZ];
5994
5995 snprintf(errorbuf, sizeof(errorbuf), "Did not find context %s", context);
5996 astman_send_error(s, m, errorbuf);
5997 return 0;
5998 }
5999 if (!ast_strlen_zero(exten) && !counters.extension_existence) {
6000 char errorbuf[BUFSIZ];
6001
6003 snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s@%s", exten, context);
6004 else
6005 snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s in any context", exten);
6006 astman_send_error(s, m, errorbuf);
6007 return 0;
6008 }
6009
6010 if (!counters.total_items) {
6011 manager_dpsendack(s, m);
6012 }
6013
6014 astman_send_list_complete_start(s, m, "ShowDialPlanComplete", counters.total_items);
6015 astman_append(s,
6016 "ListExtensions: %d\r\n"
6017 "ListPriorities: %d\r\n"
6018 "ListContexts: %d\r\n",
6019 counters.total_exten, counters.total_prio, counters.total_context);
6021
6022 /* everything ok */
6023 return 0;
6024}
static void manager_dpsendack(struct mansession *s, const struct message *m)
Send ack once.
Definition: pbx.c:5806
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:5815

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

5820{
5821 struct ast_context *c;
5822 int res = 0, old_total_exten = dpc->total_exten;
5823
5824 if (ast_strlen_zero(exten))
5825 exten = NULL;
5827 context = NULL;
5828
5829 ast_debug(3, "manager_show_dialplan: Context: -%s- Extension: -%s-\n", context, exten);
5830
5831 /* try to lock contexts */
5832 if (ast_rdlock_contexts()) {
5833 astman_send_error(s, m, "Failed to lock contexts");
5834 ast_log(LOG_WARNING, "Failed to lock contexts list for manager: listdialplan\n");
5835 return -1;
5836 }
5837
5838 c = NULL; /* walk all contexts ... */
5839 while ( (c = ast_walk_contexts(c)) ) {
5840 int idx;
5841 struct ast_exten *e;
5842
5843 if (context && strcmp(ast_get_context_name(c), context) != 0)
5844 continue; /* not the name we want */
5845
5846 dpc->context_existence = 1;
5847 dpc->total_context++;
5848
5849 ast_debug(3, "manager_show_dialplan: Found Context: %s \n", ast_get_context_name(c));
5850
5851 if (ast_rdlock_context(c)) { /* failed to lock */
5852 ast_debug(3, "manager_show_dialplan: Failed to lock context\n");
5853 continue;
5854 }
5855
5856 /* XXX note- an empty context is not printed */
5857 e = NULL; /* walk extensions in context */
5858 while ( (e = ast_walk_context_extensions(c, e)) ) {
5859 struct ast_exten *p;
5860
5861 /* looking for extension? is this our extension? */
5863 /* not the one we are looking for, continue */
5864 ast_debug(3, "manager_show_dialplan: Skipping extension %s\n", ast_get_extension_name(e));
5865 continue;
5866 }
5867 ast_debug(3, "manager_show_dialplan: Found Extension: %s \n", ast_get_extension_name(e));
5868
5869 dpc->extension_existence = 1;
5870
5871 dpc->total_exten++;
5872
5873 p = NULL; /* walk next extension peers */
5874 while ( (p = ast_walk_extension_priorities(e, p)) ) {
5875 int prio = ast_get_extension_priority(p);
5876
5877 dpc->total_prio++;
5878 if (!dpc->total_items++)
5879 manager_dpsendack(s, m);
5880 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
5881 astman_append(s, "Context: %s\r\nExtension: %s\r\n", ast_get_context_name(c), ast_get_extension_name(e) );
5882
5883 /* XXX maybe make this conditional, if p != e ? */
5885 astman_append(s, "ExtensionLabel: %s\r\n", ast_get_extension_label(p));
5886
5887 if (prio == PRIORITY_HINT) {
5888 astman_append(s, "Priority: hint\r\nApplication: %s\r\n", ast_get_extension_app(p));
5889 } else {
5890 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));
5891 }
5892 astman_append(s, "Registrar: %s\r\n\r\n", ast_get_extension_registrar(e));
5893 }
5894 }
5895
5896 for (idx = 0; idx < ast_context_includes_count(c); idx++) {
5897 const struct ast_include *i = ast_context_includes_get(c, idx);
5898
5899 if (exten) {
5900 /* Check all includes for the requested extension */
5901 if (includecount >= AST_PBX_MAX_STACK) {
5902 ast_log(LOG_WARNING, "Maximum include depth exceeded!\n");
5903 } else {
5904 int dupe = 0;
5905 int x;
5906 for (x = 0; x < includecount; x++) {
5907 if (!strcasecmp(includes[x], ast_get_include_name(i))) {
5908 dupe++;
5909 break;
5910 }
5911 }
5912 if (!dupe) {
5913 includes[includecount] = ast_get_include_name(i);
5914 manager_show_dialplan_helper(s, m, actionidtext, ast_get_include_name(i), exten, dpc, i, includecount + 1, includes);
5915 } else {
5916 ast_log(LOG_WARNING, "Avoiding circular include of %s within %s\n", ast_get_include_name(i), context);
5917 }
5918 }
5919 } else {
5920 if (!dpc->total_items++)
5921 manager_dpsendack(s, m);
5922 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
5923 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));
5924 astman_append(s, "\r\n");
5925 ast_debug(3, "manager_show_dialplan: Found Included context: %s \n", ast_get_include_name(i));
5926 }
5927 }
5928
5929 for (idx = 0; idx < ast_context_ignorepats_count(c); idx++) {
5930 const struct ast_ignorepat *ip = ast_context_ignorepats_get(c, idx);
5931 const char *ipname = ast_get_ignorepat_name(ip);
5932 char ignorepat[AST_MAX_EXTENSION];
5933
5934 snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname);
5935 if (!exten || ast_extension_match(ignorepat, exten)) {
5936 if (!dpc->total_items++)
5937 manager_dpsendack(s, m);
5938 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
5939 astman_append(s, "Context: %s\r\nIgnorePattern: %s\r\nRegistrar: %s\r\n", ast_get_context_name(c), ipname, ast_get_ignorepat_registrar(ip));
5940 astman_append(s, "\r\n");
5941 }
5942 }
5943 if (!rinclude) {
5944 for (idx = 0; idx < ast_context_switches_count(c); idx++) {
5945 const struct ast_sw *sw = ast_context_switches_get(c, idx);
5946
5947 if (!dpc->total_items++)
5948 manager_dpsendack(s, m);
5949 astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
5950 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));
5951 astman_append(s, "\r\n");
5952 ast_debug(3, "manager_show_dialplan: Found Switch : %s \n", ast_get_switch_name(sw));
5953 }
5954 }
5955
5957 }
5959
5960 if (dpc->total_exten == old_total_exten) {
5961 ast_debug(3, "manager_show_dialplan: Found nothing new\n");
5962 /* Nothing new under the sun */
5963 return -1;
5964 } else {
5965 return res;
5966 }
5967}
int ast_get_extension_priority(struct ast_exten *exten)
Definition: pbx.c:8519
const char * ast_get_extension_label(struct ast_exten *exten)
Definition: pbx.c:8514
struct ast_exten * ast_walk_extension_priorities(struct ast_exten *exten, struct ast_exten *priority)
Definition: pbx.c:8644
struct ast_exten * ast_walk_context_extensions(struct ast_context *con, struct ast_exten *exten)
Definition: pbx.c:8596
int ast_rdlock_context(struct ast_context *con)
Read locks a given context.
Definition: pbx.c:8486
const char * ast_get_extension_registrar(struct ast_exten *e)
Definition: pbx.c:8532
int total_items
Definition: pbx.c:5429
int total_context
Definition: pbx.c:5430
int context_existence
Definition: pbx.c:5433
int total_exten
Definition: pbx.c:5431
int total_prio
Definition: pbx.c:5432
int extension_existence
Definition: pbx.c:5434

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

2471{
2472 /* If the Caller*ID pattern is empty, then we're matching NO Caller*ID, so
2473 failing to get a number should count as a match, otherwise not */
2474
2475 if (ast_strlen_zero(callerid)) {
2476 return ast_strlen_zero(cidpattern) ? 1 : 0;
2477 }
2478
2479 return ast_extension_match(cidpattern, callerid);
2480}

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

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

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

3057{
3058 char *copy = ast_strdupa(ast_str_buffer(hint_args));
3059 char *tmp;
3060
3061 if ((tmp = strrchr(copy, ','))) {
3062 *tmp = '\0';
3063 }
3064
3065 ast_str_set(&hint_args, 0, "%s", copy);
3066 return ast_str_buffer(hint_args);
3067}
static int copy(char *infile, char *outfile)
Utility function to copy a file.

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

Referenced by ast_extension_state3().

◆ parse_hint_presence()

static char * parse_hint_presence ( struct ast_str hint_args)
static

Definition at line 3037 of file pbx.c.

3038{
3039 char *copy = ast_strdupa(ast_str_buffer(hint_args));
3040 char *tmp = "";
3041
3042 if ((tmp = strrchr(copy, ','))) {
3043 *tmp = '\0';
3044 tmp++;
3045 } else {
3046 return NULL;
3047 }
3048 ast_str_set(&hint_args, 0, "%s", tmp);
3049 return ast_str_buffer(hint_args);
3050}

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

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

8283{
8284 int res;
8285 if (ast_strlen_zero(condition)) { /* NULL or empty strings are false */
8286 return 0;
8287 } else if (sscanf(condition, "%30d", &res) == 1) { /* Numbers are evaluated for truth */
8288 return res;
8289 } else { /* Strings are true */
8290 return 1;
8291 }
8292}

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

991{
992 ast_free(p);
993}

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

7682{
7683 enum ast_control_frame_type pbx_reason;
7684
7685 if (dial_result == AST_DIAL_RESULT_ANSWERED) {
7686 /* Remote end answered. */
7687 pbx_reason = AST_CONTROL_ANSWER;
7688 } else if (dial_result == AST_DIAL_RESULT_HANGUP) {
7689 /* Caller hungup */
7690 pbx_reason = AST_CONTROL_HANGUP;
7691 } else {
7692 switch (cause) {
7694 pbx_reason = AST_CONTROL_BUSY;
7695 break;
7702 pbx_reason = AST_CONTROL_CONGESTION;
7703 break;
7706 /* Remote end was ringing (but isn't anymore) */
7707 pbx_reason = AST_CONTROL_RINGING;
7708 break;
7710 default:
7711 /* Call Failure (not BUSY, and not NO_ANSWER, maybe Circuit busy or down?) */
7712 pbx_reason = 0;
7713 break;
7714 }
7715 }
7716
7717 return pbx_reason;
7718}
#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 2875 of file pbx.c.

2878{
2879 struct ast_exten *e;
2880 struct ast_app *app;
2881 char *substitute = NULL;
2882 struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */
2883 char passdata[EXT_DATA_SIZE];
2884 int matching_action = (action == E_MATCH || action == E_CANMATCH || action == E_MATCHMORE);
2885
2887
2888 if (!context) {
2889 context = con->name;
2890 }
2891
2892 if (found)
2893 *found = 0;
2894
2895 e = pbx_find_extension(c, con, &q, context, exten, priority, label, callerid, action);
2896 if (e) {
2897 if (found)
2898 *found = 1;
2899 if (matching_action) {
2901 return -1; /* success, we found it */
2902 } else if (action == E_FINDLABEL) { /* map the label to a priority */
2903 int res = e->priority;
2904
2906
2907 /* the priority we were looking for */
2908 return res;
2909 } else { /* spawn */
2910 if (!e->cached_app)
2911 e->cached_app = pbx_findapp(e->app);
2912 app = e->cached_app;
2913 if (ast_strlen_zero(e->data)) {
2914 *passdata = '\0';
2915 } else {
2916 const char *tmp;
2917 if ((!(tmp = strchr(e->data, '$'))) || (!strstr(tmp, "${") && !strstr(tmp, "$["))) {
2918 /* no variables to substitute, copy on through */
2919 ast_copy_string(passdata, e->data, sizeof(passdata));
2920 } else {
2921 /* save e->data on stack for later processing after lock released */
2922 substitute = ast_strdupa(e->data);
2923 }
2924 }
2926 if (!app) {
2927 ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority);
2928 return -1;
2929 }
2932 if (ast_channel_exten(c) != exten)
2933 ast_channel_exten_set(c, exten);
2935 if (substitute) {
2936 pbx_substitute_variables_helper(c, substitute, passdata, sizeof(passdata)-1);
2937 }
2938 ast_debug(1, "Launching '%s'\n", app_name(app));
2939 if (VERBOSITY_ATLEAST(3)) {
2940 ast_verb(3, "Executing [%s@%s:%d] " COLORIZE_FMT "(\"" COLORIZE_FMT "\", \"" COLORIZE_FMT "\") %s\n",
2941 exten, context, priority,
2944 COLORIZE(COLOR_BRMAGENTA, 0, passdata),
2945 "in new stack");
2946 }
2947 return pbx_exec(c, app, passdata); /* 0 on success, -1 on failure */
2948 }
2949 } else if (q.swo) { /* not found here, but in another switch */
2950 if (found)
2951 *found = 1;
2953 if (matching_action) {
2954 return -1;
2955 } else {
2956 if (!q.swo->exec) {
2957 ast_log(LOG_WARNING, "No execution engine for switch %s\n", q.swo->name);
2958 return -1;
2959 }
2960 return q.swo->exec(c, q.foundcontext ? q.foundcontext : context, exten, priority, callerid, q.data);
2961 }
2962 } else { /* not found anywhere, see what happened */
2964 /* Using S_OR here because Solaris doesn't like NULL being passed to ast_log */
2965 switch (q.status) {
2966 case STATUS_NO_CONTEXT:
2967 if (!matching_action && !combined_find_spawn)
2968 ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", S_OR(context, ""));
2969 break;
2971 if (!matching_action && !combined_find_spawn)
2972 ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, S_OR(context, ""));
2973 break;
2974 case STATUS_NO_PRIORITY:
2975 if (!matching_action && !combined_find_spawn)
2976 ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, S_OR(context, ""));
2977 break;
2978 case STATUS_NO_LABEL:
2979 if (context && !combined_find_spawn)
2980 ast_log(LOG_NOTICE, "No such label '%s' in extension '%s' in context '%s'\n", S_OR(label, ""), exten, S_OR(context, ""));
2981 break;
2982 default:
2983 ast_debug(1, "Shouldn't happen!\n");
2984 }
2985
2986 return (matching_action) ? 0 : -1;
2987 }
2988}
#define VERBOSITY_ATLEAST(level)
#define STATUS_NO_LABEL
Definition: pbx.c:2467
#define STATUS_NO_EXTENSION
Definition: pbx.c:2465
#define STATUS_NO_CONTEXT
Definition: pbx.c:2464
#define EXT_DATA_SIZE
Definition: pbx.c:216
#define STATUS_NO_PRIORITY
Definition: pbx.c:2466
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:247
ast_switch_f * exec
Definition: pbx.h:167
const char * name
Definition: pbx.h:162
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_name(), ast_channel_priority_set(), ast_copy_string(), ast_debug, ast_log, ast_rdlock_contexts(), 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, tmp(), 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 2482 of file pbx.c.

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

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, 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, pbx_find_extension(), pbx_findswitch(), pbx_substitute_variables_helper(), priority, ast_exten::priority, 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, tmp(), 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 7720 of file pbx.c.

7726{
7728 struct ast_channel *dialed;
7729 pthread_t thread;
7730 char tmp_cid_name[128];
7731 char tmp_cid_num[128];
7732
7734 if (!outgoing) {
7735 return -1;
7736 }
7737 ast_cond_init(&outgoing->cond, NULL);
7738
7739 if (!ast_strlen_zero(app)) {
7741 outgoing->appdata = ast_strdup(appdata);
7742 } else {
7746 }
7747
7748 if (!(outgoing->dial = ast_dial_create())) {
7749 return -1;
7750 }
7751
7752 if (ast_dial_append(outgoing->dial, type, addr, assignedids)) {
7753 return -1;
7754 }
7755
7756 ast_dial_set_global_timeout(outgoing->dial, timeout);
7757
7758 if (!ast_strlen_zero(predial_callee)) {
7759 /* note casting to void * here to suppress compiler warning message (passing const to non-const function) */
7760 ast_dial_option_global_enable(outgoing->dial, AST_DIAL_OPTION_PREDIAL, (void *)predial_callee);
7761 }
7762
7763 if (ast_dial_prerun(outgoing->dial, NULL, cap)) {
7764 if (synchronous && reason) {
7766 ast_dial_reason(outgoing->dial, 0));
7767 }
7768 return -1;
7769 }
7770
7772 if (!dialed) {
7773 return -1;
7774 }
7775
7777 if (vars) {
7779 }
7780 if (!ast_strlen_zero(account)) {
7782 ast_channel_accountcode_set(dialed, account);
7783 ast_channel_peeraccount_set(dialed, account);
7785 }
7787
7788 if (!ast_strlen_zero(predial_callee)) {
7789 char *tmp = NULL;
7790 /*
7791 * The predial sub routine may have set callerid so set this into the new channel
7792 * Note... cid_num and cid_name parameters to this function will always be NULL if
7793 * predial_callee is non-NULL so we are not overwriting anything here.
7794 */
7796 if (tmp) {
7797 ast_copy_string(tmp_cid_num, tmp, sizeof(tmp_cid_num));
7798 cid_num = tmp_cid_num;
7799 }
7801 if (tmp) {
7802 ast_copy_string(tmp_cid_name, tmp, sizeof(tmp_cid_name));
7803 cid_name = tmp_cid_name;
7804 }
7805 }
7807
7808 if (!ast_strlen_zero(cid_num) || !ast_strlen_zero(cid_name)) {
7810
7811 /*
7812 * It seems strange to set the CallerID on an outgoing call leg
7813 * to whom we are calling, but this function's callers are doing
7814 * various Originate methods. This call leg goes to the local
7815 * user. Once the called party answers, the dialplan needs to
7816 * be able to access the CallerID from the CALLERID function as
7817 * if the called party had placed this call.
7818 */
7819 ast_set_callerid(dialed, cid_num, cid_name, cid_num);
7820
7822 if (!ast_strlen_zero(cid_num)) {
7823 connected.id.number.valid = 1;
7824 connected.id.number.str = (char *) cid_num;
7826 }
7827 if (!ast_strlen_zero(cid_name)) {
7828 connected.id.name.valid = 1;
7829 connected.id.name.str = (char *) cid_name;
7831 }
7833 }
7834
7835 if (early_media) {
7837 }
7838
7839 if (locked_channel) {
7840 /*
7841 * Keep a dialed channel ref since the caller wants
7842 * the channel returned. We must get the ref before
7843 * spawning off pbx_outgoing_exec().
7844 */
7845 ast_channel_ref(dialed);
7846 if (!synchronous) {
7847 /*
7848 * Lock it now to hold off pbx_outgoing_exec() in case the
7849 * calling function needs the channel state/snapshot before
7850 * dialing actually happens.
7851 */
7852 ast_channel_lock(dialed);
7853 }
7854 }
7855
7856 /* This extra reference is dereferenced by pbx_outgoing_exec */
7857 ao2_ref(outgoing, +1);
7858
7859 if (synchronous == AST_OUTGOING_WAIT_COMPLETE) {
7860 /*
7861 * Because we are waiting until this is complete anyway, there is no
7862 * sense in creating another thread that we will just need to wait
7863 * for, so instead we commandeer the current thread.
7864 */
7866 } else {
7867 outgoing->in_separate_thread = 1;
7868
7870 ast_log(LOG_WARNING, "Unable to spawn dialing thread for '%s/%s'\n", type, addr);
7871 ao2_ref(outgoing, -1);
7872 if (locked_channel) {
7873 if (!synchronous) {
7874 ast_channel_unlock(dialed);
7875 }
7876 ast_channel_unref(dialed);
7877 }
7878 return -1;
7879 }
7880
7881 if (synchronous) {
7883 /* Wait for dialing to complete */
7884 while (!outgoing->dialed) {
7886 }
7888 }
7889 }
7890
7891 if (synchronous) {
7892 /* Determine the outcome of the dialing attempt up to it being answered. */
7893 if (reason) {
7894 *reason = pbx_dial_reason(outgoing->dial_res,
7895 ast_dial_reason(outgoing->dial, 0));
7896 }
7897
7898 if (outgoing->dial_res != AST_DIAL_RESULT_ANSWERED) {
7899 /* The dial operation failed. */
7900 if (locked_channel) {
7901 ast_channel_unref(dialed);
7902 }
7903 return -1;
7904 }
7905 if (locked_channel) {
7906 ast_channel_lock(dialed);
7907 }
7908 }
7909
7910 if (locked_channel) {
7911 *locked_channel = dialed;
7912 }
7913 return 0;
7914}
pthread_t thread
Definition: app_sla.c:329
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:423
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:8307
struct ast_party_connected_line * ast_channel_connected(struct ast_channel *chan)
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:7333
@ AST_FLAG_ORIGINATED
Definition: channel.h:1039
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:2045
@ 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:205
#define ast_cond_init(cond, attr)
Definition: lock.h:201
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:7655
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:7681
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:7592
static void pbx_outgoing_destroy(void *obj)
Destructor for outgoing structure.
Definition: pbx.c:7578
@ AST_OUTGOING_WAIT_COMPLETE
Definition: pbx.h:1142
struct ast_party_dialed dialed
Dialed/Called information.
Connected Line/Party information.
Definition: channel.h:456
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:7554
#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:941

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

7579{
7580 struct pbx_outgoing *outgoing = obj;
7581
7582 if (outgoing->dial) {
7584 }
7585
7586 ast_cond_destroy(&outgoing->cond);
7587
7588 ast_free(outgoing->appdata);
7589}
int ast_dial_destroy(struct ast_dial *dial)
Destroys a dialing structure.
Definition: dial.c:1091
#define ast_cond_destroy(cond)
Definition: lock.h:202

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

7593{
7594 RAII_VAR(struct pbx_outgoing *, outgoing, data, ao2_cleanup);
7595 enum ast_dial_result res;
7596 struct ast_channel *chan;
7597
7598 res = ast_dial_run(outgoing->dial, NULL, 0);
7599
7600 if (outgoing->in_separate_thread) {
7601 /* Notify anyone interested that dialing is complete */
7603 outgoing->dial_res = res;
7604 outgoing->dialed = 1;
7605 ast_cond_signal(&outgoing->cond);
7607 } else {
7608 /* We still need the dial result, but we don't need to lock */
7609 outgoing->dial_res = res;
7610 }
7611
7612 /* If the outgoing leg was not answered we can immediately return and go no further */
7613 if (res != AST_DIAL_RESULT_ANSWERED) {
7614 return NULL;
7615 }
7616
7617 /* We steal the channel so we get ownership of when it is hung up */
7618 chan = ast_dial_answered_steal(outgoing->dial);
7619
7620 if (!ast_strlen_zero(outgoing->app)) {
7621 struct ast_app *app = pbx_findapp(outgoing->app);
7622
7623 if (app) {
7624 ast_verb(4, "Launching %s(%s) on %s\n", outgoing->app, S_OR(outgoing->appdata, ""),
7625 ast_channel_name(chan));
7626 pbx_exec(chan, app, outgoing->appdata);
7627 } else {
7628 ast_log(LOG_WARNING, "No such application '%s'\n", outgoing->app);
7629 }
7630
7631 ast_hangup(chan);
7632 } else {
7635 }
7636
7639 }
7640
7641 if (outgoing->priority > 0) {
7643 }
7644
7645 if (ast_pbx_run(chan)) {
7646 ast_log(LOG_ERROR, "Failed to start PBX on %s\n", ast_channel_name(chan));
7647 ast_hangup(chan);
7648 }
7649 }
7650
7651 return NULL;
7652}
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:203

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

7656{
7657 struct ast_channel *channel;
7658
7660 return;
7661 }
7662
7663 if (!(channel = ast_dial_get_channel(dial, 0))) {
7664 return;
7665 }
7666
7667 ast_verb(4, "Treating progress as answer on '%s' due to early media option\n",
7668 ast_channel_name(channel));
7669
7671}
int ast_queue_control(struct ast_channel *chan, enum ast_control_frame_type control)
Queue a control frame without payload.
Definition: channel.c:1231
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 8791 of file pbx.c.

8792{
8793 char *context, *exten, *pri;
8794 /* do the strsep before here, so we don't have to alloc and free */
8795 if (!*extenp) {
8796 /* Only a priority in this one */
8797 *prip = *contextp;
8798 *extenp = NULL;
8799 *contextp = NULL;
8800 } else if (!*prip) {
8801 /* Only an extension and priority in this one */
8802 *prip = *extenp;
8803 *extenp = *contextp;
8804 *contextp = NULL;
8805 }
8806 context = *contextp;
8807 exten = *extenp;
8808 pri = *prip;
8809 if (mode) {
8810 if (*pri == '+') {
8811 *mode = 1;
8812 pri++;
8813 } else if (*pri == '-') {
8814 *mode = -1;
8815 pri++;
8816 }
8817 }
8818 if ((rest && sscanf(pri, "%30d%1s", ipri, rest) != 1) || sscanf(pri, "%30d", ipri) != 1) {
8820 exten ? exten : ast_channel_exten(chan), pri,
8821 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL));
8822 if (*ipri < 1) {
8823 ast_log(LOG_WARNING, "Priority '%s' must be a number > 0, or valid label\n", pri);
8824 return -1;
8825 } else if (mode) {
8826 *mode = 0;
8827 }
8828 }
8829 return 0;
8830}
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:4180

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

8833{
8834 char *exten, *pri, *context;
8835 char *stringp;
8836 int ipri;
8837 int mode = 0;
8838 char rest[2] = "";
8839
8840 if (ast_strlen_zero(goto_string)) {
8841 ast_log(LOG_WARNING, "Goto requires an argument ([[context,]extension,]priority)\n");
8842 return -1;
8843 }
8844 stringp = ast_strdupa(goto_string);
8845 context = strsep(&stringp, ","); /* guaranteed non-null */
8846 exten = strsep(&stringp, ",");
8847 pri = strsep(&stringp, ",");
8848
8849 if (pbx_parse_location(chan, &context, &exten, &pri, &ipri, &mode, rest)) {
8850 return -1;
8851 }
8852 /* At this point we have a priority and maybe an extension and a context */
8853
8854 if (mode)
8855 ipri = ast_channel_priority(chan) + (ipri * mode);
8856
8857 if (async)
8858 ast_async_goto(chan, context, exten, ipri);
8859 else
8860 ast_explicit_goto(chan, context, exten, ipri);
8861
8862 return 0;
8863
8864}
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:8791

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

4771{
4772 int oldval = autofallthrough;
4773 autofallthrough = newval;
4774 return oldval;
4775}

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

4778{
4779 int oldval = extenpatternmatchnew;
4780 extenpatternmatchnew = newval;
4781 return oldval;
4782}

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

4785{
4786 if (overrideswitch) {
4788 }
4789 if (!ast_strlen_zero(newval)) {
4790 overrideswitch = ast_strdup(newval);
4791 } else {
4793 }
4794}

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

8917{
8918 STASIS_MESSAGE_TYPE_CLEANUP(hint_change_message_type);
8919 STASIS_MESSAGE_TYPE_CLEANUP(hint_remove_message_type);
8920
8921 if (hints) {
8922 ao2_container_unregister("hints");
8923 ao2_ref(hints, -1);
8924 hints = NULL;
8925 }
8926 if (hintdevices) {
8927 ao2_container_unregister("hintdevices");
8928 ao2_ref(hintdevices, -1);
8929 hintdevices = NULL;
8930 }
8931 if (autohints) {
8932 ao2_container_unregister("autohints");
8933 ao2_ref(autohints, -1);
8934 autohints = NULL;
8935 }
8936 if (statecbs) {
8937 ao2_container_unregister("statecbs");
8938 ao2_ref(statecbs, -1);
8939 statecbs = NULL;
8940 }
8941 if (contexts_table) {
8943 }
8944}
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 4688 of file pbx.c.

4689{
4690 /* Oh joyous kernel, we're a new thread, with nothing to do but
4691 answer this channel and get it going.
4692 */
4693 /* NOTE:
4694 The launcher of this function _MUST_ increment 'countcalls'
4695 before invoking the function; it will be decremented when the
4696 PBX has finished running on the channel
4697 */
4698 struct ast_channel *c = data;
4699
4702
4703 pthread_exit(NULL);
4704
4705 return NULL;
4706}
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 8294 of file pbx.c.

8295{
8296 struct ast_presence_state_message *presence_state;
8297 struct ast_str *hint_app = NULL;
8298 struct ast_hintdevice *device;
8299 struct ast_hintdevice *cmpdevice;
8300 struct ao2_iterator *dev_iter;
8301
8303 return;
8304 }
8305
8306 presence_state = stasis_message_data(msg);
8307
8308 if (ao2_container_count(hintdevices) == 0) {
8309 /* There are no hints monitoring devices. */
8310 return;
8311 }
8312
8313 hint_app = ast_str_create(1024);
8314 if (!hint_app) {
8315 return;
8316 }
8317
8318 cmpdevice = ast_alloca(sizeof(*cmpdevice) + strlen(presence_state->provider));
8319 strcpy(cmpdevice->hintdevice, presence_state->provider);
8320
8321 ast_mutex_lock(&context_merge_lock);/* Hold off ast_merge_contexts_and_delete */
8322 dev_iter = ao2_t_callback(hintdevices,
8325 cmpdevice,
8326 "find devices in container");
8327 if (!dev_iter) {
8329 ast_free(hint_app);
8330 return;
8331 }
8332
8333 for (; (device = ao2_iterator_next(dev_iter)); ao2_t_ref(device, -1, "Next device")) {
8334 if (device->hint) {
8335 presence_state_notify_callbacks(device->hint, &hint_app, presence_state);
8336 }
8337 }
8338 ao2_iterator_destroy(dev_iter);
8340
8341 ast_free(hint_app);
8342}
#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 3464 of file pbx.c.

3466{
3467 struct ao2_iterator cb_iter;
3468 struct ast_state_cb *state_cb;
3471
3472 ao2_lock(hint);
3473 if (!hint->exten) {
3474 /* The extension has already been destroyed */
3475 ao2_unlock(hint);
3476 return;
3477 }
3478
3479 /*
3480 * Save off strings in case the hint extension gets destroyed
3481 * while we are notifying the watchers.
3482 */
3485 sizeof(context_name));
3487 sizeof(exten_name));
3488 ast_str_set(hint_app, 0, "%s", ast_get_extension_app(hint->exten));
3489 ao2_unlock(hint);
3490
3491 /* Check to see if update is necessary */
3492 if ((hint->last_presence_state == presence_state->state) &&
3493 ((hint->last_presence_subtype && presence_state->subtype &&
3494 !strcmp(hint->last_presence_subtype, presence_state->subtype)) ||
3495 (!hint->last_presence_subtype && !presence_state->subtype)) &&
3496 ((hint->last_presence_message && presence_state->message &&
3497 !strcmp(hint->last_presence_message, presence_state->message)) ||
3498 (!hint->last_presence_message && !presence_state->message))) {
3499 /* this update is the same as the last, do nothing */
3500 return;
3501 }
3502
3503 /* update new values */
3506 hint->last_presence_state = presence_state->state;
3507 hint->last_presence_subtype = presence_state->subtype ? ast_strdup(presence_state->subtype) : NULL;
3508 hint->last_presence_message = presence_state->message ? ast_strdup(presence_state->message) : NULL;
3509
3510 /* For general callbacks */
3511 cb_iter = ao2_iterator_init(statecbs, 0);
3512 for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_ref(state_cb, -1)) {
3515 exten_name,
3516 state_cb->data,
3518 hint,
3519 NULL);
3520 }
3521 ao2_iterator_destroy(&cb_iter);
3522
3523 /* For extension callbacks */
3524 cb_iter = ao2_iterator_init(hint->callbacks, 0);
3525 for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_cleanup(state_cb)) {
3528 exten_name,
3529 state_cb->data,
3531 hint,
3532 NULL);
3533 }
3534 ao2_iterator_destroy(&cb_iter);
3535}

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

8970{
8971 struct ast_autohint *autohint = v_obj;
8972
8973 if (!autohint) {
8974 return;
8975 }
8976 prnt(where, "%s", autohint->context);
8977}

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

5439{
5440 int prio = ast_get_extension_priority(e);
5441 if (prio == PRIORITY_HINT) {
5442 snprintf(buf, buflen, "hint: %s",
5444 } else {
5445 snprintf(buf, buflen, "%d. %s(%s)",
5446 prio, ast_get_extension_app(e),
5448 }
5449}

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

8958{
8959 struct ast_hintdevice *hintdevice = v_obj;
8960
8961 if (!hintdevice) {
8962 return;
8963 }
8964 prnt(where, "%s => %s@%s", hintdevice->hintdevice,
8965 ast_get_extension_name(hintdevice->hint->exten),
8967}

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

8947{
8948 struct ast_hint *hint = v_obj;
8949
8950 if (!hint) {
8951 return;
8952 }
8953 prnt(where, "%s@%s", ast_get_extension_name(hint->exten),
8955}

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

8980{
8981 struct ast_state_cb *state_cb = v_obj;
8982
8983 if (!state_cb) {
8984 return;
8985 }
8986 prnt(where, "%d", state_cb->id);
8987}

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

4071{
4072 struct stasis_message *message;
4073
4074 if (!hint_change_message_type()) {
4075 return -1;
4076 }
4077
4078 if (!(message = stasis_message_create(hint_change_message_type(), hint))) {
4079 ao2_ref(hint, -1);
4080 return -1;
4081 }
4082
4085
4086 ao2_ref(message, -1);
4087
4088 return 0;
4089}
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:1511

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

3921{
3922 struct stasis_message *message;
3923
3924 if (!hint_remove_message_type()) {
3925 return -1;
3926 }
3927
3928 if (!(message = stasis_message_create(hint_remove_message_type(), hint))) {
3929 ao2_ref(hint, -1);
3930 return -1;
3931 }
3932
3934
3935 ao2_ref(message, -1);
3936
3937 return 0;
3938}

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

2807{
2809 struct pbx_exception *exception = NULL;
2810
2811 if (!ds) {
2813 if (!ds)
2814 return -1;
2815 if (!(exception = ast_calloc_with_stringfields(1, struct pbx_exception, 128))) {
2817 return -1;
2818 }
2819 ds->data = exception;
2820 ast_channel_datastore_add(chan, ds);
2821 } else
2822 exception = ds->data;
2823
2824 ast_string_field_set(exception, reason, reason);
2826 ast_string_field_set(exception, exten, ast_channel_exten(chan));
2827 exception->priority = ast_channel_priority(chan);
2828 set_ext_pri(chan, "e", priority);
2829 return 0;
2830}
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2385
#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 524 of file pbx.c.

525{
526 while (AST_VECTOR_SIZE(&hint->devices) > 0) {
527 char *device = AST_VECTOR_GET(&hint->devices, 0);
528
530 hintdevice_remove_cb, device, hint, "Remove device from container");
532 ast_free(device);
533 }
534
535 return 0;
536}
#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:511
#define AST_VECTOR_REMOVE_UNORDERED(vec, idx)
Remove an element from an unordered vector by index.
Definition: vector.h:438

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

4265{
4267 ast_channel_exten_set(c, exten);
4270}

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

5629{
5630 struct ast_context *c = NULL;
5631 int res = 0, old_total_exten = dpc->total_exten;
5632
5633 ast_cli(fd,"\n In-mem exten Trie for Fast Extension Pattern Matching:\n\n");
5634
5635 ast_cli(fd,"\n Explanation: Node Contents Format = <char(s) to match>:<pattern?>:<specif>:[matched extension]\n");
5636 ast_cli(fd, " Where <char(s) to match> is a set of chars, any one of which should match the current character\n");
5637 ast_cli(fd, " <pattern?>: Y if this a pattern match (eg. _XZN[5-7]), N otherwise\n");
5638 ast_cli(fd, " <specif>: an assigned 'exactness' number for this matching char. The lower the number, the more exact the match\n");
5639 ast_cli(fd, " [matched exten]: If all chars matched to this point, which extension this matches. In form: EXTEN:<exten string>\n");
5640 ast_cli(fd, " In general, you match a trie node to a string character, from left to right. All possible matching chars\n");
5641 ast_cli(fd, " are in a string vertically, separated by an unbroken string of '+' characters.\n\n");
5643
5644 /* walk all contexts ... */
5645 while ( (c = ast_walk_contexts(c)) ) {
5646 int context_info_printed = 0;
5647
5648 if (context && strcmp(ast_get_context_name(c), context))
5649 continue; /* skip this one, name doesn't match */
5650
5651 dpc->context_existence = 1;
5652
5653 if (!c->pattern_tree) {
5654 /* Ignore check_return warning from Coverity for ast_exists_extension below */
5655 ast_exists_extension(NULL, c->name, "s", 1, ""); /* do this to force the trie to built, if it is not already */
5656 }
5657
5659
5660 dpc->total_context++;
5661 ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
5663 context_info_printed = 1;
5664
5665 if (c->pattern_tree)
5666 {
5667 cli_match_char_tree(c->pattern_tree, " ", fd);
5668 } else {
5669 ast_cli(fd,"\n No Pattern Trie present. Perhaps the context is empty...or there is trouble...\n\n");
5670 }
5671
5673
5674 /* if we print something in context, make an empty line */
5675 if (context_info_printed)
5676 ast_cli(fd, "\n");
5677 }
5679
5680 return (dpc->total_exten == old_total_exten) ? -1 : res;
5681}
const char * ast_get_context_registrar(struct ast_context *c)
Definition: pbx.c:8527
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 5467 of file pbx.c.

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

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

5453{
5455 ast_cli(fd, " %-17s %-45s [%s:%d]\n",
5456 buf1, buf2,
5459 return;
5460 }
5461
5462 ast_cli(fd, " %-17s %-45s [%s]\n",
5464}
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:8542
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:8537

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

8905{
8906 const struct ast_state_cb *state_cb = obj;
8908
8909 return (state_cb->change_cb == change_cb) ? CMP_MATCH | CMP_STOP : 0;
8910}
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 1165 of file pbx.c.

1166{
1167 struct match_char *m3;
1168 struct match_char *m4;
1169 struct ast_exten *e3;
1170
1171 if (node && node->x[0] == '.' && !node->x[1]) { /* dot and ! will ALWAYS be next match in a matchmore */
1172 return node->exten;
1173 }
1174
1175 if (node && node->x[0] == '!' && !node->x[1]) {
1176 return node->exten;
1177 }
1178
1179 if (!node || !node->next_char) {
1180 return NULL;
1181 }
1182
1183 m3 = node->next_char;
1184
1185 if (m3->exten) {
1186 return m3->exten;
1187 }
1188 for (m4 = m3->alt_char; m4; m4 = m4->alt_char) {
1189 if (m4->exten) {
1190 return m4->exten;
1191 }
1192 }
1193 for (m4 = m3; m4; m4 = m4->alt_char) {
1194 e3 = trie_find_next_match(m3);
1195 if (e3) {
1196 return e3;
1197 }
1198 }
1199
1200 return NULL;
1201}

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

8410{
8413
8414 ast_manager_unregister("ShowDialPlan");
8415 ast_manager_unregister("ExtensionStateList");
8419}
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:8014
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:1134

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

6131{
6132 struct ast_context *context = NULL;
6133 struct ast_exten *eroot = NULL, *e = NULL;
6134
6136 while ((context = ast_walk_contexts(context))) {
6137 while ((eroot = ast_walk_context_extensions(context, eroot))) {
6138 while ((e = ast_walk_extension_priorities(eroot, e))) {
6139 if (e->cached_app == app)
6140 e->cached_app = NULL;
6141 }
6142 }
6143 }
6145
6146 return;
6147}

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

1070{
1071 /* if this extension is marked as deleted, then skip this -- if it never shows
1072 on the scoreboard, it will never be found, nor will halt the traversal. */
1073 if (deleted)
1074 return;
1075 board->total_specificity = spec;
1076 board->total_length = length;
1077 board->exten = exten;
1078 board->last_char = last;
1079 board->node = node;
1080#ifdef NEED_DEBUG_HERE
1081 ast_log(LOG_NOTICE,"Scoreboarding (LONGER) %s, len=%d, score=%d\n", exten->exten, length, spec);
1082#endif
1083}

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

8229{
8230 int res;
8231 struct ast_frame *f;
8232 double waitsec;
8233 int waittime;
8234
8235 if (ast_strlen_zero(data) || (sscanf(data, "%30lg", &waitsec) != 1) || (waitsec < 0))
8236 waitsec = -1;
8237 if (waitsec > -1) {
8238 waittime = waitsec * 1000.0;
8239 ast_safe_sleep_without_silence(chan, waittime);
8240 } else do {
8241 res = ast_waitfor(chan, -1);
8242 if (res < 0)
8243 return;
8244 f = ast_read(chan);
8245 if (f)
8246 ast_frfree(f);
8247 } while(f);
8248}
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3162
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4256
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:1579
#define ast_frfree(fr)
Data structure associated with a single frame of data.
union ast_frame::@226 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 768 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 387 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 790 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 795 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 778 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 773 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:2832

Definition at line 2852 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:2783

Definition at line 2790 of file pbx.c.

Referenced by acf_exception_read(), and raise_exception().

◆ extenpatternmatchnew

int extenpatternmatchnew = 0
static

Definition at line 769 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 229 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 359 of file pbx.c.

Referenced by add_hintdevice().

◆ hintdevices

struct ao2_container* hintdevices
static

Container for hint devices.

Definition at line 370 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 806 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 777 of file pbx.c.

Referenced by decrease_call_count(), and increase_call_count().

◆ overrideswitch

char* overrideswitch = NULL
static

Definition at line 770 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 6115 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 775 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 797 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 228 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:8253

Definition at line 8277 of file pbx.c.

Referenced by load_pbx(), and unload_pbx().

◆ totalcalls

int totalcalls
static

Definition at line 779 of file pbx.c.

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