Asterisk - The Open Source Telephony Project GIT-master-80b953f
Loading...
Searching...
No Matches
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 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.
 
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.
 
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.
 
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.
 
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.
 
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.
 
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.
 
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.
 
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.
 
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.
 
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.
 
static int ast_change_hint (struct ast_exten *oe, struct ast_exten *ne)
 Change hint for an extension.
 
int ast_context_add_ignorepat (const char *context, const char *value, const char *registrar)
 Add an ignorepat.
 
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.
 
int ast_context_add_include2 (struct ast_context *con, const char *value, const char *registrar)
 Add a context include.
 
int ast_context_add_switch (const char *context, const char *sw, const char *data, int eval, const char *registrar)
 Add a switch.
 
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)
 
void ast_context_destroy (struct ast_context *con, const char *registrar)
 Destroy a context (matches the specified context or ANY context if NULL)
 
int ast_context_destroy_by_name (const char *context, const char *registrar)
 Destroy a context by name.
 
struct ast_contextast_context_find (const char *name)
 Find a context.
 
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.
 
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.
 
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.
 
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.
 
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 ...
 
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.
 
int ast_context_remove_switch (const char *context, const char *sw, const char *data, const char *registrar)
 Remove a switch.
 
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.
 
void ast_context_set_autohints (struct ast_context *con, int enabled)
 Enable or disable autohints support on a context.
 
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.
 
enum ast_extension_states ast_devstate_to_extenstate (enum ast_device_state devstate)
 Map devstate to an extension state.
 
int ast_exists_extension (struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
 Determine whether an extension exists.
 
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.
 
int ast_extension_match (const char *pattern, const char *extension)
 Determine if a given extension matches a given pattern (in NXX format)
 
int ast_extension_state (struct ast_channel *c, const char *context, const char *exten)
 Check extension state for an extension by using hint.
 
static int ast_extension_state2 (struct ast_exten *e, struct ao2_container *device_state_info)
 Check state of extension by using hints.
 
const char * ast_extension_state2str (int extension_state)
 Return extension_state as string.
 
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.
 
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.
 
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.
 
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.
 
int ast_extension_state_del (int id, ast_state_cb_type change_cb)
 Deletes a state change watcher by ID.
 
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.
 
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.
 
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.
 
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.
 
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.
 
int ast_get_extension_registrar_line (struct ast_exten *e)
 Get line number of configuration file used by registrar to register this extension.
 
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.
 
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
 
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.
 
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.
 
int ast_ignore_pattern (const char *context, const char *pattern)
 Checks to see if a number should be ignored.
 
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)
 
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.
 
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.
 
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.
 
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.
 
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.
 
enum ast_pbx_result ast_pbx_run_args (struct ast_channel *c, struct ast_pbx_args *args)
 Execute the PBX in the current thread.
 
enum ast_pbx_result ast_pbx_start (struct ast_channel *c)
 Create a new thread and start the PBX.
 
int ast_processed_calls (void)
 Retrieve the total number of calls processed through the PBX since last restart.
 
int ast_rdlock_context (struct ast_context *con)
 Read locks a given context.
 
int ast_rdlock_contexts (void)
 Read locks the context list.
 
static int ast_remove_hint (struct ast_exten *e)
 Remove hint from 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)
 
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.
 
 AST_THREADSTORAGE_CUSTOM_SCOPE (extensionstate_buf, NULL, ast_free_ptr, static)
 
 AST_THREADSTORAGE_CUSTOM_SCOPE (hintdevice_data, NULL, ast_free_ptr, static)
 
 AST_THREADSTORAGE_CUSTOM_SCOPE (switch_data, NULL, ast_free_ptr, static)
 
int ast_unlock_context (struct ast_context *con)
 
int ast_unlock_contexts (void)
 Unlocks contexts.
 
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.
 
int ast_wrlock_contexts (void)
 Write locks the context list.
 
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.
 
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'
 
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.
 
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,
 
static struct ast_contextfind_context_locked (const char *context)
 lookup for a context with a given name,
 
static int find_hint_by_cb_id (void *obj, void *arg, int flags)
 Find Hint by callback id.
 
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.
 
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
 
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
 
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.
 
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.
 
static int manager_show_dialplan (struct mansession *s, const struct message *m)
 Manager listing of dial plan.
 
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.
 
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.
 
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.
 
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:
 
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.
 
static void * pbx_outgoing_exec (void *data)
 Internal function which dials an outgoing leg and sends it to a provided extension or application.
 
static void pbx_outgoing_state_callback (struct ast_dial *dial)
 Internal dialing state callback which causes early media to trigger an answer.
 
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.
 
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
 
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

 
static int publish_hint_remove (struct ast_hint *hint)
 Publish a hint removed event

 
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.
 
 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.
 
static ast_mutex_t conlock = AST_MUTEX_INIT_VALUE
 Lock for the ast_context list.
 
static ast_mutex_t context_merge_lock = AST_MUTEX_INIT_VALUE
 Lock to hold off restructuring of hints by ast_merge_contexts_and_delete.
 
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.
 
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 ao2_containerhintdevices
 Container for hint devices.
 
static struct ao2_containerhints
 
static ast_mutex_t maxcalllock = AST_MUTEX_INIT_VALUE
 
static char * overrideswitch = NULL
 
static struct ast_cli_entry pbx_cli []
 
static struct stasis_subscriptionpresence_state_sub
 Subscription for presence state change events.
 
static struct ao2_containerstatecbs
 
static int stateid = 1
 
static struct ast_custom_function testtime_function
 
static int totalcalls
 

Detailed Description

Core PBX routines.

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

Definition in file pbx.c.

Macro Definition Documentation

◆ ADVANCE

#define ADVANCE (   s)    candidate_exten_advance(s)

Definition at line 1249 of file pbx.c.

◆ BITS_PER

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

◆ EXT_DATA_SIZE

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

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

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

Definition at line 231 of file pbx.c.

◆ HASH_EXTENHINT_SIZE

#define HASH_EXTENHINT_SIZE   563

Definition at line 380 of file pbx.c.

◆ HINTDEVICE_DATA_LENGTH

#define HINTDEVICE_DATA_LENGTH   16

Definition at line 373 of file pbx.c.

◆ INC_DST_OVERFLOW_CHECK

#define INC_DST_OVERFLOW_CHECK

◆ MAX_EXTENBUF_SIZE

#define MAX_EXTENBUF_SIZE   512

Definition at line 1677 of file pbx.c.

◆ MORE

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

Definition at line 1248 of file pbx.c.

◆ NEW_MATCHER_CHK_MATCH

#define NEW_MATCHER_CHK_MATCH

◆ NEW_MATCHER_RECURSE

#define NEW_MATCHER_RECURSE

◆ SAY_STUBS

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

Definition at line 57 of file pbx.c.

◆ STATUS_NO_CONTEXT

#define STATUS_NO_CONTEXT   1

Definition at line 2479 of file pbx.c.

◆ STATUS_NO_EXTENSION

#define STATUS_NO_EXTENSION   2

Definition at line 2480 of file pbx.c.

◆ STATUS_NO_LABEL

#define STATUS_NO_LABEL   4

Definition at line 2482 of file pbx.c.

◆ STATUS_NO_PRIORITY

#define STATUS_NO_PRIORITY   3

Definition at line 2481 of file pbx.c.

◆ STATUS_SUCCESS

#define STATUS_SUCCESS   5

Definition at line 2483 of file pbx.c.

◆ SWITCH_DATA_LENGTH

#define SWITCH_DATA_LENGTH   256

Definition at line 234 of file pbx.c.

◆ VAR_HARDTRAN

#define VAR_HARDTRAN   3

Definition at line 238 of file pbx.c.

◆ VAR_NORMAL

#define VAR_NORMAL   1

Definition at line 236 of file pbx.c.

◆ VAR_SOFTTRAN

#define VAR_SOFTTRAN   2

Definition at line 237 of file pbx.c.

Function Documentation

◆ __ast_context_destroy()

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

Definition at line 8100 of file pbx.c.

8101{
8102 struct ast_context *tmp, *tmpl=NULL;
8103 struct ast_exten *exten_item, *prio_item;
8104
8105 for (tmp = list; tmp; ) {
8106 struct ast_context *next = NULL; /* next starting point */
8107 /* The following code used to skip forward to the next
8108 context with matching registrar, but this didn't
8109 make sense; individual priorities registrar'd to
8110 the matching registrar could occur in any context! */
8111 ast_debug(1, "Investigate ctx %s %s\n", tmp->name, tmp->registrar);
8112 if (con) {
8113 for (; tmp; tmpl = tmp, tmp = tmp->next) { /* skip to the matching context */
8114 ast_debug(1, "check ctx %s %s\n", tmp->name, tmp->registrar);
8115 if ( !strcasecmp(tmp->name, con->name) ) {
8116 break; /* found it */
8117 }
8118 }
8119 }
8120
8121 if (!tmp) /* not found, we are done */
8122 break;
8123 ast_wrlock_context(tmp);
8124
8125 if (registrar) {
8126 /* then search thru and remove any extens that match registrar. */
8127 struct ast_hashtab_iter *exten_iter;
8128 struct ast_hashtab_iter *prio_iter;
8129 int idx;
8130
8131 /* remove any ignorepats whose registrar matches */
8132 for (idx = ast_context_ignorepats_count(tmp) - 1; idx >= 0; idx--) {
8133 struct ast_ignorepat *ip = AST_VECTOR_GET(&tmp->ignorepats, idx);
8134
8135 if (!strcmp(ast_get_ignorepat_registrar(ip), registrar)) {
8136 AST_VECTOR_REMOVE_ORDERED(&tmp->ignorepats, idx);
8137 ignorepat_free(ip);
8138 }
8139 }
8140 /* remove any includes whose registrar matches */
8141 for (idx = ast_context_includes_count(tmp) - 1; idx >= 0; idx--) {
8142 struct ast_include *i = AST_VECTOR_GET(&tmp->includes, idx);
8143
8144 if (!strcmp(ast_get_include_registrar(i), registrar)) {
8145 AST_VECTOR_REMOVE_ORDERED(&tmp->includes, idx);
8146 include_free(i);
8147 }
8148 }
8149 /* remove any switches whose registrar matches */
8150 for (idx = ast_context_switches_count(tmp) - 1; idx >= 0; idx--) {
8151 struct ast_sw *sw = AST_VECTOR_GET(&tmp->alts, idx);
8152
8153 if (!strcmp(ast_get_switch_registrar(sw), registrar)) {
8154 AST_VECTOR_REMOVE_ORDERED(&tmp->alts, idx);
8155 sw_free(sw);
8156 }
8157 }
8158
8159 if (tmp->root_table) { /* it is entirely possible that the context is EMPTY */
8160 exten_iter = ast_hashtab_start_traversal(tmp->root_table);
8161 while ((exten_item=ast_hashtab_next(exten_iter))) {
8162 int end_traversal = 1;
8163
8164 /*
8165 * If the extension could not be removed from the root_table due to
8166 * a loaded PBX app, it can exist here but have its peer_table be
8167 * destroyed due to a previous pass through this function.
8168 */
8169 if (!exten_item->peer_table) {
8170 continue;
8171 }
8172
8173 prio_iter = ast_hashtab_start_traversal(exten_item->peer_table);
8174 while ((prio_item=ast_hashtab_next(prio_iter))) {
8176 char cidmatch[AST_MAX_EXTENSION];
8177 if (!prio_item->registrar || strcmp(prio_item->registrar, registrar) != 0) {
8178 continue;
8179 }
8180 ast_verb(5, "Remove %s/%s/%d, registrar=%s; con=%s(%p); con->root=%p\n",
8181 tmp->name, prio_item->name, prio_item->priority, registrar, con? con->name : "<nil>", con, con? con->root_table: NULL);
8182 ast_copy_string(extension, prio_item->exten, sizeof(extension));
8183 if (prio_item->cidmatch) {
8184 ast_copy_string(cidmatch, prio_item->cidmatch, sizeof(cidmatch));
8185 }
8186 end_traversal &= ast_context_remove_extension_callerid2(tmp, extension, prio_item->priority, cidmatch, prio_item->matchcid, NULL, 1);
8187 }
8188 /* Explanation:
8189 * ast_context_remove_extension_callerid2 will destroy the extension that it comes across. This
8190 * destruction includes destroying the exten's peer_table, which we are currently traversing. If
8191 * ast_context_remove_extension_callerid2 ever should return '0' then this means we have destroyed
8192 * the hashtable which we are traversing, and thus calling ast_hashtab_end_traversal will result
8193 * in reading invalid memory. Thus, if we detect that we destroyed the hashtable, then we will simply
8194 * free the iterator
8195 */
8196 if (end_traversal) {
8197 ast_hashtab_end_traversal(prio_iter);
8198 } else {
8199 ast_free(prio_iter);
8200 }
8201 }
8202 ast_hashtab_end_traversal(exten_iter);
8203 }
8204
8205 /* delete the context if it's registrar matches, is empty, has refcount of 1, */
8206 /* it's not empty, if it has includes, ignorepats, or switches that are registered from
8207 another registrar. It's not empty if there are any extensions */
8208 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)) {
8209 ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar);
8210 ast_hashtab_remove_this_object(contexttab, tmp);
8211
8212 next = tmp->next;
8213 if (tmpl)
8214 tmpl->next = next;
8215 else
8216 contexts = next;
8217 /* Okay, now we're safe to let it go -- in a sense, we were
8218 ready to let it go as soon as we locked it. */
8219 ast_unlock_context(tmp);
8221 } else {
8222 ast_debug(1,"Couldn't delete ctx %s/%s; refc=%d; tmp.root=%p\n", tmp->name, tmp->registrar,
8223 tmp->refcount, tmp->root);
8224 ast_unlock_context(tmp);
8225 next = tmp->next;
8226 tmpl = tmp;
8227 }
8228 } else if (con) {
8229 ast_verb(3, "Deleting context %s registrar=%s\n", tmp->name, tmp->registrar);
8230 ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar);
8231 ast_hashtab_remove_this_object(contexttab, tmp);
8232
8233 next = tmp->next;
8234 if (tmpl)
8235 tmpl->next = next;
8236 else
8237 contexts = next;
8238 /* Okay, now we're safe to let it go -- in a sense, we were
8239 ready to let it go as soon as we locked it. */
8240 ast_unlock_context(tmp);
8242 }
8243
8244 /* if we have a specific match, we are done, otherwise continue */
8245 tmp = con ? NULL : next;
8246 }
8247}
#define ast_free(a)
Definition astmm.h:180
#define AST_MAX_EXTENSION
Definition channel.h:134
#define ast_hashtab_start_traversal(tab)
Definition hashtab.h:356
void * ast_hashtab_remove_this_object(struct ast_hashtab *tab, void *obj)
Hash the object and then compare ptrs in bucket list instead of calling the compare routine,...
Definition hashtab.c:789
void ast_hashtab_end_traversal(struct ast_hashtab_iter *it)
end the traversal, free the iterator, unlock if necc.
Definition hashtab.c:674
void * ast_hashtab_next(struct ast_hashtab_iter *it)
Gets the next object in the list, advances iter one step returns null on end of traversal.
Definition hashtab.c:683
#define ast_debug(level,...)
Log a DEBUG message.
#define ast_verb(level,...)
int ast_wrlock_context(struct ast_context *con)
Write locks a given context.
Definition pbx.c:8525
int ast_unlock_context(struct ast_context *con)
Definition pbx.c:8535
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:5019
int ast_context_ignorepats_count(const struct ast_context *con)
Definition pbx.c:8766
static struct ast_context * contexts
Definition pbx.c:796
int ast_context_switches_count(const struct ast_context *con)
Definition pbx.c:8678
int ast_context_includes_count(const struct ast_context *con)
Definition pbx.c:8723
static void __ast_internal_context_destroy(struct ast_context *con)
Definition pbx.c:8059
const char * ast_get_ignorepat_registrar(const struct ast_ignorepat *ip)
const char * ast_get_include_registrar(const struct ast_include *i)
Definition pbx_include.c:60
const char * ast_get_switch_registrar(const struct ast_sw *sw)
Definition pbx_sw.c:63
static char * registrar
Definition pbx_ael.c:81
void ignorepat_free(struct ast_ignorepat *ip)
void include_free(struct ast_include *inc)
void sw_free(struct ast_sw *sw)
Definition pbx_sw.c:101
#define NULL
Definition resample.c:96
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition strings.h:425
ast_context: An extension context
Definition pbx.c:299
const char * registrar
Definition pbx.c:301
struct ast_context * next
Definition pbx.c:307
const char * name
Definition pbx.c:300
ast_exten: An extension The dialplan is saved as a linked list with each context having it's own link...
Definition pbx.c:252
char * exten
Definition pbx.c:253
struct ast_hashtab * peer_table
Definition pbx.c:266
char * name
Definition pbx.c:254
const char * registrar
Definition pbx.c:268
const char * cidmatch
Definition pbx.c:256
int priority
Definition pbx.c:258
int matchcid
Definition pbx.c:255
an iterator for traversing the buckets
Definition hashtab.h:106
ast_ignorepat: Ignore patterns in dial plan
ast_include: include= support in extensions.conf
Definition pbx_include.c:37
ast_sw: Switch statement in extensions.conf
Definition pbx_sw.c:37
struct ast_sw * next
Definition pbx_sw.c:44
structure to hold extensions
#define AST_VECTOR_REMOVE_ORDERED(vec, idx)
Remove an element from a vector by index while maintaining order.
Definition vector.h:459
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition vector.h:691

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

Referenced by ast_context_destroy().

◆ __ast_goto_if_exists()

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

Definition at line 8804 of file pbx.c.

8805{
8806 int (*goto_func)(struct ast_channel *chan, const char *context, const char *exten, int priority);
8807
8808 if (!chan)
8809 return -2;
8810
8811 if (context == NULL)
8813 if (exten == NULL)
8814 exten = ast_channel_exten(chan);
8815
8816 goto_func = (async) ? ast_async_goto : ast_explicit_goto;
8818 S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL)))
8819 return goto_func(chan, context, exten, priority);
8820 else {
8821 return AST_PBX_GOTO_FAILED;
8822 }
8823}
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:4211
int ast_explicit_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
Definition pbx.c:6985
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:7013
#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]
char context[AST_MAX_CONTEXT]
Number structure.

References ast_async_goto(), ast_channel_caller(), ast_channel_context(), ast_channel_exten(), ast_exists_extension(), ast_explicit_goto(), AST_PBX_GOTO_FAILED, ast_channel::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 8059 of file pbx.c.

8060{
8061 struct ast_exten *e, *el, *en;
8062 struct ast_context *tmp = con;
8063
8064 /* Free includes */
8067
8068 /* Free ignorepats */
8071
8072 /* Free switches */
8074 AST_VECTOR_FREE(&tmp->alts);
8075
8076 /* destroy the hash tabs */
8077 if (tmp->root_table) {
8079 }
8080 /* and destroy the pattern tree */
8081 if (tmp->pattern_tree)
8083
8084 for (e = tmp->root; e;) {
8085 for (en = e->peer; en;) {
8086 el = en;
8087 en = en->peer;
8089 }
8090 el = e;
8091 e = e->next;
8093 }
8094 tmp->root = NULL;
8095 ast_rwlock_destroy(&tmp->lock);
8096 ast_free(tmp);
8097}
static EditLine * el
Definition asterisk.c:348
void ast_hashtab_destroy(struct ast_hashtab *tab, void(*objdestroyfunc)(void *obj))
This func will free the hash table and all its memory.
Definition hashtab.c:363
#define ast_rwlock_destroy(rwlock)
Definition lock.h:240
static void destroy_pattern_tree(struct match_char *pattern_tree)
Definition pbx.c:1808
static void destroy_exten(struct ast_exten *e)
Definition pbx.c:4710
struct ast_sws alts
Definition pbx.c:310
struct ast_exten * root
Definition pbx.c:304
struct match_char * pattern_tree
Definition pbx.c:306
struct ast_ignorepats ignorepats
Definition pbx.c:309
struct ast_includes includes
Definition pbx.c:308
struct ast_hashtab * root_table
Definition pbx.c:305
ast_rwlock_t lock
Definition pbx.c:303
struct ast_exten * peer
Definition pbx.c:265
struct ast_exten * next
Definition pbx.c:271
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
Definition vector.h:185
#define AST_VECTOR_CALLBACK_VOID(vec, callback,...)
Execute a callback on every element in a vector disregarding callback return.
Definition vector.h:873

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

Referenced by __ast_context_destroy(), and ast_merge_contexts_and_delete().

◆ __ast_pbx_run()

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

Definition at line 4342 of file pbx.c.

4344{
4345 int found = 0; /* set if we find at least one match */
4346 int res = 0;
4347 int autoloopflag;
4348 int error = 0; /* set an error conditions */
4349 struct ast_pbx *pbx;
4350 ast_callid callid;
4351
4352 /* A little initial setup here */
4353 if (ast_channel_pbx(c)) {
4354 ast_log(LOG_WARNING, "%s already has PBX structure??\n", ast_channel_name(c));
4355 /* XXX and now what ? */
4357 }
4358 if (!(pbx = ast_calloc(1, sizeof(*pbx)))) {
4359 return AST_PBX_FAILED;
4360 }
4361
4363 /* If the thread isn't already associated with a callid, we should create that association. */
4364 if (!callid) {
4365 /* Associate new PBX thread with the channel call id if it is available.
4366 * If not, create a new one instead.
4367 */
4368 callid = ast_channel_callid(c);
4369 if (!callid) {
4370 callid = ast_create_callid();
4371 if (callid) {
4373 ast_channel_callid_set(c, callid);
4375 }
4376 }
4378 callid = 0;
4379 }
4380
4381 ast_channel_pbx_set(c, pbx);
4382 /* Set reasonable defaults */
4383 ast_channel_pbx(c)->rtimeoutms = 10000;
4384 ast_channel_pbx(c)->dtimeoutms = 5000;
4385
4387 autoloopflag = ast_test_flag(ast_channel_flags(c), AST_FLAG_IN_AUTOLOOP); /* save value to restore at the end */
4390
4392 /* If not successful fall back to 's' - but only if there is no given exten */
4393 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));
4394 /* XXX the original code used the existing priority in the call to
4395 * ast_exists_extension(), and reset it to 1 afterwards.
4396 * I believe the correct thing is to set it to 1 immediately.
4397 */
4398 set_ext_pri(c, "s", 1);
4399 }
4400
4401 for (;;) {
4402 char dst_exten[256]; /* buffer to accumulate digits */
4403 int pos = 0; /* XXX should check bounds */
4404 int digit = 0;
4405 int invalid = 0;
4406 int timeout = 0;
4407
4408 /* No digits pressed yet */
4409 dst_exten[pos] = '\0';
4410
4411 /* loop on priorities in this context/exten */
4414 &found, 1))) {
4415
4416 if (!ast_check_hangup(c)) {
4418 continue;
4419 }
4420
4421 /* Check softhangup flags. */
4424 continue;
4425 }
4428 S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4429 set_ext_pri(c, "T", 1);
4430 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
4433 continue;
4434 } else if (ast_exists_extension(c, ast_channel_context(c), "e", 1,
4435 S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4436 raise_exception(c, "ABSOLUTETIMEOUT", 1);
4437 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
4440 continue;
4441 }
4442
4443 /* Call timed out with no special extension to jump to. */
4444 error = 1;
4445 break;
4446 }
4447 ast_debug(1, "Extension %s, priority %d returned normally even though call was hung up\n",
4449 error = 1;
4450 break;
4451 } /* end while - from here on we can use 'break' to go out */
4452 if (found && res) {
4453 /* Something bad happened, or a hangup has been requested. */
4454 if (strchr("0123456789ABCDEF*#", res)) {
4455 ast_debug(1, "Oooh, got something to jump out with ('%c')!\n", res);
4456 pos = 0;
4457 dst_exten[pos++] = digit = res;
4458 dst_exten[pos] = '\0';
4459 } else if (res == AST_PBX_INCOMPLETE) {
4460 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));
4461 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));
4462
4463 /* Don't cycle on incomplete - this will happen if the only extension that matches is our "incomplete" extension */
4465 S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4466 invalid = 1;
4467 } else {
4468 ast_copy_string(dst_exten, ast_channel_exten(c), sizeof(dst_exten));
4469 digit = 1;
4470 pos = strlen(dst_exten);
4471 }
4472 } else {
4473 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));
4474 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));
4475
4476 if ((res == AST_PBX_ERROR)
4478 S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4479 /* if we are already on the 'e' exten, don't jump to it again */
4480 if (!strcmp(ast_channel_exten(c), "e")) {
4481 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));
4482 error = 1;
4483 } else {
4484 raise_exception(c, "ERROR", 1);
4485 continue;
4486 }
4487 }
4488
4491 continue;
4492 }
4495 S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4496 set_ext_pri(c, "T", 1);
4497 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
4500 continue;
4501 } else if (ast_exists_extension(c, ast_channel_context(c), "e", 1,
4502 S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4503 raise_exception(c, "ABSOLUTETIMEOUT", 1);
4504 /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
4507 continue;
4508 }
4509 /* Call timed out with no special extension to jump to. */
4510 }
4511 error = 1;
4512 break;
4513 }
4514 }
4515 if (error)
4516 break;
4517
4518 /*!\note
4519 * We get here on a failure of some kind: non-existing extension or
4520 * hangup. We have options, here. We can either catch the failure
4521 * and continue, or we can drop out entirely. */
4522
4523 if (invalid
4524 || (ast_strlen_zero(dst_exten) &&
4526 S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL)))) {
4527 /*!\note
4528 * If there is no match at priority 1, it is not a valid extension anymore.
4529 * Try to continue at "i" (for invalid) or "e" (for exception) or exit if
4530 * neither exist.
4531 */
4533 S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4534 ast_verb(3, "Channel '%s' sent to invalid extension: context,exten,priority=%s,%s,%d\n",
4536 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", ast_channel_exten(c));
4537 set_ext_pri(c, "i", 1);
4538 } else if (ast_exists_extension(c, ast_channel_context(c), "e", 1,
4539 S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4540 raise_exception(c, "INVALID", 1);
4541 } else {
4542 ast_log(LOG_WARNING, "Channel '%s' sent to invalid extension but no invalid handler: context,exten,priority=%s,%s,%d\n",
4544 error = 1; /* we know what to do with it */
4545 break;
4546 }
4548 /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */
4550 } else { /* keypress received, get more digits for a full extension */
4551 int waittime = 0;
4552 if (digit)
4553 waittime = ast_channel_pbx(c)->dtimeoutms;
4554 else if (!autofallthrough)
4555 waittime = ast_channel_pbx(c)->rtimeoutms;
4556 if (!waittime) {
4557 const char *status = pbx_builtin_getvar_helper(c, "DIALSTATUS");
4558 if (!status)
4559 status = "UNKNOWN";
4560 ast_verb(3, "Auto fallthrough, channel '%s' status is '%s'\n", ast_channel_name(c), status);
4561 if (!strcasecmp(status, "CONGESTION"))
4562 res = indicate_congestion(c, "10");
4563 else if (!strcasecmp(status, "CHANUNAVAIL"))
4564 res = indicate_congestion(c, "10");
4565 else if (!strcasecmp(status, "BUSY"))
4566 res = indicate_busy(c, "10");
4567 error = 1; /* XXX disable message */
4568 break; /* exit from the 'for' loop */
4569 }
4570
4571 if (collect_digits(c, waittime, dst_exten, sizeof(dst_exten), pos))
4572 break;
4573 if (res == AST_PBX_INCOMPLETE && ast_strlen_zero(&dst_exten[pos]))
4574 timeout = 1;
4575 if (!timeout
4576 && ast_exists_extension(c, ast_channel_context(c), dst_exten, 1,
4577 S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) { /* Prepare the next cycle */
4578 set_ext_pri(c, dst_exten, 1);
4579 } else {
4580 /* No such extension */
4581 if (!timeout && !ast_strlen_zero(dst_exten)) {
4582 /* An invalid extension */
4584 S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4585 ast_verb(3, "Invalid extension '%s' in context '%s' on %s\n", dst_exten, ast_channel_context(c), ast_channel_name(c));
4586 pbx_builtin_setvar_helper(c, "INVALID_EXTEN", dst_exten);
4587 set_ext_pri(c, "i", 1);
4588 } else if (ast_exists_extension(c, ast_channel_context(c), "e", 1,
4589 S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4590 raise_exception(c, "INVALID", 1);
4591 } else {
4593 "Invalid extension '%s', but no rule 'i' or 'e' in context '%s'\n",
4594 dst_exten, ast_channel_context(c));
4595 found = 1; /* XXX disable message */
4596 break;
4597 }
4598 } else {
4599 /* A simple timeout */
4601 S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4602 ast_verb(3, "Timeout on %s\n", ast_channel_name(c));
4603 set_ext_pri(c, "t", 1);
4604 } else if (ast_exists_extension(c, ast_channel_context(c), "e", 1,
4605 S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4606 raise_exception(c, "RESPONSETIMEOUT", 1);
4607 } else {
4609 "Timeout, but no rule 't' or 'e' in context '%s'\n",
4611 found = 1; /* XXX disable message */
4612 break;
4613 }
4614 }
4615 }
4616 }
4617 }
4618
4619 if (!found && !error) {
4620 ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", ast_channel_name(c));
4621 }
4622
4623 if (!args || !args->no_hangup_chan) {
4627 S_COR(ast_channel_caller(c)->id.number.valid,
4628 ast_channel_caller(c)->id.number.str, NULL))) {
4630 }
4632 }
4633
4636 ast_clear_flag(ast_channel_flags(c), AST_FLAG_BRIDGE_HANGUP_RUN); /* from one round to the next, make sure this gets cleared */
4640
4641 if (!args || !args->no_hangup_chan) {
4642 ast_hangup(c);
4643 }
4644
4645 return AST_PBX_SUCCESS;
4646}
char digit
jack_status_t status
Definition app_jack.c:149
#define ast_calloc(num, len)
A wrapper for calloc()
Definition astmm.h:202
#define ast_log
Definition astobj2.c:42
const char * ast_channel_name(const struct ast_channel *chan)
void ast_channel_clear_softhangup(struct ast_channel *chan, int flag)
Clear a set of softhangup flags from a channel.
Definition channel.c:2423
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition channel.c:2552
#define ast_channel_lock(chan)
Definition channel.h:2982
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)
@ AST_SOFTHANGUP_ASYNCGOTO
Definition channel.h:1146
@ AST_SOFTHANGUP_TIMEOUT
Definition channel.h:1158
@ AST_SOFTHANGUP_APPUNLOAD
Definition channel.h:1163
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition channel.c:446
int ast_softhangup(struct ast_channel *chan, int cause)
Softly hangup up a channel.
Definition channel.c:2462
struct timeval * ast_channel_whentohangup(struct ast_channel *chan)
@ AST_FLAG_BRIDGE_HANGUP_RUN
Definition channel.h:1038
@ AST_FLAG_IN_AUTOLOOP
Definition channel.h:1017
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:2983
void ast_channel_pbx_set(struct ast_channel *chan, struct ast_pbx *value)
int indicate_busy(struct ast_channel *chan, const char *data)
int indicate_congestion(struct ast_channel *chan, const char *data)
ast_callid ast_read_threadstorage_callid(void)
extracts the callid from the thread
Definition logger.c:2268
int ast_callid_threadassoc_add(ast_callid callid)
Adds a known callid to thread storage of the calling thread.
Definition logger.c:2290
ast_callid ast_create_callid(void)
factory function to create a new uniquely identifying callid.
Definition logger.c:2263
unsigned int ast_callid
#define LOG_WARNING
static void pbx_destroy(struct ast_pbx *p)
Definition pbx.c:1005
static int autofallthrough
Definition pbx.c:783
int raise_exception(struct ast_channel *chan, const char *reason, int priority)
Definition pbx.c:2821
void ast_pbx_h_exten_run(struct ast_channel *chan, const char *context)
Run the h exten from the given context.
Definition pbx.c:4241
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:4236
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:4231
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:4315
void set_ext_pri(struct ast_channel *c, const char *exten, int pri)
Definition pbx.c:4300
@ AST_PBX_FAILED
Definition pbx.h:374
@ AST_PBX_SUCCESS
Definition pbx.h:373
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 struct @521 args
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition strings.h:65
Definition pbx.h:216
int rtimeoutms
Definition pbx.h:218
int dtimeoutms
Definition pbx.h:217
static struct test_val c
int error(const char *format,...)
#define ast_test_flag(p, flag)
Definition utils.h:64
#define ast_set2_flag(p, value, flag)
Definition utils.h:95
#define ast_clear_flag(p, flag)
Definition utils.h:78
#define ast_set_flag(p, flag)
Definition utils.h:71

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().

◆ _extension_match_core()

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

Definition at line 2238 of file pbx.c.

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

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

Referenced by extension_match_core().

◆ acf_exception_read()

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

Definition at line 2854 of file pbx.c.

2855{
2856 struct ast_datastore *ds;
2857 struct pbx_exception *exception;
2858 int res = 0;
2859
2860 ast_channel_lock(chan);
2862 if (!ds || !ds->data) {
2863 ast_channel_unlock(chan);
2864 return -1;
2865 }
2866 exception = ds->data;
2867 if (!strcasecmp(data, "REASON"))
2868 ast_copy_string(buf, exception->reason, buflen);
2869 else if (!strcasecmp(data, "CONTEXT"))
2870 ast_copy_string(buf, exception->context, buflen);
2871 else if (!strncasecmp(data, "EXTEN", 5))
2872 ast_copy_string(buf, exception->exten, buflen);
2873 else if (!strcasecmp(data, "PRIORITY"))
2874 snprintf(buf, buflen, "%d", exception->priority);
2875 else
2876 res = -1;
2877
2878 ast_channel_unlock(chan);
2879 return res;
2880}
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:2390
char buf[BUFSIZE]
Definition eagi_proxy.c:66
static const struct ast_datastore_info exception_store_info
Definition pbx.c:2805
Structure for a data store object.
Definition datastore.h:64
void * data
Definition datastore.h:66
const ast_string_field context
Definition pbx.c:645
const ast_string_field exten
Definition pbx.c:645
int priority
Definition pbx.c:647
const ast_string_field reason
Definition pbx.c:645

References ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, 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 8388 of file pbx.c.

8389{
8390 const char *action_id = astman_get_header(m, "ActionID");
8391 struct ast_hint *hint;
8392 struct ao2_iterator it_hints;
8393 int hint_count = 0;
8394
8395 if (!hints) {
8396 astman_send_error(s, m, "No dialplan hints are available");
8397 return 0;
8398 }
8399
8400 astman_send_listack(s, m, "Extension Statuses will follow", "start");
8401
8402 ao2_lock(hints);
8403 it_hints = ao2_iterator_init(hints, 0);
8404 for (; (hint = ao2_iterator_next(&it_hints)); ao2_ref(hint, -1)) {
8405
8406 ao2_lock(hint);
8407
8408 /* Ignore pattern matching hints; they are stored in the
8409 * hints container but aren't real from the perspective of
8410 * an AMI user
8411 */
8412 if (hint->exten->exten[0] == '_') {
8413 ao2_unlock(hint);
8414 continue;
8415 }
8416
8417 ++hint_count;
8418
8419 astman_append(s, "Event: ExtensionStatus\r\n");
8420 if (!ast_strlen_zero(action_id)) {
8421 astman_append(s, "ActionID: %s\r\n", action_id);
8422 }
8423 astman_append(s,
8424 "Exten: %s\r\n"
8425 "Context: %s\r\n"
8426 "Hint: %s\r\n"
8427 "Status: %d\r\n"
8428 "StatusText: %s\r\n\r\n",
8429 hint->exten->exten,
8430 hint->exten->parent->name,
8431 hint->exten->app,
8432 hint->laststate,
8434 ao2_unlock(hint);
8435 }
8436
8437 ao2_iterator_destroy(&it_hints);
8439
8440 astman_send_list_complete_start(s, m, "ExtensionStateListComplete", hint_count);
8442
8443 return 0;
8444}
#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:2030
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition manager.c:1988
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:2066
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
Definition manager.c:1649
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
Definition manager.c:2074
void astman_append(struct mansession *s, const char *fmt,...)
Definition manager.c:1909
const char * ast_extension_state2str(int extension_state)
Return extension_state as string.
Definition pbx.c:3162
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition astobj2.h:1821
const char * app
Definition pbx.c:261
struct ast_context * parent
Definition pbx.c:260
Structure for dial plan hints.
Definition pbx.c:346
int laststate
Definition pbx.c:357
struct ast_exten * exten
Hint extension.
Definition pbx.c:353

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

Referenced by load_pbx().

◆ add_exten_to_pattern_tree()

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

Definition at line 1678 of file pbx.c.

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

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

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

◆ add_hintdevice()

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

add hintdevice structure and link it into the container.

Definition at line 572 of file pbx.c.

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

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

Referenced by ast_add_hint(), and ast_change_hint().

◆ add_pattern_node()

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

Definition at line 1479 of file pbx.c.

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

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

Referenced by add_exten_to_pattern_tree().

◆ add_priority()

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

add the extension in the priority chain.

Return values
0on success.
-1on failure.

Definition at line 7111 of file pbx.c.

7113{
7114 struct ast_exten *ep;
7115 struct ast_exten *eh=e;
7116 int repeated_label = 0; /* Track if this label is a repeat, assume no. */
7117
7118 for (ep = NULL; e ; ep = e, e = e->peer) {
7119 if (e->label && tmp->label && e->priority != tmp->priority && !strcmp(e->label, tmp->label)) {
7120 if (strcmp(e->name, tmp->name)) {
7122 "Extension '%s' priority %d in '%s', label '%s' already in use at aliased extension '%s' priority %d\n",
7123 tmp->name, tmp->priority, con->name, tmp->label, e->name, e->priority);
7124 } else {
7126 "Extension '%s' priority %d in '%s', label '%s' already in use at priority %d\n",
7127 tmp->name, tmp->priority, con->name, tmp->label, e->priority);
7128 }
7129 repeated_label = 1;
7130 }
7131 if (e->priority >= tmp->priority) {
7132 break;
7133 }
7134 }
7135
7136 if (repeated_label) { /* Discard the label since it's a repeat. */
7137 tmp->label = NULL;
7138 }
7139
7140 if (!e) { /* go at the end, and ep is surely set because the list is not empty */
7142
7143 if (tmp->label) {
7145 }
7146 ep->peer = tmp;
7147 return 0; /* success */
7148 }
7149 if (e->priority == tmp->priority) {
7150 /* Can't have something exactly the same. Is this a
7151 replacement? If so, replace, otherwise, bonk. */
7152 if (!replace) {
7153 if (strcmp(e->name, tmp->name)) {
7155 "Unable to register extension '%s' priority %d in '%s', already in use by aliased extension '%s'\n",
7156 tmp->name, tmp->priority, con->name, e->name);
7157 } else {
7159 "Unable to register extension '%s' priority %d in '%s', already in use\n",
7160 tmp->name, tmp->priority, con->name);
7161 }
7162
7163 return -1;
7164 }
7165 /* we are replacing e, so copy the link fields and then update
7166 * whoever pointed to e to point to us
7167 */
7168 tmp->next = e->next; /* not meaningful if we are not first in the peer list */
7169 tmp->peer = e->peer; /* always meaningful */
7170 if (ep) { /* We're in the peer list, just insert ourselves */
7172
7173 if (e->label) {
7175 }
7176
7178 if (tmp->label) {
7180 }
7181
7182 ep->peer = tmp;
7183 } else if (el) { /* We're the first extension. Take over e's functions */
7184 struct match_char *x = add_exten_to_pattern_tree(con, e, 1);
7185 tmp->peer_table = e->peer_table;
7186 tmp->peer_label_table = e->peer_label_table;
7189 if (e->label) {
7191 }
7192 if (tmp->label) {
7194 }
7195
7198 el->next = tmp;
7199 /* The pattern trie points to this exten; replace the pointer,
7200 and all will be well */
7201 if (x) { /* if the trie isn't formed yet, don't sweat this */
7202 if (x->exten) { /* this test for safety purposes */
7203 x->exten = tmp; /* replace what would become a bad pointer */
7204 } else {
7205 ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n");
7206 }
7207 }
7208 } else { /* We're the very first extension. */
7209 struct match_char *x = add_exten_to_pattern_tree(con, e, 1);
7212 tmp->peer_table = e->peer_table;
7213 tmp->peer_label_table = e->peer_label_table;
7216 if (e->label) {
7218 }
7219 if (tmp->label) {
7221 }
7222
7225 con->root = tmp;
7226 /* The pattern trie points to this exten; replace the pointer,
7227 and all will be well */
7228 if (x) { /* if the trie isn't formed yet; no problem */
7229 if (x->exten) { /* this test for safety purposes */
7230 x->exten = tmp; /* replace what would become a bad pointer */
7231 } else {
7232 ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n");
7233 }
7234 }
7235 }
7236 if (tmp->priority == PRIORITY_HINT)
7237 ast_change_hint(e,tmp);
7238 /* Destroy the old one */
7239 if (e->datad)
7240 e->datad(e->data);
7241 ast_free(e);
7242 } else { /* Slip ourselves in just before e */
7243 tmp->peer = e;
7244 tmp->next = e->next; /* extension chain, or NULL if e is not the first extension */
7245 if (ep) { /* Easy enough, we're just in the peer list */
7246 if (tmp->label) {
7248 }
7250 ep->peer = tmp;
7251 } else { /* we are the first in some peer list, so link in the ext list */
7252 tmp->peer_table = e->peer_table;
7253 tmp->peer_label_table = e->peer_label_table;
7254 e->peer_table = 0;
7255 e->peer_label_table = 0;
7257 if (tmp->label) {
7259 }
7262 if (el)
7263 el->next = tmp; /* in the middle... */
7264 else
7265 con->root = tmp; /* ... or at the head */
7266 e->next = NULL; /* e is no more at the head, so e->next must be reset */
7267 }
7268 /* And immediately return success. */
7269 if (tmp->priority == PRIORITY_HINT) {
7270 ast_add_hint(tmp);
7271 }
7272 }
7273 return 0;
7274}
static int replace(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)
#define ast_hashtab_insert_safe(tab, obj)
Definition hashtab.h:316
void * ast_hashtab_remove_object_via_lookup(struct ast_hashtab *tab, void *obj)
Looks up the object, removes the corresponding bucket.
Definition hashtab.c:746
static struct match_char * add_exten_to_pattern_tree(struct ast_context *con, struct ast_exten *e1, int findonly)
Definition pbx.c:1678
static int ast_change_hint(struct ast_exten *oe, struct ast_exten *ne)
Change hint for an extension.
Definition pbx.c:4128
static int ast_add_hint(struct ast_exten *e)
Add hint to hint list, check initial extension state.
Definition pbx.c:4014
#define PRIORITY_HINT
Definition pbx.h:54
struct ast_hashtab * peer_label_table
Definition pbx.c:267
const char * label
Definition pbx.c:259

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

Referenced by ast_add_extension2_lockopt().

◆ alloc_device_state_info()

static struct ao2_container * alloc_device_state_info ( void  )
static

Definition at line 3112 of file pbx.c.

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

References AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_container_alloc_list, and NULL.

Referenced by ast_extension_state_extended(), and device_state_notify_callbacks().

◆ already_in_tree()

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

Definition at line 1417 of file pbx.c.

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

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

Referenced by add_exten_to_pattern_tree().

◆ ast_active_calls()

int ast_active_calls ( void  )

Retrieve the number of active calls.

Definition at line 4796 of file pbx.c.

4797{
4798 return countcalls;
4799}
static int countcalls
Definition pbx.c:793

References countcalls.

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

◆ ast_add_extension()

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

Add and extension to an extension context.

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

Definition at line 6968 of file pbx.c.

6971{
6972 int ret = -1;
6973 struct ast_context *c;
6974
6975 c = find_context_locked(context);
6976 if (c) {
6977 ret = ast_add_extension2(c, replace, extension, priority, label, callerid,
6978 application, data, datad, registrar, NULL, 0);
6980 }
6981
6982 return ret;
6983}
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:7301
static struct ast_context * find_context_locked(const char *context)
lookup for a context with a given name,
Definition pbx.c:4850
int ast_unlock_contexts(void)
Unlocks contexts.
Definition pbx.c:8517
char data[]
Definition pbx.c:319

References ast_add_extension2(), ast_unlock_contexts(), c, 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(), AST_TEST_DEFINE(), create_test_dialplan(), device_state_cb(), extension_state_add_destroy(), handle_cli_dialplan_add_extension(), internal_extension_state_extended(), join_conference_bridge(), load_module(), register_extension(), register_peer_exten(), session_register_apps(), sla_build_station(), and sla_build_trunk().

◆ ast_add_extension2()

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

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

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

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

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

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

Definition at line 7301 of file pbx.c.

7305{
7306 return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid,
7307 application, data, datad, registrar, registrar_file, registrar_line, 1);
7308}
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:7327

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

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

◆ ast_add_extension2_lockopt()

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

Same as ast_add_extension2() but controls the context locking.

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

Definition at line 7327 of file pbx.c.

7331{
7332 /*
7333 * Sort extensions (or patterns) according to the rules indicated above.
7334 * These are implemented by the function ext_cmp()).
7335 * All priorities for the same ext/pattern/cid are kept in a list,
7336 * using the 'peer' field as a link field..
7337 */
7338 struct ast_exten *tmp, *tmp2, *e, *el = NULL;
7339 int res;
7340 int length;
7341 char *p;
7342 char expand_buf[VAR_BUF_SIZE];
7343 struct ast_exten dummy_exten = {0};
7344 char dummy_name[1024];
7345 int exten_fluff;
7346 int callerid_fluff;
7347
7349 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",
7350 con->name);
7351 /* We always need to deallocate 'data' on failure */
7352 if (datad) {
7353 datad(data);
7354 }
7355 return -1;
7356 }
7357
7358 /* If we are adding a hint evaluate in variables and global variables */
7359 if (priority == PRIORITY_HINT && strstr(application, "${") && extension[0] != '_') {
7360 int inhibited;
7362
7363 if (c) {
7366 }
7367
7368 /*
7369 * We can allow dangerous functions when adding a hint since
7370 * altering dialplan is itself a privileged activity. Otherwise,
7371 * we could never execute dangerous functions.
7372 */
7374 pbx_substitute_variables_helper(c, application, expand_buf, sizeof(expand_buf));
7375 if (0 < inhibited) {
7377 }
7378
7379 application = expand_buf;
7380 if (c) {
7382 }
7383 }
7384
7385 if (priority == PRIORITY_HINT) {
7386 /* Fluff in a hint is fine. This prevents the removal of dashes from dynamically
7387 * created hints during a reload. */
7388 exten_fluff = 0;
7389 } else {
7390 exten_fluff = ext_fluff_count(extension);
7391 }
7392
7393 callerid_fluff = callerid ? ext_fluff_count(callerid) : 0;
7394
7395 length = sizeof(struct ast_exten);
7396 length += strlen(extension) + 1;
7397 if (exten_fluff) {
7398 length += strlen(extension) + 1 - exten_fluff;
7399 }
7400 length += strlen(application) + 1;
7401 if (label) {
7402 length += strlen(label) + 1;
7403 }
7404 if (callerid) {
7405 length += strlen(callerid) + 1;
7406 if (callerid_fluff) {
7407 length += strlen(callerid) + 1 - callerid_fluff;
7408 }
7409 } else {
7410 length ++; /* just the '\0' */
7411 }
7412 if (registrar_file) {
7413 length += strlen(registrar_file) + 1;
7414 }
7415
7416 /* Be optimistic: Build the extension structure first */
7417 tmp = ast_calloc(1, length);
7418 if (!tmp) {
7419 /* We always need to deallocate 'data' on failure */
7420 if (datad) {
7421 datad(data);
7422 }
7423 return -1;
7424 }
7425
7426 if (ast_strlen_zero(label)) /* let's turn empty labels to a null ptr */
7427 label = 0;
7428
7429 /* use p as dst in assignments, as the fields are const char * */
7430 p = tmp->stuff;
7431 if (label) {
7432 tmp->label = p;
7433 strcpy(p, label);
7434 p += strlen(label) + 1;
7435 }
7436 tmp->name = p;
7437 p += ext_strncpy(p, extension, strlen(extension) + 1, 0);
7438 if (exten_fluff) {
7439 tmp->exten = p;
7440 p += ext_strncpy(p, extension, strlen(extension) + 1 - exten_fluff, 1);
7441 } else {
7442 /* no fluff, we don't need a copy. */
7443 tmp->exten = tmp->name;
7444 }
7445 tmp->priority = priority;
7446 tmp->cidmatch_display = tmp->cidmatch = p; /* but use p for assignments below */
7447
7448 /* Blank callerid and NULL callerid are two SEPARATE things. Do NOT confuse the two!!! */
7449 if (callerid) {
7450 p += ext_strncpy(p, callerid, strlen(callerid) + 1, 0);
7451 if (callerid_fluff) {
7452 tmp->cidmatch = p;
7453 p += ext_strncpy(p, callerid, strlen(callerid) + 1 - callerid_fluff, 1);
7454 }
7456 } else {
7457 *p++ = '\0';
7459 }
7460
7461 if (registrar_file) {
7462 tmp->registrar_file = p;
7463 strcpy(p, registrar_file);
7464 p += strlen(registrar_file) + 1;
7465 } else {
7466 tmp->registrar_file = NULL;
7467 }
7468
7469 tmp->app = p;
7470 strcpy(p, application);
7471 tmp->parent = con;
7472 tmp->data = data;
7473 tmp->datad = datad;
7474 tmp->registrar = registrar;
7476
7477 if (lock_context) {
7478 ast_wrlock_context(con);
7479 }
7480
7481 if (con->pattern_tree) { /* usually, on initial load, the pattern_tree isn't formed until the first find_exten; so if we are adding
7482 an extension, and the trie exists, then we need to incrementally add this pattern to it. */
7483 ext_strncpy(dummy_name, tmp->exten, sizeof(dummy_name), 1);
7484 dummy_exten.exten = dummy_name;
7485 dummy_exten.matchcid = AST_EXT_MATCHCID_OFF;
7486 dummy_exten.cidmatch = 0;
7487 tmp2 = ast_hashtab_lookup(con->root_table, &dummy_exten);
7488 if (!tmp2) {
7489 /* hmmm, not in the trie; */
7490 add_exten_to_pattern_tree(con, tmp, 0);
7491 ast_hashtab_insert_safe(con->root_table, tmp); /* for the sake of completeness */
7492 }
7493 }
7494 res = 0; /* some compilers will think it is uninitialized otherwise */
7495 for (e = con->root; e; el = e, e = e->next) { /* scan the extension list */
7496 res = ext_cmp(e->exten, tmp->exten);
7497 if (res == 0) { /* extension match, now look at cidmatch */
7498 if (e->matchcid == AST_EXT_MATCHCID_OFF && tmp->matchcid == AST_EXT_MATCHCID_OFF)
7499 res = 0;
7500 else if (tmp->matchcid == AST_EXT_MATCHCID_ON && e->matchcid == AST_EXT_MATCHCID_OFF)
7501 res = 1;
7502 else if (e->matchcid == AST_EXT_MATCHCID_ON && tmp->matchcid == AST_EXT_MATCHCID_OFF)
7503 res = -1;
7504 else
7505 res = ext_cmp(e->cidmatch, tmp->cidmatch);
7506 }
7507 if (res >= 0)
7508 break;
7509 }
7510 if (e && res == 0) { /* exact match, insert in the priority chain */
7511 res = add_priority(con, tmp, el, e, replace);
7512 if (res < 0) {
7513 if (con->pattern_tree) {
7514 struct match_char *x = add_exten_to_pattern_tree(con, tmp, 1);
7515
7516 if (x->exten) {
7517 x->deleted = 1;
7518 x->exten = 0;
7519 }
7520
7522 }
7523
7524 if (tmp->datad) {
7525 tmp->datad(tmp->data);
7526 /* if you free this, null it out */
7527 tmp->data = NULL;
7528 }
7529
7530 ast_free(tmp);
7531 }
7532 if (lock_context) {
7533 ast_unlock_context(con);
7534 }
7535 if (res < 0) {
7536 errno = EEXIST;
7537 return -1;
7538 }
7539 } else {
7540 /*
7541 * not an exact match, this is the first entry with this pattern,
7542 * so insert in the main list right before 'e' (if any)
7543 */
7544 tmp->next = e;
7550 0);
7556 0);
7557
7558 if (el) { /* there is another exten already in this context */
7559 el->next = tmp;
7560 } else { /* this is the first exten in this context */
7561 if (!con->root_table) {
7567 0);
7568 }
7569 con->root = tmp;
7570 }
7571 if (label) {
7573 }
7576
7577 if (lock_context) {
7578 ast_unlock_context(con);
7579 }
7580 if (tmp->priority == PRIORITY_HINT) {
7581 ast_add_hint(tmp);
7582 }
7583 }
7584 if (DEBUG_ATLEAST(1)) {
7585 if (tmp->matchcid == AST_EXT_MATCHCID_ON) {
7586 ast_log(LOG_DEBUG, "Added extension '%s' priority %d (CID match '%s') to %s (%p)\n",
7587 tmp->name, tmp->priority, tmp->cidmatch_display, con->name, con);
7588 } else {
7589 ast_log(LOG_DEBUG, "Added extension '%s' priority %d to %s (%p)\n",
7590 tmp->name, tmp->priority, con->name, con);
7591 }
7592 }
7593
7594 return 0;
7595}
void ast_channel_exten_set(struct ast_channel *chan, const char *value)
#define ast_channel_unref(c)
Decrease channel reference count.
Definition channel.h:3018
void ast_channel_context_set(struct ast_channel *chan, const char *value)
#define ast_dummy_channel_alloc()
Create a fake channel structure.
Definition channel.h:1328
int ast_hashtab_newsize_java(struct ast_hashtab *tab)
Create a prime number roughly 2x the current table size.
Definition hashtab.c:127
void * ast_hashtab_lookup(struct ast_hashtab *tab, const void *obj)
Lookup this object in the hash table.
Definition hashtab.c:486
#define ast_hashtab_create(initial_buckets, compare, resize, newsize, hash, do_locking)
Create the hashtable list.
Definition hashtab.h:254
int ast_hashtab_resize_java(struct ast_hashtab *tab)
Determines if a table resize should occur using the Java algorithm (if the table load factor is 75% o...
Definition hashtab.c:84
#define DEBUG_ATLEAST(level)
#define LOG_DEBUG
int errno
static int hashtab_compare_extens(const void *ha_a, const void *ah_b)
Definition pbx.c:713
static int hashtab_compare_exten_numbers(const void *ah_a, const void *ah_b)
Definition pbx.c:741
static int ext_cmp(const char *left, const char *right)
Definition pbx.c:2155
static int add_priority(struct ast_context *con, struct ast_exten *tmp, struct ast_exten *el, struct ast_exten *e, int replace)
add the extension in the priority chain.
Definition pbx.c:7111
static int ext_fluff_count(const char *exten)
Definition pbx.c:2177
static unsigned int hashtab_hash_extens(const void *obj)
Definition pbx.c:761
static unsigned int hashtab_hash_priority(const void *obj)
Definition pbx.c:771
static unsigned int ext_strncpy(char *dst, const char *src, size_t dst_size, int nofluff)
Definition pbx.c:7070
static int hashtab_compare_exten_labels(const void *ah_a, const void *ah_b)
Definition pbx.c:748
static unsigned int hashtab_hash_labels(const void *obj)
Definition pbx.c:777
int ast_thread_inhibit_escalations_swap(int inhibit)
Swap the current thread escalation inhibit setting.
@ AST_EXT_MATCHCID_ON
Definition pbx.h:79
@ AST_EXT_MATCHCID_OFF
Definition pbx.h:78
int ast_thread_inhibit_escalations(void)
Inhibit (in the current thread) the execution of dialplan functions which cause privilege escalations...
void pbx_substitute_variables_helper(struct ast_channel *c, const char *cp1, char *cp2, int count)
Definition ael_main.c:211
#define VAR_BUF_SIZE
Definition pbx_private.h:68
const char * cidmatch_display
Definition pbx.c:257
char stuff[0]
Definition pbx.c:272
const char * registrar_file
Definition pbx.c:269
int registrar_line
Definition pbx.c:270
void * data
Definition pbx.c:263
void(* datad)(void *)
Definition pbx.c:264

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

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

◆ ast_add_extension2_nolock()

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

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

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

Definition at line 7310 of file pbx.c.

7314{
7315 return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid,
7316 application, data, datad, registrar, registrar_file, registrar_line, 0);
7317}

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

6951{
6952 int ret = -1;
6953 struct ast_context *c;
6954
6955 c = find_context(context);
6956 if (c) {
6957 ret = ast_add_extension2_lockopt(c, replace, extension, priority, label, callerid,
6958 application, data, datad, registrar, NULL, 0, 1);
6959 }
6960
6961 return ret;
6962}
static struct ast_context * find_context(const char *context)
lookup for a context with a given name,
Definition pbx.c:4836

References ast_add_extension2_lockopt(), c, 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 4014 of file pbx.c.

4015{
4016 struct ast_hint *hint_new;
4017 struct ast_hint *hint_found;
4018 char *message = NULL;
4019 char *subtype = NULL;
4020 int presence_state;
4021
4022 if (!e) {
4023 return -1;
4024 }
4025
4026 /*
4027 * We must create the hint we wish to add before determining if
4028 * it is already in the hints container to avoid possible
4029 * deadlock when getting the current extension state.
4030 */
4031 hint_new = ao2_alloc(sizeof(*hint_new), destroy_hint);
4032 if (!hint_new) {
4033 return -1;
4034 }
4035 AST_VECTOR_INIT(&hint_new->devices, 8);
4036
4037 /* Initialize new hint. */
4039 if (!hint_new->callbacks) {
4040 ao2_ref(hint_new, -1);
4041 return -1;
4042 }
4043 hint_new->exten = e;
4044 if (strstr(e->app, "${") && e->exten[0] == '_') {
4045 /* The hint is dynamic and hasn't been evaluated yet */
4046 hint_new->laststate = AST_DEVICE_INVALID;
4048 } else {
4049 hint_new->laststate = ast_extension_state2(e, NULL);
4050 if ((presence_state = extension_presence_state_helper(e, &subtype, &message)) > 0) {
4051 hint_new->last_presence_state = presence_state;
4052 hint_new->last_presence_subtype = subtype;
4053 hint_new->last_presence_message = message;
4054 }
4055 }
4056
4057 /* Prevent multiple add hints from adding the same hint at the same time. */
4058 ao2_lock(hints);
4059
4060 /* Search if hint exists, do nothing */
4061 hint_found = ao2_find(hints, e, 0);
4062 if (hint_found) {
4063 ao2_ref(hint_found, -1);
4065 ao2_ref(hint_new, -1);
4066 ast_debug(2, "HINTS: Not re-adding existing hint %s: %s\n",
4068 return -1;
4069 }
4070
4071 /* Add new hint to the hints container */
4072 ast_debug(2, "HINTS: Adding hint %s: %s\n",
4074 ao2_link(hints, hint_new);
4075 if (add_hintdevice(hint_new, ast_get_extension_app(e))) {
4076 ast_log(LOG_WARNING, "Could not add devices for hint: %s@%s.\n",
4079 }
4080
4081 /* if not dynamic */
4082 if (!(strstr(e->app, "${") && e->exten[0] == '_')) {
4083 struct ast_state_cb *state_cb;
4084 struct ao2_iterator cb_iter;
4085
4086 /* For general callbacks */
4087 cb_iter = ao2_iterator_init(statecbs, 0);
4088 for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_ref(state_cb, -1)) {
4092 state_cb->data,
4094 hint_new,
4095 NULL);
4096 }
4097 ao2_iterator_destroy(&cb_iter);
4098 }
4100 ao2_ref(hint_new, -1);
4101
4102 return 0;
4103}
#define ao2_link(container, obj)
Add an object to a container.
Definition astobj2.h:1532
@ AO2_ALLOC_OPT_LOCK_MUTEX
Definition astobj2.h:363
#define ao2_find(container, arg, flags)
Definition astobj2.h:1736
#define ao2_alloc(data_size, destructor_fn)
Definition astobj2.h:409
@ AST_DEVICE_INVALID
Definition devicestate.h:57
static struct ao2_container * statecbs
Definition pbx.c:823
const char * ast_get_extension_app(struct ast_exten *e)
Definition pbx.c:8601
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:3286
static void destroy_hint(void *obj)
Definition pbx.c:3939
struct ast_context * ast_get_extension_context(struct ast_exten *exten)
Definition pbx.c:8548
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:3149
const char * ast_get_context_name(struct ast_context *con)
Definition pbx.c:8543
static int extension_presence_state_helper(struct ast_exten *e, char **subtype, char **message)
Definition pbx.c:3236
static int hint_id_cmp(void *obj, void *arg, int flags)
Definition pbx.c:3925
static int add_hintdevice(struct ast_hint *hint, const char *devicelist)
add hintdevice structure and link it into the container.
Definition pbx.c:572
const char * ast_get_extension_name(struct ast_exten *exten)
Definition pbx.c:8553
@ AST_HINT_UPDATE_DEVICE
Definition pbx.h:91
@ AST_PRESENCE_INVALID
struct ao2_container * callbacks
Definition pbx.c:354
int last_presence_state
Definition pbx.c:360
char * last_presence_subtype
Definition pbx.c:361
char * last_presence_message
Definition pbx.c:362
ast_state_cb: An extension state notify register item
Definition pbx.c:323
ast_state_cb_type change_cb
Definition pbx.c:331
void * data
Definition pbx.c:327
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
Definition vector.h:124

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

Referenced by add_priority(), and ast_add_extension2_lockopt().

◆ ast_async_goto()

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

Set the channel to next execute the specified dialplan location.

See also
ast_async_parseable_goto, ast_async_goto_if_exists
Note
If the AST_SOFTHANGUP_ASYNCGOTO flag is set, it can prevent the dialplan location from being overwritten by ast_explicit_goto.
Do NOT hold any channel locks when calling this function.

Definition at line 7013 of file pbx.c.

7014{
7015 struct ast_channel *newchan;
7016
7017 ast_channel_lock(chan);
7018 /* Channels in a bridge or running a PBX can be sent directly to the specified destination */
7019 if (ast_channel_is_bridged(chan) || ast_channel_pbx(chan)) {
7021 priority += 1;
7022 }
7025 ast_channel_unlock(chan);
7026 return 0;
7027 }
7028 ast_channel_unlock(chan);
7029
7030 /* Otherwise, we need to gain control of the channel first */
7031 newchan = ast_channel_yank(chan);
7032 if (!newchan) {
7033 ast_log(LOG_WARNING, "Unable to gain control of channel %s\n", ast_channel_name(chan));
7034 return -1;
7035 }
7037 if (ast_pbx_start(newchan)) {
7038 ast_hangup(newchan);
7039 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(newchan));
7040 return -1;
7041 }
7042
7043 return 0;
7044}
struct ast_channel * ast_channel_yank(struct ast_channel *yankee)
Gain control of a channel in the system.
Definition channel.c:10681
int ast_channel_is_bridged(const struct ast_channel *chan)
Determine if a channel is in a bridge.
Definition channel.c:10633
int ast_softhangup_nolock(struct ast_channel *chan, int cause)
Softly hangup up a channel (no channel lock)
Definition channel.c:2449
enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
Create a new thread and start the PBX.
Definition pbx.c:4744

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, ast_channel::context, ast_channel::exten, LOG_WARNING, and priority.

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

◆ ast_async_goto_by_name()

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

Set the channel to next execute the specified dialplan location.

Definition at line 7046 of file pbx.c.

7047{
7048 struct ast_channel *chan;
7049 int res = -1;
7050
7051 if ((chan = ast_channel_get_by_name(channame))) {
7052 res = ast_async_goto(chan, context, exten, priority);
7053 chan = ast_channel_unref(chan);
7054 }
7055
7056 return res;
7057}
struct ast_channel * ast_channel_get_by_name(const char *search)
Find a channel by name or uniqueid.
Definition channel.c:1417

References ast_async_goto(), ast_channel_get_by_name(), ast_channel_unref, ast_channel::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 8830 of file pbx.c.

8831{
8832 return __ast_goto_if_exists(chan, context, exten, priority, 1);
8833}
static int __ast_goto_if_exists(struct ast_channel *chan, const char *context, const char *exten, int priority, int async)
Definition pbx.c:8804

References __ast_goto_if_exists(), ast_channel::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 8915 of file pbx.c.

8916{
8917 return pbx_parseable_goto(chan, goto_string, 1);
8918}
static int pbx_parseable_goto(struct ast_channel *chan, const char *goto_string, int async)
Definition pbx.c:8876

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

4227{
4228 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH, 0, 0);
4229}
@ 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:2905

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

4129{
4130 struct ast_hint *hint;
4131
4132 if (!oe || !ne) {
4133 return -1;
4134 }
4135
4136 ao2_lock(hints);/* Locked to hold off others while we move the hint around. */
4137
4138 /*
4139 * Unlink the hint from the hints container as the extension
4140 * name (which is the hash value) could change.
4141 */
4142 hint = ao2_find(hints, oe, OBJ_UNLINK);
4143 if (!hint) {
4146 return -1;
4147 }
4148
4149 remove_hintdevice(hint);
4150
4151 /* Update the hint and put it back in the hints container. */
4152 ao2_lock(hint);
4153 hint->exten = ne;
4154
4155 ao2_unlock(hint);
4156
4157 ao2_link(hints, hint);
4158 if (add_hintdevice(hint, ast_get_extension_app(ne))) {
4159 ast_log(LOG_WARNING, "Could not add devices for hint: %s@%s.\n",
4162 }
4164
4165 publish_hint_change(hint, ne);
4166
4167 ao2_ref(hint, -1);
4168
4169 return 0;
4170}
@ OBJ_UNLINK
Definition astobj2.h:1039
#define ast_mutex_unlock(a)
Definition lock.h:197
static int publish_hint_change(struct ast_hint *hint, struct ast_exten *ne)
Publish a hint changed event
Definition pbx.c:4106
static int remove_hintdevice(struct ast_hint *hint)
Definition pbx.c:539
static ast_mutex_t context_merge_lock
Lock to hold off restructuring of hints by ast_merge_contexts_and_delete.
Definition pbx.c:810

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

Referenced by add_priority().

◆ ast_context_add_ignorepat()

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

Add an ignorepat.

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

Adds an ignore pattern to a particular context.

Return values
0on success
-1on failure

Definition at line 6875 of file pbx.c.

6876{
6877 int ret = -1;
6878 struct ast_context *c;
6879
6880 c = find_context_locked(context);
6881 if (c) {
6884 }
6885 return ret;
6886}
int ast_context_add_ignorepat2(struct ast_context *con, const char *value, const char *registrar)
Definition pbx.c:6888
int value
Definition syslog.c:37

References ast_context_add_ignorepat2(), ast_unlock_contexts(), c, 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 6888 of file pbx.c.

6889{
6890 struct ast_ignorepat *ignorepat = ignorepat_alloc(value, registrar);
6891 int idx;
6892
6893 if (!ignorepat) {
6894 return -1;
6895 }
6896
6897 ast_wrlock_context(con);
6898 for (idx = 0; idx < ast_context_ignorepats_count(con); idx++) {
6899 const struct ast_ignorepat *i = ast_context_ignorepats_get(con, idx);
6900
6901 if (!strcasecmp(ast_get_ignorepat_name(i), value)) {
6902 /* Already there */
6903 ast_unlock_context(con);
6904 ignorepat_free(ignorepat);
6905 errno = EEXIST;
6906 return -1;
6907 }
6908 }
6909 if (AST_VECTOR_APPEND(&con->ignorepats, ignorepat)) {
6910 ignorepat_free(ignorepat);
6911 ast_unlock_context(con);
6912 return -1;
6913 }
6914 ast_unlock_context(con);
6915
6916 return 0;
6917}
const struct ast_ignorepat * ast_context_ignorepats_get(const struct ast_context *con, int idx)
Definition pbx.c:8771
const char * ast_get_ignorepat_name(const struct ast_ignorepat *ip)
struct ast_ignorepat * ignorepat_alloc(const char *value, const char *registrar)

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

6705{
6706 int ret = -1;
6707 struct ast_context *c;
6708
6709 c = find_context_locked(context);
6710 if (c) {
6711 ret = ast_context_add_include2(c, include, registrar);
6713 }
6714 return ret;
6715}
int ast_context_add_include2(struct ast_context *con, const char *value, const char *registrar)
Add a context include.
Definition pbx.c:6724

References ast_context_add_include2(), ast_unlock_contexts(), c, 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 6724 of file pbx.c.

6726{
6727 struct ast_include *new_include;
6728 int idx;
6729
6730 /* allocate new include structure ... */
6731 new_include = include_alloc(value, registrar);
6732 if (!new_include) {
6733 return -1;
6734 }
6735
6736 ast_wrlock_context(con);
6737
6738 /* ... go to last include and check if context is already included too... */
6739 for (idx = 0; idx < ast_context_includes_count(con); idx++) {
6740 const struct ast_include *i = ast_context_includes_get(con, idx);
6741
6742 if (!strcasecmp(ast_get_include_name(i), ast_get_include_name(new_include))) {
6743 include_free(new_include);
6744 ast_unlock_context(con);
6745 errno = EEXIST;
6746 return -1;
6747 }
6748 }
6749
6750 /* ... include new context into context list, unlock, return */
6751 if (AST_VECTOR_APPEND(&con->includes, new_include)) {
6752 include_free(new_include);
6753 ast_unlock_context(con);
6754 return -1;
6755 }
6756 ast_debug(1, "Including context '%s' in context '%s'\n",
6757 ast_get_include_name(new_include), ast_get_context_name(con));
6758
6759 ast_unlock_context(con);
6760
6761 return 0;
6762}
const struct ast_include * ast_context_includes_get(const struct ast_context *con, int idx)
Definition pbx.c:8728
const char * ast_get_include_name(const struct ast_include *include)
Definition pbx_include.c:50
struct ast_include * include_alloc(const char *value, const char *registrar)
Definition pbx_include.c:74

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

Referenced by ast_context_add_include(), and context_merge_incls_swits_igps_other_registrars().

◆ ast_context_add_switch()

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

Add a switch.

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

This function registers a switch with the asterisk switch architecture

Return values
0on success
-1on failure

Definition at line 6769 of file pbx.c.

6770{
6771 int ret = -1;
6772 struct ast_context *c;
6773
6774 c = find_context_locked(context);
6775 if (c) { /* found, add switch to this context */
6776 ret = ast_context_add_switch2(c, sw, data, eval, registrar);
6778 }
6779 return ret;
6780}
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:6789

References ast_context_add_switch2(), ast_unlock_contexts(), c, 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 6789 of file pbx.c.

6791{
6792 int idx;
6793 struct ast_sw *new_sw;
6794
6795 /* allocate new sw structure ... */
6796 if (!(new_sw = sw_alloc(value, data, eval, registrar))) {
6797 return -1;
6798 }
6799
6800 /* ... try to lock this context ... */
6801 ast_wrlock_context(con);
6802
6803 /* ... go to last sw and check if context is already swd too... */
6804 for (idx = 0; idx < ast_context_switches_count(con); idx++) {
6805 const struct ast_sw *i = ast_context_switches_get(con, idx);
6806
6807 if (!strcasecmp(ast_get_switch_name(i), ast_get_switch_name(new_sw)) &&
6808 !strcasecmp(ast_get_switch_data(i), ast_get_switch_data(new_sw))) {
6809 sw_free(new_sw);
6810 ast_unlock_context(con);
6811 errno = EEXIST;
6812 return -1;
6813 }
6814 }
6815
6816 /* ... sw new context into context list, unlock, return */
6817 if (AST_VECTOR_APPEND(&con->alts, new_sw)) {
6818 sw_free(new_sw);
6819 ast_unlock_context(con);
6820 return -1;
6821 }
6822
6823 ast_verb(3, "Including switch '%s/%s' in context '%s'\n",
6825
6826 ast_unlock_context(con);
6827
6828 return 0;
6829}
const struct ast_sw * ast_context_switches_get(const struct ast_context *con, int idx)
Definition pbx.c:8683
const char * ast_get_switch_name(const struct ast_sw *sw)
Definition pbx_sw.c:48
const char * ast_get_switch_data(const struct ast_sw *sw)
Definition pbx_sw.c:53
struct ast_sw * sw_alloc(const char *value, const char *data, int eval, const char *registrar)
Definition pbx_sw.c:68
int eval
Definition pbx_sw.c:43
const char * data
Definition pbx_sw.c:42

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

Referenced by ast_context_add_switch(), and context_merge_incls_swits_igps_other_registrars().

◆ ast_context_destroy()

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

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

Parameters
concontext to destroy
registrarwho registered it

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

Definition at line 8265 of file pbx.c.

8266{
8270}
void __ast_context_destroy(struct ast_context *list, struct ast_hashtab *contexttab, struct ast_context *con, const char *registrar)
Definition pbx.c:8100
int ast_wrlock_contexts(void)
Write locks the context list.
Definition pbx.c:8507
static struct ast_hashtab * contexts_table
Definition pbx.c:797

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

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

8250{
8251 struct ast_context *con;
8252 int ret = -1;
8253
8255 con = ast_context_find(context);
8256 if (con) {
8258 ret = 0;
8259 }
8261
8262 return ret;
8263}
void ast_context_destroy(void)
Definition ael_main.c:414
struct ast_context * ast_context_find(const char *name)
Find a context.
Definition pbx.c:2454

References ast_context_destroy(), ast_context_find(), ast_unlock_contexts(), ast_wrlock_contexts(), and registrar.

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

◆ ast_context_find()

struct ast_context * ast_context_find ( const char *  name)

Find a context.

Parameters
namename of the context to find

Will search for the context with the given name.

Returns
the ast_context on success, NULL on failure.

Definition at line 2454 of file pbx.c.

2455{
2456 struct ast_context *tmp;
2457 struct ast_context item = {
2458 .name = name,
2459 };
2460
2461 if (!name) {
2462 return NULL;
2463 }
2465 if (contexts_table) {
2467 } else {
2468 tmp = NULL;
2469 while ((tmp = ast_walk_contexts(tmp))) {
2470 if (!strcasecmp(name, tmp->name)) {
2471 break;
2472 }
2473 }
2474 }
2476 return tmp;
2477}
struct ast_context * ast_walk_contexts(void)
Definition ael_main.c:401
int ast_rdlock_contexts(void)
Read locks the context list.
Definition pbx.c:8512
const char * name
static struct aco_type item

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

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

◆ ast_context_find_or_create()

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

Register a new context or find an existing one.

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

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

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

Returns
NULL on failure, and an ast_context structure on success

Definition at line 6185 of file pbx.c.

6186{
6187 struct ast_context *tmp, **local_contexts;
6188 struct ast_context search = {
6189 .name = name,
6190 };
6191 size_t name_bytes = strlen(name);
6192 size_t registrar_bytes = strlen(registrar);
6193 int length = sizeof(struct ast_context) + name_bytes + registrar_bytes + 2;
6194
6195 if (!contexts_table) {
6196 /* Protect creation of contexts_table from reentrancy. */
6198 if (!contexts_table) {
6204 0);
6205 }
6207 }
6208
6209 if (!extcontexts) {
6212 tmp = ast_hashtab_lookup(contexts_table, &search);
6213 if (tmp) {
6214 tmp->refcount++;
6216 return tmp;
6217 }
6218 } else { /* local contexts just in a linked list; search there for the new context; slow, linear search, but not frequent */
6219 local_contexts = extcontexts;
6220 tmp = ast_hashtab_lookup(exttable, &search);
6221 if (tmp) {
6222 tmp->refcount++;
6223 return tmp;
6224 }
6225 }
6226
6227 if ((tmp = ast_calloc(1, length))) {
6228 ast_rwlock_init(&tmp->lock);
6229 tmp->name = memcpy(&tmp->data[0], name, name_bytes);
6230 tmp->registrar = memcpy(&tmp->data[name_bytes + 1], registrar, registrar_bytes);
6231 tmp->root = NULL;
6232 tmp->root_table = NULL;
6233 AST_VECTOR_INIT(&tmp->includes, 0);
6234 AST_VECTOR_INIT(&tmp->ignorepats, 0);
6235 AST_VECTOR_INIT(&tmp->alts, 0);
6236 tmp->refcount = 1;
6237
6238 /* The context 'name' must be stored at the beginning of 'data.' The
6239 * order of subsequent strings (currently only 'registrar') is not
6240 * relevant. */
6241 ast_assert(tmp->name == &tmp->data[0]);
6242 } else {
6243 ast_log(LOG_ERROR, "Danger! We failed to allocate a context for %s!\n", name);
6244 if (!extcontexts) {
6246 }
6247 return NULL;
6248 }
6249
6250 if (!extcontexts) {
6251 tmp->next = *local_contexts;
6252 *local_contexts = tmp;
6253 ast_hashtab_insert_safe(contexts_table, tmp); /*put this context into the tree */
6255 } else {
6256 tmp->next = *local_contexts;
6257 if (exttable)
6258 ast_hashtab_insert_immediate(exttable, tmp); /*put this context into the tree */
6259
6260 *local_contexts = tmp;
6261 }
6262 ast_debug(1, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar);
6263 return tmp;
6264}
#define ast_hashtab_insert_immediate(tab, obj)
Insert without checking.
Definition hashtab.h:290
#define ast_rwlock_init(rwlock)
wrapper for rwlock with tracking enabled
Definition lock.h:231
int ast_hashtab_compare_contexts(const void *ah_a, const void *ah_b)
hashtable functions for contexts
Definition pbx.c:703
unsigned int ast_hashtab_hash_contexts(const void *obj)
Definition pbx.c:755
static struct ast_context * local_contexts
Definition pbx_config.c:117
int refcount
Definition pbx.c:311
#define ast_assert(a)
Definition utils.h:779

References ast_context::alts, ast_assert, ast_calloc, ast_debug, ast_hashtab_compare_contexts(), ast_hashtab_create, ast_hashtab_hash_contexts(), ast_hashtab_insert_immediate, ast_hashtab_insert_safe, ast_hashtab_lookup(), ast_hashtab_newsize_java(), ast_hashtab_resize_java(), ast_log, ast_rdlock_contexts(), ast_rwlock_init, ast_unlock_contexts(), AST_VECTOR_INIT, ast_wrlock_contexts(), contexts, contexts_table, ast_context::data, ast_context::ignorepats, ast_context::includes, local_contexts, ast_context::lock, LOG_ERROR, name, ast_context::name, ast_context::next, NULL, ast_context::refcount, ast_context::registrar, registrar, ast_context::root, and ast_context::root_table.

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

◆ ast_context_ignorepats_count()

int ast_context_ignorepats_count ( const struct ast_context con)

◆ ast_context_ignorepats_get()

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

◆ ast_context_includes_count()

int ast_context_includes_count ( const struct ast_context con)

◆ ast_context_includes_get()

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

◆ ast_context_remove_extension()

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

Simply remove extension from context.

Note
This function will lock conlock.

Definition at line 4984 of file pbx.c.

4985{
4987}
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:4989
@ AST_EXT_MATCHCID_ANY
Definition pbx.h:80

References ast_context_remove_extension_callerid(), AST_EXT_MATCHCID_ANY, 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 5014 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 4989 of file pbx.c.

4990{
4991 int ret = -1; /* default error return */
4992 struct ast_context *c;
4993
4994 c = find_context_locked(context);
4995 if (c) { /* ... remove extension ... */
4997 matchcallerid, registrar, 0);
4999 }
5000
5001 return ret;
5002}

References ast_context_remove_extension_callerid2(), ast_unlock_contexts(), c, 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 5019 of file pbx.c.

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

6836{
6837 int ret = -1;
6838 struct ast_context *c;
6839
6840 c = find_context_locked(context);
6841 if (c) {
6842 ret = ast_context_remove_ignorepat2(c, ignorepat, registrar);
6844 }
6845 return ret;
6846}
int ast_context_remove_ignorepat2(struct ast_context *con, const char *ignorepat, const char *registrar)
Definition pbx.c:6848

References ast_context_remove_ignorepat2(), ast_unlock_contexts(), c, 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 6848 of file pbx.c.

6849{
6850 int idx;
6851
6852 ast_wrlock_context(con);
6853
6854 for (idx = 0; idx < ast_context_ignorepats_count(con); idx++) {
6855 struct ast_ignorepat *ip = AST_VECTOR_GET(&con->ignorepats, idx);
6856
6857 if (!strcmp(ast_get_ignorepat_name(ip), ignorepat) &&
6860 ignorepat_free(ip);
6861 ast_unlock_context(con);
6862 return 0;
6863 }
6864 }
6865
6866 ast_unlock_context(con);
6867 errno = EINVAL;
6868 return -1;
6869}

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

4873{
4874 int ret = -1;
4875 struct ast_context *c;
4876
4877 c = find_context_locked(context);
4878 if (c) {
4879 /* found, remove include from this context ... */
4880 ret = ast_context_remove_include2(c, include, registrar);
4882 }
4883 return ret;
4884}
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:4895

References ast_context_remove_include2(), ast_unlock_contexts(), c, 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 4895 of file pbx.c.

4896{
4897 int ret = -1;
4898 int idx;
4899
4900 ast_wrlock_context(con);
4901
4902 /* find our include */
4903 for (idx = 0; idx < ast_context_includes_count(con); idx++) {
4904 struct ast_include *i = AST_VECTOR_GET(&con->includes, idx);
4905
4906 if (!strcmp(ast_get_include_name(i), include) &&
4907 (!registrar || !strcmp(ast_get_include_registrar(i), registrar))) {
4908
4909 /* remove from list */
4910 ast_verb(3, "Removing inclusion of context '%s' in context '%s; registrar=%s'\n", include, ast_get_context_name(con), registrar);
4912
4913 /* free include and return */
4914 include_free(i);
4915 ret = 0;
4916 break;
4917 }
4918 }
4919
4920 ast_unlock_context(con);
4921
4922 return ret;
4923}

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

4931{
4932 int ret = -1; /* default error return */
4933 struct ast_context *c;
4934
4935 c = find_context_locked(context);
4936 if (c) {
4937 /* remove switch from this context ... */
4940 }
4941 return ret;
4942}
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:4952

References ast_context_remove_switch2(), ast_unlock_contexts(), c, 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 4952 of file pbx.c.

4953{
4954 int idx;
4955 int ret = -1;
4956
4957 ast_wrlock_context(con);
4958
4959 /* walk switches */
4960 for (idx = 0; idx < ast_context_switches_count(con); idx++) {
4961 struct ast_sw *i = AST_VECTOR_GET(&con->alts, idx);
4962
4963 if (!strcmp(ast_get_switch_name(i), sw) &&
4964 !strcmp(ast_get_switch_data(i), data) &&
4965 (!registrar || !strcmp(ast_get_switch_registrar(i), registrar))) {
4966
4967 /* found, remove from list */
4968 ast_verb(3, "Removing switch '%s' from context '%s; registrar=%s'\n", sw, ast_get_context_name(con), registrar);
4969 AST_VECTOR_REMOVE_ORDERED(&con->alts, idx);
4970
4971 /* free switch and return */
4972 sw_free(i);
4973 ret = 0;
4974 break;
4975 }
4976 }
4977
4978 ast_unlock_context(con);
4979
4980 return ret;
4981}

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

6267{
6268 con->autohints = enabled;
6269}
static int enabled
Definition dnsmgr.c:91
int autohints
Definition pbx.c:312

References ast_context::autohints, and enabled.

Referenced by pbx_load_config().

◆ ast_context_switches_count()

int ast_context_switches_count ( const struct ast_context con)

◆ ast_context_switches_get()

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

◆ ast_context_verify_includes()

int ast_context_verify_includes ( struct ast_context con)

Verifies includes in an ast_contect structure.

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

Definition at line 8776 of file pbx.c.

8777{
8778 int idx;
8779 int res = 0;
8780 int includecount = ast_context_includes_count(con);
8781
8782 if (includecount >= AST_PBX_MAX_STACK) {
8783 ast_log(LOG_WARNING, "Context %s contains too many includes (%d). Maximum is %d.\n",
8784 ast_get_context_name(con), includecount, AST_PBX_MAX_STACK);
8785 }
8786
8787 for (idx = 0; idx < includecount; idx++) {
8788 const struct ast_include *inc = ast_context_includes_get(con, idx);
8789
8790 if (ast_context_find(include_rname(inc))) {
8791 continue;
8792 }
8793
8794 res = -1;
8795 ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n",
8797 break;
8798 }
8799
8800 return res;
8801}
#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.

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

3043{
3044 switch (devstate) {
3045 case AST_DEVICE_ONHOLD:
3046 return AST_EXTENSION_ONHOLD;
3047 case AST_DEVICE_BUSY:
3048 return AST_EXTENSION_BUSY;
3049 case AST_DEVICE_UNKNOWN:
3052 case AST_DEVICE_INVALID:
3056 case AST_DEVICE_RINGING:
3057 return AST_EXTENSION_RINGING;
3058 case AST_DEVICE_INUSE:
3059 return AST_EXTENSION_INUSE;
3062 case AST_DEVICE_TOTAL: /* not a device state, included for completeness */
3063 break;
3064 }
3065
3067}
@ 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 4211 of file pbx.c.

4212{
4213 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH, 0, 0);
4214}

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

Referenced by __analog_ss_thread(), __ast_goto_if_exists(), __ast_pbx_run(), action_originate(), add_to_regcontext(), analog_ss_thread(), ast_app_dtget(), ast_bridge_setup_after_goto(), ast_pbx_outgoing_exten_predial(), ast_sip_persistent_endpoint_update_state(), chan_pjsip_cng_tone_detected(), cli_console_dial(), comeback_goto(), conf_run(), dahdi_handle_dtmf(), dial_exec_full(), dialplan_has_destination_cb(), disa_exec(), dp_lookup(), dundi_lookup_local(), fax_detect_framehook(), findmeexec(), get_destination(), gosub_exec(), grab_transfer(), handle_gosub(), isexten_function_read(), jingle_new(), join_conference_bridge(), key_dial_page(), leave_voicemail(), local_call(), local_devicestate(), loopback_exists(), minivm_greet_exec(), my_handle_dtmf(), new_subscribe(), onModeChanged(), ooh323_rtp_read(), options_on_rx_request(), pbx_builtin_waitexten(), privacy_exec(), readexten_exec(), refer_incoming_attended_request(), refer_incoming_blind_request(), register_peer_exten(), show_debug_helper(), socket_process_helper(), try_calling(), vm_authenticate(), and waitstream_core().

◆ ast_explicit_goto()

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

Definition at line 6985 of file pbx.c.

6986{
6987 if (!chan)
6988 return -1;
6989
6990 ast_channel_lock(chan);
6991
6993 ast_channel_unlock(chan);
6994 return -1;
6995 }
6996 if (!ast_strlen_zero(context))
6997 ast_channel_context_set(chan, context);
6998 if (!ast_strlen_zero(exten))
6999 ast_channel_exten_set(chan, exten);
7000 if (priority > -1) {
7001 /* see flag description in channel.h for explanation */
7003 --priority;
7004 }
7006 }
7007
7008 ast_channel_unlock(chan);
7009
7010 return 0;
7011}

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

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

◆ ast_extension_close()

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

Definition at line 2447 of file pbx.c.

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

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

Referenced by lua_find_extension(), and realtime_switch_common().

◆ ast_extension_cmp()

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

Determine if one extension should match before another.

Parameters
aextension to compare with b
bextension to compare with a

Checks whether or extension a should match before extension b

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

Definition at line 2212 of file pbx.c.

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

References a, b, and ext_cmp().

Referenced by lua_extension_cmp().

◆ ast_extension_match()

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

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

Parameters
patternpattern to match
extensionextension to check against the pattern.

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

Return values
1on match
0on failure

Definition at line 2442 of file pbx.c.

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

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

Referenced by ast_ignore_pattern(), do_say(), find_matching_priority(), 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 3206 of file pbx.c.

3207{
3208 return internal_extension_state_extended(c, context, exten, NULL);
3209}
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:3177

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

3150{
3151 struct ast_str *hint_app = ast_str_thread_get(&extensionstate_buf, 32);
3152
3153 if (!e || !hint_app) {
3154 return -1;
3155 }
3156
3157 ast_str_set(&hint_app, 0, "%s", ast_get_extension_app(e));
3158 return ast_extension_state3(hint_app, device_state_info);
3159}
static int ast_extension_state3(struct ast_str *hint_app, struct ao2_container *device_state_info)
Definition pbx.c:3117

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

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

3163{
3164 int i;
3165
3166 for (i = 0; (i < ARRAY_LEN(extension_states)); i++) {
3167 if (extension_states[i].extension_state == extension_state)
3168 return extension_states[i].text;
3169 }
3170 return "Unknown";
3171}
static const struct cfextension_states extension_states[]
const char *const text
Definition pbx.c:628

References ARRAY_LEN, extension_states, and cfextension_states::text.

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

◆ ast_extension_state3()

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

Definition at line 3117 of file pbx.c.

3118{
3119 char *cur;
3120 char *rest;
3121 struct ast_devstate_aggregate agg;
3122
3123 /* One or more devices separated with a & character */
3124 rest = parse_hint_device(hint_app);
3125
3127 while ((cur = strsep(&rest, "&"))) {
3129
3131 if (device_state_info) {
3132 struct ast_device_state_info *obj;
3133
3134 obj = ao2_alloc_options(sizeof(*obj) + strlen(cur), device_state_info_dt, AO2_ALLOC_OPT_LOCK_NOLOCK);
3135 /* if failed we cannot add this device */
3136 if (obj) {
3137 obj->device_state = state;
3138 strcpy(obj->device_name, cur);
3139 ao2_link(device_state_info, obj);
3140 ao2_ref(obj, -1);
3141 }
3142 }
3143 }
3144
3146}
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition astobj2.h:404
void ast_devstate_aggregate_add(struct ast_devstate_aggregate *agg, enum ast_device_state state)
Add a device state to the aggregate device state.
void ast_devstate_aggregate_init(struct ast_devstate_aggregate *agg)
Initialize aggregate device state.
enum ast_device_state ast_devstate_aggregate_result(struct ast_devstate_aggregate *agg)
Get the aggregate device state result.
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:3042
static char * parse_hint_device(struct ast_str *hint_args)
Definition pbx.c:3092
static void device_state_info_dt(void *obj)
Definition pbx.c:3105
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.

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

3861{
3862 return extension_state_add_destroy(context, exten, change_cb, NULL, data, 0);
3863}
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:3763

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

3855{
3856 return extension_state_add_destroy(context, exten, change_cb, destroy_cb, data, 0);
3857}

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

3867{
3868 return extension_state_add_destroy(context, exten, change_cb, destroy_cb, data, 1);
3869}

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

3873{
3874 return extension_state_add_destroy(context, exten, change_cb, NULL, data, 1);
3875}

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

3893{
3894 struct ast_state_cb *p_cur;
3895 int ret = -1;
3896
3897 if (!id) { /* id == 0 is a callback without extension */
3898 if (!change_cb) {
3899 return ret;
3900 }
3902 if (p_cur) {
3903 ret = 0;
3904 ao2_ref(p_cur, -1);
3905 }
3906 } else { /* callback with extension, find the callback based on ID */
3907 struct ast_hint *hint;
3908
3909 ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */
3910 hint = ao2_callback(hints, 0, find_hint_by_cb_id, &id);
3911 if (hint) {
3912 p_cur = ao2_find(hint->callbacks, &id, OBJ_UNLINK);
3913 if (p_cur) {
3914 ret = 0;
3915 ao2_ref(p_cur, -1);
3916 }
3917 ao2_ref(hint, -1);
3918 }
3920 }
3921
3922 return ret;
3923}
#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:3878

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

3214{
3215 struct ao2_container *container = NULL;
3216 int ret;
3217
3218 if (device_state_info) {
3220 }
3221
3222 ret = internal_extension_state_extended(c, context, exten, container);
3223 if (ret < 0 && container) {
3224 ao2_ref(container, -1);
3225 container = NULL;
3226 }
3227
3228 if (device_state_info) {
3230 *device_state_info = container;
3231 }
3232
3233 return ret;
3234}
static struct ao2_container * alloc_device_state_info(void)
Definition pbx.c:3112
static void get_device_state_causing_channels(struct ao2_container *c)
Definition pbx.c:3332
struct ao2_container * container
Definition res_fax.c:603
Generic container type.

References alloc_device_state_info(), ao2_ref, c, container, 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 4216 of file pbx.c.

4217{
4218 return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
4219}
@ E_FINDLABEL
Definition extconf.h:220

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

4222{
4223 return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
4224}

References c, E_FINDLABEL, ast_exten::exten, ast_exten::label, NULL, pbx_extension_helper(), 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 8571 of file pbx.c.

8572{
8573 return c ? c->registrar : NULL;
8574}

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)

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

8613{
8614 struct ast_exten *e;
8615 struct pbx_find_info q = { .stacklen = 0 }; /* the rest is set in pbx_find_context */
8617 e = pbx_find_extension(c, NULL, &q, context, exten, priority, NULL, "", E_MATCH);
8618 if (e) {
8619 if (buf) {
8620 const char *tmp = ast_get_extension_app_data(e);
8621 if (tmp) {
8622 ast_copy_string(buf, tmp, bufsize);
8623 }
8624 }
8626 return 0;
8627 }
8629 return -1;
8630}
void * ast_get_extension_app_data(struct ast_exten *e)
Definition pbx.c:8606
struct ast_exten * pbx_find_extension(struct ast_channel *chan, struct ast_context *bypass, struct pbx_find_info *q, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action)
Definition pbx.c:2497

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

Referenced by eval_exten_read().

◆ ast_get_extension_label()

const char * ast_get_extension_label ( struct ast_exten exten)

Definition at line 8558 of file pbx.c.

8559{
8560 return exten ? exten->label : NULL;
8561}

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

8592{
8593 return e ? e->matchcid : 0;
8594}

References ast_exten::matchcid.

Referenced by complete_dialplan_remove_extension(), find_matching_priority(), 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)

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

8582{
8583 return e ? e->registrar_file : NULL;
8584}

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

8587{
8588 return e ? e->registrar_line : 0;
8589}

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

4174{
4175 struct ast_exten *e = ast_hint_extension(c, context, exten);
4176
4177 if (e) {
4178 if (hint)
4179 ast_copy_string(hint, ast_get_extension_app(e), hintsize);
4180 if (name) {
4181 const char *tmp = ast_get_extension_app_data(e);
4182 if (tmp)
4183 ast_copy_string(name, tmp, namesize);
4184 }
4185 return -1;
4186 }
4187 return 0;
4188}
static struct ast_exten * ast_hint_extension(struct ast_channel *c, const char *context, const char *exten)
Definition pbx.c:3033

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

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

◆ ast_goto_if_exists()

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

Definition at line 8825 of file pbx.c.

8826{
8827 return __ast_goto_if_exists(chan, context, exten, priority, 0);
8828}

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

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

◆ ast_hashtab_compare_contexts()

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

hashtable functions for contexts

Definition at line 703 of file pbx.c.

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

References bc, and ast_context::name.

Referenced by ast_context_find_or_create().

◆ ast_hashtab_hash_contexts()

unsigned int ast_hashtab_hash_contexts ( const void *  obj)

Definition at line 755 of file pbx.c.

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

References ast_hashtab_hash_string(), and ast_context::name.

Referenced by ast_context_find_or_create().

◆ ast_hint_extension()

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

Definition at line 3033 of file pbx.c.

3034{
3035 struct ast_exten *e;
3037 e = ast_hint_extension_nolock(c, context, exten);
3039 return e;
3040}
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:3027

References ast_hint_extension_nolock(), ast_rdlock_contexts(), ast_unlock_contexts(), c, 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 3027 of file pbx.c.

3028{
3029 struct pbx_find_info q = { .stacklen = 0 }; /* the rest is set in pbx_find_context */
3030 return pbx_find_extension(c, NULL, &q, context, exten, PRIORITY_HINT, NULL, "", E_MATCH);
3031}

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

3263{
3264 struct ast_exten *e;
3265
3266 if (!(e = ast_hint_extension(c, context, exten))) { /* Do we have a hint for this extension ? */
3267 return -1; /* No hint, return -1 */
3268 }
3269
3270 if (e->exten[0] == '_') {
3271 /* Create this hint on-the-fly */
3272 ao2_lock(hints);
3274 e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr,
3275 e->registrar);
3277 if (!(e = ast_hint_extension(c, context, exten))) {
3278 /* Improbable, but not impossible */
3279 return -1;
3280 }
3281 }
3282
3283 return extension_presence_state_helper(e, subtype, message);
3284}
static const char app[]
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:6968

References ao2_lock, ao2_unlock, ast_exten::app, ast_add_extension(), ast_free_ptr(), ast_hint_extension(), ast_strdup, c, ast_exten::cidmatch, 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 6919 of file pbx.c.

6920{
6921 int ret = 0;
6922 struct ast_context *con;
6923
6925 con = ast_context_find(context);
6926 if (con) {
6927 int idx;
6928
6929 for (idx = 0; idx < ast_context_ignorepats_count(con); idx++) {
6930 const struct ast_ignorepat *pat = ast_context_ignorepats_get(con, idx);
6931
6933 ret = 1;
6934 break;
6935 }
6936 }
6937 }
6939
6940 return ret;
6941}
int ast_extension_match(const char *pattern, const char *extension)
Determine if a given extension matches a given pattern (in NXX format)
Definition pbx.c:2442
const char pattern[0]

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

4232{
4233 return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE, 0, 0);
4234}

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

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

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

8911{
8912 return pbx_parseable_goto(chan, goto_string, 0);
8913}

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

4242{
4243 int autoloopflag;
4244 int found;
4245 int spawn_error;
4246
4247 ast_channel_lock(chan);
4248
4249 /*
4250 * Make sure that the channel is marked as hungup since we are
4251 * going to run the h exten on it.
4252 */
4254
4255 /* Set h exten location */
4256 if (context != ast_channel_context(chan)) {
4257 ast_channel_context_set(chan, context);
4258 }
4259 ast_channel_exten_set(chan, "h");
4260 ast_channel_priority_set(chan, 1);
4261
4262 /* Save autoloop flag */
4265 ast_channel_unlock(chan);
4266
4267 for (;;) {
4268 spawn_error = ast_spawn_extension(chan, ast_channel_context(chan),
4270 S_COR(ast_channel_caller(chan)->id.number.valid,
4271 ast_channel_caller(chan)->id.number.str, NULL), &found, 1);
4272
4273 ast_channel_lock(chan);
4274 if (spawn_error) {
4275 /* The code after the loop needs the channel locked. */
4276 break;
4277 }
4279 ast_channel_unlock(chan);
4280 }
4281 if (found && spawn_error) {
4282 /* Something bad happened, or a hangup has been requested. */
4283 ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n",
4286 ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n",
4289 }
4290
4291 /* An "h" exten has been run, so indicate that one has been run. */
4293
4294 /* Restore autoloop flag */
4296 ast_channel_unlock(chan);
4297}
@ AST_SOFTHANGUP_HANGUP_EXEC
Definition channel.h:1174

References ast_channel_caller(), ast_channel_context(), ast_channel_context_set(), ast_channel_exten(), ast_channel_exten_set(), ast_channel_flags(), ast_channel_lock, ast_channel_name(), ast_channel_priority(), ast_channel_priority_set(), ast_channel_unlock, ast_debug, AST_FLAG_BRIDGE_HANGUP_RUN, AST_FLAG_IN_AUTOLOOP, ast_set2_flag, ast_set_flag, AST_SOFTHANGUP_HANGUP_EXEC, ast_softhangup_nolock(), ast_spawn_extension(), ast_test_flag, ast_verb, 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 9033 of file pbx.c.

9034{
9037 if (hints) {
9039 }
9042 if (hintdevices) {
9044 }
9045 /* This is protected by the context_and_merge lock */
9048 if (autohints) {
9050 }
9052 if (statecbs) {
9054 }
9055
9057
9058 if (STASIS_MESSAGE_TYPE_INIT(hint_change_message_type) != 0) {
9059 return -1;
9060 }
9061 if (STASIS_MESSAGE_TYPE_INIT(hint_remove_message_type) != 0) {
9062 return -1;
9063 }
9064
9065 return (hints && hintdevices && autohints && statecbs) ? 0 : -1;
9066}
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:9013
static void print_statecbs_key(void *v_obj, void *where, ao2_prnt_fn *prnt)
Definition pbx.c:9023
static int hint_cmp(void *obj, void *arg, int flags)
Definition pbx.c:8940
static struct ao2_container * autohints
Container for autohint contexts.
Definition pbx.c:402
static int hintdevice_hash_cb(const void *obj, const int flags)
Definition pbx.c:417
static int hint_hash(const void *obj, const int flags)
Definition pbx.c:8920
static int statecbs_cmp(void *obj, void *arg, int flags)
Definition pbx.c:8948
static int autohint_hash_cb(const void *obj, const int flags)
Definition pbx.c:475
static void print_hintdevices_key(void *v_obj, void *where, ao2_prnt_fn *prnt)
Definition pbx.c:9001
static void print_hints_key(void *v_obj, void *where, ao2_prnt_fn *prnt)
Definition pbx.c:8990
#define HASH_EXTENHINT_SIZE
Definition pbx.c:380
static int hintdevice_cmp_multiple(void *obj, void *arg, int flags)
Definition pbx.c:443
static void pbx_shutdown(void)
Definition pbx.c:8960
static int autohint_cmp(void *obj, void *arg, int flags)
Definition pbx.c:496
#define STASIS_MESSAGE_TYPE_INIT(name)
Boiler-plate messaging macro for initializing message types.
Definition stasis.h:1493

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

Referenced by asterisk_daemon().

◆ ast_pbx_outgoing_app()

int ast_pbx_outgoing_app ( const char *  type,
struct ast_format_cap cap,
const char *  addr,
int  timeout,
const char *  app,
const char *  appdata,
int *  reason,
int  synchronous,
const char *  cid_num,
const char *  cid_name,
struct ast_variable vars,
const char *  account,
struct ast_channel **  locked_channel,
const struct ast_assigned_ids assignedids 
)

Synchronously or asynchronously make an outbound call and execute an application on the channel.

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

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

Definition at line 8024 of file pbx.c.

8029{
8030 return ast_pbx_outgoing_app_predial(type, cap, addr, timeout, app, appdata, reason, synchronous,
8031 cid_num, cid_name, vars, account, locked_channel, assignedids, NULL);
8032}
static const char type[]
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:8034

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

8039{
8040 if (reason) {
8041 *reason = 0;
8042 }
8043 if (locked_channel) {
8044 *locked_channel = NULL;
8045 }
8046 if (ast_strlen_zero(app)) {
8047 return -1;
8048 }
8049
8050 return pbx_outgoing_attempt(type, cap, addr, timeout, NULL, NULL, 0, app, appdata,
8051 reason, synchronous, cid_num, cid_name, vars, account, locked_channel, 0,
8052 assignedids, predial_callee);
8053}
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:7764

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

7965{
7966 return ast_pbx_outgoing_exten_predial(type, cap, addr, timeout, context, exten, priority, reason,
7967 synchronous, cid_num, cid_name, vars, account, locked_channel, early_media, assignedids, NULL);
7968}
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:7970

References ast_pbx_outgoing_exten_predial(), 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 7970 of file pbx.c.

7975{
7976 int res;
7977 int my_reason;
7978
7979 if (!reason) {
7980 reason = &my_reason;
7981 }
7982 *reason = 0;
7983 if (locked_channel) {
7984 *locked_channel = NULL;
7985 }
7986
7987 res = pbx_outgoing_attempt(type, cap, addr, timeout, context, exten, priority,
7988 NULL, NULL, reason, synchronous, cid_num, cid_name, vars, account, locked_channel,
7989 early_media, assignedids, predial_callee);
7990
7991 if (res < 0 /* Call failed to get connected for some reason. */
7992 && 0 < synchronous
7993 && ast_exists_extension(NULL, context, "failed", 1, NULL)) {
7994 struct ast_channel *failed;
7995
7996 /* We do not have to worry about a locked_channel if dialing failed. */
7997 ast_assert(!locked_channel || !*locked_channel);
7998
7999 /*!
8000 * \todo XXX Not good. The channel name is not unique if more than
8001 * one originate fails at a time.
8002 */
8003 failed = ast_channel_alloc(0, AST_STATE_DOWN, cid_num, cid_name, account,
8004 "failed", context, NULL, NULL, 0, "OutgoingSpoolFailed");
8005 if (failed) {
8006 char failed_reason[12];
8007
8008 ast_set_variables(failed, vars);
8009 snprintf(failed_reason, sizeof(failed_reason), "%d", *reason);
8010 pbx_builtin_setvar_helper(failed, "REASON", failed_reason);
8011 ast_channel_unlock(failed);
8012
8013 if (ast_pbx_run(failed)) {
8014 ast_log(LOG_ERROR, "Unable to run PBX on '%s'\n",
8015 ast_channel_name(failed));
8016 ast_hangup(failed);
8017 }
8018 }
8019 }
8020
8021 return res;
8022}
#define ast_channel_alloc(needqueue, state, cid_num, cid_name, acctcode, exten, context, assignedids, requestor, amaflag,...)
Create a channel structure.
Definition channel.h:1299
void ast_set_variables(struct ast_channel *chan, struct ast_variable *vars)
adds a list of channel variables to a channel
Definition channel.c:8199
@ AST_STATE_DOWN
enum ast_pbx_result ast_pbx_run(struct ast_channel *c)
Execute the PBX in the current thread.
Definition pbx.c:4791

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, ast_channel::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 4791 of file pbx.c.

4792{
4793 return ast_pbx_run_args(c, NULL);
4794}
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:4771

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

4772{
4774
4775 if (!ast_fully_booted) {
4776 ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n");
4777 return AST_PBX_FAILED;
4778 }
4779
4780 if (increase_call_count(c)) {
4781 return AST_PBX_CALL_LIMIT;
4782 }
4783
4784 res = __ast_pbx_run(c, args);
4785
4787
4788 return res;
4789}
#define ast_fully_booted
Definition options.h:127
static void decrease_call_count(void)
Definition pbx.c:4702
static int increase_call_count(const struct ast_channel *c)
Increase call count for channel.
Definition pbx.c:4653
static enum ast_pbx_result __ast_pbx_run(struct ast_channel *c, struct ast_pbx_args *args)
Definition pbx.c:4342
ast_pbx_result
The result codes when starting the PBX on a channel with ast_pbx_start.
Definition pbx.h:372
@ AST_PBX_CALL_LIMIT
Definition pbx.h:375

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

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

◆ ast_pbx_start()

enum ast_pbx_result ast_pbx_start ( struct ast_channel c)

Create a new thread and start the PBX.

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

Definition at line 4744 of file pbx.c.

4745{
4746 pthread_t t;
4747
4748 if (!c) {
4749 ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
4750 return AST_PBX_FAILED;
4751 }
4752
4753 if (!ast_fully_booted) {
4754 ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n");
4755 return AST_PBX_FAILED;
4756 }
4757
4759 return AST_PBX_CALL_LIMIT;
4760
4761 /* Start a new thread, and get something handling this channel. */
4763 ast_log(LOG_WARNING, "Failed to create new channel thread\n");
4765 return AST_PBX_FAILED;
4766 }
4767
4768 return AST_PBX_SUCCESS;
4769}
static void * pbx_thread(void *data)
Definition pbx.c:4724
#define ast_pthread_create_detached(a, b, c, d)
Definition utils.h:628

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

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

◆ ast_processed_calls()

int ast_processed_calls ( void  )

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

Definition at line 4801 of file pbx.c.

4802{
4803 return totalcalls;
4804}
static int totalcalls
Definition pbx.c:794

References totalcalls.

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

◆ ast_rdlock_context()

int ast_rdlock_context ( struct ast_context con)

Read locks a given context.

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

Definition at line 8530 of file pbx.c.

8531{
8532 return ast_rwlock_rdlock(&con->lock);
8533}
#define ast_rwlock_rdlock(a)
Definition lock.h:242

References ast_rwlock_rdlock, and ast_context::lock.

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

◆ ast_rdlock_contexts()

int ast_rdlock_contexts ( void  )

◆ ast_remove_hint()

static int ast_remove_hint ( struct ast_exten e)
static

Remove hint from extension.

Definition at line 3977 of file pbx.c.

3978{
3979 /* Cleanup the Notifys if hint is removed */
3980 struct ast_hint *hint;
3981
3982 if (!e) {
3983 return -1;
3984 }
3985
3986 hint = ao2_find(hints, e, OBJ_UNLINK);
3987 if (!hint) {
3988 return -1;
3989 }
3990
3991 remove_hintdevice(hint);
3992
3993 /*
3994 * The extension is being destroyed so we must save some
3995 * information to notify that the extension is deactivated.
3996 */
3997 ao2_lock(hint);
4000 sizeof(hint->context_name));
4002 sizeof(hint->exten_name));
4003 hint->exten = NULL;
4004 ao2_unlock(hint);
4005
4006 publish_hint_remove(hint);
4007
4008 ao2_ref(hint, -1);
4009
4010 return 0;
4011}
static int publish_hint_remove(struct ast_hint *hint)
Publish a hint removed event
Definition pbx.c:3956
char exten_name[AST_MAX_EXTENSION]
Definition pbx.c:365
char context_name[AST_MAX_CONTEXT]
Definition pbx.c:364

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

Referenced by destroy_exten().

◆ ast_spawn_extension()

int ast_spawn_extension ( struct ast_channel c,
const char *  context,
const char *  exten,
int  priority,
const char *  callerid,
int *  found,
int  combined_find_spawn 
)

Launch a new extension (i.e. new stack)

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

This adds a new extension to the asterisk extension list.

Note
It is possible for autoservice to be started and stopped on c during this function call, it is important that c is not locked prior to calling this. Otherwise a deadlock may occur
Return values
0on success
-1on failure.

Definition at line 4236 of file pbx.c.

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

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

4192{
4193 struct ast_exten *e = ast_hint_extension(c, context, exten);
4194
4195 if (!e) {
4196 return 0;
4197 }
4198
4199 if (hint) {
4200 ast_str_set(hint, hintsize, "%s", ast_get_extension_app(e));
4201 }
4202 if (name) {
4203 const char *tmp = ast_get_extension_app_data(e);
4204 if (tmp) {
4205 ast_str_set(name, namesize, "%s", tmp);
4206 }
4207 }
4208 return -1;
4209}

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

Referenced by ast_str_retrieve_variable().

◆ AST_THREADSTORAGE_CUSTOM_SCOPE() [1/3]

AST_THREADSTORAGE_CUSTOM_SCOPE ( extensionstate_buf  ,
NULL  ,
ast_free_ptr  ,
static   
)

◆ AST_THREADSTORAGE_CUSTOM_SCOPE() [2/3]

AST_THREADSTORAGE_CUSTOM_SCOPE ( hintdevice_data  ,
NULL  ,
ast_free_ptr  ,
static   
)

◆ AST_THREADSTORAGE_CUSTOM_SCOPE() [3/3]

AST_THREADSTORAGE_CUSTOM_SCOPE ( switch_data  ,
NULL  ,
ast_free_ptr  ,
static   
)

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

8642{
8643 if (!exten)
8644 return con ? con->root : NULL;
8645 else
8646 return exten->next;
8647}

References ast_exten::exten, ast_exten::next, 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 8733 of file pbx.c.

8735{
8736 if (!con) {
8737 return NULL;
8738 }
8739
8740 if (ip) {
8741 int idx;
8742 int next = 0;
8743
8744 for (idx = 0; idx < ast_context_ignorepats_count(con); idx++) {
8745 const struct ast_ignorepat *i = ast_context_ignorepats_get(con, idx);
8746
8747 if (next) {
8748 return i;
8749 }
8750
8751 if (ip == i) {
8752 next = 1;
8753 }
8754 }
8755
8756 return NULL;
8757 }
8758
8759 if (!ast_context_ignorepats_count(con)) {
8760 return NULL;
8761 }
8762
8763 return ast_context_ignorepats_get(con, 0);
8764}
struct ast_ignorepat * next
Definition extconf.c:2386

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

◆ ast_walk_context_includes()

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

Definition at line 8694 of file pbx.c.

8696{
8697 if (inc) {
8698 int idx;
8699 int next = 0;
8700
8701 for (idx = 0; idx < ast_context_includes_count(con); idx++) {
8702 const struct ast_include *include = AST_VECTOR_GET(&con->includes, idx);
8703
8704 if (next) {
8705 return include;
8706 }
8707
8708 if (inc == include) {
8709 next = 1;
8710 }
8711 }
8712
8713 return NULL;
8714 }
8715
8716 if (!ast_context_includes_count(con)) {
8717 return NULL;
8718 }
8719
8720 return ast_context_includes_get(con, 0);
8721}
struct ast_include * next
Definition extconf.c:2368

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

Referenced by context_included().

◆ ast_walk_context_switches()

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

Definition at line 8649 of file pbx.c.

8651{
8652 if (sw) {
8653 int idx;
8654 int next = 0;
8655
8656 for (idx = 0; idx < ast_context_switches_count(con); idx++) {
8657 const struct ast_sw *s = ast_context_switches_get(con, idx);
8658
8659 if (next) {
8660 return s;
8661 }
8662
8663 if (sw == s) {
8664 next = 1;
8665 }
8666 }
8667
8668 return NULL;
8669 }
8670
8671 if (!ast_context_switches_count(con)) {
8672 return NULL;
8673 }
8674
8675 return ast_context_switches_get(con, 0);
8676}

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)

Definition at line 8635 of file pbx.c.

8636{
8637 return con ? con->next : contexts;
8638}

References contexts, contexts, and ast_context::next.

◆ ast_walk_extension_priorities()

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

◆ ast_wrlock_context()

int ast_wrlock_context ( struct ast_context con)

◆ ast_wrlock_contexts()

int ast_wrlock_contexts ( void  )

◆ autohint_cmp()

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

Definition at line 496 of file pbx.c.

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

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

Referenced by ast_pbx_init().

◆ autohint_hash_cb()

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

Definition at line 475 of file pbx.c.

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

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

Referenced by ast_pbx_init().

◆ candidate_exten_advance()

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

Definition at line 1239 of file pbx.c.

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

References str.

◆ cli_match_char_tree()

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

Definition at line 1131 of file pbx.c.

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

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

4316{
4317 int digit;
4318
4319 buf[pos] = '\0'; /* make sure it is properly terminated */
4321 S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
4322 /* As long as we're willing to wait, and as long as it's not defined,
4323 keep reading digits until we can't possibly get a right answer anymore. */
4324 digit = ast_waitfordigit(c, waittime);
4327 } else {
4328 if (!digit) /* No entry */
4329 break;
4330 if (digit < 0) /* Error, maybe a hangup */
4331 return -1;
4332 if (pos < buflen - 1) { /* XXX maybe error otherwise ? */
4333 buf[pos++] = digit;
4334 buf[pos] = '\0';
4335 }
4336 waittime = ast_channel_pbx(c)->dtimeoutms;
4337 }
4338 }
4339 return 0;
4340}
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
Definition channel.c:3191

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

Referenced by __ast_pbx_run().

◆ compare_char()

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

Definition at line 694 of file pbx.c.

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

References a, b, and bc.

Referenced by get_pattern_node().

◆ complete_core_show_hint()

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

autocomplete for CLI command 'core show hint'

Definition at line 5255 of file pbx.c.

5256{
5257 struct ast_hint *hint;
5258 char *ret = NULL;
5259 int which = 0;
5260 int wordlen;
5261 struct ao2_iterator i;
5262
5263 if (pos != 3)
5264 return NULL;
5265
5266 wordlen = strlen(word);
5267
5268 /* walk through all hints */
5269 i = ao2_iterator_init(hints, 0);
5270 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
5271 ao2_lock(hint);
5272 if (!hint->exten) {
5273 /* The extension has already been destroyed */
5274 ao2_unlock(hint);
5275 continue;
5276 }
5277 if (!strncasecmp(word, ast_get_extension_name(hint->exten), wordlen) && ++which > state) {
5279 ao2_unlock(hint);
5280 ao2_ref(hint, -1);
5281 break;
5282 }
5283 ao2_unlock(hint);
5284 }
5286
5287 return ret;
5288}
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 5434 of file pbx.c.

5436{
5437 struct ast_context *c = NULL;
5438 char *ret = NULL;
5439 int which = 0;
5440 int wordlen;
5441
5442 /* we are do completion of [exten@]context on second position only */
5443 if (pos != 2)
5444 return NULL;
5445
5447
5448 wordlen = strlen(word);
5449
5450 /* walk through all contexts and return the n-th match */
5451 while ( (c = ast_walk_contexts(c)) ) {
5452 if (!strncasecmp(word, ast_get_context_name(c), wordlen) && ++which > state) {
5454 break;
5455 }
5456 }
5457
5459
5460 return ret;
5461}

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

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

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

6289{
6290 int idx;
6291
6292 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);
6293 /* copy in the includes, switches, and ignorepats */
6294 /* walk through includes */
6295 for (idx = 0; idx < ast_context_includes_count(old); idx++) {
6296 const struct ast_include *i = ast_context_includes_get(old, idx);
6297
6298 if (!strcmp(ast_get_include_registrar(i), registrar)) {
6299 continue; /* not mine */
6300 }
6302 }
6303
6304 /* walk through switches */
6305 for (idx = 0; idx < ast_context_switches_count(old); idx++) {
6306 const struct ast_sw *sw = ast_context_switches_get(old, idx);
6307
6308 if (!strcmp(ast_get_switch_registrar(sw), registrar)) {
6309 continue; /* not mine */
6310 }
6312 }
6313
6314 /* walk thru ignorepats ... */
6315 for (idx = 0; idx < ast_context_ignorepats_count(old); idx++) {
6316 const struct ast_ignorepat *ip = ast_context_ignorepats_get(old, idx);
6317
6318 if (strcmp(ast_get_ignorepat_registrar(ip), registrar) == 0) {
6319 continue; /* not mine */
6320 }
6322 }
6323}
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 6326 of file pbx.c.

6327{
6328 struct ast_context *con;
6329 struct ast_hashtab_iter *iter;
6330
6331 /* Remove all autohints as the below iteration will recreate them */
6333
6334 iter = ast_hashtab_start_traversal(table);
6335 while ((con = ast_hashtab_next(iter))) {
6336 size_t name_len = strlen(con->name) + 1;
6337 size_t registrar_len = strlen(con->registrar) + 1;
6338 struct ast_autohint *autohint;
6339
6340 if (!con->autohints) {
6341 continue;
6342 }
6343
6344 autohint = ao2_alloc_options(sizeof(*autohint) + name_len + registrar_len, NULL, AO2_ALLOC_OPT_LOCK_NOLOCK);
6345 if (!autohint) {
6346 continue;
6347 }
6348
6349 ast_copy_string(autohint->context, con->name, name_len);
6350 autohint->registrar = autohint->context + name_len;
6351 ast_copy_string(autohint->registrar, con->registrar, registrar_len);
6352
6353 ao2_link(autohints, autohint);
6354 ao2_ref(autohint, -1);
6355
6356 ast_verb(3, "Enabled autohints support on context '%s'\n", con->name);
6357 }
6359}
@ OBJ_NODATA
Definition astobj2.h:1044
@ OBJ_MULTIPLE
Definition astobj2.h:1049
char * registrar
Name of the registrar.
Definition pbx.c:409

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

Referenced by ast_merge_contexts_and_delete().

◆ create_match_char_tree()

static void create_match_char_tree ( struct ast_context con)
static

Definition at line 1785 of file pbx.c.

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

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

Referenced by pbx_find_extension().

◆ decrease_call_count()

static void decrease_call_count ( void  )
static

Definition at line 4702 of file pbx.c.

4703{
4705 if (countcalls > 0)
4706 countcalls--;
4708}
static ast_mutex_t maxcalllock
Definition pbx.c:792

References ast_mutex_lock, ast_mutex_unlock, countcalls, and maxcalllock.

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

◆ destroy_exten()

static void destroy_exten ( struct ast_exten e)
static

Definition at line 4710 of file pbx.c.

4711{
4712 if (e->priority == PRIORITY_HINT)
4713 ast_remove_hint(e);
4714
4715 if (e->peer_table)
4717 if (e->peer_label_table)
4719 if (e->datad)
4720 e->datad(e->data);
4721 ast_free(e);
4722}
static int ast_remove_hint(struct ast_exten *e)
Remove hint from extension.
Definition pbx.c:3977

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

3940{
3941 struct ast_hint *hint = obj;
3942 int i;
3943
3944 ao2_cleanup(hint->callbacks);
3945
3946 for (i = 0; i < AST_VECTOR_SIZE(&hint->devices); i++) {
3947 char *device = AST_VECTOR_GET(&hint->devices, i);
3948 ast_free(device);
3949 }
3950 AST_VECTOR_FREE(&hint->devices);
3953}
#define ao2_cleanup(obj)
Definition astobj2.h:1934

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

Referenced by ast_add_hint().

◆ destroy_pattern_tree()

static void destroy_pattern_tree ( struct match_char pattern_tree)
static

Definition at line 1808 of file pbx.c.

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

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

Referenced by __ast_internal_context_destroy(), and destroy_pattern_tree().

◆ destroy_state_cb()

static void destroy_state_cb ( void *  doomed)
static

Definition at line 3750 of file pbx.c.

3751{
3752 struct ast_state_cb *state_cb = doomed;
3753
3754 if (state_cb->destroy_cb) {
3755 state_cb->destroy_cb(state_cb->id, state_cb->data);
3756 }
3757}
int id
Definition pbx.c:325
ast_state_cb_destroy_type destroy_cb
Definition pbx.c:333

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

Referenced by extension_state_add_destroy().

◆ device_state_cb()

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

Definition at line 3620 of file pbx.c.

3621{
3622 struct ast_device_state_message *dev_state;
3623 struct ast_str *hint_app;
3624 struct ast_hintdevice *device;
3625 struct ast_hintdevice *cmpdevice;
3626 struct ao2_iterator *dev_iter;
3627 struct ao2_iterator auto_iter;
3628 struct ast_autohint *autohint;
3629 char *virtual_device;
3630 char *type;
3631 char *device_name;
3632
3634 return;
3635 }
3636
3637 if (hint_remove_message_type() == stasis_message_type(msg)) {
3638 /* The extension has already been destroyed */
3639 struct ast_state_cb *state_cb;
3640 struct ao2_iterator cb_iter;
3641 struct ast_hint *hint = stasis_message_data(msg);
3642
3643 ao2_lock(hint);
3645 ao2_unlock(hint);
3646
3647 cb_iter = ao2_iterator_init(hint->callbacks, 0);
3648 for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_ref(state_cb, -1)) {
3650 hint->context_name,
3651 hint->exten_name,
3652 state_cb->data,
3654 hint,
3655 NULL);
3656 }
3657 ao2_iterator_destroy(&cb_iter);
3658 return;
3659 }
3660
3662 return;
3663 }
3664
3665 dev_state = stasis_message_data(msg);
3666 if (dev_state->eid) {
3667 /* ignore non-aggregate states */
3668 return;
3669 }
3670
3672 /* There are no hints monitoring devices. */
3673 return;
3674 }
3675
3676 hint_app = ast_str_create(1024);
3677 if (!hint_app) {
3678 return;
3679 }
3680
3681 cmpdevice = ast_alloca(sizeof(*cmpdevice) + strlen(dev_state->device));
3682 strcpy(cmpdevice->hintdevice, dev_state->device);
3683
3684 ast_mutex_lock(&context_merge_lock);/* Hold off ast_merge_contexts_and_delete */
3685
3686 /* Initially we find all hints for the device and notify them */
3687 dev_iter = ao2_t_callback(hintdevices,
3690 cmpdevice,
3691 "find devices in container");
3692 if (dev_iter) {
3693 for (; (device = ao2_iterator_next(dev_iter)); ao2_t_ref(device, -1, "Next device")) {
3694 if (device->hint) {
3695 device_state_notify_callbacks(device->hint, &hint_app);
3696 }
3697 }
3698 ao2_iterator_destroy(dev_iter);
3699 }
3700
3701 /* Second stage we look for any autohint contexts and if the device is not already in the hints
3702 * we create it.
3703 */
3704 type = ast_strdupa(dev_state->device);
3705 if (ast_strlen_zero(type)) {
3706 goto end;
3707 }
3708
3709 /* Determine if this is a virtual/custom device or a real device */
3710 virtual_device = strchr(type, ':');
3711 device_name = strchr(type, '/');
3712 if (virtual_device && (!device_name || (virtual_device < device_name))) {
3713 device_name = virtual_device;
3714 }
3715
3716 /* Invalid device state name - not a virtual/custom device and not a real device */
3717 if (ast_strlen_zero(device_name)) {
3718 goto end;
3719 }
3720
3721 *device_name++ = '\0';
3722
3723 auto_iter = ao2_iterator_init(autohints, 0);
3724 for (; (autohint = ao2_iterator_next(&auto_iter)); ao2_t_ref(autohint, -1, "Next autohint")) {
3725 if (ast_get_hint(NULL, 0, NULL, 0, NULL, autohint->context, device_name)) {
3726 continue;
3727 }
3728
3729 /* The device has no hint in the context referenced by this autohint so create one */
3730 ast_add_extension(autohint->context, 0, device_name,
3731 PRIORITY_HINT, NULL, NULL, dev_state->device,
3732 ast_strdup(dev_state->device), ast_free_ptr, autohint->registrar);
3733
3734 /* Since this hint was just created there are no watchers, so we don't need to notify anyone */
3735 }
3736 ao2_iterator_destroy(&auto_iter);
3737
3738end:
3740 ast_free(hint_app);
3741 return;
3742}
#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:3573
static void device_state_notify_callbacks(struct ast_hint *hint, struct ast_str **hint_app)
Definition pbx.c:3406
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:4173
@ AST_EXTENSION_DEACTIVATED
Definition pbx.h:63
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.
const struct ast_eid * eid
The EID of the server where this message originated.

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

Referenced by load_pbx().

◆ device_state_info_dt()

static void device_state_info_dt ( void *  obj)
static

Definition at line 3105 of file pbx.c.

3106{
3107 struct ast_device_state_info *info = obj;
3108
3109 ao2_cleanup(info->causing_channel);
3110}

References ao2_cleanup.

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

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

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

Referenced by device_state_cb(), and handle_hint_change_message_type().

◆ exception_store_free()

static void exception_store_free ( void *  data)
static

Definition at line 2798 of file pbx.c.

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

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

3293{
3294 int res = 0;
3295 struct ast_state_cb_info info = { 0, };
3296
3297 info.reason = reason;
3298
3299 /* Copy over current hint data */
3300 if (hint) {
3301 ao2_lock(hint);
3302 info.exten_state = hint->laststate;
3303 info.device_state_info = device_state_info;
3304 info.presence_state = hint->last_presence_state;
3305 if (!(ast_strlen_zero(hint->last_presence_subtype))) {
3306 info.presence_subtype = ast_strdupa(hint->last_presence_subtype);
3307 } else {
3308 info.presence_subtype = "";
3309 }
3310 if (!(ast_strlen_zero(hint->last_presence_message))) {
3311 info.presence_message = ast_strdupa(hint->last_presence_message);
3312 } else {
3313 info.presence_message = "";
3314 }
3315 ao2_unlock(hint);
3316 } else {
3317 info.exten_state = AST_EXTENSION_REMOVED;
3318 }
3319
3320 res = cb(context, exten, &info, data);
3321
3322 return res;
3323}
@ 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(), ast_state_cb_info::device_state_info, ast_hint::last_presence_message, ast_hint::last_presence_state, ast_hint::last_presence_subtype, ast_hint::laststate, and ast_state_cb_info::reason.

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

◆ ext_cmp()

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

Definition at line 2155 of file pbx.c.

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

References ext_cmp_exten(), and ext_cmp_pattern().

Referenced by ast_add_extension2_lockopt(), and ast_extension_cmp().

◆ ext_cmp_exten()

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

Definition at line 1905 of file pbx.c.

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

Referenced by _extension_match_core(), and ext_cmp().

◆ ext_cmp_exten_partial()

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

Definition at line 1862 of file pbx.c.

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

Referenced by _extension_match_core().

◆ ext_cmp_exten_strlen()

static int ext_cmp_exten_strlen ( const char *  str)
static

Definition at line 1832 of file pbx.c.

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

References len(), and str.

Referenced by _extension_match_core().

◆ ext_cmp_pattern()

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

Definition at line 2107 of file pbx.c.

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

References ARRAY_LEN, and ext_cmp_pattern_pos().

Referenced by _extension_match_core(), and ext_cmp().

◆ ext_cmp_pattern_pos()

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

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

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

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

Definition at line 1992 of file pbx.c.

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

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

Referenced by ext_cmp_pattern().

◆ ext_fluff_count()

static int ext_fluff_count ( const char *  exten)
static

Definition at line 2177 of file pbx.c.

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

References ast_exten::exten.

Referenced by ast_add_extension2_lockopt().

◆ ext_strncpy()

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

Definition at line 7070 of file pbx.c.

7071{
7072 unsigned int count;
7073 unsigned int insquares;
7074 unsigned int is_pattern;
7075
7076 if (!dst_size--) {
7077 /* There really is no dst buffer */
7078 return 0;
7079 }
7080
7081 count = 0;
7082 insquares = 0;
7083 is_pattern = *src == '_';
7084 while (*src && count < dst_size) {
7085 if (*src == '[') {
7086 if (is_pattern) {
7087 insquares = 1;
7088 }
7089 } else if (*src == ']') {
7090 insquares = 0;
7091 } else if (*src == ' ' && !insquares) {
7092 ++src;
7093 continue;
7094 } else if (*src == '-' && !insquares && nofluff) {
7095 ++src;
7096 continue;
7097 }
7098 *dst++ = *src++;
7099 ++count;
7100 }
7101 *dst = '\0';
7102
7103 return count + 1;
7104}

Referenced by ast_add_extension2_lockopt(), and ast_context_remove_extension_callerid2().

◆ extension_match_core()

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

Definition at line 2429 of file pbx.c.

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

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

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

◆ extension_presence_state_helper()

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

Definition at line 3236 of file pbx.c.

3237{
3238 struct ast_str *hint_app = ast_str_thread_get(&extensionstate_buf, 32);
3239 char *presence_provider;
3240 const char *app;
3241
3242 if (!e || !hint_app) {
3243 return -1;
3244 }
3245
3247 if (ast_strlen_zero(app)) {
3248 return -1;
3249 }
3250
3251 ast_str_set(&hint_app, 0, "%s", app);
3252 presence_provider = parse_hint_presence(hint_app);
3253
3254 if (ast_strlen_zero(presence_provider)) {
3255 /* No presence string in the hint */
3256 return 0;
3257 }
3258
3259 return ast_presence_state(presence_provider, subtype, message);
3260}
static char * parse_hint_presence(struct ast_str *hint_args)
Definition pbx.c:3073
ast_presence_state

References app, ast_get_extension_app(), ast_str_set(), ast_str_thread_get(), ast_strlen_zero(), 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 3763 of file pbx.c.

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

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

4837{
4838 struct ast_context item = {
4839 .name = context,
4840 };
4841
4843}

References ast_hashtab_lookup(), 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 4850 of file pbx.c.

4851{
4852 struct ast_context *c;
4853 struct ast_context item = {
4854 .name = context,
4855 };
4856
4859 if (!c) {
4861 }
4862
4863 return c;
4864}

References ast_hashtab_lookup(), ast_rdlock_contexts(), ast_unlock_contexts(), c, 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 3878 of file pbx.c.

3879{
3880 struct ast_state_cb *state_cb;
3881 const struct ast_hint *hint = obj;
3882 int *id = arg;
3883
3884 if ((state_cb = ao2_find(hint->callbacks, id, 0))) {
3885 ao2_ref(state_cb, -1);
3886 return CMP_MATCH | CMP_STOP;
3887 }
3888
3889 return 0;
3890}

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

Referenced by ast_extension_state_del().

◆ get_canmatch_exten()

static struct ast_exten * get_canmatch_exten ( struct match_char node)
static

Definition at line 1161 of file pbx.c.

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

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

◆ get_device_state_causing_channels()

static void get_device_state_causing_channels ( struct ao2_container c)
static

Definition at line 3332 of file pbx.c.

3333{
3334 struct ao2_iterator iter;
3336 struct ast_channel *chan;
3337
3338 if (!c || !ao2_container_count(c)) {
3339 return;
3340 }
3341 iter = ao2_iterator_init(c, 0);
3342 for (; (info = ao2_iterator_next(&iter)); ao2_ref(info, -1)) {
3343 enum ast_channel_state search_state = 0; /* prevent false uninit warning */
3344 char match[AST_CHANNEL_NAME];
3345 struct ast_channel_iterator *chan_iter;
3346 struct timeval chantime = {0, }; /* prevent false uninit warning */
3347
3348 switch (info->device_state) {
3349 case AST_DEVICE_RINGING:
3351 /* find ringing channel */
3352 search_state = AST_STATE_RINGING;
3353 break;
3354 case AST_DEVICE_BUSY:
3355 /* find busy channel */
3356 search_state = AST_STATE_BUSY;
3357 break;
3358 case AST_DEVICE_ONHOLD:
3359 case AST_DEVICE_INUSE:
3360 /* find up channel */
3361 search_state = AST_STATE_UP;
3362 break;
3363 case AST_DEVICE_UNKNOWN:
3365 case AST_DEVICE_INVALID:
3367 case AST_DEVICE_TOTAL /* not a state */:
3368 /* no channels are of interest */
3369 continue;
3370 }
3371
3372 /* iterate over all channels of the device */
3373 snprintf(match, sizeof(match), "%s-", info->device_name);
3374 chan_iter = ast_channel_iterator_by_name_new(match, strlen(match));
3375 for (; (chan = ast_channel_iterator_next(chan_iter)); ast_channel_unref(chan)) {
3376 ast_channel_lock(chan);
3377 /* this channel's state doesn't match */
3378 if (search_state != ast_channel_state(chan)) {
3379 ast_channel_unlock(chan);
3380 continue;
3381 }
3382 /* any non-ringing channel will fit */
3383 if (search_state != AST_STATE_RINGING) {
3384 ast_channel_unlock(chan);
3385 info->causing_channel = chan; /* is kept ref'd! */
3386 break;
3387 }
3388 /* but we need the oldest ringing channel of the device to match with undirected pickup */
3389 if (!info->causing_channel) {
3390 chantime = ast_channel_creationtime(chan);
3391 ast_channel_ref(chan); /* must ref it! */
3392 info->causing_channel = chan;
3393 } else if (ast_tvcmp(ast_channel_creationtime(chan), chantime) < 0) {
3394 chantime = ast_channel_creationtime(chan);
3395 ast_channel_unref(info->causing_channel);
3396 ast_channel_ref(chan); /* must ref it! */
3397 info->causing_channel = chan;
3398 }
3399 ast_channel_unlock(chan);
3400 }
3402 }
3403 ao2_iterator_destroy(&iter);
3404}
static int match(struct ast_sockaddr *addr, unsigned short callno, unsigned short dcallno, const struct chan_iax2_pvt *cur, int check_dcallno)
Definition chan_iax2.c:2388
struct ast_channel_iterator * ast_channel_iterator_by_name_new(const char *name, size_t name_len)
Create a new channel iterator based on name.
Definition channel.c:1368
struct ast_channel_iterator * ast_channel_iterator_destroy(struct ast_channel_iterator *i)
Destroy a channel iterator.
Definition channel.c:1349
struct ast_channel * ast_channel_iterator_next(struct ast_channel_iterator *i)
Get the next channel for a channel iterator.
Definition channel.c:1388
#define ast_channel_ref(c)
Increase channel reference count.
Definition channel.h:3007
struct timeval ast_channel_creationtime(struct ast_channel *chan)
#define AST_CHANNEL_NAME
Definition channel.h:173
ast_channel_state
ast_channel states
@ AST_STATE_RINGING
@ AST_STATE_BUSY
@ AST_STATE_UP
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, and match().

Referenced by ast_extension_state_extended(), and device_state_notify_callbacks().

◆ get_pattern_node()

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

Definition at line 1533 of file pbx.c.

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

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

Referenced by add_exten_to_pattern_tree().

◆ handle_debug_dialplan()

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

Send ack once.

Definition at line 5786 of file pbx.c.

5787{
5788 char *exten = NULL, *context = NULL;
5789 /* Variables used for different counters */
5790 struct dialplan_counters counters;
5791 const char *incstack[AST_PBX_MAX_STACK];
5792
5793 switch (cmd) {
5794 case CLI_INIT:
5795 e->command = "dialplan debug";
5796 e->usage =
5797 "Usage: dialplan debug [context]\n"
5798 " Show dialplan context Trie(s). Usually only useful to folks debugging the deep internals of the fast pattern matcher\n";
5799 return NULL;
5800 case CLI_GENERATE:
5801 return complete_show_dialplan_context(a->line, a->word, a->pos, a->n);
5802 }
5803
5804 memset(&counters, 0, sizeof(counters));
5805
5806 if (a->argc != 2 && a->argc != 3)
5807 return CLI_SHOWUSAGE;
5808
5809 /* we obtain [exten@]context? if yes, split them ... */
5810 /* note: we ignore the exten totally here .... */
5811 if (a->argc == 3) {
5812 if (strchr(a->argv[2], '@')) { /* split into exten & context */
5813 context = ast_strdupa(a->argv[2]);
5814 exten = strsep(&context, "@");
5815 /* change empty strings to NULL */
5816 if (ast_strlen_zero(exten))
5817 exten = NULL;
5818 } else { /* no '@' char, only context given */
5819 context = ast_strdupa(a->argv[2]);
5820 }
5821 if (ast_strlen_zero(context))
5822 context = NULL;
5823 }
5824 /* else Show complete dial plan, context and exten are NULL */
5825 show_debug_helper(a->fd, context, exten, &counters, NULL, 0, incstack);
5826
5827 /* check for input failure and throw some error messages */
5828 if (context && !counters.context_existence) {
5829 ast_cli(a->fd, "There is no existence of '%s' context\n", context);
5830 return CLI_FAILURE;
5831 }
5832
5833
5834 ast_cli(a->fd,"-= %d %s. =-\n",
5835 counters.total_context, counters.total_context == 1 ? "context" : "contexts");
5836
5837 /* everything ok */
5838 return CLI_SUCCESS;
5839}
#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:5434
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:5664
char * command
Definition cli.h:186
const char * usage
Definition cli.h:177
Counters for the show dialplan manager command.
Definition pbx.c:5464

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

3574{
3575 struct ast_hint *hint;
3576 struct ast_str *hint_app;
3577
3578 if (hint_change_message_type() != stasis_message_type(msg)) {
3579 return 0;
3580 }
3581
3582 if (!(hint_app = ast_str_create(1024))) {
3583 return -1;
3584 }
3585
3586 hint = stasis_message_data(msg);
3587
3588 switch (reason) {
3590 device_state_notify_callbacks(hint, &hint_app);
3591 break;
3593 {
3594 char *presence_subtype = NULL;
3595 char *presence_message = NULL;
3596 int state;
3597
3599 hint->exten, &presence_subtype, &presence_message);
3600 {
3601 struct ast_presence_state_message presence_state = {
3603 .subtype = presence_subtype,
3604 .message = presence_message
3605 };
3606
3607 presence_state_notify_callbacks(hint, &hint_app, &presence_state);
3608 }
3609
3610 ast_free(presence_subtype);
3611 ast_free(presence_message);
3612 }
3613 break;
3614 }
3615
3616 ast_free(hint_app);
3617 return 1;
3618}
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:3500
@ 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(), and ast_presence_state_message::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 6092 of file pbx.c.

6093{
6094 int oldval = 0;
6095
6096 switch (cmd) {
6097 case CLI_INIT:
6098 e->command = "dialplan set extenpatternmatchnew true";
6099 e->usage =
6100 "Usage: dialplan set extenpatternmatchnew true|false\n"
6101 " Use the NEW extension pattern matching algorithm, true or false.\n";
6102 return NULL;
6103 case CLI_GENERATE:
6104 return NULL;
6105 }
6106
6107 if (a->argc != 4)
6108 return CLI_SHOWUSAGE;
6109
6110 oldval = pbx_set_extenpatternmatchnew(1);
6111
6112 if (oldval)
6113 ast_cli(a->fd, "\n -- Still using the NEW pattern match algorithm for extension names in the dialplan.\n");
6114 else
6115 ast_cli(a->fd, "\n -- Switched to using the NEW pattern match algorithm for extension names in the dialplan.\n");
6116
6117 return CLI_SUCCESS;
6118}
int pbx_set_extenpatternmatchnew(int newval)
Definition pbx.c:4813

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

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

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

5292{
5293 struct ast_hint *hint;
5294 int watchers;
5295 int num = 0, extenlen;
5296 struct ao2_iterator i;
5298
5299 switch (cmd) {
5300 case CLI_INIT:
5301 e->command = "core show hint";
5302 e->usage =
5303 "Usage: core show hint <exten>\n"
5304 " List registered hint.\n"
5305 " Hint details are shown in five columns. In order from left to right, they are:\n"
5306 " 1. Hint extension URI.\n"
5307 " 2. List of mapped device or presence state identifiers.\n"
5308 " 3. Current extension state. The aggregate of mapped device states.\n"
5309 " 4. Current presence state for the mapped presence state provider.\n"
5310 " 5. Watchers - number of subscriptions and other entities watching this hint.\n";
5311 return NULL;
5312 case CLI_GENERATE:
5313 return complete_core_show_hint(a->line, a->word, a->pos, a->n);
5314 }
5315
5316 if (a->argc < 4)
5317 return CLI_SHOWUSAGE;
5318
5319 if (ao2_container_count(hints) == 0) {
5320 ast_cli(a->fd, "There are no registered dialplan hints\n");
5321 return CLI_SUCCESS;
5322 }
5323
5324 extenlen = strlen(a->argv[3]);
5325 i = ao2_iterator_init(hints, 0);
5326 for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
5327 ao2_lock(hint);
5328 if (!hint->exten) {
5329 /* The extension has already been destroyed */
5330 ao2_unlock(hint);
5331 continue;
5332 }
5333 if (!strncasecmp(ast_get_extension_name(hint->exten), a->argv[3], extenlen)) {
5334 watchers = ao2_container_count(hint->callbacks);
5335 sprintf(buf, "%s@%s",
5338 ast_cli(a->fd, "%-30.30s: %-60.60s State:%-15.15s Presence:%-15.15s Watchers %2d\n",
5339 buf,
5343 watchers);
5344 num++;
5345 }
5346 ao2_unlock(hint);
5347 }
5349 if (!num)
5350 ast_cli(a->fd, "No hints matching extension %s\n", a->argv[3]);
5351 else
5352 ast_cli(a->fd, "%d hint%s matching extension %s\n", num, (num!=1 ? "s":""), a->argv[3]);
5353 return CLI_SUCCESS;
5354}
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:5255
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 5192 of file pbx.c.

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

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

6121{
6122 int oldval = 0;
6123
6124 switch (cmd) {
6125 case CLI_INIT:
6126 e->command = "dialplan set extenpatternmatchnew false";
6127 e->usage =
6128 "Usage: dialplan set extenpatternmatchnew true|false\n"
6129 " Use the NEW extension pattern matching algorithm, true or false.\n";
6130 return NULL;
6131 case CLI_GENERATE:
6132 return NULL;
6133 }
6134
6135 if (a->argc != 4)
6136 return CLI_SHOWUSAGE;
6137
6138 oldval = pbx_set_extenpatternmatchnew(0);
6139
6140 if (!oldval)
6141 ast_cli(a->fd, "\n -- Still using the OLD pattern match algorithm for extension names in the dialplan.\n");
6142 else
6143 ast_cli(a->fd, "\n -- Switched to using the OLD pattern match algorithm for extension names in the dialplan.\n");
6144
6145 return CLI_SUCCESS;
6146}

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

◆ hashtab_compare_exten_labels()

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

Definition at line 748 of file pbx.c.

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

References bc, ast_exten::label, and S_OR.

Referenced by ast_add_extension2_lockopt().

◆ hashtab_compare_exten_numbers()

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

Definition at line 741 of file pbx.c.

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

References bc, and ast_exten::priority.

Referenced by ast_add_extension2_lockopt().

◆ hashtab_compare_extens()

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

Definition at line 713 of file pbx.c.

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

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

Referenced by ast_add_extension2_lockopt().

◆ hashtab_hash_extens()

static unsigned int hashtab_hash_extens ( const void *  obj)
static

Definition at line 761 of file pbx.c.

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

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

Referenced by ast_add_extension2_lockopt().

◆ hashtab_hash_labels()

static unsigned int hashtab_hash_labels ( const void *  obj)
static

Definition at line 777 of file pbx.c.

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

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

Referenced by ast_add_extension2_lockopt().

◆ hashtab_hash_priority()

static unsigned int hashtab_hash_priority ( const void *  obj)
static

Definition at line 771 of file pbx.c.

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

References ast_hashtab_hash_int(), and ast_exten::priority.

Referenced by ast_add_extension2_lockopt().

◆ hint_cmp()

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

Definition at line 8940 of file pbx.c.

8941{
8942 const struct ast_hint *hint = obj;
8943 const struct ast_exten *exten = arg;
8944
8945 return (hint->exten == exten) ? CMP_MATCH | CMP_STOP : 0;
8946}

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

8921{
8922 const struct ast_hint *hint = obj;
8923 const char *exten_name;
8924 int res;
8925
8928 /*
8929 * If the exten or extension name isn't set, return 0 so that
8930 * the ao2_find() search will start in the first bucket.
8931 */
8932 res = 0;
8933 } else {
8935 }
8936
8937 return res;
8938}

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

3926{
3927 const struct ast_state_cb *cb = obj;
3928 int *id = arg;
3929
3930 return (cb->id == *id) ? CMP_MATCH | CMP_STOP : 0;
3931}

References CMP_MATCH, CMP_STOP, and ast_state_cb::id.

Referenced by ast_add_hint().

◆ hintdevice_cmp_multiple()

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

Definition at line 443 of file pbx.c.

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

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

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

◆ hintdevice_destroy()

static void hintdevice_destroy ( void *  obj)
static

Definition at line 560 of file pbx.c.

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

References ao2_ref, ast_hintdevice::hint, and NULL.

Referenced by add_hintdevice().

◆ hintdevice_hash_cb()

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

Definition at line 417 of file pbx.c.

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

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

Referenced by ast_pbx_init().

◆ hintdevice_remove_cb()

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

Definition at line 526 of file pbx.c.

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

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

Referenced by remove_hintdevice().

◆ increase_call_count()

static int increase_call_count ( const struct ast_channel c)
static

Increase call count for channel.

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

Definition at line 4653 of file pbx.c.

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

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

Referenced by ast_pbx_run_args(), and ast_pbx_start().

◆ insert_in_next_chars_alt_char_list()

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

Definition at line 1438 of file pbx.c.

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

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

Referenced by add_pattern_node().

◆ internal_extension_state_extended()

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

Definition at line 3177 of file pbx.c.

3179{
3180 struct ast_exten *e;
3181
3182 if (!(e = ast_hint_extension(c, context, exten))) { /* Do we have a hint for this extension ? */
3183 return -1; /* No hint, return -1 */
3184 }
3185
3186 if (e->exten[0] == '_') {
3187 /* Create this hint on-the-fly, we explicitly lock hints here to ensure the
3188 * same locking order as if this were done through configuration file - that is
3189 * hints is locked first and then (if needed) contexts is locked
3190 */
3191 ao2_lock(hints);
3193 e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr,
3194 e->registrar);
3196 if (!(e = ast_hint_extension(c, context, exten))) {
3197 /* Improbable, but not impossible */
3198 return -1;
3199 }
3200 }
3201
3202 return ast_extension_state2(e, device_state_info); /* Check all devices in the hint */
3203}

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

8466{
8467 int res = 0;
8468
8470
8471 /* Initialize the PBX */
8472 ast_verb(1, "Asterisk PBX Core Initializing\n");
8473
8474 ast_verb(5, "Registering builtin functions:\n");
8478
8479 /* Register manager application */
8482
8483 if (res) {
8484 return -1;
8485 }
8486
8488 return -1;
8489 }
8491 stasis_subscription_accept_message_type(device_state_sub, hint_change_message_type());
8492 stasis_subscription_accept_message_type(device_state_sub, hint_remove_message_type());
8494
8496 return -1;
8497 }
8500
8501 return 0;
8502}
#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.
#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:204
#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:6006
static int action_extensionstatelist(struct mansession *s, const struct message *m)
Definition pbx.c:8388
static struct stasis_subscription * presence_state_sub
Subscription for presence state change events.
Definition pbx.c:790
static void presence_state_cb(void *unused, struct stasis_subscription *sub, struct stasis_message *msg)
Definition pbx.c:8338
static void unload_pbx(void)
Definition pbx.c:8453
static struct ast_custom_function testtime_function
Definition pbx.c:8321
static void device_state_cb(void *unused, struct stasis_subscription *sub, struct stasis_message *msg)
Definition pbx.c:3620
static struct ast_cli_entry pbx_cli[]
Definition pbx.c:6151
static struct stasis_subscription * device_state_sub
Subscription for device state change events.
Definition pbx.c:788
static struct ast_custom_function exception_function
Definition pbx.c:2882
int __ast_custom_function_register(struct ast_custom_function *acf, struct ast_module *mod)
Register a custom function.
struct stasis_topic * ast_presence_state_topic_all(void)
Get presence state topic.
struct stasis_message_type * ast_presence_state_message_type(void)
Get presence state message type.
@ STASIS_SUBSCRIPTION_FILTER_SELECTIVE
Definition stasis.h:297
int stasis_subscription_accept_message_type(struct stasis_subscription *subscription, const struct stasis_message_type *type)
Indicate to a subscription that we are interested in a message type.
Definition stasis.c:1090
int stasis_subscription_set_filter(struct stasis_subscription *subscription, enum stasis_subscription_message_filter filter)
Set the message type filtering level on a subscription.
Definition stasis.c:1144
#define stasis_subscribe(topic, callback, data)
Definition stasis.h:649

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

Referenced by asterisk_daemon().

◆ manager_dpsendack()

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

Send ack once.

Definition at line 5842 of file pbx.c.

5843{
5844 astman_send_listack(s, m, "DialPlan list will follow", "start");
5845}

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

6007{
6008 const char *exten, *context;
6009 const char *id = astman_get_header(m, "ActionID");
6010 const char *incstack[AST_PBX_MAX_STACK];
6011 char idtext[256];
6012
6013 /* Variables used for different counters */
6014 struct dialplan_counters counters;
6015
6016 if (!ast_strlen_zero(id))
6017 snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id);
6018 else
6019 idtext[0] = '\0';
6020
6021 memset(&counters, 0, sizeof(counters));
6022
6023 exten = astman_get_header(m, "Extension");
6024 context = astman_get_header(m, "Context");
6025
6026 manager_show_dialplan_helper(s, m, idtext, context, exten, &counters, NULL, 0, incstack);
6027
6028 if (!ast_strlen_zero(context) && !counters.context_existence) {
6029 char errorbuf[BUFSIZ];
6030
6031 snprintf(errorbuf, sizeof(errorbuf), "Did not find context %s", context);
6032 astman_send_error(s, m, errorbuf);
6033 return 0;
6034 }
6035 if (!ast_strlen_zero(exten) && !counters.extension_existence) {
6036 char errorbuf[BUFSIZ];
6037
6038 if (!ast_strlen_zero(context))
6039 snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s@%s", exten, context);
6040 else
6041 snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s in any context", exten);
6042 astman_send_error(s, m, errorbuf);
6043 return 0;
6044 }
6045
6046 if (!counters.total_items) {
6047 manager_dpsendack(s, m);
6048 }
6049
6050 astman_send_list_complete_start(s, m, "ShowDialPlanComplete", counters.total_items);
6051 astman_append(s,
6052 "ListExtensions: %d\r\n"
6053 "ListPriorities: %d\r\n"
6054 "ListContexts: %d\r\n",
6055 counters.total_exten, counters.total_prio, counters.total_context);
6057
6058 /* everything ok */
6059 return 0;
6060}
static void manager_dpsendack(struct mansession *s, const struct message *m)
Send ack once.
Definition pbx.c:5842
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:5851

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

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

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, dialplan_counters::context_existence, ast_exten::exten, dialplan_counters::extension_existence, LOG_WARNING, manager_dpsendack(), manager_show_dialplan_helper(), NULL, PRIORITY_HINT, dialplan_counters::total_context, dialplan_counters::total_exten, dialplan_counters::total_items, and dialplan_counters::total_prio.

Referenced by manager_show_dialplan(), and manager_show_dialplan_helper().

◆ matchcid()

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

Definition at line 2485 of file pbx.c.

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

References ast_extension_match(), and ast_strlen_zero().

Referenced by pbx_find_extension().

◆ new_find_extension()

static void new_find_extension ( const char *  str,
struct scoreboard score,
struct match_char tree,
int  length,
int  spec,
const char *  callerid,
const char *  label,
enum ext_match_t  action 
)
static

Definition at line 1251 of file pbx.c.

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

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

Referenced by new_find_extension(), and pbx_find_extension().

◆ parse_hint_device()

static char * parse_hint_device ( struct ast_str hint_args)
static

Definition at line 3092 of file pbx.c.

3093{
3094 char *copy = ast_strdupa(ast_str_buffer(hint_args));
3095 char *tmp;
3096
3097 if ((tmp = strrchr(copy, ','))) {
3098 *tmp = '\0';
3099 }
3100
3101 ast_str_set(&hint_args, 0, "%s", copy);
3102 return ast_str_buffer(hint_args);
3103}
static int copy(char *infile, char *outfile)
Utility function to copy a file.

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

Referenced by ast_extension_state3().

◆ parse_hint_presence()

static char * parse_hint_presence ( struct ast_str hint_args)
static

Definition at line 3073 of file pbx.c.

3074{
3075 char *copy = ast_strdupa(ast_str_buffer(hint_args));
3076 char *tmp = "";
3077
3078 if ((tmp = strrchr(copy, ','))) {
3079 *tmp = '\0';
3080 tmp++;
3081 } else {
3082 return NULL;
3083 }
3084 ast_str_set(&hint_args, 0, "%s", tmp);
3085 return ast_str_buffer(hint_args);
3086}

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

Referenced by extension_presence_state_helper().

◆ pbx_checkcondition()

int pbx_checkcondition ( const char *  condition)

Evaluate a condition.

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

Definition at line 8326 of file pbx.c.

8327{
8328 int res;
8329 if (ast_strlen_zero(condition)) { /* NULL or empty strings are false */
8330 return 0;
8331 } else if (sscanf(condition, "%30d", &res) == 1) { /* Numbers are evaluated for truth */
8332 return res;
8333 } else { /* Strings are true */
8334 return 1;
8335 }
8336}

References ast_strlen_zero().

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

◆ pbx_destroy()

static void pbx_destroy ( struct ast_pbx p)
static

Definition at line 1005 of file pbx.c.

1006{
1007 ast_free(p);
1008}

References ast_free.

Referenced by __ast_pbx_run().

◆ pbx_dial_reason()

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

Attempt to convert disconnect cause to old originate reason.

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

Definition at line 7725 of file pbx.c.

7726{
7727 enum ast_control_frame_type pbx_reason;
7728
7729 if (dial_result == AST_DIAL_RESULT_ANSWERED) {
7730 /* Remote end answered. */
7731 pbx_reason = AST_CONTROL_ANSWER;
7732 } else if (dial_result == AST_DIAL_RESULT_HANGUP) {
7733 /* Caller hungup */
7734 pbx_reason = AST_CONTROL_HANGUP;
7735 } else {
7736 switch (cause) {
7738 pbx_reason = AST_CONTROL_BUSY;
7739 break;
7746 pbx_reason = AST_CONTROL_CONGESTION;
7747 break;
7750 /* Remote end was ringing (but isn't anymore) */
7751 pbx_reason = AST_CONTROL_RINGING;
7752 break;
7754 default:
7755 /* Call Failure (not BUSY, and not NO_ANSWER, maybe Circuit busy or down?) */
7756 pbx_reason = 0;
7757 break;
7758 }
7759 }
7760
7761 return pbx_reason;
7762}
#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_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 2905 of file pbx.c.

2908{
2909 struct ast_exten *e;
2910 struct ast_app *app;
2911 char *substitute = NULL;
2912 struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */
2913 char passdata[EXT_DATA_SIZE];
2914 int matching_action = (action == E_MATCH || action == E_CANMATCH || action == E_MATCHMORE);
2915
2917
2918 if (!context) {
2919 context = con->name;
2920 }
2921
2922 if (found)
2923 *found = 0;
2924
2925 e = pbx_find_extension(c, con, &q, context, exten, priority, label, callerid, action);
2926 if (e) {
2927 if (found)
2928 *found = 1;
2929 if (matching_action) {
2931 return -1; /* success, we found it */
2932 } else if (action == E_FINDLABEL) { /* map the label to a priority */
2933 int res = e->priority;
2934
2936
2937 /* the priority we were looking for */
2938 return res;
2939 } else { /* spawn */
2940 if (!e->cached_app)
2941 e->cached_app = pbx_findapp(e->app);
2942 app = e->cached_app;
2943 if (ast_strlen_zero(e->data)) {
2944 *passdata = '\0';
2945 } else {
2946 const char *tmp;
2947 if ((!(tmp = strchr(e->data, '$'))) || (!strstr(tmp, "${") && !strstr(tmp, "$["))) {
2948 /* no variables to substitute, copy on through */
2949 ast_copy_string(passdata, e->data, sizeof(passdata));
2950 } else {
2951 /* save e->data on stack for later processing after lock released */
2952 substitute = ast_strdupa(e->data);
2953 }
2954 }
2956 if (!app) {
2957 ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority);
2958 return -1;
2959 }
2963 return 0;
2964 }
2965 if (ast_channel_context(c) != context)
2966 ast_channel_context_set(c, context);
2967 if (ast_channel_exten(c) != exten)
2968 ast_channel_exten_set(c, exten);
2971 if (substitute) {
2972 pbx_substitute_variables_helper(c, substitute, passdata, sizeof(passdata)-1);
2973 }
2974 ast_debug(1, "Launching '%s'\n", app_name(app));
2975 if (VERBOSITY_ATLEAST(3)) {
2976 ast_verb(3, "Executing [%s@%s:%d] " COLORIZE_FMT "(\"" COLORIZE_FMT "\", \"" COLORIZE_FMT "\") %s\n",
2977 exten, context, priority,
2980 COLORIZE(COLOR_BRMAGENTA, 0, passdata),
2981 "in new stack");
2982 }
2983 return pbx_exec(c, app, passdata); /* 0 on success, -1 on failure */
2984 }
2985 } else if (q.swo) { /* not found here, but in another switch */
2986 if (found)
2987 *found = 1;
2989 if (matching_action) {
2990 return -1;
2991 } else {
2992 if (!q.swo->exec) {
2993 ast_log(LOG_WARNING, "No execution engine for switch %s\n", q.swo->name);
2994 return -1;
2995 }
2996 return q.swo->exec(c, q.foundcontext ? q.foundcontext : context, exten, priority, callerid, q.data);
2997 }
2998 } else { /* not found anywhere, see what happened */
3000 /* Using S_OR here because Solaris doesn't like NULL being passed to ast_log */
3001 switch (q.status) {
3002 case STATUS_NO_CONTEXT:
3003 if (!matching_action && !combined_find_spawn)
3004 ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", S_OR(context, ""));
3005 break;
3007 if (!matching_action && !combined_find_spawn)
3008 ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, S_OR(context, ""));
3009 break;
3010 case STATUS_NO_PRIORITY:
3011 if (!matching_action && !combined_find_spawn)
3012 ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, S_OR(context, ""));
3013 break;
3014 case STATUS_NO_LABEL:
3015 if (context && !combined_find_spawn)
3016 ast_log(LOG_NOTICE, "No such label '%s' in extension '%s' in context '%s'\n", S_OR(label, ""), exten, S_OR(context, ""));
3017 break;
3018 default:
3019 ast_debug(1, "Shouldn't happen!\n");
3020 }
3021
3022 return (matching_action) ? 0 : -1;
3023 }
3024}
#define VERBOSITY_ATLEAST(level)
#define STATUS_NO_LABEL
Definition pbx.c:2482
#define STATUS_NO_EXTENSION
Definition pbx.c:2480
#define STATUS_NO_CONTEXT
Definition pbx.c:2479
#define EXT_DATA_SIZE
Definition pbx.c:231
#define STATUS_NO_PRIORITY
Definition pbx.c:2481
int pbx_exec(struct ast_channel *c, struct ast_app *app, const char *data)
Execute an application.
Definition pbx_app.c:483
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:475
ast_app: A registered application
Definition pbx_app.c:45
struct ast_app * cached_app
Definition pbx.c:262
ast_switch_f * exec
Definition pbx.h:169
const char * name
Definition pbx.h:164
struct ast_switch * swo
Definition extconf.h:239
const char * foundcontext
Definition extconf.h:241
const char * data
Definition extconf.h:240
#define COLOR_BRCYAN
Definition term.h:63
#define COLORIZE(fg, bg, str)
Definition term.h:72
#define COLORIZE_FMT
Shortcut macros for coloring a set of text.
Definition term.h:71
#define COLOR_BRMAGENTA
Definition term.h:61

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

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

◆ pbx_find_extension()

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

Definition at line 2497 of file pbx.c.

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

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

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

◆ pbx_outgoing_attempt()

static int pbx_outgoing_attempt ( const char *  type,
struct ast_format_cap cap,
const char *  addr,
int  timeout,
const char *  context,
const char *  exten,
int  priority,
const char *  app,
const char *  appdata,
int *  reason,
int  synchronous,
const char *  cid_num,
const char *  cid_name,
struct ast_variable vars,
const char *  account,
struct ast_channel **  locked_channel,
int  early_media,
const struct ast_assigned_ids assignedids,
const char *  predial_callee 
)
static

Definition at line 7764 of file pbx.c.

7770{
7772 struct ast_channel *dialed;
7773 pthread_t thread;
7774 char tmp_cid_name[128];
7775 char tmp_cid_num[128];
7776
7778 if (!outgoing) {
7779 return -1;
7780 }
7781 ast_cond_init(&outgoing->cond, NULL);
7782
7783 if (!ast_strlen_zero(app)) {
7785 outgoing->appdata = ast_strdup(appdata);
7786 } else {
7790 }
7791
7792 if (!(outgoing->dial = ast_dial_create())) {
7793 return -1;
7794 }
7795
7796 if (ast_dial_append(outgoing->dial, type, addr, assignedids)) {
7797 return -1;
7798 }
7799
7800 ast_dial_set_global_timeout(outgoing->dial, timeout);
7801
7802 if (!ast_strlen_zero(predial_callee)) {
7803 /* note casting to void * here to suppress compiler warning message (passing const to non-const function) */
7804 ast_dial_option_global_enable(outgoing->dial, AST_DIAL_OPTION_PREDIAL, (void *)predial_callee);
7805 }
7806
7807 if (ast_dial_prerun(outgoing->dial, NULL, cap)) {
7808 if (synchronous && reason) {
7810 ast_dial_reason(outgoing->dial, 0));
7811 }
7812 return -1;
7813 }
7814
7816 if (!dialed) {
7817 return -1;
7818 }
7819
7821 if (vars) {
7823 }
7824 if (!ast_strlen_zero(account)) {
7826 ast_channel_accountcode_set(dialed, account);
7827 ast_channel_peeraccount_set(dialed, account);
7829 }
7831
7832 if (!ast_strlen_zero(predial_callee)) {
7833 char *tmp = NULL;
7834 /*
7835 * The predial sub routine may have set callerid so set this into the new channel
7836 * Note... cid_num and cid_name parameters to this function will always be NULL if
7837 * predial_callee is non-NULL so we are not overwriting anything here.
7838 */
7840 if (tmp) {
7841 ast_copy_string(tmp_cid_num, tmp, sizeof(tmp_cid_num));
7842 cid_num = tmp_cid_num;
7843 }
7845 if (tmp) {
7846 ast_copy_string(tmp_cid_name, tmp, sizeof(tmp_cid_name));
7847 cid_name = tmp_cid_name;
7848 }
7849 }
7851
7852 if (!ast_strlen_zero(cid_num) || !ast_strlen_zero(cid_name)) {
7854
7855 /*
7856 * It seems strange to set the CallerID on an outgoing call leg
7857 * to whom we are calling, but this function's callers are doing
7858 * various Originate methods. This call leg goes to the local
7859 * user. Once the called party answers, the dialplan needs to
7860 * be able to access the CallerID from the CALLERID function as
7861 * if the called party had placed this call.
7862 */
7863 ast_set_callerid(dialed, cid_num, cid_name, cid_num);
7864
7866 if (!ast_strlen_zero(cid_num)) {
7867 connected.id.number.valid = 1;
7868 connected.id.number.str = (char *) cid_num;
7870 }
7871 if (!ast_strlen_zero(cid_name)) {
7872 connected.id.name.valid = 1;
7873 connected.id.name.str = (char *) cid_name;
7875 }
7877 }
7878
7879 if (early_media) {
7881 }
7882
7883 if (locked_channel) {
7884 /*
7885 * Keep a dialed channel ref since the caller wants
7886 * the channel returned. We must get the ref before
7887 * spawning off pbx_outgoing_exec().
7888 */
7889 ast_channel_ref(dialed);
7890 if (!synchronous) {
7891 /*
7892 * Lock it now to hold off pbx_outgoing_exec() in case the
7893 * calling function needs the channel state/snapshot before
7894 * dialing actually happens.
7895 */
7896 ast_channel_lock(dialed);
7897 }
7898 }
7899
7900 /* This extra reference is dereferenced by pbx_outgoing_exec */
7901 ao2_ref(outgoing, +1);
7902
7903 if (synchronous == AST_OUTGOING_WAIT_COMPLETE) {
7904 /*
7905 * Because we are waiting until this is complete anyway, there is no
7906 * sense in creating another thread that we will just need to wait
7907 * for, so instead we commandeer the current thread.
7908 */
7910 } else {
7911 outgoing->in_separate_thread = 1;
7912
7914 ast_log(LOG_WARNING, "Unable to spawn dialing thread for '%s/%s'\n", type, addr);
7915 ao2_ref(outgoing, -1);
7916 if (locked_channel) {
7917 if (!synchronous) {
7918 ast_channel_unlock(dialed);
7919 }
7920 ast_channel_unref(dialed);
7921 }
7922 return -1;
7923 }
7924
7925 if (synchronous) {
7927 /* Wait for dialing to complete */
7928 while (!outgoing->dialed) {
7930 }
7932 }
7933 }
7934
7935 if (synchronous) {
7936 /* Determine the outcome of the dialing attempt up to it being answered. */
7937 if (reason) {
7938 *reason = pbx_dial_reason(outgoing->dial_res,
7939 ast_dial_reason(outgoing->dial, 0));
7940 }
7941
7942 if (outgoing->dial_res != AST_DIAL_RESULT_ANSWERED) {
7943 /* The dial operation failed. */
7944 if (locked_channel) {
7945 ast_channel_unref(dialed);
7946 }
7947 return -1;
7948 }
7949 if (locked_channel) {
7950 ast_channel_lock(dialed);
7951 }
7952 }
7953
7954 if (locked_channel) {
7955 *locked_channel = dialed;
7956 }
7957 return 0;
7958}
pthread_t thread
Definition app_sla.c:335
void * ao2_object_get_lockaddr(void *obj)
Return the mutex lock address of an object.
Definition astobj2.c:476
#define AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED
Definition callerid.h:437
static int connected
Definition cdr_pgsql.c:73
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:8392
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:7386
@ AST_FLAG_ORIGINATED
Definition channel.h:1059
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:2032
@ 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:1272
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:1287
int ast_dial_reason(struct ast_dial *dial, int num)
Get the reason an outgoing channel has failed.
Definition dial.c:1250
@ 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:1261
int ast_dial_option_global_enable(struct ast_dial *dial, enum ast_dial_option option, void *data)
Enables an option globally.
Definition dial.c:1148
void ast_channel_stage_snapshot_done(struct ast_channel *chan)
Clear flag to indicate channel snapshot is being staged, and publish snapshot.
void ast_channel_stage_snapshot(struct ast_channel *chan)
Set flag to indicate channel snapshot is being staged.
#define ast_cond_wait(cond, mutex)
Definition lock.h:212
#define ast_cond_init(cond, attr)
Definition lock.h:208
static void pbx_outgoing_state_callback(struct ast_dial *dial)
Internal dialing state callback which causes early media to trigger an answer.
Definition pbx.c:7699
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:7725
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:7636
static void pbx_outgoing_destroy(void *obj)
Destructor for outgoing structure.
Definition pbx.c:7622
@ AST_OUTGOING_WAIT_COMPLETE
Definition pbx.h:1146
struct ast_party_dialed dialed
Dialed/Called information.
Connected Line/Party information.
Definition channel.h:458
const ast_string_field app
Definition pbx_spool.c:95
const ast_string_field context
Definition pbx_spool.c:95
const ast_string_field exten
Definition pbx_spool.c:95
int priority
Definition pbx_spool.c:96
Structure which contains information about an outgoing dial.
Definition pbx.c:7598
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition utils.h:981

References ao2_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, ast_channel::context, outgoing::context, ast_channel::dialed, ast_channel::exten, outgoing::exten, LOG_WARNING, name, NULL, pbx_dial_reason(), pbx_outgoing_destroy(), pbx_outgoing_exec(), pbx_outgoing_state_callback(), priority, outgoing::priority, RAII_VAR, S_COR, thread, and type.

Referenced by ast_pbx_outgoing_app_predial(), and ast_pbx_outgoing_exten_predial().

◆ pbx_outgoing_destroy()

static void pbx_outgoing_destroy ( void *  obj)
static

Destructor for outgoing structure.

Definition at line 7622 of file pbx.c.

7623{
7624 struct pbx_outgoing *outgoing = obj;
7625
7626 if (outgoing->dial) {
7628 }
7629
7630 ast_cond_destroy(&outgoing->cond);
7631
7632 ast_free(outgoing->appdata);
7633}
int ast_dial_destroy(struct ast_dial *dial)
Destroys a dialing structure.
Definition dial.c:1094
#define ast_cond_destroy(cond)
Definition lock.h:209

References ast_cond_destroy, ast_dial_destroy(), and ast_free.

Referenced by pbx_outgoing_attempt().

◆ pbx_outgoing_exec()

static void * pbx_outgoing_exec ( void *  data)
static

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

Definition at line 7636 of file pbx.c.

7637{
7638 RAII_VAR(struct pbx_outgoing *, outgoing, data, ao2_cleanup);
7639 enum ast_dial_result res;
7640 struct ast_channel *chan;
7641
7642 res = ast_dial_run(outgoing->dial, NULL, 0);
7643
7644 if (outgoing->in_separate_thread) {
7645 /* Notify anyone interested that dialing is complete */
7647 outgoing->dial_res = res;
7648 outgoing->dialed = 1;
7649 ast_cond_signal(&outgoing->cond);
7651 } else {
7652 /* We still need the dial result, but we don't need to lock */
7653 outgoing->dial_res = res;
7654 }
7655
7656 /* If the outgoing leg was not answered we can immediately return and go no further */
7657 if (res != AST_DIAL_RESULT_ANSWERED) {
7658 return NULL;
7659 }
7660
7661 /* We steal the channel so we get ownership of when it is hung up */
7662 chan = ast_dial_answered_steal(outgoing->dial);
7663
7664 if (!ast_strlen_zero(outgoing->app)) {
7665 struct ast_app *app = pbx_findapp(outgoing->app);
7666
7667 if (app) {
7668 ast_verb(4, "Launching %s(%s) on %s\n", outgoing->app, S_OR(outgoing->appdata, ""),
7669 ast_channel_name(chan));
7670 pbx_exec(chan, app, outgoing->appdata);
7671 } else {
7672 ast_log(LOG_WARNING, "No such application '%s'\n", outgoing->app);
7673 }
7674
7675 ast_hangup(chan);
7676 } else {
7679 }
7680
7683 }
7684
7685 if (outgoing->priority > 0) {
7687 }
7688
7689 if (ast_pbx_run(chan)) {
7690 ast_log(LOG_ERROR, "Failed to start PBX on %s\n", ast_channel_name(chan));
7691 ast_hangup(chan);
7692 }
7693 }
7694
7695 return NULL;
7696}
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:938
struct ast_channel * ast_dial_answered_steal(struct ast_dial *dial)
Steal the channel that answered.
Definition dial.c:992
#define ast_cond_signal(cond)
Definition lock.h:210

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

Referenced by pbx_outgoing_attempt().

◆ pbx_outgoing_state_callback()

static void pbx_outgoing_state_callback ( struct ast_dial dial)
static

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

Definition at line 7699 of file pbx.c.

7700{
7701 struct ast_channel *channel;
7702
7704 return;
7705 }
7706
7707 if (!(channel = ast_dial_get_channel(dial, 0))) {
7708 return;
7709 }
7710
7711 ast_verb(4, "Treating progress as answer on '%s' due to early media option\n",
7712 ast_channel_name(channel));
7713
7715}
int ast_queue_control(struct ast_channel *chan, enum ast_control_frame_type control)
Queue a control frame without payload.
Definition channel.c:1289
enum ast_dial_result ast_dial_state(struct ast_dial *dial)
Return state of dial.
Definition dial.c:1011
@ 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 8835 of file pbx.c.

8836{
8837 char *context, *exten, *pri;
8838 /* do the strsep before here, so we don't have to alloc and free */
8839 if (!*extenp) {
8840 /* Only a priority in this one */
8841 *prip = *contextp;
8842 *extenp = NULL;
8843 *contextp = NULL;
8844 } else if (!*prip) {
8845 /* Only an extension and priority in this one */
8846 *prip = *extenp;
8847 *extenp = *contextp;
8848 *contextp = NULL;
8849 }
8850 context = *contextp;
8851 exten = *extenp;
8852 pri = *prip;
8853 if (mode) {
8854 if (*pri == '+') {
8855 *mode = 1;
8856 pri++;
8857 } else if (*pri == '-') {
8858 *mode = -1;
8859 pri++;
8860 }
8861 }
8862 if ((rest && sscanf(pri, "%30d%1s", ipri, rest) != 1) || sscanf(pri, "%30d", ipri) != 1) {
8863 *ipri = ast_findlabel_extension(chan, context ? context : ast_channel_context(chan),
8864 exten ? exten : ast_channel_exten(chan), pri,
8866 if (*ipri < 1) {
8867 ast_log(LOG_WARNING, "Priority '%s' must be a number > 0, or valid label\n", pri);
8868 return -1;
8869 } else if (mode) {
8870 *mode = 0;
8871 }
8872 }
8873 return 0;
8874}
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:4216

References ast_channel_caller(), ast_channel_context(), ast_channel_exten(), ast_findlabel_extension(), ast_log, ast_channel::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 8876 of file pbx.c.

8877{
8878 char *exten, *pri, *context;
8879 char *stringp;
8880 int ipri;
8881 int mode = 0;
8882 char rest[2] = "";
8883
8884 if (ast_strlen_zero(goto_string)) {
8885 ast_log(LOG_WARNING, "Goto requires an argument ([[context,]extension,]priority)\n");
8886 return -1;
8887 }
8888 stringp = ast_strdupa(goto_string);
8889 context = strsep(&stringp, ","); /* guaranteed non-null */
8890 exten = strsep(&stringp, ",");
8891 pri = strsep(&stringp, ",");
8892
8893 if (pbx_parse_location(chan, &context, &exten, &pri, &ipri, &mode, rest)) {
8894 return -1;
8895 }
8896 /* At this point we have a priority and maybe an extension and a context */
8897
8898 if (mode)
8899 ipri = ast_channel_priority(chan) + (ipri * mode);
8900
8901 if (async)
8902 ast_async_goto(chan, context, exten, ipri);
8903 else
8904 ast_explicit_goto(chan, context, exten, ipri);
8905
8906 return 0;
8907
8908}
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:8835

References ast_async_goto(), ast_channel_priority(), ast_explicit_goto(), ast_log, ast_strdupa, ast_strlen_zero(), ast_channel::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 4806 of file pbx.c.

4807{
4808 int oldval = autofallthrough;
4809 autofallthrough = newval;
4810 return oldval;
4811}

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

4814{
4815 int oldval = extenpatternmatchnew;
4816 extenpatternmatchnew = newval;
4817 return oldval;
4818}

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

4821{
4822 if (overrideswitch) {
4824 }
4825 if (!ast_strlen_zero(newval)) {
4826 overrideswitch = ast_strdup(newval);
4827 } else {
4829 }
4830}

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

8961{
8962 STASIS_MESSAGE_TYPE_CLEANUP(hint_change_message_type);
8963 STASIS_MESSAGE_TYPE_CLEANUP(hint_remove_message_type);
8964
8965 if (hints) {
8966 ao2_container_unregister("hints");
8967 ao2_ref(hints, -1);
8968 hints = NULL;
8969 }
8970 if (hintdevices) {
8971 ao2_container_unregister("hintdevices");
8972 ao2_ref(hintdevices, -1);
8973 hintdevices = NULL;
8974 }
8975 if (autohints) {
8976 ao2_container_unregister("autohints");
8977 ao2_ref(autohints, -1);
8978 autohints = NULL;
8979 }
8980 if (statecbs) {
8981 ao2_container_unregister("statecbs");
8982 ao2_ref(statecbs, -1);
8983 statecbs = NULL;
8984 }
8985 if (contexts_table) {
8987 }
8988}
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 4724 of file pbx.c.

4725{
4726 /* Oh joyous kernel, we're a new thread, with nothing to do but
4727 answer this channel and get it going.
4728 */
4729 /* NOTE:
4730 The launcher of this function _MUST_ increment 'countcalls'
4731 before invoking the function; it will be decremented when the
4732 PBX has finished running on the channel
4733 */
4734 struct ast_channel *c = data;
4735
4738
4739 pthread_exit(NULL);
4740
4741 return NULL;
4742}
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 8338 of file pbx.c.

8339{
8340 struct ast_presence_state_message *presence_state;
8341 struct ast_str *hint_app = NULL;
8342 struct ast_hintdevice *device;
8343 struct ast_hintdevice *cmpdevice;
8344 struct ao2_iterator *dev_iter;
8345
8347 return;
8348 }
8349
8350 presence_state = stasis_message_data(msg);
8351
8352 if (ao2_container_count(hintdevices) == 0) {
8353 /* There are no hints monitoring devices. */
8354 return;
8355 }
8356
8357 hint_app = ast_str_create(1024);
8358 if (!hint_app) {
8359 return;
8360 }
8361
8362 cmpdevice = ast_alloca(sizeof(*cmpdevice) + strlen(presence_state->provider));
8363 strcpy(cmpdevice->hintdevice, presence_state->provider);
8364
8365 ast_mutex_lock(&context_merge_lock);/* Hold off ast_merge_contexts_and_delete */
8366 dev_iter = ao2_t_callback(hintdevices,
8369 cmpdevice,
8370 "find devices in container");
8371 if (!dev_iter) {
8373 ast_free(hint_app);
8374 return;
8375 }
8376
8377 for (; (device = ao2_iterator_next(dev_iter)); ao2_t_ref(device, -1, "Next device")) {
8378 if (device->hint) {
8379 presence_state_notify_callbacks(device->hint, &hint_app, presence_state);
8380 }
8381 }
8382 ao2_iterator_destroy(dev_iter);
8384
8385 ast_free(hint_app);
8386}
#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(), and stasis_message_data().

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

3502{
3503 struct ao2_iterator cb_iter;
3504 struct ast_state_cb *state_cb;
3507
3508 ao2_lock(hint);
3509 if (!hint->exten) {
3510 /* The extension has already been destroyed */
3511 ao2_unlock(hint);
3512 return;
3513 }
3514
3515 /*
3516 * Save off strings in case the hint extension gets destroyed
3517 * while we are notifying the watchers.
3518 */
3521 sizeof(context_name));
3523 sizeof(exten_name));
3524 ast_str_set(hint_app, 0, "%s", ast_get_extension_app(hint->exten));
3525 ao2_unlock(hint);
3526
3527 /* Check to see if update is necessary */
3528 if ((hint->last_presence_state == presence_state->state) &&
3529 ((hint->last_presence_subtype && presence_state->subtype &&
3530 !strcmp(hint->last_presence_subtype, presence_state->subtype)) ||
3531 (!hint->last_presence_subtype && !presence_state->subtype)) &&
3532 ((hint->last_presence_message && presence_state->message &&
3533 !strcmp(hint->last_presence_message, presence_state->message)) ||
3534 (!hint->last_presence_message && !presence_state->message))) {
3535 /* this update is the same as the last, do nothing */
3536 return;
3537 }
3538
3539 /* update new values */
3542 hint->last_presence_state = presence_state->state;
3543 hint->last_presence_subtype = presence_state->subtype ? ast_strdup(presence_state->subtype) : NULL;
3544 hint->last_presence_message = presence_state->message ? ast_strdup(presence_state->message) : NULL;
3545
3546 /* For general callbacks */
3547 cb_iter = ao2_iterator_init(statecbs, 0);
3548 for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_ref(state_cb, -1)) {
3551 exten_name,
3552 state_cb->data,
3554 hint,
3555 NULL);
3556 }
3557 ao2_iterator_destroy(&cb_iter);
3558
3559 /* For extension callbacks */
3560 cb_iter = ao2_iterator_init(hint->callbacks, 0);
3561 for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_cleanup(state_cb)) {
3564 exten_name,
3565 state_cb->data,
3567 hint,
3568 NULL);
3569 }
3570 ao2_iterator_destroy(&cb_iter);
3571}

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

9014{
9015 struct ast_autohint *autohint = v_obj;
9016
9017 if (!autohint) {
9018 return;
9019 }
9020 prnt(where, "%s", autohint->context);
9021}

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

5475{
5476 int prio = ast_get_extension_priority(e);
5477 if (prio == PRIORITY_HINT) {
5478 snprintf(buf, buflen, "hint: %s",
5480 } else {
5481 snprintf(buf, buflen, "%d. %s(%s)",
5482 prio, ast_get_extension_app(e),
5484 }
5485}

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

9002{
9003 struct ast_hintdevice *hintdevice = v_obj;
9004
9005 if (!hintdevice) {
9006 return;
9007 }
9008 prnt(where, "%s => %s@%s", hintdevice->hintdevice,
9009 ast_get_extension_name(hintdevice->hint->exten),
9011}

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

8991{
8992 struct ast_hint *hint = v_obj;
8993
8994 if (!hint) {
8995 return;
8996 }
8997 prnt(where, "%s@%s", ast_get_extension_name(hint->exten),
8999}

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

9024{
9025 struct ast_state_cb *state_cb = v_obj;
9026
9027 if (!state_cb) {
9028 return;
9029 }
9030 prnt(where, "%d", state_cb->id);
9031}

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

4107{
4108 struct stasis_message *message;
4109
4110 if (!hint_change_message_type()) {
4111 return -1;
4112 }
4113
4114 if (!(message = stasis_message_create(hint_change_message_type(), hint))) {
4115 ao2_ref(hint, -1);
4116 return -1;
4117 }
4118
4121
4122 ao2_ref(message, -1);
4123
4124 return 0;
4125}
struct stasis_message * stasis_message_create(struct stasis_message_type *type, void *data)
Create a new message.
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic's subscribers.
Definition stasis.c:1578

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

Referenced by ast_change_hint().

◆ publish_hint_remove()

static int publish_hint_remove ( struct ast_hint hint)
static

Publish a hint removed event

Definition at line 3956 of file pbx.c.

3957{
3958 struct stasis_message *message;
3959
3960 if (!hint_remove_message_type()) {
3961 return -1;
3962 }
3963
3964 if (!(message = stasis_message_create(hint_remove_message_type(), hint))) {
3965 ao2_ref(hint, -1);
3966 return -1;
3967 }
3968
3970
3971 ao2_ref(message, -1);
3972
3973 return 0;
3974}

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

Referenced by ast_remove_hint().

◆ raise_exception()

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

pbx.c functions needed by pbx_builtins.c

Definition at line 2821 of file pbx.c.

2822{
2823 struct ast_datastore *ds;
2824 struct pbx_exception *exception;
2825
2826 ast_channel_lock(chan);
2828 if (!ds) {
2830 if (!ds) {
2831 ast_channel_unlock(chan);
2832 return -1;
2833 }
2834 if (!(exception = ast_calloc_with_stringfields(1, struct pbx_exception, 128))) {
2836 ast_channel_unlock(chan);
2837 return -1;
2838 }
2839 ds->data = exception;
2840 ast_channel_datastore_add(chan, ds);
2841 } else
2842 exception = ds->data;
2843
2844 ast_string_field_set(exception, reason, reason);
2846 ast_string_field_set(exception, exten, ast_channel_exten(chan));
2847 exception->priority = ast_channel_priority(chan);
2848 ast_channel_unlock(chan);
2849
2850 set_ext_pri(chan, "e", priority);
2851 return 0;
2852}
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition channel.c:2376
#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.
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.

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

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

◆ remove_hintdevice()

static int remove_hintdevice ( struct ast_hint hint)
static

Definition at line 539 of file pbx.c.

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

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

Referenced by ast_change_hint(), and ast_remove_hint().

◆ set_ext_pri()

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

helper function to set extension and priority

Definition at line 4300 of file pbx.c.

4301{
4303 ast_channel_exten_set(c, exten);
4306}

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

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

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

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, c, ast_exten::cidmatch, 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 5488 of file pbx.c.

5489{
5491 ast_cli(fd, " %-17s %-45s [%s:%d]\n",
5492 buf1, buf2,
5495 return;
5496 }
5497
5498 ast_cli(fd, " %-17s %-45s [%s]\n",
5499 buf1, buf2, ast_get_extension_registrar(exten));
5500}
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:8586
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:8581

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

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

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

References ast_state_cb::change_cb, CMP_MATCH, and CMP_STOP.

Referenced by ast_pbx_init().

◆ trie_find_next_match()

static struct ast_exten * trie_find_next_match ( struct match_char node)
static

Definition at line 1180 of file pbx.c.

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

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

Referenced by pbx_find_extension(), and trie_find_next_match().

◆ unload_pbx()

static void unload_pbx ( void  )
static

Definition at line 8453 of file pbx.c.

8454{
8457
8458 ast_manager_unregister("ShowDialPlan");
8459 ast_manager_unregister("ExtensionStateList");
8463}
void ast_cli_unregister_multiple(void)
Definition ael_main.c:408
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition manager.c:7704
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
struct stasis_subscription * stasis_unsubscribe_and_join(struct stasis_subscription *subscription)
Cancel a subscription, blocking until the last message is processed.
Definition stasis.c:1201

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

Referenced by load_pbx().

◆ unreference_cached_app()

void unreference_cached_app ( struct ast_app app)

pbx.c function needed by pbx_app.c

Definition at line 6166 of file pbx.c.

6167{
6168 struct ast_context *context = NULL;
6169 struct ast_exten *eroot = NULL, *e = NULL;
6170
6172 while ((context = ast_walk_contexts(context))) {
6173 while ((eroot = ast_walk_context_extensions(context, eroot))) {
6174 while ((e = ast_walk_extension_priorities(eroot, e))) {
6175 if (e->cached_app == app)
6176 e->cached_app = NULL;
6177 }
6178 }
6179 }
6181
6182 return;
6183}

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

Referenced by ast_unregister_application().

◆ update_scoreboard()

static void update_scoreboard ( struct scoreboard board,
int  length,
int  spec,
struct ast_exten exten,
char  last,
const char *  callerid,
int  deleted,
struct match_char node 
)
static

Definition at line 1084 of file pbx.c.

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

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

Referenced by new_find_extension().

◆ wait_for_hangup()

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

Definition at line 8272 of file pbx.c.

8273{
8274 int res;
8275 struct ast_frame *f;
8276 double waitsec;
8277 int waittime;
8278
8279 if (ast_strlen_zero(data) || (sscanf(data, "%30lg", &waitsec) != 1) || (waitsec < 0))
8280 waitsec = -1;
8281 if (waitsec > -1) {
8282 waittime = waitsec * 1000.0;
8283 ast_safe_sleep_without_silence(chan, waittime);
8284 } else do {
8285 res = ast_waitfor(chan, -1);
8286 if (res < 0)
8287 return;
8288 f = ast_read(chan);
8289 if (f)
8290 ast_frfree(f);
8291 } while(f);
8292}
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition channel.c:3178
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition channel.c:4290
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:1566
#define ast_frfree(fr)
Data structure associated with a single frame of data.
union ast_frame::@235 data

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

Referenced by indicate_busy(), and indicate_congestion().

Variable Documentation

◆ autofallthrough

int autofallthrough = 1
static

Definition at line 783 of file pbx.c.

Referenced by __ast_pbx_run(), and pbx_set_autofallthrough().

◆ autohints

struct ao2_container* autohints
static

Container for autohint contexts.

Definition at line 402 of file pbx.c.

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

◆ conlock

Lock for the ast_context list.

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

Definition at line 805 of file pbx.c.

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

◆ context_merge_lock

ast_mutex_t context_merge_lock = AST_MUTEX_INIT_VALUE
static

Lock to hold off restructuring of hints by ast_merge_contexts_and_delete.

Definition at line 810 of file pbx.c.

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

◆ contexts

struct ast_context* contexts
static

◆ contexts_table

struct ast_hashtab* contexts_table = NULL
static

◆ countcalls

int countcalls
static

Definition at line 793 of file pbx.c.

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

◆ device_state_sub

struct stasis_subscription* device_state_sub
static

Subscription for device state change events.

Definition at line 788 of file pbx.c.

Referenced by load_pbx(), and unload_pbx().

◆ exception_function

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

Definition at line 2882 of file pbx.c.

2882 {
2883 .name = "EXCEPTION",
2884 .read = acf_exception_read,
2885};

Referenced by load_pbx(), and unload_pbx().

◆ exception_store_info

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

Definition at line 2805 of file pbx.c.

2805 {
2806 .type = "EXCEPTION",
2807 .destroy = exception_store_free,
2808};

Referenced by acf_exception_read(), and raise_exception().

◆ extenpatternmatchnew

int extenpatternmatchnew = 0
static

Definition at line 784 of file pbx.c.

Referenced by pbx_find_extension(), and pbx_set_extenpatternmatchnew().

◆ extension_states

const struct cfextension_states extension_states[]
static

Referenced by ast_extension_state2str().

◆ hintdevices

struct ao2_container* hintdevices
static

Container for hint devices.

Definition at line 385 of file pbx.c.

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

◆ hints

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

Definition at line 821 of file pbx.c.

◆ maxcalllock

ast_mutex_t maxcalllock = AST_MUTEX_INIT_VALUE
static

Definition at line 792 of file pbx.c.

Referenced by decrease_call_count(), and increase_call_count().

◆ overrideswitch

char* overrideswitch = NULL
static

Definition at line 785 of file pbx.c.

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

◆ pbx_cli

struct ast_cli_entry pbx_cli[]
static

Definition at line 6151 of file pbx.c.

6151 {
6152#if 0
6153 AST_CLI_DEFINE(handle_eat_memory, "Eats all available memory"),
6154#endif
6155 AST_CLI_DEFINE(handle_show_hints, "Show dialplan hints"),
6156 AST_CLI_DEFINE(handle_show_hint, "Show dialplan hint"),
6157#ifdef AST_DEVMODE
6158 AST_CLI_DEFINE(handle_show_device2extenstate, "Show expected exten state from multiple device states"),
6159#endif
6160 AST_CLI_DEFINE(handle_show_dialplan, "Show dialplan"),
6161 AST_CLI_DEFINE(handle_debug_dialplan, "Show fast extension pattern matching data structures"),
6162 AST_CLI_DEFINE(handle_unset_extenpatternmatchnew, "Use the Old extension pattern matching algorithm."),
6163 AST_CLI_DEFINE(handle_set_extenpatternmatchnew, "Use the New extension pattern matching algorithm."),
6164};
#define AST_CLI_DEFINE(fn, txt,...)
Definition cli.h:197
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
Definition pbx.c:5192
static char * handle_unset_extenpatternmatchnew(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition pbx.c:6120
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
Definition pbx.c:5291
static char * handle_debug_dialplan(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Send ack once.
Definition pbx.c:5786
static char * handle_set_extenpatternmatchnew(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition pbx.c:6092
static char * handle_show_dialplan(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition pbx.c:5719

Referenced by load_pbx(), and unload_pbx().

◆ presence_state_sub

struct stasis_subscription* presence_state_sub
static

Subscription for presence state change events.

Definition at line 790 of file pbx.c.

Referenced by load_pbx(), and unload_pbx().

◆ statecbs

struct ao2_container* statecbs
static

◆ stateid

int stateid = 1
static

Definition at line 812 of file pbx.c.

Referenced by extension_state_add_destroy().

◆ 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:8297

Definition at line 8321 of file pbx.c.

8321 {
8322 .name = "TESTTIME",
8323 .write = testtime_write,
8324};

Referenced by load_pbx(), and unload_pbx().

◆ totalcalls

int totalcalls
static

Definition at line 794 of file pbx.c.

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